xref: /xnu-11215/iokit/Kernel/IOCommandPool.cpp (revision bb611c8f)
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::
withWorkLoop(IOWorkLoop * inWorkLoop)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::
initWithWorkLoop(IOWorkLoop * inWorkLoop)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::
commandPool(IOService * inOwner,IOWorkLoop * inWorkLoop,UInt32 inSize)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::
init(IOService *,IOWorkLoop * inWorkLoop,UInt32)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
free(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>
getCommand(bool blockForCommand)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::
gatedGetCommand(IOCommand ** command,bool blockForCommand)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::
returnCommand(IOCommand * command)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::
gatedReturnCommand(IOCommand * command)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