Annotation of XNU/iokit/Families/IONetworking/IOPacketQueue.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
                     24:  *
                     25:  * IOPacketQueue.cpp - Implements a FIFO mbuf packet queue.
                     26:  *
                     27:  * HISTORY
                     28:  * 9-Dec-1998       Joe Liu (jliu) created.
                     29:  *
                     30:  */
                     31: 
                     32: #include <IOKit/assert.h>
                     33: #include <IOKit/IOLib.h>    // IOLog
                     34: #include <IOKit/network/IOPacketQueue.h>
                     35: 
                     36: // Get the mbuf definitions from BSD headers.
                     37: //
                     38: extern "C" {
                     39: #include <sys/param.h>
                     40: #include <sys/mbuf.h>
                     41: }
                     42: 
                     43: #define super OSObject
                     44: OSDefineMetaClassAndStructors( IOPacketQueue, OSObject )
                     45: 
                     46: //---------------------------------------------------------------------------
                     47: // Lock macros.
                     48: 
                     49: #define LOCK         IOSimpleLockLock(_lock)
                     50: #define UNLOCK       IOSimpleLockUnlock(_lock)
                     51: 
                     52: //---------------------------------------------------------------------------
                     53: // Factory method that will construct and initialize an IOPacketQueue instance.
                     54: //
                     55: // capacity: The initial capacity of the queue. Can be changed
                     56: //           later through setCapacity().
                     57: //
                     58: // Returns an IOPacketQueue instance upon success, or 0 otherwise.
                     59: 
                     60: bool IOPacketQueue::initWithCapacity(UInt32 capacity)
                     61: {
                     62:     _head = _tail = (struct mbuf *) 0;
                     63:     _size = _peakSize = 0;
                     64:     _capacity = capacity;
                     65: 
                     66:     if (!super::init()) {
                     67:         IOLog("IOPacketQueue: super::init() failed\n");
                     68:         return false;
                     69:     }
                     70: 
                     71:     if ((_lock = IOSimpleLockAlloc()) == 0)
                     72:         return false;
                     73: 
                     74:     IOSimpleLockInit(_lock);
                     75: 
                     76:     return true;
                     77: }
                     78: 
                     79: //---------------------------------------------------------------------------
                     80: // Factory method that will construct and initialize an IOPacketQueue instance.
                     81: //
                     82: // capacity: The initial capacity of the queue. Can be changed later
                     83: //           through setCapacity().
                     84: //
                     85: // Returns an IOPacketQueue instance on success, or 0 otherwise.
                     86: 
                     87: IOPacketQueue * IOPacketQueue::withCapacity(UInt32 capacity)
                     88: {
                     89:     IOPacketQueue * queue = new IOPacketQueue;
                     90: 
                     91:     if (queue && !queue->initWithCapacity(capacity)) {
                     92:         queue->release();
                     93:         return 0;
                     94:     }
                     95:     return queue;
                     96: }
                     97: 
                     98: //---------------------------------------------------------------------------
                     99: // Frees the IOPacketQueue instance. Release all packets in the queue to the
                    100: // free mbuf pool, then call super::free().
                    101: 
                    102: void IOPacketQueue::free()
                    103: {
                    104:     if (_lock) {
                    105:         setCapacity(0);
                    106:         lockFlush();
                    107:         IOSimpleLockFree(_lock);
                    108:     }
                    109:     super::free();
                    110: }
                    111: 
                    112: //---------------------------------------------------------------------------
                    113: // Get the size of the queue.
                    114: // Returns the number of packets currently held in the queue.
                    115: 
                    116: UInt32 IOPacketQueue::getSize() const
                    117: {
                    118:     return (_size);
                    119: }
                    120: 
                    121: //---------------------------------------------------------------------------
                    122: // The queue contains a counter that records the peak size of the queue.
                    123: // This method returns the value in the counter, and can optionally reset
                    124: // the counter back to zero.
                    125: //
                    126: // reset: Reset the peak size counter to zero if true.
                    127: //
                    128: // Returns the peak size count.
                    129: 
                    130: UInt32 IOPacketQueue::getPeakSize(bool reset = false)
                    131: {
                    132:     UInt32 peak = _peakSize;
                    133:     if (reset)
                    134:         _peakSize = 0;
                    135:     return peak;
                    136: }
                    137: 
                    138: //---------------------------------------------------------------------------
                    139: // Adjust the queue's capacity. If the capacity is set to a value that
                    140: // is smaller than its current size, then the queue will drop incoming packets,
                    141: // but existing packets in the queue will remain intact.
                    142: //
                    143: // capacity: The new capacity.
                    144: //
                    145: // Returns true if the new capacity was accepted, false otherwise.
                    146: 
                    147: bool IOPacketQueue::setCapacity(UInt32 capacity)
                    148: {
                    149:     LOCK;
                    150:     _capacity = capacity;
                    151:     UNLOCK;
                    152:     return true;
                    153: }
                    154: 
                    155: //---------------------------------------------------------------------------
                    156: // Get the capacity of the queue.
                    157: // Returns the current queue capacity.
                    158: 
                    159: UInt32 IOPacketQueue::getCapacity() const
                    160: {
                    161:     return _capacity;
                    162: }
                    163: 
                    164: //---------------------------------------------------------------------------
                    165: // Peek at the head of the queue without dequeueing the packet.
                    166: // An ensuing call to peek() or dequeue() will return the same packet.
                    167: // Returns the packet at the head of the queue. The caller must not modify
                    168: // the packet returned.
                    169: // Return the packet at the head of the queue.
                    170: 
                    171: const struct mbuf * IOPacketQueue::peek() const
                    172: {
                    173:     return (_head);
                    174: }
                    175: 
                    176: //---------------------------------------------------------------------------
                    177: // Queueing macros.
                    178: 
                    179: static inline UInt32 _freePacketChain(struct mbuf * m)
                    180: {
                    181:     UInt32 count = 0;
                    182:     struct mbuf * ml;
                    183: 
                    184:     while ((ml = m)) {
                    185:         m = ml->m_nextpkt;
                    186:         ml->m_nextpkt = 0;
                    187:         m_freem(ml);
                    188:         count++;
                    189:     }
                    190: 
                    191:     return count;
                    192: }
                    193: 
                    194: static inline void _prepend(
                    195:     struct mbuf * m,        /* not modified */
                    196:     struct mbuf * & head,   /* modified */
                    197:     struct mbuf * & tail,   /* modified */
                    198:     UInt32 & size)          /* modified */
                    199: {
                    200:     assert(m);
                    201: 
                    202:     if (size++ > 0) {
                    203:         struct mbuf * mtail = m;
                    204:         while (mtail->m_nextpkt) {
                    205:             mtail = mtail->m_nextpkt;
                    206:             size++;
                    207:         }
                    208: 
                    209:         assert(head);
                    210:         mtail->m_nextpkt = head;
                    211:         head = m;
                    212:     }
                    213:     else {
                    214:         assert(!head && !tail);
                    215:         head = tail = m;
                    216:         while (tail->m_nextpkt) {
                    217:             tail = tail->m_nextpkt;
                    218:             size++;
                    219:         }
                    220:     }
                    221: } 
                    222: 
                    223: static inline struct mbuf * _enqueue(
                    224:     struct mbuf * m,        /* mbuf chain to append to tail */
                    225:     struct mbuf * & head,   /* modified */
                    226:     struct mbuf * & tail,   /* modified */
                    227:     UInt32 capacity,        /* not modified */
                    228:     UInt32 & size,          /* modified */
                    229:     UInt32 & peakSize)      /* modified */
                    230: {
                    231:     assert(m);
                    232: 
                    233:     if (size >= capacity)
                    234:         goto overflow;
                    235: 
                    236:     if (size++ > 0) {
                    237:         assert(tail);
                    238:         tail->m_nextpkt = m;
                    239:         tail = m;
                    240:     }
                    241:     else {
                    242:         assert(!head && !tail);
                    243:         head = tail = m;
                    244:     }
                    245:     
                    246:     m = 0;
                    247: 
                    248:     while (tail->m_nextpkt) {
                    249:         if (size >= capacity) {
                    250:             m = tail->m_nextpkt;
                    251:             tail->m_nextpkt = 0;
                    252:             goto overflow;
                    253:         }
                    254: 
                    255:         tail = tail->m_nextpkt;
                    256:         size++;
                    257:     }
                    258: 
                    259:     if (size > peakSize)
                    260:         peakSize = size;
                    261: 
                    262: overflow:
                    263:     return m;
                    264: }
                    265: 
                    266: static inline struct mbuf * _dequeue(
                    267:     struct mbuf * & head,   /* modified */
                    268:     struct mbuf * & tail,   /* modified */
                    269:     UInt32 & size)          /* modified */
                    270: {
                    271:     if (size == 0)
                    272:         return 0;
                    273: 
                    274:     assert(head);
                    275: 
                    276:     struct mbuf *m = head;
                    277:     head = head->m_nextpkt;
                    278:     m->m_nextpkt = 0;
                    279:     if (--size == 0)
                    280:         head = tail = 0;
                    281: 
                    282:     return m;
                    283: }
                    284: 
                    285: static inline struct mbuf * _dequeueAll(
                    286:     struct mbuf * & head,   /* modified */
                    287:     struct mbuf * & tail,   /* modified */
                    288:     UInt32 & size)          /* modified */
                    289: {
                    290:     if (size == 0)
                    291:         return 0;
                    292:     
                    293:     assert(head);
                    294: 
                    295:     struct mbuf *m = head;
                    296:     head = tail = 0;
                    297:     size = 0;
                    298: 
                    299:     return m;
                    300: }
                    301: 
                    302: //---------------------------------------------------------------------------
                    303: // Traverse a packet chain linked through the mbuf nextpkt field, and free
                    304: // each packet.
                    305: //
                    306: // m: The mbuf at the head of the mbuf chain.
                    307: //
                    308: // Returns the number of mbufs freed.
                    309: 
                    310: UInt32 IOPacketQueue::freePacketChain(struct mbuf * m)
                    311: {
                    312:     return _freePacketChain(m);
                    313: }
                    314: 
                    315: //---------------------------------------------------------------------------
                    316: // Add a packet (or a packet chain) to the head of the queue. Unlike enqueue(),
                    317: // the capacity is not checked, and the input packet is never dropped.
                    318: //
                    319: // m: A single packet, or packet chain, to be added to the head of the queue.
                    320: 
                    321: void IOPacketQueue::prepend(struct mbuf * m)
                    322: {
                    323:     _prepend(m, _head, _tail, _size);
                    324: }
                    325: 
                    326: //---------------------------------------------------------------------------
                    327: // Add a packet (or a packet chain) to the tail of the queue.
                    328: //
                    329: // m: A single packet, or a packet chain, to be added to the tail of the queue.
                    330: 
                    331: UInt32 IOPacketQueue::enqueue(struct mbuf * m)
                    332: {
                    333:     m = _enqueue(m, _head, _tail, _capacity, _size, _peakSize);
                    334:     return (m ? _freePacketChain(m) : 0);
                    335: }
                    336: 
                    337: //---------------------------------------------------------------------------
                    338: // Remove a single packet from the head of the queue.
                    339: //
                    340: // Returns the dequeued packet. A NULL is returned if the queue is empty.
                    341: 
                    342: struct mbuf * IOPacketQueue::dequeue()
                    343: {   
                    344:     return _dequeue(_head, _tail, _size);
                    345: }
                    346: 
                    347: //---------------------------------------------------------------------------
                    348: // Removes all packets from the queue and return the first packet of the
                    349: // packet chain.
                    350: //
                    351: // Returns the head of the dequeued packet chain.
                    352: 
                    353: struct mbuf * IOPacketQueue::dequeueAll()
                    354: {
                    355:     return _dequeueAll(_head, _tail, _size);
                    356: }
                    357: 
                    358: //---------------------------------------------------------------------------
                    359: // Removes all packets from the queue and put them back to the free mbuf
                    360: // pool. The size of the queue will be zero after the call.
                    361: //
                    362: // Returns the number of packets freed.
                    363: 
                    364: UInt32 IOPacketQueue::flush()
                    365: {
                    366:     return (freePacketChain(dequeueAll()));
                    367: }
                    368: 
                    369: //---------------------------------------------------------------------------
                    370: // Locked forms of prepend/enqueue/dequeue/dequeueAll methods.
                    371: // A spinlock is used to enforce mutual exclusion between methods that
                    372: // with a "lock" prefix.
                    373: 
                    374: void IOPacketQueue::lockPrepend(struct mbuf * m)
                    375: {
                    376:     LOCK;
                    377:     _prepend(m, _head, _tail, _size);
                    378:     UNLOCK;  
                    379: }
                    380: 
                    381: UInt32 IOPacketQueue::lockEnqueue(struct mbuf * m)
                    382: {
                    383:     LOCK;
                    384:     m = _enqueue(m, _head, _tail, _capacity, _size, _peakSize);
                    385:     UNLOCK;
                    386:     return (m ? _freePacketChain(m) : 0);
                    387: }
                    388: 
                    389: struct mbuf * IOPacketQueue::lockDequeue()
                    390: {
                    391:     struct mbuf * m;
                    392:     LOCK;
                    393:     m = _dequeue(_head, _tail, _size);
                    394:     UNLOCK;
                    395:     return m;
                    396: }
                    397: 
                    398: struct mbuf * IOPacketQueue::lockDequeueAll()
                    399: {
                    400:     struct mbuf * m;
                    401:     LOCK;
                    402:     m = _dequeueAll(_head, _tail, _size);
                    403:     UNLOCK;
                    404:     return m;
                    405: }
                    406: 
                    407: UInt32 IOPacketQueue::lockFlush()
                    408: {
                    409:     return (freePacketChain(lockDequeueAll()));
                    410: }

unix.superglobalmegacorp.com

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