Annotation of libelwix/src/ring.c, revision 1.7.2.1

1.2       misho       1: /*************************************************************************
                      2: * (C) 2025 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.7.2.1 ! misho       6: * $Id: ring.c,v 1.7 2026/02/18 01:34:17 misho Exp $
1.2       misho       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: 
1.5       misho      15: Copyright 2004 - 2026
1.2       misho      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: #include "global.h"
                     47: 
                     48: 
                     49: /*
                     50:  * rbuf_init() - Init ring buffer
                     51:  *
                     52:  * @rbuf = Ring buffer
                     53:  * @num = Number of elements in buffer
                     54:  * return: -1 error or 0 ok
                     55:  */
                     56: int
                     57: rbuf_init(ringbuf_t *rbuf, int num)
                     58: {
                     59:        if (!rbuf)
                     60:                return -1;
                     61: 
1.3       misho      62:        atomic_store_explicit((atomic_int*) &rbuf->rb_head, 0, memory_order_relaxed);
                     63:        atomic_store_explicit((atomic_int*) &rbuf->rb_tail, 0, memory_order_relaxed);
1.7.2.1 ! misho      64:        atomic_store_explicit((atomic_int*) &rbuf->rb_full, 0, memory_order_relaxed);
1.2       misho      65: 
                     66:        rbuf->rb_buffer = e_calloc(num, sizeof(struct iovec));
                     67:        if (!rbuf->rb_buffer)
                     68:                return -1;
                     69:        else
                     70:                rbuf->rb_bufnum = num;
                     71:        memset(rbuf->rb_buffer, 0, num * sizeof(struct iovec));
                     72: 
                     73:        return 0;
                     74: }
                     75: 
                     76: /*
                     77:  * rbuf_free() - Free ring buffer
                     78:  *
                     79:  * @rbuf = Ring buffer
                     80:  * return: none
                     81:  */
                     82: void
                     83: rbuf_free(ringbuf_t *rbuf)
                     84: {
                     85:        if (!rbuf)
                     86:                return;
                     87: 
                     88:        if (rbuf->rb_buffer) {
                     89:                e_free(rbuf->rb_buffer);
                     90:                rbuf->rb_buffer = NULL;
                     91:                rbuf->rb_bufnum = 0;
                     92:        }
                     93: 
1.3       misho      94:        atomic_store_explicit((atomic_int*) &rbuf->rb_head, 0, memory_order_relaxed);
                     95:        atomic_store_explicit((atomic_int*) &rbuf->rb_tail, 0, memory_order_relaxed);
1.7.2.1 ! misho      96:        atomic_store_explicit((atomic_int*) &rbuf->rb_full, 0, memory_order_relaxed);
1.2       misho      97: }
                     98: 
                     99: /*
                    100:  * rbuf_purge() - Purge all buffer
                    101:  *
                    102:  * @rbuf = Ring buffer
                    103:  * return: none
                    104:  */
                    105: void
                    106: rbuf_purge(ringbuf_t *rbuf)
                    107: {
                    108:        if (!rbuf)
                    109:                return;
                    110: 
                    111:        if (rbuf->rb_buffer)
                    112:                memset(rbuf->rb_buffer, 0, rbuf->rb_bufnum * sizeof(struct iovec));
                    113: 
1.3       misho     114:        atomic_store_explicit((atomic_int*) &rbuf->rb_head, 0, memory_order_relaxed);
                    115:        atomic_store_explicit((atomic_int*) &rbuf->rb_tail, 0, memory_order_relaxed);
1.7.2.1 ! misho     116:        atomic_store_explicit((atomic_int*) &rbuf->rb_full, 0, memory_order_relaxed);
1.2       misho     117: }
                    118: 
                    119: /*
                    120:  * rbuf_isempty() - Check buffer is empty
                    121:  *
                    122:  * @rbuf = Ring buffer
                    123:  * return: -1 error, 0 it isn't empty
                    124:  */
                    125: int
                    126: rbuf_isempty(ringbuf_t *rbuf)
                    127: {
1.7.2.1 ! misho     128:        if (!rbuf || !rbuf->rb_bufnum)
1.2       misho     129:                return -1;
                    130: 
1.7.2.1 ! misho     131:        if (atomic_load_explicit((atomic_int*) &rbuf->rb_full, memory_order_acquire))
        !           132:                return 0;
        !           133: 
1.3       misho     134:        return (atomic_load_explicit((atomic_int*) &rbuf->rb_head, memory_order_acquire) ==
1.7.2.1 ! misho     135:                        atomic_load_explicit((atomic_int*) &rbuf->rb_tail, memory_order_acquire));
1.2       misho     136: }
                    137: 
                    138: /*
                    139:  * rbuf_isfull() - Check buffer is full
                    140:  *
                    141:  * @rbuf = Ring buffer
                    142:  * return: -1 error or 0 it isn't full
                    143:  */
                    144: int
                    145: rbuf_isfull(ringbuf_t *rbuf)
                    146: {
1.7.2.1 ! misho     147:        int h, t;
        !           148: 
        !           149:        if (!rbuf || !rbuf->rb_bufnum)
1.2       misho     150:                return -1;
                    151: 
1.7.2.1 ! misho     152:        if (!atomic_load_explicit((atomic_int*) &rbuf->rb_full, memory_order_acquire))
        !           153:                return 0;
        !           154: 
        !           155:        t = atomic_load_explicit((atomic_int*) &rbuf->rb_tail, memory_order_acquire);
        !           156:        h = atomic_load_explicit((atomic_int*) &rbuf->rb_head, memory_order_acquire);
        !           157:        return (h == t);
1.2       misho     158: }
                    159: 
                    160: /*
                    161:  * rbuf_enqueue() - Enqueue data to buffer
                    162:  *
                    163:  * @rbuf = Ring buffer
                    164:  * @data = Data
                    165:  * @len = Length
1.7.2.1 ! misho     166:  * @lost = Permit to lost data
1.2       misho     167:  * return: -1 error, 1 buffer is full or 0 ok
                    168:  */
                    169: int
