Lely core libraries  2.2.5
buf.c
Go to the documentation of this file.
1 
24 #include "can.h"
25 #define LELY_CAN_BUF_INLINE extern inline
26 #include <lely/can/buf.h>
27 #include <lely/util/errnum.h>
28 
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #ifndef LELY_CAN_BUF_SIZE
34 #define LELY_CAN_BUF_SIZE 16
36 #endif
37 
38 int
39 can_buf_init(struct can_buf *buf, size_t size)
40 {
41  assert(buf);
42 
43  // Computer the nearest power of two minus one.
44  buf->size = LELY_CAN_BUF_SIZE;
45  while (buf->size - 1 < size)
46  buf->size *= 2;
47  buf->size--;
48 
49  buf->ptr = malloc((buf->size + 1) * sizeof(struct can_msg));
50  if (!buf->ptr) {
51  set_errc(errno2c(errno));
52  return -1;
53  }
54 
55 #ifdef LELY_NO_ATOMICS
56  buf->begin = 0;
57  buf->end = 0;
58 #else
59  atomic_init(&buf->begin, 0);
60  atomic_init(&buf->end, 0);
61 #endif
62 
63  return 0;
64 }
65 
66 void
67 can_buf_fini(struct can_buf *buf)
68 {
69  assert(buf);
70 
71  free(buf->ptr);
72 }
73 
74 struct can_buf *
76 {
77  int errc = 0;
78 
79  struct can_buf *buf = malloc(sizeof(*buf));
80  if (!buf) {
81  errc = errno2c(errno);
82  goto error_alloc_buf;
83  }
84 
85  if (can_buf_init(buf, size) == -1) {
86  errc = get_errc();
87  goto error_init_buf;
88  }
89 
90  return buf;
91 
92 error_init_buf:
93  free(buf);
94 error_alloc_buf:
95  set_errc(errc);
96  return NULL;
97 }
98 
99 void
100 can_buf_destroy(struct can_buf *buf)
101 {
102  if (!buf)
103  return;
104 
105  can_buf_fini(buf);
106 
107  free(buf);
108 }
109 
110 size_t
111 can_buf_reserve(struct can_buf *buf, size_t n)
112 {
113  assert(buf);
114 
115 #ifdef LELY_NO_ATOMICS
116  size_t begin = buf->begin & buf->size;
117  size_t end = buf->end & buf->size;
118 #else
119  size_t begin = atomic_load(&buf->begin) & buf->size;
120  size_t end = atomic_load(&buf->end) & buf->size;
121 #endif
122 
123  // Do not resize the buffer if it is not necessary.
124  size_t capacity = (begin - end - 1) & buf->size;
125  if (capacity >= n)
126  return capacity;
127 
128  size_t size = LELY_CAN_BUF_SIZE;
129  while (size - 1 < buf->size - capacity + n)
130  size *= 2;
131  size--;
132 
133  // Reallocate the existing buffer.
134  struct can_msg *ptr =
135  realloc(buf->ptr, (size + 1) * sizeof(struct can_msg));
136  if (!ptr) {
137  set_errc(errno2c(errno));
138  return 0;
139  }
140  buf->ptr = ptr;
141 
142  // If the buffer consists of two regions (because of wrapping), move the
143  // second region to the end of the buffer.
144  if (begin > end) {
145  struct can_msg *end = buf->ptr + buf->size + 1;
146  struct can_msg *src = buf->ptr + begin;
147  begin += size - buf->size;
148  struct can_msg *dst = buf->ptr + begin;
149  memmove(dst, src, (end - src) * sizeof(struct can_msg));
150  }
151 
152  buf->size = size;
153 #ifdef LELY_NO_ATOMICS
154  buf->begin = begin;
155  buf->end = end;
156 #else
157  atomic_store(&buf->begin, begin);
158  atomic_store(&buf->end, end);
159 #endif
160 
161  return (begin - end - 1) & buf->size;
162 }
can_buf
A CAN frame buffer.
Definition: buf.h:47
string.h
can_buf::size
size_t size
The total size (in number of frames) of the buffer, excluding the unused frame used to distinguish be...
Definition: buf.h:56
can_msg
A CAN or CAN FD format frame.
Definition: msg.h:87
can_buf::ptr
struct can_msg * ptr
A pointer to the allocated memory for the buffer.
Definition: buf.h:49
get_errc
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
can_buf_fini
void can_buf_fini(struct can_buf *buf)
Finalizes a CAN frame buffer.
Definition: buf.c:67
errno2c
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
can_buf_reserve
size_t can_buf_reserve(struct can_buf *buf, size_t n)
Resizes a CAN frame buffer, if necessary, to make room for at least n additional frames.
Definition: buf.c:111
can_buf_init
int can_buf_init(struct can_buf *buf, size_t size)
Initializes a CAN frame buffer.
Definition: buf.c:39
LELY_CAN_BUF_SIZE
#define LELY_CAN_BUF_SIZE
The minimum size (in number of frames) of a CAN frame buffer.
Definition: buf.c:35
buf.h
set_errc
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
errnum.h
can.h
can_buf::begin
size_t begin
The offset (with respect to ptr) of the first value available for reading (and two past the last avai...
Definition: buf.h:63
can_buf_create
struct can_buf * can_buf_create(size_t size)
Allocates and initializes a CAN frame buffer.
Definition: buf.c:75
can_buf::end
size_t end
The offset (with respect to ptr) of one past the last value available for reading (and the first avai...
Definition: buf.h:73
stdlib.h