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 #define IOKIT_ENABLE_SHARED_PTR 41 42 #include <IOKit/IOCommandPool.h> 43 #include <libkern/c++/OSSharedPtr.h> 44 45 #define super OSObject 46 OSDefineMetaClassAndStructors(IOCommandPool, OSObject); 47 OSMetaClassDefineReservedUnused(IOCommandPool, 0); 48 OSMetaClassDefineReservedUnused(IOCommandPool, 1); 49 OSMetaClassDefineReservedUnused(IOCommandPool, 2); 50 OSMetaClassDefineReservedUnused(IOCommandPool, 3); 51 OSMetaClassDefineReservedUnused(IOCommandPool, 4); 52 OSMetaClassDefineReservedUnused(IOCommandPool, 5); 53 OSMetaClassDefineReservedUnused(IOCommandPool, 6); 54 OSMetaClassDefineReservedUnused(IOCommandPool, 7); 55 56 //-------------------------------------------------------------------------- 57 // withWorkLoop - primary initializer and factory method 58 //-------------------------------------------------------------------------- 59 60 OSSharedPtr<IOCommandPool> 61 IOCommandPool:: 62 withWorkLoop(IOWorkLoop *inWorkLoop) 63 { 64 OSSharedPtr<IOCommandPool> me = OSMakeShared<IOCommandPool>(); 65 66 if (me && !me->initWithWorkLoop(inWorkLoop)) { 67 return nullptr; 68 } 69 70 return me; 71 } 72 73 74 bool 75 IOCommandPool:: 76 initWithWorkLoop(IOWorkLoop *inWorkLoop) 77 { 78 assert(inWorkLoop); 79 80 if (!super::init()) { 81 return false; 82 } 83 84 queue_init(&fQueueHead); 85 86 fSerializer = IOCommandGate::commandGate(this); 87 assert(fSerializer); 88 if (!fSerializer) { 89 return false; 90 } 91 92 if (kIOReturnSuccess != inWorkLoop->addEventSource(fSerializer.get())) { 93 return false; 94 } 95 96 return true; 97 } 98 99 //-------------------------------------------------------------------------- 100 // commandPool & init - obsolete initializer and factory method 101 //-------------------------------------------------------------------------- 102 103 OSSharedPtr<IOCommandPool> 104 IOCommandPool:: 105 commandPool(IOService * inOwner, IOWorkLoop *inWorkLoop, UInt32 inSize) 106 { 107 OSSharedPtr<IOCommandPool> me = OSMakeShared<IOCommandPool>(); 108 109 if (me && !me->init(inOwner, inWorkLoop, inSize)) { 110 return nullptr; 111 } 112 113 return me; 114 } 115 116 bool 117 IOCommandPool:: 118 init(IOService */* inOwner */, IOWorkLoop *inWorkLoop, UInt32 /* inSize */) 119 { 120 return initWithWorkLoop(inWorkLoop); 121 } 122 123 124 //-------------------------------------------------------------------------- 125 // free - free all allocated resources 126 //-------------------------------------------------------------------------- 127 128 void 129 IOCommandPool::free(void) 130 { 131 if (fSerializer) { 132 // remove our event source from owner's workloop 133 IOWorkLoop *wl = fSerializer->getWorkLoop(); 134 if (wl) { 135 wl->removeEventSource(fSerializer.get()); 136 } 137 138 fSerializer.reset(); 139 } 140 141 // Tell our superclass to cleanup too 142 super::free(); 143 } 144 145 146 //-------------------------------------------------------------------------- 147 // getCommand - Gets a command from the pool. Pass true in 148 // blockForCommand if you want your thread to sleep 149 // waiting for resources 150 //-------------------------------------------------------------------------- 151 152 OSSharedPtr<IOCommand> 153 IOCommandPool::getCommand(bool blockForCommand) 154 { 155 IOReturn result = kIOReturnSuccess; 156 IOCommand *command = NULL; 157 158 IOCommandGate::Action func = OSMemberFunctionCast( 159 IOCommandGate::Action, this, &IOCommandPool::gatedGetCommand); 160 result = fSerializer-> 161 runAction(func, (void *) &command, (void *) blockForCommand); 162 if (kIOReturnSuccess == result) { 163 return OSSharedPtr<IOCommand>(command, OSNoRetain); 164 } else { 165 return NULL; 166 } 167 } 168 169 170 //-------------------------------------------------------------------------- 171 // gatedGetCommand - Static callthrough function 172 // (on safe side of command gate) 173 //-------------------------------------------------------------------------- 174 175 IOReturn 176 IOCommandPool:: 177 gatedGetCommand(IOCommand **command, bool blockForCommand) 178 { 179 while (queue_empty(&fQueueHead)) { 180 if (!blockForCommand) { 181 return kIOReturnNoResources; 182 } 183 184 fSleepers++; 185 fSerializer->commandSleep(&fSleepers, THREAD_UNINT); 186 } 187 188 queue_remove_first(&fQueueHead, 189 *command, IOCommand *, fCommandChain); 190 return kIOReturnSuccess; 191 } 192 193 194 //-------------------------------------------------------------------------- 195 // returnCommand - Returns command to the pool. 196 //-------------------------------------------------------------------------- 197 198 void 199 IOCommandPool:: 200 returnCommand(IOCommand *command) 201 { 202 IOCommandGate::Action func = OSMemberFunctionCast( 203 IOCommandGate::Action, this, &IOCommandPool::gatedReturnCommand); 204 (void) fSerializer->runAction(func, (void *) command); 205 } 206 207 208 //-------------------------------------------------------------------------- 209 // gatedReturnCommand - Callthrough function 210 // (on safe side of command gate) 211 //-------------------------------------------------------------------------- 212 213 IOReturn 214 IOCommandPool:: 215 gatedReturnCommand(IOCommand *command) 216 { 217 queue_enter_first(&fQueueHead, command, IOCommand *, fCommandChain); 218 if (fSleepers) { 219 fSerializer->commandWakeup(&fSleepers, /* oneThread */ true); 220 fSleepers--; 221 } 222 return kIOReturnSuccess; 223 } 224