1.7.2.1 ! misho     170: rbuf_enqueue(ringbuf_t *rbuf, void *data, size_t len, int lost)
1.2       misho     171: {
1.7.2.1 ! misho     172:        int h, t, f, n, t2, drop = 0;
1.2       misho     173:        struct iovec *iov;
                    174: 
1.7.2.1 ! misho     175:        if (!rbuf || !rbuf->rb_buffer || !rbuf->rb_bufnum)
1.2       misho     176:                return -1;
                    177: 
1.7.2.1 ! misho     178:        f = atomic_load_explicit((atomic_int*) &rbuf->rb_full, memory_order_acquire);
1.3       misho     179:        t = atomic_load_explicit((atomic_int*) &rbuf->rb_tail, memory_order_acquire);
1.7.2.1 ! misho     180:        h = atomic_load_explicit((atomic_int*) &rbuf->rb_head, memory_order_acquire);
1.2       misho     181: 
1.7.2.1 ! misho     182:        if (f && h == t) {
        !           183:                if (!lost)
        !           184:                        return 1;
        !           185:                else
        !           186:                        drop = 1;
        !           187:        }
        !           188: 
        !           189:        n = (h + 1) % rbuf->rb_bufnum;
1.2       misho     190: 
                    191:        iov = rbuf->rb_buffer + h;
                    192:        iov->iov_len = len;
                    193:        iov->iov_base = data;
                    194: 
1.3       misho     195:        atomic_store_explicit((atomic_int*) &rbuf->rb_head, n, memory_order_release);
1.7.2.1 ! misho     196:        if (drop) {
        !           197:                t2 = (t + 1) % rbuf->rb_bufnum;
        !           198:                while (42) {
        !           199:                        drop = t;
        !           200:                        if (atomic_compare_exchange_weak_explicit((atomic_int*) &rbuf->rb_tail,
        !           201:                                                &drop, t2, memory_order_release, memory_order_relaxed))
        !           202:                                break;
        !           203:                        t = drop;
        !           204:                        t2 = (t + 1) % rbuf->rb_bufnum;
        !           205:                }
        !           206:        } else
        !           207:                t2 = atomic_load_explicit((atomic_int*) &rbuf->rb_tail, memory_order_acquire);
        !           208:        atomic_store_explicit((atomic_int*) &rbuf->rb_full, (n == t2), memory_order_release);
1.2       misho     209:        return 0;
                    210: }
                    211: 
                    212: /*
                    213:  * rbuf_dequeue() - Dequeue data from buffer
                    214:  *
                    215:  * @rbuf = Ring buffer
                    216:  * @out = Data, if =NULL, just dequeue data
                    217:  * return: -1 error, 1 buffer is empty or 0 ok
                    218:  */
                    219: int
