Contiki-NG
Toggle main menu visibility
Loading...
Searching...
No Matches
ringbuf.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2008, Swedish Institute of Computer Science.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the Institute nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*
29
* This file is part of the Contiki operating system.
30
*
31
*/
32
33
/**
34
* \file
35
* Ring buffer library implementation
36
* \author
37
* Adam Dunkels <adam@sics.se>
38
*/
39
40
#include "
lib/ringbuf.h
"
41
#include <
sys/cc.h
>
42
/*---------------------------------------------------------------------------*/
43
int
44
ringbuf_put
(
struct
ringbuf
*r, uint8_t c)
45
{
46
/* Check if buffer is full. If it is full, return 0 to indicate that
47
the element was not inserted into the buffer.
48
49
XXX: there is a potential risk for a race condition here, because
50
the ->get_ptr field may be written concurrently by the
51
ringbuf_get() function. To avoid this, access to ->get_ptr must
52
be atomic. We use an uint8_t type, which makes access atomic on
53
most platforms, but C does not guarantee this.
54
*/
55
if
(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
56
return
0;
57
}
58
/*
59
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
60
* the access to non-volatile variables.
61
* In this case a reader might read from the moved index/ptr before
62
* its value (c) is written. Reordering makes little sense, but
63
* better safe than sorry.
64
*/
65
CC_ACCESS_NOW
(uint8_t, r->data[r->put_ptr]) = c;
66
CC_ACCESS_NOW
(uint8_t, r->put_ptr) = (r->put_ptr + 1) & r->mask;
67
return
1;
68
}
69
/*---------------------------------------------------------------------------*/
70
int
71
ringbuf_get
(
struct
ringbuf
*r)
72
{
73
uint8_t c;
74
75
/* Check if there are bytes in the buffer. If so, we return the
76
first one and increase the pointer. If there are no bytes left, we
77
return -1.
78
79
XXX: there is a potential risk for a race condition here, because
80
the ->put_ptr field may be written concurrently by the
81
ringbuf_put() function. To avoid this, access to ->get_ptr must
82
be atomic. We use an uint8_t type, which makes access atomic on
83
most platforms, but C does not guarantee this.
84
*/
85
if
(((r->put_ptr - r->get_ptr) & r->mask) != 0) {
86
/*
87
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
88
* the access to non-volatile variables.
89
* In this case the memory might be freed and overwritten by
90
* increasing get_ptr before the value was copied to c.
91
* Opposed to the put-operation this would even make sense,
92
* because the register used for mask can be reused to save c
93
* (on some architectures).
94
*/
95
c =
CC_ACCESS_NOW
(uint8_t, r->data[r->get_ptr]);
96
CC_ACCESS_NOW
(uint8_t, r->get_ptr) = (r->get_ptr + 1) & r->mask;
97
return
c;
98
}
else
{
99
return
-1;
100
}
101
}
102
/*---------------------------------------------------------------------------*/
103
int
104
ringbuf_size
(
struct
ringbuf
*r)
105
{
106
return
r->mask + 1;
107
}
108
/*---------------------------------------------------------------------------*/
109
int
110
ringbuf_elements
(
struct
ringbuf
*r)
111
{
112
return
(r->put_ptr - r->get_ptr) & r->mask;
113
}
114
/*---------------------------------------------------------------------------*/
cc.h
Default definitions of C compiler quirk work-arounds.
CC_ACCESS_NOW
#define CC_ACCESS_NOW(type, variable)
This macro ensures that the access to a non-volatile variable can not be reordered or optimized by th...
Definition
cc.h:145
ringbuf_size
int ringbuf_size(struct ringbuf *r)
Get the size of a ring buffer.
Definition
ringbuf.c:104
ringbuf_get
int ringbuf_get(struct ringbuf *r)
Get a byte from the ring buffer.
Definition
ringbuf.c:71
ringbuf_put
int ringbuf_put(struct ringbuf *r, uint8_t c)
Insert a byte into the ring buffer.
Definition
ringbuf.c:44
ringbuf_elements
int ringbuf_elements(struct ringbuf *r)
Get the number of elements currently in the ring buffer.
Definition
ringbuf.c:110
ringbuf.h
Header file for the ring buffer library.
ringbuf
Structure that holds the state of a ring buffer.
Definition
ringbuf.h:68
os
lib
ringbuf.c
Generated on
for Contiki-NG by
1.17.0