1 #ifndef _HAVE_JACK_
2 /*
3   Copyright (C) 2000 Paul Davis
4   Copyright (C) 2003 Rohan Drape
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU Lesser General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20   ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code.
21   This is safe for the case of one read thread and one write thread.
22 */
23 
24 #include <config.h>
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #ifdef USE_MLOCK
29 #include <sys/mman.h>
30 #endif /* USE_MLOCK */
31 //#include <jack/ringbuffer.h>
32 #include "audio/ringbuffer.h"
33 
34 /* Create a new ringbuffer to hold at least `sz' bytes of data. The
35    actual buffer size is rounded up to the next power of two.  */
36 
37 jack_ringbuffer_t *
jack_ringbuffer_create(size_t sz)38 jack_ringbuffer_create (size_t sz)
39 {
40   unsigned int power_of_two;
41   jack_ringbuffer_t *rb;
42 
43   if ((rb = malloc (sizeof (jack_ringbuffer_t))) == NULL)
44     {
45       return NULL;
46     }
47 
48   for (power_of_two = 1; (unsigned int) 1 << power_of_two < sz; power_of_two++);
49 
50   rb->size = 1 << power_of_two;
51   rb->size_mask = rb->size;
52   rb->size_mask -= 1;
53   rb->write_ptr = 0;
54   rb->read_ptr = 0;
55   if ((rb->buf = malloc (rb->size)) == NULL)
56     {
57       free (rb);
58       return NULL;
59     }
60   rb->mlocked = 0;
61 
62   return rb;
63 }
64 
65 /* Free all data associated with the ringbuffer `rb'. */
66 
67 void
jack_ringbuffer_free(jack_ringbuffer_t * rb)68 jack_ringbuffer_free (jack_ringbuffer_t * rb)
69 {
70 #ifdef USE_MLOCK
71   if (rb->mlocked)
72     {
73       munlock (rb->buf, rb->size);
74     }
75 #endif /* USE_MLOCK */
76   free (rb->buf);
77   free (rb);
78 }
79 
80 /* Lock the data block of `rb' using the system call 'mlock'.  */
81 
82 int
jack_ringbuffer_mlock(jack_ringbuffer_t * rb)83 jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
84 {
85 #ifdef USE_MLOCK
86   if (mlock (rb->buf, rb->size))
87     {
88       return -1;
89     }
90 #endif /* USE_MLOCK */
91   rb->mlocked = 1;
92   return 0;
93 }
94 
95 /* Reset the read and write pointers to zero. This is not thread
96    safe. */
97 
98 void
jack_ringbuffer_reset(jack_ringbuffer_t * rb)99 jack_ringbuffer_reset (jack_ringbuffer_t * rb)
100 {
101   rb->read_ptr = 0;
102   rb->write_ptr = 0;
103 }
104 
105 /* Return the number of bytes available for reading.  This is the
106    number of bytes in front of the read pointer and behind the write
107    pointer.  */
108 
109 size_t
jack_ringbuffer_read_space(const jack_ringbuffer_t * rb)110 jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
111 {
112   size_t w, r;
113 
114   w = rb->write_ptr;
115   r = rb->read_ptr;
116 
117   if (w > r)
118     {
119       return w - r;
120     }
121   else
122     {
123       return (w - r + rb->size) & rb->size_mask;
124     }
125 }
126 
127 /* Return the number of bytes available for writing.  This is the
128    number of bytes in front of the write pointer and behind the read
129    pointer.  */
130 
131 size_t
jack_ringbuffer_write_space(const jack_ringbuffer_t * rb)132 jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
133 {
134   size_t w, r;
135 
136   w = rb->write_ptr;
137   r = rb->read_ptr;
138 
139   if (w > r)
140     {
141       return ((r - w + rb->size) & rb->size_mask) - 1;
142     }
143   else if (w < r)
144     {
145       return (r - w) - 1;
146     }
147   else
148     {
149       return rb->size - 1;
150     }
151 }
152 
153 /* The copying data reader.  Copy at most `cnt' bytes from `rb' to
154    `dest'.  Returns the actual number of bytes copied. */
155 
156 size_t
jack_ringbuffer_read(jack_ringbuffer_t * rb,char * dest,size_t cnt)157 jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
158 {
159   size_t free_cnt;
160   size_t cnt2;
161   size_t to_read;
162   size_t n1, n2;
163 
164   if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0)
165     {
166       return 0;
167     }
168 
169   to_read = cnt > free_cnt ? free_cnt : cnt;
170 
171   cnt2 = rb->read_ptr + to_read;
172 
173   if (cnt2 > rb->size)
174     {
175       n1 = rb->size - rb->read_ptr;
176       n2 = cnt2 & rb->size_mask;
177     }
178   else
179     {
180       n1 = to_read;
181       n2 = 0;
182     }
183 
184   memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
185   rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
186 
187   if (n2)
188     {
189       memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
190       rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
191     }
192 
193   return to_read;
194 }
195 
196 /* The copying data reader w/o read pointer advance.  Copy at most
197    `cnt' bytes from `rb' to `dest'.  Returns the actual number of bytes
198    copied. */
199 
200 size_t
jack_ringbuffer_peek(jack_ringbuffer_t * rb,char * dest,size_t cnt)201 jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
202 {
203   size_t free_cnt;
204   size_t cnt2;
205   size_t to_read;
206   size_t n1, n2;
207   size_t tmp_read_ptr;
208 
209   tmp_read_ptr = rb->read_ptr;
210 
211   if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0)
212     {
213       return 0;
214     }
215 
216   to_read = cnt > free_cnt ? free_cnt : cnt;
217 
218   cnt2 = tmp_read_ptr + to_read;
219 
220   if (cnt2 > rb->size)
221     {
222       n1 = rb->size - tmp_read_ptr;
223       n2 = cnt2 & rb->size_mask;
224     }
225   else
226     {
227       n1 = to_read;
228       n2 = 0;
229     }
230 
231   memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
232   tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
233 
234   if (n2)
235     {
236       memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
237     }
238 
239   return to_read;
240 }
241 
242 
243 /* The copying data writer.  Copy at most `cnt' bytes to `rb' from
244    `src'.  Returns the actual number of bytes copied. */
245 
246 size_t
jack_ringbuffer_write(jack_ringbuffer_t * rb,const char * src,size_t cnt)247 jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
248 {
249   size_t free_cnt;
250   size_t cnt2;
251   size_t to_write;
252   size_t n1, n2;
253 
254   if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0)
255     {
256       return 0;
257     }
258 
259   to_write = cnt > free_cnt ? free_cnt : cnt;
260 
261   cnt2 = rb->write_ptr + to_write;
262 
263   if (cnt2 > rb->size)
264     {
265       n1 = rb->size - rb->write_ptr;
266       n2 = cnt2 & rb->size_mask;
267     }
268   else
269     {
270       n1 = to_write;
271       n2 = 0;
272     }
273 
274   memcpy (&(rb->buf[rb->write_ptr]), src, n1);
275   rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
276 
277   if (n2)
278     {
279       memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
280       rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
281     }
282 
283   return to_write;
284 }
285 
286 /* Advance the read pointer `cnt' places. */
287 
288 void
jack_ringbuffer_read_advance(jack_ringbuffer_t * rb,size_t cnt)289 jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
290 {
291   size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
292   rb->read_ptr = tmp;
293 }
294 
295 /* Advance the write pointer `cnt' places. */
296 
297 void
jack_ringbuffer_write_advance(jack_ringbuffer_t * rb,size_t cnt)298 jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
299 {
300   size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
301   rb->write_ptr = tmp;
302 }
303 
304 /* The non-copying data reader.  `vec' is an array of two places.  Set
305    the values at `vec' to hold the current readable data at `rb'.  If
306    the readable data is in one segment the second segment has zero
307    length.  */
308 
309 void
jack_ringbuffer_get_read_vector(const jack_ringbuffer_t * rb,jack_ringbuffer_data_t * vec)310 jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb, jack_ringbuffer_data_t * vec)
311 {
312   size_t free_cnt;
313   size_t cnt2;
314   size_t w, r;
315 
316   w = rb->write_ptr;
317   r = rb->read_ptr;
318 
319   if (w > r)
320     {
321       free_cnt = w - r;
322     }
323   else
324     {
325       free_cnt = (w - r + rb->size) & rb->size_mask;
326     }
327 
328   cnt2 = r + free_cnt;
329 
330   if (cnt2 > rb->size)
331     {
332 
333       /* Two part vector: the rest of the buffer after the current write
334          ptr, plus some from the start of the buffer. */
335 
336       vec[0].buf = &(rb->buf[r]);
337       vec[0].len = rb->size - r;
338       vec[1].buf = rb->buf;
339       vec[1].len = cnt2 & rb->size_mask;
340 
341     }
342   else
343     {
344 
345       /* Single part vector: just the rest of the buffer */
346 
347       vec[0].buf = &(rb->buf[r]);
348       vec[0].len = free_cnt;
349       vec[1].len = 0;
350     }
351 }
352 
353 /* The non-copying data writer.  `vec' is an array of two places.  Set
354    the values at `vec' to hold the current writeable data at `rb'.  If
355    the writeable data is in one segment the second segment has zero
356    length.  */
357 
358 void
jack_ringbuffer_get_write_vector(const jack_ringbuffer_t * rb,jack_ringbuffer_data_t * vec)359 jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb, jack_ringbuffer_data_t * vec)
360 {
361   size_t free_cnt;
362   size_t cnt2;
363   size_t w, r;
364 
365   w = rb->write_ptr;
366   r = rb->read_ptr;
367 
368   if (w > r)
369     {
370       free_cnt = ((r - w + rb->size) & rb->size_mask) - 1;
371     }
372   else if (w < r)
373     {
374       free_cnt = (r - w) - 1;
375     }
376   else
377     {
378       free_cnt = rb->size - 1;
379     }
380 
381   cnt2 = w + free_cnt;
382 
383   if (cnt2 > rb->size)
384     {
385 
386       /* Two part vector: the rest of the buffer after the current write
387          ptr, plus some from the start of the buffer. */
388 
389       vec[0].buf = &(rb->buf[w]);
390       vec[0].len = rb->size - w;
391       vec[1].buf = rb->buf;
392       vec[1].len = cnt2 & rb->size_mask;
393     }
394   else
395     {
396       vec[0].buf = &(rb->buf[w]);
397       vec[0].len = free_cnt;
398       vec[1].len = 0;
399     }
400 }
401 #endif //_HAVE_JACK_
402