1.4       misho     220: rbuf_dequeue(ringbuf_t *rbuf, struct iovec **out)
1.2       misho     221: {
1.7.2.1 ! misho     222:        int h, t, n, f;
1.2       misho     223: 
1.7.2.1 ! misho     224:        if (!rbuf || !rbuf->rb_buffer || !rbuf->rb_bufnum)
1.2       misho     225:                return -1;
                    226: 
1.7.2.1 ! misho     227:        while (42) {
        !           228:                h = atomic_load_explicit((atomic_int*) &rbuf->rb_head, memory_order_acquire);
        !           229:                f = atomic_load_explicit((atomic_int*) &rbuf->rb_full, memory_order_acquire);
        !           230:                t = atomic_load_explicit((atomic_int*) &rbuf->rb_tail, memory_order_acquire);
1.2       misho     231: 
1.7.2.1 ! misho     232:                if (!f && h == t)
        !           233:                        return 1;
        !           234: 
        !           235:                n = (t + 1) % rbuf->rb_bufnum;
1.2       misho     236: 
1.7.2.1 ! misho     237:                f = t;
        !           238:                if (atomic_compare_exchange_weak_explicit((atomic_int*) &rbuf->rb_tail,
        !           239:                                        &f, n, memory_order_release, memory_order_relaxed)) {
        !           240:                        if (out)
        !           241:                                *out = rbuf->rb_buffer + t;
        !           242: 
        !           243:                        atomic_store_explicit((atomic_int*) &rbuf->rb_full, 0, memory_order_release);
        !           244:                        break;
        !           245:                }
        !           246:        }
1.2       misho     247: 
                    248:        return 0;
                    249: }
1.5       misho     250: 
                    251: 
                    252: /*
                    253:  * lrb_init() - Init linear ring buffer
                    254:  *
                    255:  * @lrb = Linear ring buffer
                    256:  * @size = Size of ring buffer
                    257:  * return: -1 error or 0 ok
                    258:  */
                    259: int
                    260: lrb_init(lrbuf_t *lrb, u_int size)
                    261: {
                    262:        if (!lrb)
                    263:                return -1;
                    264: 
                    265:        atomic_store_explicit((atomic_int*) &lrb->lrb_head, 0, memory_order_relaxed);
                    266:        atomic_store_explicit((atomic_int*) &lrb->lrb_tail, 0, memory_order_relaxed);
1.7.2.1 ! misho     267:        atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_relaxed);
1.5       misho     268: 
                    269:        lrb->lrb_data = e_malloc(size);
                    270:        if (!lrb->lrb_data)
                    271:                return -1;
                    272:        else
                    273:                lrb->lrb_size = size;
                    274:        memset(lrb->lrb_data, 0, lrb->lrb_size);
                    275: 
                    276:        return 0;
                    277: }
                    278: 
                    279: /*
                    280:  * lrb_free() - Free linear ring buffer
                    281:  *
                    282:  * @lrb = Linear ring buffer
                    283:  * return: none
                    284:  */
                    285: void
                    286: lrb_free(lrbuf_t *lrb)
                    287: {
                    288:        if (!lrb)
                    289:                return;
                    290: 
                    291:        if (lrb->lrb_data) {
                    292:                e_free(lrb->lrb_data);
                    293:                lrb->lrb_data = NULL;
                    294:                lrb->lrb_size = 0;
                    295:        }
                    296: 
                    297:        atomic_store_explicit((atomic_int*) &lrb->lrb_head, 0, memory_order_relaxed);
                    298:        atomic_store_explicit((atomic_int*) &lrb->lrb_tail, 0, memory_order_relaxed);
1.7.2.1 ! misho     299:        atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_relaxed);
1.5       misho     300: }
                    301: 
                    302: /*
                    303:  * lrb_purge() - Purge all buffer
                    304:  *
                    305:  * @lrb = Linear ring buffer
                    306:  * return: none
                    307:  */
                    308: void
                    309: lrb_purge(lrbuf_t *lrb)
                    310: {
                    311:        if (!lrb)
                    312:                return;
                    313: 
                    314:        if (lrb->lrb_data)
                    315:                memset(lrb->lrb_data, 0, lrb->lrb_size);
                    316: 
                    317:        atomic_store_explicit((atomic_int*) &lrb->lrb_head, 0, memory_order_relaxed);
                    318:        atomic_store_explicit((atomic_int*) &lrb->lrb_tail, 0, memory_order_relaxed);
                    319:        atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_relaxed);
                    320: }
                    321: 
                    322: /*
                    323:  * lrb_isempty() - Check buffer is empty
                    324:  *
                    325:  * @lrb = Linear ring buffer
                    326:  * return: -1 error, 0 it isn't empty
                    327:  */
                    328: int
                    329: lrb_isempty(lrbuf_t *lrb)
                    330: {
1.7.2.1 ! misho     331:        if (!lrb || !lrb->lrb_size)
1.5       misho     332:                return -1;
                    333: 
1.7.2.1 ! misho     334:        if (atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire))
        !           335:                return 0;
        !           336: 
        !           337:        return (atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire) ==
        !           338:                        atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire));
