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