Lely core libraries 1.9.2
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
35#define LELY_CAN_BUF_SIZE 16
36#endif
37
38int
39can_buf_init(struct can_buf *buf, size_t size)
40{
41 assert(buf);
42
43 // Computer the nearest power of two minus one.
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
66void
68{
69 assert(buf);
70
71 free(buf->ptr);
72}
73
74struct 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
92error_init_buf:
93 free(buf);
94error_alloc_buf:
95 set_errc(errc);
96 return NULL;
97}
98
99void
100can_buf_destroy(struct can_buf *buf)
101{
102 if (!buf)
103 return;
104
105 can_buf_fini(buf);
106
107 free(buf);
108}
109
110size_t
111can_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}
struct can_buf * can_buf_create(size_t size)
Allocates and initializes a CAN frame buffer.
Definition: buf.c:75
#define LELY_CAN_BUF_SIZE
The minimum size (in number of frames) of a CAN frame buffer.
Definition: buf.c:35
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
int can_buf_init(struct can_buf *buf, size_t size)
Initializes a CAN frame buffer.
Definition: buf.c:39
void can_buf_fini(struct can_buf *buf)
Finalizes a CAN frame buffer.
Definition: buf.c:67
This header file is part of the CAN library; it contains the CAN frame buffer declarations.
This header file is part of the utilities library; it contains the native and platform-independent er...
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
This is the internal header file of the CAN library.
#define atomic_store(object, desired)
Equivalent to atomic_store_explicit(object, desired, memory_order_seq_cst).
Definition: stdatomic.h:313
#define atomic_load(object)
Equivalent to #atomic_load_explicit(object, memory_order_seq_cst).
Definition: stdatomic.h:332
#define atomic_init(obj, value)
Initializes the atomic object at obj with the value value.
Definition: stdatomic.h:221
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A CAN frame buffer.
Definition: buf.h:47
struct can_msg * ptr
A pointer to the allocated memory for the buffer.
Definition: buf.h:49
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
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
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
A CAN or CAN FD format frame.
Definition: msg.h:88