1.5       misho     339: }
                    340: 
                    341: /*
                    342:  * lrb_isfull() - Check buffer is full
                    343:  *
                    344:  * @lrb = Linear ring buffer
                    345:  * return: -1 error or 0 it isn't full
                    346:  */
                    347: int
                    348: lrb_isfull(lrbuf_t *lrb)
                    349: {
                    350:        int h, t;
                    351: 
1.7.2.1 ! misho     352:        if (!lrb || !lrb->lrb_size)
1.5       misho     353:                return -1;
                    354: 
                    355:        if (!atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire))
                    356:                return 0;
                    357: 
                    358:        t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire);
                    359:        h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire);
                    360:        return (h == t);
                    361: }
                    362: 
                    363: /*
1.6       misho     364:  * lrb_getw() - Get address for write
                    365:  *
                    366:  * @lrb = Linear ring buffer
                    367:  * @len = Return available buffer length for write
                    368:  * return: NULL error or !=NULL pointer for write
                    369:  * remark: After use of lrb_getw() and write to pointer.
                    370:  *             You should update ring buffer with lrb_enqueue(,NULL,wrote_len,)
                    371:  */
                    372: void *
                    373: lrb_getw(lrbuf_t *lrb, size_t *len)
                    374: {
                    375:        int h;
                    376: 
                    377:        if (!lrb || !lrb->lrb_data || !lrb->lrb_size)
                    378:                return NULL;
                    379: 
                    380:        h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_relaxed);
                    381:        if (len)
                    382:                *len = lrb->lrb_size - h;
                    383: 
                    384:        return (lrb->lrb_data + h);
                    385: }
                    386: 
                    387: /*
1.5       misho     388:  * lrb_enqueue() - Enqueue data to buffer
                    389:  *
                    390:  * @lrb = Linear ring buffer
                    391:  * @data = Data
                    392:  * @len = Length
                    393:  * @lost = Permit to lost data
                    394:  * return: -1 error, 1 buffer is full or 0 ok
                    395:  */
                    396: int
                    397: lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int lost)
                    398: {
1.6       misho     399:        int h, t = 0, n, t2 = 0, unused, drop = 0;
1.5       misho     400: 
1.7.2.1 ! misho     401:        if (!lrb || !lrb->lrb_data || !lrb->lrb_size)
1.5       misho     402:                return -1;
1.7.2.1 ! misho     403:        if (lrb->lrb_size <= len)
1.5       misho     404:                return 1;
                    405: 
                    406:        lrb_unused(lrb, unused);
                    407:        if (!lost) {
                    408:                if (len > unused)
                    409:                        return 1;
                    410:        } else {
                    411:                drop = len - unused;
                    412:                if(drop < 0)
                    413:                        drop ^= drop;
                    414:        }
                    415: 
                    416:        if (drop > 0) {
                    417:                t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire);
                    418:                t2 = (t + drop) % lrb->lrb_size;
                    419:        }
                    420:        h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_relaxed);
                    421:        n = lrb->lrb_size - h;
                    422:        if (len < n) {
1.6       misho     423:                if (data)
                    424:                        memcpy(lrb->lrb_data + h, data, len);
1.5       misho     425:                n = h + len;
                    426:        } else {
1.6       misho     427:                if (data) {
                    428:                        memcpy(lrb->lrb_data + h, data, n);
                    429:                        memcpy(lrb->lrb_data, data + n, len - n);
                    430:                }
1.5       misho     431:                n = len - n;
                    432:        }
                    433: 
                    434:        h = n;
                    435:        atomic_store_explicit((atomic_int*) &lrb->lrb_head, h, memory_order_release);
                    436:        if (drop > 0)
                    437:                while (42) {
                    438:                        n = t;
                    439:                        if (atomic_compare_exchange_weak_explicit((atomic_int*) &lrb->lrb_tail,
                    440:                                                &n, t2, memory_order_release, memory_order_relaxed))
                    441:                                break;
                    442:                        t = n;
                    443:                        t2 = (t + drop) % lrb->lrb_size;
                    444:                }
                    445:        else
                    446:                t2 = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire);
                    447:        atomic_store_explicit((atomic_int*) &lrb->lrb_full, (h == t2), memory_order_release);
                    448:        return 0;
                    449: }
                    450: 
                    451: /*
1.6       misho     452:  * lrb_getr() - Get address for read
                    453:  *
                    454:  * @lrb = Linear ring buffer
                    455:  * @len = Return available data length for read
                    456:  * return: NULL error or !=NULL pointer for read
                    457:  * remark: After use of lrb_getr() and read from pointer.
                    458:  *             You could update ring buffer with lrb_dequeue(,NULL,read_len)
                    459:  */
                    460: void *
                    461: lrb_getr(lrbuf_t *lrb, size_t *len)
                    462: {
                    463:        int t;
                    464: 
                    465:        if (!lrb || !lrb->lrb_data || !lrb->lrb_size)
                    466:                return NULL;
                    467: 
                    468:        t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire);
                    469:        if (len)
                    470:                lrb_queued(lrb, *len);
                    471: 
                    472:        return (lrb->lrb_data + t);
                    473: }
                    474: 
                    475: /*
1.5       misho     476:  * lrb_dequeue() - Dequeue data from buffer
                    477:  *
                    478:  * @lrb = Linear ring buffer
                    479:  * @data = Data, if =NULL, just dequeue data
                    480:  * @len = Length of data
                    481:  * return: -1 error, 0 buffer is empty or >0 stored data bytes
                    482:  */
                    483: int
                    484: lrb_dequeue(lrbuf_t *lrb, void *data, size_t len)
                    485: {
                    486:        int h, t, t2, n, l, f;
                    487: 
1.7.2.1 ! misho     488:        if (!lrb || !lrb->lrb_size)
1.5       misho     489:                return -1;
1.7.2.1 ! misho     490:        if (!len || lrb_isempty(lrb))
1.5       misho     491:                return 0;
                    492:        if (lrb->lrb_size <= len)
                    493:                len = lrb->lrb_size - 1;
                    494: 
                    495:        while (42) {
                    496:                t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire);
                    497:                h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire);
                    498:                f = atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire);
                    499: 
                    500:                l = h - t;
                    501:                if (l < 0)
                    502:                        l += lrb->lrb_size;
                    503:                if (!l) {
                    504:                        if (!f)
                    505:                                return 0;
                    506:                        l = lrb->lrb_size;
                    507:                }
                    508:                if (l > len)
                    509:                        l = len;
                    510: 
                    511:                n = lrb->lrb_size - t;
                    512:                if (l < n) {
                    513:                        if (data)
                    514:                                memcpy(data, lrb->lrb_data + t, l);
                    515:                        t2 = t + l;
                    516:                } else {
                    517:                        if (data) {
                    518:                                memcpy(data, lrb->lrb_data + t, n);
1.7.2.1 ! misho     519:                                memcpy(((u_char*) data) + n, lrb->lrb_data, l - n);
1.5       misho     520:                        }
                    521:                        t2 = l - n;
                    522:                }
                    523: 
                    524:                n = t;
                    525:                if (atomic_compare_exchange_weak_explicit((atomic_int*) &lrb->lrb_tail,
                    526:                                        &n, t2, memory_order_release, memory_order_relaxed)) {
                    527:                        atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_release);
                    528:                        return l;
                    529:                }
                    530:        }
                    531: 
                    532:        return 0;
                    533: }

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