Annotation of 43BSDTahoe/ucb/telnet/Source/ring.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that this notice is preserved and that due credit is given
        !             7:  * to the University of California at Berkeley. The name of the University
        !             8:  * may not be used to endorse or promote products derived from this
        !             9:  * software without specific prior written permission. This software
        !            10:  * is provided ``as is'' without express or implied warranty.
        !            11:  */
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)ring.c     1.8 (Berkeley) 3/8/88";
        !            15: #endif /* not lint */
        !            16: 
        !            17: /*
        !            18:  * This defines a structure for a ring buffer.
        !            19:  *
        !            20:  * The circular buffer has two parts:
        !            21:  *(((
        !            22:  *     full:   [consume, supply)
        !            23:  *     empty:  [supply, consume)
        !            24:  *]]]
        !            25:  *
        !            26:  */
        !            27: 
        !            28: #include       <stdio.h>
        !            29: #include       <errno.h>
        !            30: 
        !            31: #ifdef size_t
        !            32: #undef size_t
        !            33: #endif
        !            34: 
        !            35: #include       <sys/types.h>
        !            36: #include       <sys/ioctl.h>
        !            37: #include       <sys/socket.h>
        !            38: 
        !            39: #include       "ring.h"
        !            40: #include       "general.h"
        !            41: 
        !            42: /* Internal macros */
        !            43: 
        !            44: #if    !defined(MIN)
        !            45: #define        MIN(a,b)        (((a)<(b))? (a):(b))
        !            46: #endif /* !defined(MIN) */
        !            47: 
        !            48: #define        ring_subtract(d,a,b)    ((((int)(a))-((int)(b)) >= 0)? \
        !            49:                                        (a)-(b): (((a)-(b))+(d)->size))
        !            50: 
        !            51: #define        ring_increment(d,a,c)   (((a)+(c) < (d)->top)? \
        !            52:                                        (a)+(c) : (((a)+(c))-(d)->size))
        !            53: 
        !            54: #define        ring_decrement(d,a,c)   (((a)-(c) >= (d)->bottom)? \
        !            55:                                        (a)-(c) : (((a)-(c))-(d)->size))
        !            56: 
        !            57: 
        !            58: /*
        !            59:  * The following is a clock, used to determine full, empty, etc.
        !            60:  *
        !            61:  * There is some trickiness here.  Since the ring buffers are initialized
        !            62:  * to ZERO on allocation, we need to make sure, when interpreting the
        !            63:  * clock, that when the times are EQUAL, then the buffer is FULL.
        !            64:  */
        !            65: static u_long ring_clock = 0;
        !            66: 
        !            67: 
        !            68: #define        ring_empty(d) (((d)->consume == (d)->supply) && \
        !            69:                                ((d)->consumetime >= (d)->supplytime))
        !            70: #define        ring_full(d) (((d)->supply == (d)->consume) && \
        !            71:                                ((d)->supplytime > (d)->consumetime))
        !            72: 
        !            73: 
        !            74: 
        !            75: 
        !            76: 
        !            77: /* Buffer state transition routines */
        !            78: 
        !            79: ring_init(ring, buffer, count)
        !            80: Ring *ring;
        !            81: char *buffer;
        !            82: int count;
        !            83: {
        !            84:     memset((char *)ring, 0, sizeof *ring);
        !            85: 
        !            86:     ring->size = count;
        !            87: 
        !            88:     ring->supply = ring->consume = ring->bottom = buffer;
        !            89: 
        !            90:     ring->top = ring->bottom+ring->size;
        !            91: 
        !            92:     return 1;
        !            93: }
        !            94: 
        !            95: /* Mark routines */
        !            96: 
        !            97: /*
        !            98:  * Mark the most recently supplied byte.
        !            99:  */
        !           100: 
        !           101: void
        !           102: ring_mark(ring)
        !           103: Ring *ring;
        !           104: {
        !           105:     ring->mark = ring_decrement(ring, ring->supply, 1);
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * Is the ring pointing to the mark?
        !           110:  */
        !           111: 
        !           112: int
        !           113: ring_at_mark(ring)
        !           114: Ring *ring;
        !           115: {
        !           116:     if (ring->mark == ring->consume) {
        !           117:        return 1;
        !           118:     } else {
        !           119:        return 0;
        !           120:     }
        !           121: }
        !           122: 
        !           123: /*
        !           124:  * Clear any mark set on the ring.
        !           125:  */
        !           126: 
        !           127: void
        !           128: ring_clear_mark(ring)
        !           129: Ring *ring;
        !           130: {
        !           131:     ring->mark = 0;
        !           132: }
        !           133: 
        !           134: /*
        !           135:  * Add characters from current segment to ring buffer.
        !           136:  */
        !           137: void
        !           138: ring_supplied(ring, count)
        !           139: Ring *ring;
        !           140: int count;
        !           141: {
        !           142:     ring->supply = ring_increment(ring, ring->supply, count);
        !           143:     ring->supplytime = ++ring_clock;
        !           144: }
        !           145: 
        !           146: /*
        !           147:  * We have just consumed "c" bytes.
        !           148:  */
        !           149: void
        !           150: ring_consumed(ring, count)
        !           151: Ring *ring;
        !           152: int count;
        !           153: {
        !           154:     if (count == 0)    /* don't update anything */
        !           155:        return;
        !           156: 
        !           157:     if (ring->mark &&
        !           158:                (ring_subtract(ring, ring->mark, ring->consume) < count)) {
        !           159:        ring->mark = 0;
        !           160:     }
        !           161:     ring->consume = ring_increment(ring, ring->consume, count);
        !           162:     ring->consumetime = ++ring_clock;
        !           163:     /*
        !           164:      * Try to encourage "ring_empty_consecutive()" to be large.
        !           165:      */
        !           166:     if (ring_empty(ring)) {
        !           167:        ring->consume = ring->supply = ring->bottom;
        !           168:     }
        !           169: }
        !           170: 
        !           171: 
        !           172: 
        !           173: /* Buffer state query routines */
        !           174: 
        !           175: 
        !           176: /* Number of bytes that may be supplied */
        !           177: int
        !           178: ring_empty_count(ring)
        !           179: Ring *ring;
        !           180: {
        !           181:     if (ring_empty(ring)) {    /* if empty */
        !           182:            return ring->size;
        !           183:     } else {
        !           184:        return ring_subtract(ring, ring->consume, ring->supply);
        !           185:     }
        !           186: }
        !           187: 
        !           188: /* number of CONSECUTIVE bytes that may be supplied */
        !           189: int
        !           190: ring_empty_consecutive(ring)
        !           191: Ring *ring;
        !           192: {
        !           193:     if ((ring->consume < ring->supply) || ring_empty(ring)) {
        !           194:                            /*
        !           195:                             * if consume is "below" supply, or empty, then
        !           196:                             * return distance to the top
        !           197:                             */
        !           198:        return ring_subtract(ring, ring->top, ring->supply);
        !           199:     } else {
        !           200:                                    /*
        !           201:                                     * else, return what we may.
        !           202:                                     */
        !           203:        return ring_subtract(ring, ring->consume, ring->supply);
        !           204:     }
        !           205: }
        !           206: 
        !           207: /* Return the number of bytes that are available for consuming
        !           208:  * (but don't give more than enough to get to cross over set mark)
        !           209:  */
        !           210: 
        !           211: int
        !           212: ring_full_count(ring)
        !           213: Ring *ring;
        !           214: {
        !           215:     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
        !           216:        if (ring_full(ring)) {
        !           217:            return ring->size;  /* nothing consumed, but full */
        !           218:        } else {
        !           219:            return ring_subtract(ring, ring->supply, ring->consume);
        !           220:        }
        !           221:     } else {
        !           222:        return ring_subtract(ring, ring->mark, ring->consume);
        !           223:     }
        !           224: }
        !           225: 
        !           226: /*
        !           227:  * Return the number of CONSECUTIVE bytes available for consuming.
        !           228:  * However, don't return more than enough to cross over set mark.
        !           229:  */
        !           230: int
        !           231: ring_full_consecutive(ring)
        !           232: Ring *ring;
        !           233: {
        !           234:     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
        !           235:        if ((ring->supply < ring->consume) || ring_full(ring)) {
        !           236:            return ring_subtract(ring, ring->top, ring->consume);
        !           237:        } else {
        !           238:            return ring_subtract(ring, ring->supply, ring->consume);
        !           239:        }
        !           240:     } else {
        !           241:        if (ring->mark < ring->consume) {
        !           242:            return ring_subtract(ring, ring->top, ring->consume);
        !           243:        } else {        /* Else, distance to mark */
        !           244:            return ring_subtract(ring, ring->mark, ring->consume);
        !           245:        }
        !           246:     }
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * Move data into the "supply" portion of of the ring buffer.
        !           251:  */
        !           252: void
        !           253: ring_supply_data(ring, buffer, count)
        !           254: Ring *ring;
        !           255: char *buffer;
        !           256: int count;
        !           257: {
        !           258:     int i;
        !           259: 
        !           260:     while (count) {
        !           261:        i = MIN(count, ring_empty_consecutive(ring));
        !           262:        memcpy(ring->supply, buffer, i);
        !           263:        ring_supplied(ring, i);
        !           264:        count -= i;
        !           265:        buffer += i;
        !           266:     }
        !           267: }
        !           268: 
        !           269: 
        !           270: /*
        !           271:  * Move data from the "consume" portion of the ring buffer
        !           272:  */
        !           273: void
        !           274: ring_consume_data(ring, buffer, count)
        !           275: Ring *ring;
        !           276: char *buffer;
        !           277: int count;
        !           278: {
        !           279:     int i;
        !           280: 
        !           281:     while (count) {
        !           282:        i = MIN(count, ring_full_consecutive(ring));
        !           283:        memcpy(buffer, ring->consume, i);
        !           284:        ring_consumed(ring, i);
        !           285:        count -= i;
        !           286:        buffer += i;
        !           287:     }
        !           288: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.