1/* 2 * Copyright (c) 1998-2008 Apple 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 * IOPacketQueue.cpp - Implements a FIFO mbuf packet queue. 24 * 25 * HISTORY 26 * 9-Dec-1998 Joe Liu (jliu) created. 27 * 28 */ 29 30#include <IOKit/assert.h> 31#include <IOKit/IOLib.h> // IOLog 32#include <IOKit/network/IOPacketQueue.h> 33#include "IOMbufQueue.h" 34 35#define super OSObject 36OSDefineMetaClassAndStructors( IOPacketQueue, OSObject ) 37OSMetaClassDefineReservedUnused( IOPacketQueue, 0); 38OSMetaClassDefineReservedUnused( IOPacketQueue, 1); 39OSMetaClassDefineReservedUnused( IOPacketQueue, 2); 40OSMetaClassDefineReservedUnused( IOPacketQueue, 3); 41OSMetaClassDefineReservedUnused( IOPacketQueue, 4); 42OSMetaClassDefineReservedUnused( IOPacketQueue, 5); 43OSMetaClassDefineReservedUnused( IOPacketQueue, 6); 44OSMetaClassDefineReservedUnused( IOPacketQueue, 7); 45OSMetaClassDefineReservedUnused( IOPacketQueue, 8); 46OSMetaClassDefineReservedUnused( IOPacketQueue, 9); 47OSMetaClassDefineReservedUnused( IOPacketQueue, 10); 48OSMetaClassDefineReservedUnused( IOPacketQueue, 11); 49OSMetaClassDefineReservedUnused( IOPacketQueue, 12); 50OSMetaClassDefineReservedUnused( IOPacketQueue, 13); 51OSMetaClassDefineReservedUnused( IOPacketQueue, 14); 52OSMetaClassDefineReservedUnused( IOPacketQueue, 15); 53 54 55//--------------------------------------------------------------------------- 56// Lock macros 57 58#define LOCK IOSimpleLockLock(_lock) 59#define UNLOCK IOSimpleLockUnlock(_lock) 60 61//--------------------------------------------------------------------------- 62// Initialize an IOPacketQueue object. 63 64bool IOPacketQueue::initWithCapacity(UInt32 capacity) 65{ 66 if (super::init() == false) 67 { 68 IOLog("IOPacketQueue: super::init() failed\n"); 69 return false; 70 } 71 72 _queue = IONew(IOMbufQueue, 1); 73 if (_queue == 0) 74 return false; 75 76 IOMbufQueueInit(_queue, capacity); 77 78 if ((_lock = IOSimpleLockAlloc()) == 0) 79 return false; 80 81 IOSimpleLockInit(_lock); 82 83 return true; 84} 85 86//--------------------------------------------------------------------------- 87// Factory method that will construct and initialize an IOPacketQueue object. 88 89IOPacketQueue * IOPacketQueue::withCapacity(UInt32 capacity) 90{ 91 IOPacketQueue * queue = new IOPacketQueue; 92 93 if (queue && !queue->initWithCapacity(capacity)) 94 { 95 queue->release(); 96 queue = 0; 97 } 98 return queue; 99} 100 101//--------------------------------------------------------------------------- 102// Frees the IOPacketQueue instance. 103 104void IOPacketQueue::free() 105{ 106 if (_lock) 107 { 108 IOSimpleLockFree(_lock); 109 _lock = 0; 110 } 111 112 if (_queue) 113 { 114 flush(); 115 IODelete(_queue, IOMbufQueue, 1); 116 _queue = 0; 117 } 118 119 super::free(); 120} 121 122//--------------------------------------------------------------------------- 123// Get the current size of the queue. 124 125UInt32 IOPacketQueue::getSize() const 126{ 127 return IOMbufQueueGetSize(_queue); 128} 129 130//--------------------------------------------------------------------------- 131// Change the capacity of the queue. 132 133bool IOPacketQueue::setCapacity(UInt32 capacity) 134{ 135 IOMbufQueueSetCapacity(_queue, capacity); 136 return true; 137} 138 139//--------------------------------------------------------------------------- 140// Get the capacity of the queue. 141 142UInt32 IOPacketQueue::getCapacity() const 143{ 144 return IOMbufQueueGetCapacity(_queue); 145} 146 147//--------------------------------------------------------------------------- 148// Peek at the head of the queue without dequeueing the packet. 149 150const mbuf_t IOPacketQueue::peek() const 151{ 152 return IOMbufQueuePeek(_queue); 153} 154 155//--------------------------------------------------------------------------- 156// Add a packet chain to the head of the queue. 157 158void IOPacketQueue::prepend(mbuf_t m) 159{ 160 IOMbufQueuePrepend(_queue, m); 161} 162 163void IOPacketQueue::prepend(IOPacketQueue * queue) 164{ 165 IOMbufQueuePrepend(_queue, queue->_queue); 166} 167 168//--------------------------------------------------------------------------- 169// Add a packet chain to the tail of the queue. 170 171bool IOPacketQueue::enqueue(mbuf_t m) 172{ 173 return IOMbufQueueEnqueue(_queue, m); 174} 175 176bool IOPacketQueue::enqueue(IOPacketQueue * queue) 177{ 178 return IOMbufQueueEnqueue(_queue, queue->_queue); 179} 180 181UInt32 IOPacketQueue::enqueueWithDrop(mbuf_t m) 182{ 183 return IOMbufQueueEnqueue(_queue, m) ? 0 : IOMbufFree(m); 184} 185 186//--------------------------------------------------------------------------- 187// Remove a single packet from the head of the queue. 188 189mbuf_t IOPacketQueue::dequeue() 190{ 191 return IOMbufQueueDequeue(_queue); 192} 193 194//--------------------------------------------------------------------------- 195// Remove all packets from the queue and return the chain of packet(s). 196 197mbuf_t IOPacketQueue::dequeueAll() 198{ 199 return IOMbufQueueDequeueAll(_queue); 200} 201 202//--------------------------------------------------------------------------- 203// Remove all packets from the queue and put them back to the free mbuf 204// pool. The size of the queue will be cleared to zero. 205 206UInt32 IOPacketQueue::flush() 207{ 208 return IOMbufFree(IOMbufQueueDequeueAll(_queue)); 209} 210 211//--------------------------------------------------------------------------- 212// Locked forms of prepend/enqueue/dequeue/dequeueAll methods. 213// A spinlock will enforce mutually exclusive queue access. 214 215void IOPacketQueue::lockPrepend(mbuf_t m) 216{ 217 LOCK; 218 IOMbufQueuePrepend(_queue, m); 219 UNLOCK; 220} 221 222bool IOPacketQueue::lockEnqueue(mbuf_t m) 223{ 224 bool ok; 225 LOCK; 226 ok = IOMbufQueueEnqueue(_queue, m); 227 UNLOCK; 228 return ok; 229} 230 231UInt32 IOPacketQueue::lockEnqueueWithDrop(mbuf_t m) 232{ 233 bool ok; 234 LOCK; 235 ok = IOMbufQueueEnqueue(_queue, m); 236 UNLOCK; 237 return ok ? 0 : IOMbufFree(m); 238} 239 240mbuf_t IOPacketQueue::lockDequeue() 241{ 242 mbuf_t m; 243 LOCK; 244 m = IOMbufQueueDequeue(_queue); 245 UNLOCK; 246 return m; 247} 248 249mbuf_t IOPacketQueue::lockDequeueAll() 250{ 251 mbuf_t m; 252 LOCK; 253 m = IOMbufQueueDequeueAll(_queue); 254 UNLOCK; 255 return m; 256} 257 258UInt32 IOPacketQueue::lockFlush() 259{ 260 mbuf_t m; 261 LOCK; 262 m = IOMbufQueueDequeueAll(_queue); 263 UNLOCK; 264 return IOMbufFree(m); 265} 266