1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * 31 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 32 * 33 * HISTORY 34 * 35 * 2001-01-17 gvdl Re-implement on IOCommandGate::commandSleep 36 * 10/9/2000 CJS Created IOCommandPool class and implementation 37 * 38 */ 39 40#include <IOKit/IOCommandPool.h> 41 42#define super OSObject 43OSDefineMetaClassAndStructors(IOCommandPool, OSObject); 44OSMetaClassDefineReservedUnused(IOCommandPool, 0); 45OSMetaClassDefineReservedUnused(IOCommandPool, 1); 46OSMetaClassDefineReservedUnused(IOCommandPool, 2); 47OSMetaClassDefineReservedUnused(IOCommandPool, 3); 48OSMetaClassDefineReservedUnused(IOCommandPool, 4); 49OSMetaClassDefineReservedUnused(IOCommandPool, 5); 50OSMetaClassDefineReservedUnused(IOCommandPool, 6); 51OSMetaClassDefineReservedUnused(IOCommandPool, 7); 52 53//-------------------------------------------------------------------------- 54// withWorkLoop - primary initializer and factory method 55//-------------------------------------------------------------------------- 56 57IOCommandPool *IOCommandPool:: 58withWorkLoop(IOWorkLoop *inWorkLoop) 59{ 60 IOCommandPool * me = new IOCommandPool; 61 62 if (me && !me->initWithWorkLoop(inWorkLoop)) { 63 me->release(); 64 return 0; 65 } 66 67 return me; 68} 69 70 71bool IOCommandPool:: 72initWithWorkLoop(IOWorkLoop *inWorkLoop) 73{ 74 assert(inWorkLoop); 75 76 if (!super::init()) 77 return false; 78 79 queue_init(&fQueueHead); 80 81 fSerializer = IOCommandGate::commandGate(this); 82 assert(fSerializer); 83 if (!fSerializer) 84 return false; 85 86 if (kIOReturnSuccess != inWorkLoop->addEventSource(fSerializer)) 87 return false; 88 89 return true; 90} 91 92//-------------------------------------------------------------------------- 93// commandPool & init - obsolete initializer and factory method 94//-------------------------------------------------------------------------- 95 96IOCommandPool *IOCommandPool:: 97commandPool(IOService * inOwner, IOWorkLoop *inWorkLoop, UInt32 inSize) 98{ 99 IOCommandPool * me = new IOCommandPool; 100 101 if (me && !me->init(inOwner, inWorkLoop, inSize)) { 102 me->release(); 103 return 0; 104 } 105 106 return me; 107} 108 109bool IOCommandPool:: 110init(IOService */* inOwner */, IOWorkLoop *inWorkLoop, UInt32 /* inSize */) 111{ 112 return initWithWorkLoop(inWorkLoop); 113} 114 115 116//-------------------------------------------------------------------------- 117// free - free all allocated resources 118//-------------------------------------------------------------------------- 119 120void 121IOCommandPool::free(void) 122{ 123 if (fSerializer) { 124 // remove our event source from owner's workloop 125 IOWorkLoop *wl = fSerializer->getWorkLoop(); 126 if (wl) 127 wl->removeEventSource(fSerializer); 128 129 fSerializer->release(); 130 fSerializer = 0; 131 } 132 133 // Tell our superclass to cleanup too 134 super::free(); 135} 136 137 138//-------------------------------------------------------------------------- 139// getCommand - Gets a command from the pool. Pass true in 140// blockForCommand if you want your thread to sleep 141// waiting for resources 142//-------------------------------------------------------------------------- 143 144IOCommand * 145IOCommandPool::getCommand(bool blockForCommand) 146{ 147 IOReturn result = kIOReturnSuccess; 148 IOCommand *command = 0; 149 150 IOCommandGate::Action func = OSMemberFunctionCast( 151 IOCommandGate::Action, this, &IOCommandPool::gatedGetCommand); 152 result = fSerializer-> 153 runAction(func, (void *) &command, (void *) blockForCommand); 154 if (kIOReturnSuccess == result) 155 return command; 156 else 157 return 0; 158} 159 160 161//-------------------------------------------------------------------------- 162// gatedGetCommand - Static callthrough function 163// (on safe side of command gate) 164//-------------------------------------------------------------------------- 165 166IOReturn IOCommandPool:: 167gatedGetCommand(IOCommand **command, bool blockForCommand) 168{ 169 while (queue_empty(&fQueueHead)) { 170 if (!blockForCommand) 171 return kIOReturnNoResources; 172 173 fSleepers++; 174 fSerializer->commandSleep(&fSleepers, THREAD_UNINT); 175 } 176 177 queue_remove_first(&fQueueHead, 178 *command, IOCommand *, fCommandChain); 179 return kIOReturnSuccess; 180} 181 182 183//-------------------------------------------------------------------------- 184// returnCommand - Returns command to the pool. 185//-------------------------------------------------------------------------- 186 187void IOCommandPool:: 188returnCommand(IOCommand *command) 189{ 190 IOCommandGate::Action func = OSMemberFunctionCast( 191 IOCommandGate::Action, this, &IOCommandPool::gatedReturnCommand); 192 (void) fSerializer->runAction(func, (void *) command); 193} 194 195 196//-------------------------------------------------------------------------- 197// gatedReturnCommand - Callthrough function 198// (on safe side of command gate) 199//-------------------------------------------------------------------------- 200 201IOReturn IOCommandPool:: 202gatedReturnCommand(IOCommand *command) 203{ 204 queue_enter_first(&fQueueHead, command, IOCommand *, fCommandChain); 205 if (fSleepers) { 206 fSerializer->commandWakeup(&fSleepers, /* oneThread */ true); 207 fSleepers--; 208 } 209 return kIOReturnSuccess; 210} 211