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