]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOCommandPool.cpp
xnu-201.19.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCommandPool.cpp
1 /*
2 * Copyright (c) 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 /*
24 *
25 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
26 *
27 * HISTORY
28 *
29 * 2001-01-17 gvdl Re-implement on IOCommandGate::commandSleep
30 * 10/9/2000 CJS Created IOCommandPool class and implementation
31 *
32 */
33
34 #include <IOKit/IOCommandPool.h>
35
36 #define super OSObject
37 OSDefineMetaClassAndStructors(IOCommandPool, OSObject);
38 OSMetaClassDefineReservedUnused(IOCommandPool, 0);
39 OSMetaClassDefineReservedUnused(IOCommandPool, 1);
40 OSMetaClassDefineReservedUnused(IOCommandPool, 2);
41 OSMetaClassDefineReservedUnused(IOCommandPool, 3);
42 OSMetaClassDefineReservedUnused(IOCommandPool, 4);
43 OSMetaClassDefineReservedUnused(IOCommandPool, 5);
44 OSMetaClassDefineReservedUnused(IOCommandPool, 6);
45 OSMetaClassDefineReservedUnused(IOCommandPool, 7);
46
47 //--------------------------------------------------------------------------
48 // withWorkLoop - primary initializer and factory method
49 //--------------------------------------------------------------------------
50
51 IOCommandPool *IOCommandPool::
52 withWorkLoop(IOWorkLoop *inWorkLoop)
53 {
54 IOCommandPool * me = new IOCommandPool;
55
56 if (me && !me->initWithWorkLoop(inWorkLoop)) {
57 me->release();
58 return 0;
59 }
60
61 return me;
62 }
63
64
65 bool IOCommandPool::
66 initWithWorkLoop(IOWorkLoop *inWorkLoop)
67 {
68 assert(inWorkLoop);
69
70 if (!super::init())
71 return false;
72
73 queue_init(&fQueueHead);
74
75 fSerializer = IOCommandGate::commandGate(this);
76 assert(fSerializer);
77 if (!fSerializer)
78 return false;
79
80 if (kIOReturnSuccess != inWorkLoop->addEventSource(fSerializer))
81 return false;
82
83 return true;
84 }
85
86 //--------------------------------------------------------------------------
87 // commandPool & init - obsolete initializer and factory method
88 //--------------------------------------------------------------------------
89
90 IOCommandPool *IOCommandPool::
91 commandPool(IOService * inOwner, IOWorkLoop *inWorkLoop, UInt32 inSize)
92 {
93 IOCommandPool * me = new IOCommandPool;
94
95 if (me && !me->init(inOwner, inWorkLoop, inSize)) {
96 me->release();
97 return 0;
98 }
99
100 return me;
101 }
102
103 bool IOCommandPool::
104 init(IOService */* inOwner */, IOWorkLoop *inWorkLoop, UInt32 /* inSize */)
105 {
106 return initWithWorkLoop(inWorkLoop);
107 }
108
109
110 //--------------------------------------------------------------------------
111 // free - free all allocated resources
112 //--------------------------------------------------------------------------
113
114 void
115 IOCommandPool::free(void)
116 {
117 if (fSerializer) {
118 // remove our event source from owner's workloop
119 IOWorkLoop *wl = fSerializer->getWorkLoop();
120 if (wl)
121 wl->removeEventSource(fSerializer);
122
123 fSerializer->release();
124 fSerializer = 0;
125 }
126
127 // Tell our superclass to cleanup too
128 super::free();
129 }
130
131
132 //--------------------------------------------------------------------------
133 // getCommand - Gets a command from the pool. Pass true in
134 // blockForCommand if you want your thread to sleep
135 // waiting for resources
136 //--------------------------------------------------------------------------
137
138 IOCommand *
139 IOCommandPool::getCommand(bool blockForCommand)
140 {
141 IOReturn result = kIOReturnSuccess;
142 IOCommand *command = 0;
143
144 result = fSerializer->runAction((IOCommandGate::Action)
145 &IOCommandPool::gatedGetCommand,
146 (void *) &command, (void *) blockForCommand);
147 if (kIOReturnSuccess == result)
148 return command;
149 else
150 return 0;
151 }
152
153
154 //--------------------------------------------------------------------------
155 // gatedGetCommand - Static callthrough function
156 // (on safe side of command gate)
157 //--------------------------------------------------------------------------
158
159 IOReturn IOCommandPool::
160 gatedGetCommand(IOCommand **command, bool blockForCommand)
161 {
162 while (queue_empty(&fQueueHead)) {
163 if (!blockForCommand)
164 return kIOReturnNoResources;
165
166 fSleepers++;
167 fSerializer->commandSleep(&fSleepers, THREAD_UNINT);
168 }
169
170 queue_remove_first(&fQueueHead,
171 *command, IOCommand *, fCommandChain);
172 return kIOReturnSuccess;
173 }
174
175
176 //--------------------------------------------------------------------------
177 // returnCommand - Returns command to the pool.
178 //--------------------------------------------------------------------------
179
180 void IOCommandPool::
181 returnCommand(IOCommand *command)
182 {
183 (void) fSerializer->runAction((IOCommandGate::Action)
184 &IOCommandPool::gatedReturnCommand, (void *) command);
185 }
186
187
188 //--------------------------------------------------------------------------
189 // gatedReturnCommand - Callthrough function
190 // (on safe side of command gate)
191 //--------------------------------------------------------------------------
192
193 IOReturn IOCommandPool::
194 gatedReturnCommand(IOCommand *command)
195 {
196 queue_enter(&fQueueHead, command, IOCommand *, fCommandChain);
197 if (fSleepers) {
198 fSerializer->commandWakeup(&fSleepers, /* oneThread */ true);
199 fSleepers--;
200 }
201 return kIOReturnSuccess;
202 }