xref: /xnu-11215/iokit/Kernel/IOCommandPool.cpp (revision d0c1fef6)
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
43 OSDefineMetaClassAndStructors(IOCommandPool, OSObject);
44 OSMetaClassDefineReservedUnused(IOCommandPool, 0);
45 OSMetaClassDefineReservedUnused(IOCommandPool, 1);
46 OSMetaClassDefineReservedUnused(IOCommandPool, 2);
47 OSMetaClassDefineReservedUnused(IOCommandPool, 3);
48 OSMetaClassDefineReservedUnused(IOCommandPool, 4);
49 OSMetaClassDefineReservedUnused(IOCommandPool, 5);
50 OSMetaClassDefineReservedUnused(IOCommandPool, 6);
51 OSMetaClassDefineReservedUnused(IOCommandPool, 7);
52 
53 //--------------------------------------------------------------------------
54 //	withWorkLoop -	primary initializer and factory method
55 //--------------------------------------------------------------------------
56 
57 IOCommandPool *IOCommandPool::
58 withWorkLoop(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 
71 bool IOCommandPool::
72 initWithWorkLoop(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 
96 IOCommandPool *IOCommandPool::
97 commandPool(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 
109 bool IOCommandPool::
110 init(IOService */* inOwner */, IOWorkLoop *inWorkLoop, UInt32 /* inSize */)
111 {
112     return initWithWorkLoop(inWorkLoop);
113 }
114 
115 
116 //--------------------------------------------------------------------------
117 //	free -	free all allocated resources
118 //--------------------------------------------------------------------------
119 
120 void
121 IOCommandPool::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 
144 IOCommand *
145 IOCommandPool::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 
166 IOReturn IOCommandPool::
167 gatedGetCommand(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 
187 void IOCommandPool::
188 returnCommand(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 
201 IOReturn IOCommandPool::
202 gatedReturnCommand(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