|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.