File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / inc / elwix / aring.h
Revision 1.9: download - view: text, annotated - select for diffs - revision graph
Wed Feb 18 11:41:47 2026 UTC (2 days, 4 hours ago) by misho
Branches: MAIN
CVS tags: elwix6_18, HEAD, ELWIX6_17
Version 6.17

    1: /*************************************************************************
    2: * (C) 2025 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: aring.h,v 1.9 2026/02/18 11:41:47 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004 - 2026
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #ifndef __ARING_H
   47: #define __ARING_H
   48: 
   49: #define E_ATOMIC_ALIGN	alignas(sizeof(int) * 8)
   50: 
   51: typedef struct {
   52: 	E_ATOMIC_ALIGN	int		rb_head;
   53: 	E_ATOMIC_ALIGN	int		rb_tail;
   54: 	E_ATOMIC_ALIGN	unsigned int	rb_full;
   55: 			int		rb_bufnum;
   56: 			struct iovec	*rb_buffer;
   57: } ringbuf_t;
   58: #define rbuf_head(x)		atomic_load_explicit((atomic_int*) &(x)->rb_head, memory_order_relaxed)
   59: #define rbuf_tail(x)		atomic_load_explicit((atomic_int*) &(x)->rb_tail, memory_order_relaxed)
   60: #define rbuf_hptr(x)		((x)->rb_buffer + rbuf_head((x)))
   61: #define rbuf_tptr(x)		((x)->rb_buffer + rbuf_tail((x)))
   62: #define rbuf_ptr(x, n)		((x)->rb_buffer + ((rbuf_tail((x)) + (n)) % (x)->rb_bufnum))
   63: #define rbuf_num(x)		((x)->rb_bufnum)
   64: #define rbuf_getb(x)		((x)->rb_buffer)
   65: #define rbuf_get(x, n)		*rbuf_ptr((x), (n))
   66: #define rbuf_isrewind(x)	(rbuf_head((x)) < rbuf_tail((x)))
   67: #define rbuf_queued(x, r)	do { \
   68: 					u_int _h, _t; \
   69: 					_t = atomic_load_explicit((atomic_int*) &(x)->rb_tail, memory_order_acquire); \
   70: 					_h = atomic_load_explicit((atomic_int*) &(x)->rb_head, memory_order_relaxed); \
   71: 					if (_h == _t) \
   72: 						(r) = atomic_load_explicit((atomic_int*) &(x)->rb_full, memory_order_acquire) ? \
   73: 							(x)->rb_bufnum : 0; \
   74: 					else \
   75: 						(r) = (_h + (x)->rb_bufnum - _t) % (x)->rb_bufnum; \
   76: 				} while (0)
   77: #define rbuf_unused(x, r)	do { \
   78: 					u_int _r; \
   79: 					rbuf_queued((x), _r); \
   80: 					(r) = (x)->rb_bufnum - _r; \
   81: 				} while (0)
   82: 
   83: 
   84: typedef struct {
   85: 	E_ATOMIC_ALIGN	unsigned int	lrb_head;
   86: 	E_ATOMIC_ALIGN	unsigned int	lrb_tail;
   87: 	E_ATOMIC_ALIGN	unsigned int	lrb_full;
   88: 			int		lrb_size;
   89: 			unsigned char	*lrb_data;
   90: } lrbuf_t;
   91: #define lrb_head(x)		atomic_load_explicit((atomic_int*) &(x)->lrb_head, memory_order_relaxed)
   92: #define lrb_tail(x)		atomic_load_explicit((atomic_int*) &(x)->lrb_tail, memory_order_relaxed)
   93: #define lrb_hptr(x)		((x)->lrb_data + lrb_head((x)))
   94: #define lrb_tptr(x)		((x)->lrb_data + lrb_tail((x)))
   95: #define lrb_ptr(x, n)		((x)->lrb_data + ((lrb_tail((x)) + (n)) % (x)->lrb_size))
   96: #define lrb_size(x)		((x)->lrb_size)
   97: #define lrb_getb(x)		((x)->lrb_data)
   98: #define lrb_getc(x, n)		*lrb_ptr((x), (n))
   99: #define lrb_isrewind(x)		(lrb_head((x)) < lrb_tail((x)))
  100: #define lrb_queued(x, r)	do { \
  101: 					u_int _h, _t; \
  102: 					_t = atomic_load_explicit((atomic_int*) &(x)->lrb_tail, memory_order_acquire); \
  103: 					_h = atomic_load_explicit((atomic_int*) &(x)->lrb_head, memory_order_relaxed); \
  104: 					if (_h == _t) \
  105: 						(r) = atomic_load_explicit((atomic_int*) &(x)->lrb_full, memory_order_acquire) ? \
  106: 							(x)->lrb_size : 0; \
  107: 					else \
  108: 						(r) = (_h + (x)->lrb_size - _t) % (x)->lrb_size; \
  109: 				} while (0)
  110: #define lrb_unused(x, r)	do { \
  111: 					u_int _r; \
  112: 					lrb_queued((x), _r); \
  113: 					(r) = (x)->lrb_size - _r; \
  114: 				} while (0)
  115: 
  116: 
  117: /*
  118:  * rbuf_init() - Init ring buffer
  119:  *
  120:  * @rbuf = Ring buffer
  121:  * @num = Number of elements in buffer
  122:  * return: -1 error or 0 ok
  123:  */
  124: int rbuf_init(ringbuf_t *rbuf, int num);
  125: /*
  126:  * rbuf_free() - Free ring buffer
  127:  *
  128:  * @rbuf = Ring buffer
  129:  * return: none
  130:  */
  131: void rbuf_free(ringbuf_t *rbuf);
  132: /*
  133:  * rbuf_purge() - Purge all buffer
  134:  *
  135:  * @rbuf = Ring buffer
  136:  * return: none
  137:  */
  138: void rbuf_purge(ringbuf_t *rbuf);
  139: /*
  140:  * rbuf_isempty() - Check buffer is empty
  141:  *
  142:  * @rbuf = Ring buffer
  143:  * return: -1 error, 0 it isn't empty
  144:  */
  145: int rbuf_isempty(ringbuf_t *rbuf);
  146: /*
  147:  * rbuf_isfull() - Check buffer is full
  148:  *
  149:  * @rbuf = Ring buffer
  150:  * return: -1 error or 0 it isn't full
  151:  */
  152: int rbuf_isfull(ringbuf_t *rbuf);
  153: 
  154: /*
  155:  * rbuf_enqueue() - Enqueue data to buffer
  156:  *
  157:  * @rbuf = Ring buffer
  158:  * @data = Data
  159:  * @len = Length
  160:  * @lost = Permit to lost data
  161:  * return: -1 error, 1 can't add data, buffer is full or 0 ok
  162:  */
  163: int rbuf_enqueue(ringbuf_t *rbuf, void *data, size_t len, int lost);
  164: /*
  165:  * rbuf_dequeue() - Dequeue data from buffer
  166:  *
  167:  * @rbuf = Ring buffer
  168:  * @out = Data, if =NULL, just dequeue data
  169:  * return: -1 error, 1 buffer is empty or 0 ok
  170:  */
  171: int rbuf_dequeue(ringbuf_t *rbuf, struct iovec **out);
  172: 
  173: 
  174: /*
  175:  * lrb_init() - Init linear ring buffer
  176:  *
  177:  * @lrb = Linear ring buffer
  178:  * @size = Size of ring buffer
  179:  * return: -1 error or 0 ok
  180:  */
  181: int lrb_init(lrbuf_t *lrb, u_int size);
  182: /*
  183:  * lrb_free() - Free linear ring buffer
  184:  *
  185:  * @lrb = Linear ring buffer
  186:  * return: none
  187:  */
  188: void lrb_free(lrbuf_t *lrb);
  189: /*
  190:  * lrb_purge() - Purge all buffer
  191:  *
  192:  * @lrb = Linear ring buffer
  193:  * return: none
  194:  */
  195: void lrb_purge(lrbuf_t *lrb);
  196: /*
  197:  * lrb_isempty() - Check buffer is empty
  198:  *
  199:  * @lrb = Linear ring buffer
  200:  * return: -1 error, 0 it isn't empty
  201:  */
  202: int lrb_isempty(lrbuf_t *lrb);
  203: /*
  204:  * lrb_isfull() - Check buffer is full
  205:  *
  206:  * @lrb = Linear ring buffer
  207:  * return: -1 error or 0 it isn't full
  208:  */
  209: int lrb_isfull(lrbuf_t *lrb);
  210: /*
  211:  * lrb_enqueue() - Enqueue data to buffer
  212:  *
  213:  * @lrb = Linear ring buffer
  214:  * @data = Data
  215:  * @len = Length
  216:  * @lost = Permit to lost data
  217:  * return: -1 error, 1 buffer is full or 0 ok
  218:  */
  219: int lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int lost);
  220: /*
  221:  * lrb_dequeue() - Dequeue data from buffer
  222:  *
  223:  * @lrb = Linear ring buffer
  224:  * @data = Data, if =NULL, just dequeue data
  225:  * @len = Length of data
  226:  * return: -1 error, 0 buffer is empty or >0 stored data bytes
  227:  */
  228: int lrb_dequeue(lrbuf_t *lrb, void *data, size_t len);
  229: /*
  230:  * lrb_getw() - Get address for write
  231:  *
  232:  * @lrb = Linear ring buffer
  233:  * @len = Return available buffer length for write
  234:  * return: NULL error or !=NULL pointer for write
  235:  * remark: After use of lrb_getw() and write to pointer.
  236:  * 		You should update ring buffer with lrb_enqueue(,NULL,wrote_len,)
  237:  */
  238: void *lrb_getw(lrbuf_t *lrb, size_t *len);
  239: /*
  240:  * lrb_getr() - Get address for read
  241:  *
  242:  * @lrb = Linear ring buffer
  243:  * @len = Return available data length for read
  244:  * return: NULL error or !=NULL pointer for read
  245:  * remark: After use of lrb_getr() and read from pointer.
  246:  * 		You could update ring buffer with lrb_dequeue(,NULL,read_len)
  247:  */
  248: void *lrb_getr(lrbuf_t *lrb, size_t *len);
  249: 
  250: 
  251: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>