1*043036a2SApple OSS Distributions /* 2*043036a2SApple OSS Distributions * Copyright (c) 1998-2019 Apple Inc. All rights reserved. 3*043036a2SApple OSS Distributions * 4*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5*043036a2SApple OSS Distributions * 6*043036a2SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7*043036a2SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8*043036a2SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9*043036a2SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10*043036a2SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11*043036a2SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12*043036a2SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13*043036a2SApple OSS Distributions * terms of an Apple operating system software license agreement. 14*043036a2SApple OSS Distributions * 15*043036a2SApple OSS Distributions * Please obtain a copy of the License at 16*043036a2SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17*043036a2SApple OSS Distributions * 18*043036a2SApple OSS Distributions * The Original Code and all software distributed under the License are 19*043036a2SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20*043036a2SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21*043036a2SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22*043036a2SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23*043036a2SApple OSS Distributions * Please see the License for the specific language governing rights and 24*043036a2SApple OSS Distributions * limitations under the License. 25*043036a2SApple OSS Distributions * 26*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27*043036a2SApple OSS Distributions */ 28*043036a2SApple OSS Distributions /*[ 29*043036a2SApple OSS Distributions * 1999-8-10 Godfrey van der Linden(gvdl) 30*043036a2SApple OSS Distributions * Created. 31*043036a2SApple OSS Distributions * ]*/ 32*043036a2SApple OSS Distributions /*! @language embedded-c++ */ 33*043036a2SApple OSS Distributions 34*043036a2SApple OSS Distributions #ifndef _IOKIT_IOCOMMANDGATE_H 35*043036a2SApple OSS Distributions #define _IOKIT_IOCOMMANDGATE_H 36*043036a2SApple OSS Distributions 37*043036a2SApple OSS Distributions #include <IOKit/IOEventSource.h> 38*043036a2SApple OSS Distributions #include <libkern/c++/OSPtr.h> 39*043036a2SApple OSS Distributions 40*043036a2SApple OSS Distributions /*! 41*043036a2SApple OSS Distributions * @class IOCommandGate : public IOEventSource 42*043036a2SApple OSS Distributions * @abstract Single-threaded work loop client request mechanism. 43*043036a2SApple OSS Distributions * @discussion An IOCommandGate instance is an extremely lightweight mechanism 44*043036a2SApple OSS Distributions * that executes an action on the driver's work loop. Although the code does not 45*043036a2SApple OSS Distributions * technically execute on the work loop itself, a single-threaded work loop semantic 46*043036a2SApple OSS Distributions * is maintained for this event source using the work loop gate. The command gate 47*043036a2SApple OSS Distributions * tests for a potential self dead lock by checking if the runCommand request is 48*043036a2SApple OSS Distributions * made from the work loop's thread, it doesn't check for a mutual dead lock though 49*043036a2SApple OSS Distributions * where a pair of work loop's dead lock each other. 50*043036a2SApple OSS Distributions * <br><br> 51*043036a2SApple OSS Distributions * The IOCommandGate is a lighter weight version of the IOCommandQueue and 52*043036a2SApple OSS Distributions * should be used in preference. Generally use a command queue whenever you need a 53*043036a2SApple OSS Distributions * client to submit a request to a work loop. A typical command gate action would 54*043036a2SApple OSS Distributions * check if the hardware is active, if so it will add the request to a pending 55*043036a2SApple OSS Distributions * queue internal to the device or the device's family. Otherwise if the hardware 56*043036a2SApple OSS Distributions * is inactive then this request can be acted upon immediately. 57*043036a2SApple OSS Distributions * <br><br> 58*043036a2SApple OSS Distributions * CAUTION: The runAction, runCommand, and attemptCommand functions cannot be called from an interrupt context. 59*043036a2SApple OSS Distributions * 60*043036a2SApple OSS Distributions */ 61*043036a2SApple OSS Distributions class IOCommandGate : public IOEventSource 62*043036a2SApple OSS Distributions { 63*043036a2SApple OSS Distributions OSDeclareDefaultStructors(IOCommandGate); 64*043036a2SApple OSS Distributions 65*043036a2SApple OSS Distributions public: 66*043036a2SApple OSS Distributions /*! 67*043036a2SApple OSS Distributions * @typedef Action 68*043036a2SApple OSS Distributions * @discussion Type and arguments of callout C function that is used when 69*043036a2SApple OSS Distributions * a runCommand is executed by a client. Cast to this type when you want a C++ 70*043036a2SApple OSS Distributions * member function to be used. Note the arg1 - arg3 parameters are straight pass 71*043036a2SApple OSS Distributions * through from the runCommand to the action callout. 72*043036a2SApple OSS Distributions * @param owner 73*043036a2SApple OSS Distributions * Target of the function, can be used as a refcon. The owner is set 74*043036a2SApple OSS Distributions * during initialisation of the IOCommandGate instance. Note if a C++ function 75*043036a2SApple OSS Distributions * was specified this parameter is implicitly the first paramter in the target 76*043036a2SApple OSS Distributions * member function's parameter list. 77*043036a2SApple OSS Distributions * @param arg0 Argument to action from run operation. 78*043036a2SApple OSS Distributions * @param arg1 Argument to action from run operation. 79*043036a2SApple OSS Distributions * @param arg2 Argument to action from run operation. 80*043036a2SApple OSS Distributions * @param arg3 Argument to action from run operation. 81*043036a2SApple OSS Distributions */ 82*043036a2SApple OSS Distributions typedef IOReturn (*Action)(OSObject *owner, 83*043036a2SApple OSS Distributions void *arg0, void *arg1, 84*043036a2SApple OSS Distributions void *arg2, void *arg3); 85*043036a2SApple OSS Distributions 86*043036a2SApple OSS Distributions protected: 87*043036a2SApple OSS Distributions 88*043036a2SApple OSS Distributions /*! @struct ExpansionData 89*043036a2SApple OSS Distributions * @discussion This structure will be used to expand the capablilties of the IOWorkLoop in the future. 90*043036a2SApple OSS Distributions */ 91*043036a2SApple OSS Distributions struct ExpansionData { }; 92*043036a2SApple OSS Distributions 93*043036a2SApple OSS Distributions /*! @var reserved 94*043036a2SApple OSS Distributions * Reserved for future use. (Internal use only) */ 95*043036a2SApple OSS Distributions APPLE_KEXT_WSHADOW_PUSH; 96*043036a2SApple OSS Distributions ExpansionData *reserved; 97*043036a2SApple OSS Distributions APPLE_KEXT_WSHADOW_POP; 98*043036a2SApple OSS Distributions 99*043036a2SApple OSS Distributions public: 100*043036a2SApple OSS Distributions /*! @function commandGate 101*043036a2SApple OSS Distributions * @abstract Factory method to create and initialise an IOCommandGate, See $link init. 102*043036a2SApple OSS Distributions * @result Returns a pointer to the new command gate if sucessful, 0 otherwise. */ 103*043036a2SApple OSS Distributions static OSPtr<IOCommandGate> commandGate(OSObject *owner, Action action = NULL); 104*043036a2SApple OSS Distributions 105*043036a2SApple OSS Distributions /*! @function init 106*043036a2SApple OSS Distributions * @abstract Class initialiser. 107*043036a2SApple OSS Distributions * @discussion Initialiser for IOCommandGate operates only on newly 'newed' 108*043036a2SApple OSS Distributions * objects. Shouldn't be used to re-init an existing instance. 109*043036a2SApple OSS Distributions * @param owner Owner of this, newly created, instance of the IOCommandGate. This argument will be used as the first parameter in the action callout. 110*043036a2SApple OSS Distributions * @param action 111*043036a2SApple OSS Distributions * Pointer to a C function that is called whenever a client of the 112*043036a2SApple OSS Distributions * IOCommandGate calls runCommand. NB Can be a C++ member function but caller 113*043036a2SApple OSS Distributions * must cast the member function to $link IOCommandGate::Action and they will get a 114*043036a2SApple OSS Distributions * compiler warning. Defaults to zero, see $link IOEventSource::setAction. 115*043036a2SApple OSS Distributions * @result True if inherited classes initialise successfully. */ 116*043036a2SApple OSS Distributions virtual bool init(OSObject *owner, Action action = NULL); 117*043036a2SApple OSS Distributions 118*043036a2SApple OSS Distributions // Superclass overrides 119*043036a2SApple OSS Distributions virtual void free() APPLE_KEXT_OVERRIDE; 120*043036a2SApple OSS Distributions virtual void setWorkLoop(IOWorkLoop *inWorkLoop) APPLE_KEXT_OVERRIDE; 121*043036a2SApple OSS Distributions 122*043036a2SApple OSS Distributions /*! @function runCommand 123*043036a2SApple OSS Distributions * @abstract Single thread a command with the target work loop. 124*043036a2SApple OSS Distributions * @discussion Client function that causes the current action to be called in 125*043036a2SApple OSS Distributions * a single threaded manner. Beware the work loop's gate is recursive and command 126*043036a2SApple OSS Distributions * gates can cause direct or indirect re-entrancy. When the executing on a 127*043036a2SApple OSS Distributions * client's thread runCommand will sleep until the work loop's gate opens for 128*043036a2SApple OSS Distributions * execution of client actions, the action is single threaded against all other 129*043036a2SApple OSS Distributions * work loop event sources. If the command is disabled the attempt to run a command will be stalled until enable is called. 130*043036a2SApple OSS Distributions * @param arg0 Parameter for action of command gate, defaults to 0. 131*043036a2SApple OSS Distributions * @param arg1 Parameter for action of command gate, defaults to 0. 132*043036a2SApple OSS Distributions * @param arg2 Parameter for action of command gate, defaults to 0. 133*043036a2SApple OSS Distributions * @param arg3 Parameter for action of command gate, defaults to 0. 134*043036a2SApple OSS Distributions * @result kIOReturnSuccess if successful. kIOReturnAborted if a disabled command gate is free()ed before being reenabled, kIOReturnNoResources if no action available. 135*043036a2SApple OSS Distributions */ 136*043036a2SApple OSS Distributions virtual IOReturn runCommand(void *arg0 = NULL, void *arg1 = NULL, 137*043036a2SApple OSS Distributions void *arg2 = NULL, void *arg3 = NULL); 138*043036a2SApple OSS Distributions 139*043036a2SApple OSS Distributions /*! @function runAction 140*043036a2SApple OSS Distributions * @abstract Single thread a call to an action with the target work loop. 141*043036a2SApple OSS Distributions * @discussion Client function that causes the given action to be called in 142*043036a2SApple OSS Distributions * a single threaded manner. Beware the work loop's gate is recursive and command 143*043036a2SApple OSS Distributions * gates can cause direct or indirect re-entrancy. When the executing on a 144*043036a2SApple OSS Distributions * client's thread runAction will sleep until the work loop's gate opens for 145*043036a2SApple OSS Distributions * execution of client actions, the action is single threaded against all other 146*043036a2SApple OSS Distributions * work loop event sources. If the command is disabled the attempt to run a command will be stalled until enable is called. 147*043036a2SApple OSS Distributions * @param action Pointer to function to be executed in the context of the work loop. 148*043036a2SApple OSS Distributions * @param arg0 Parameter for action parameter, defaults to 0. 149*043036a2SApple OSS Distributions * @param arg1 Parameter for action parameter, defaults to 0. 150*043036a2SApple OSS Distributions * @param arg2 Parameter for action parameter, defaults to 0. 151*043036a2SApple OSS Distributions * @param arg3 Parameter for action parameter, defaults to 0. 152*043036a2SApple OSS Distributions * @result The return value of action if it was called, kIOReturnBadArgument if action is not defined, kIOReturnAborted if a disabled command gate is free()ed before being reenabled. 153*043036a2SApple OSS Distributions */ 154*043036a2SApple OSS Distributions virtual IOReturn runAction(Action action, 155*043036a2SApple OSS Distributions void *arg0 = NULL, void *arg1 = NULL, 156*043036a2SApple OSS Distributions void *arg2 = NULL, void *arg3 = NULL); 157*043036a2SApple OSS Distributions 158*043036a2SApple OSS Distributions #ifdef __BLOCKS__ 159*043036a2SApple OSS Distributions /*! @function runActionBlock 160*043036a2SApple OSS Distributions * @abstract Single thread a call to an action with the target work loop. 161*043036a2SApple OSS Distributions * @discussion Client function that causes the given action to be called in 162*043036a2SApple OSS Distributions * a single threaded manner. Beware the work loop's gate is recursive and command 163*043036a2SApple OSS Distributions * gates can cause direct or indirect re-entrancy. When the executing on a 164*043036a2SApple OSS Distributions * client's thread runAction will sleep until the work loop's gate opens for 165*043036a2SApple OSS Distributions * execution of client actions, the action is single threaded against all other 166*043036a2SApple OSS Distributions * work loop event sources. If the command is disabled the attempt to run a command will be stalled until enable is called. 167*043036a2SApple OSS Distributions * @param action Block to be executed in the context of the work loop. 168*043036a2SApple OSS Distributions * @result The return value of action if it was called, kIOReturnBadArgument if action is not defined, kIOReturnAborted if a disabled command gate is free()ed before being reenabled. 169*043036a2SApple OSS Distributions */ 170*043036a2SApple OSS Distributions IOReturn runActionBlock(ActionBlock action); 171*043036a2SApple OSS Distributions #endif /* __BLOCKS__ */ 172*043036a2SApple OSS Distributions 173*043036a2SApple OSS Distributions /*! @function attemptCommand 174*043036a2SApple OSS Distributions * @abstract Single thread a command with the target work loop. 175*043036a2SApple OSS Distributions * @discussion Client function that causes the current action to be called in 176*043036a2SApple OSS Distributions * a single threaded manner. When the executing on a client's thread attemptCommand will fail if the work loop's gate is closed. 177*043036a2SApple OSS Distributions * @param arg0 Parameter for action of command gate, defaults to 0. 178*043036a2SApple OSS Distributions * @param arg1 Parameter for action of command gate, defaults to 0. 179*043036a2SApple OSS Distributions * @param arg2 Parameter for action of command gate, defaults to 0. 180*043036a2SApple OSS Distributions * @param arg3 Parameter for action of command gate, defaults to 0. 181*043036a2SApple OSS Distributions * @result kIOReturnSuccess if successful. kIOReturnNotPermitted if this event source is currently disabled, kIOReturnNoResources if no action available, kIOReturnCannotLock if lock attempt fails. 182*043036a2SApple OSS Distributions */ 183*043036a2SApple OSS Distributions virtual IOReturn attemptCommand(void *arg0 = NULL, void *arg1 = NULL, 184*043036a2SApple OSS Distributions void *arg2 = NULL, void *arg3 = NULL); 185*043036a2SApple OSS Distributions 186*043036a2SApple OSS Distributions /*! @function attemptAction 187*043036a2SApple OSS Distributions * @abstract Single thread a call to an action with the target work loop. 188*043036a2SApple OSS Distributions * @discussion Client function that causes the given action to be called in 189*043036a2SApple OSS Distributions * a single threaded manner. Beware the work loop's gate is recursive and command 190*043036a2SApple OSS Distributions * gates can cause direct or indirect re-entrancy. When the executing on a 191*043036a2SApple OSS Distributions * client's thread attemptCommand will fail if the work loop's gate is closed. 192*043036a2SApple OSS Distributions * @param action Pointer to function to be executed in context of the work loop. 193*043036a2SApple OSS Distributions * @param arg0 Parameter for action parameter, defaults to 0. 194*043036a2SApple OSS Distributions * @param arg1 Parameter for action parameter, defaults to 0. 195*043036a2SApple OSS Distributions * @param arg2 Parameter for action parameter, defaults to 0. 196*043036a2SApple OSS Distributions * @param arg3 Parameter for action parameter, defaults to 0. 197*043036a2SApple OSS Distributions * @result kIOReturnSuccess if successful. kIOReturnBadArgument if action is not defined, kIOReturnNotPermitted if this event source is currently disabled, kIOReturnCannotLock if lock attempt fails. 198*043036a2SApple OSS Distributions * 199*043036a2SApple OSS Distributions */ 200*043036a2SApple OSS Distributions virtual IOReturn attemptAction(Action action, 201*043036a2SApple OSS Distributions void *arg0 = NULL, void *arg1 = NULL, 202*043036a2SApple OSS Distributions void *arg2 = NULL, void *arg3 = NULL); 203*043036a2SApple OSS Distributions 204*043036a2SApple OSS Distributions /*! @function commandSleep 205*043036a2SApple OSS Distributions * @abstract Put a thread that is currently holding the command gate to sleep. 206*043036a2SApple OSS Distributions * @discussion Put a thread to sleep waiting for an event but release the gate first. If the event occurs then the commandGate is closed before the function returns. If the thread does not hold the gate, panic. 207*043036a2SApple OSS Distributions * @param event Pointer to an address. 208*043036a2SApple OSS Distributions * @param interruptible THREAD_UNINT, THREAD_INTERRUPTIBLE or THREAD_ABORTSAFE. THREAD_UNINT specifies that the sleep cannot be interrupted by a signal. THREAD_INTERRUPTIBLE specifies that the sleep may be interrupted by a "kill -9" signal. THREAD_ABORTSAFE (the default value) specifies that the sleep may be interrupted by any user signal. 209*043036a2SApple OSS Distributions * @result THREAD_AWAKENED - normal wakeup, THREAD_TIMED_OUT - timeout expired, THREAD_INTERRUPTED - interrupted, THREAD_RESTART - restart operation entirely. */ 210*043036a2SApple OSS Distributions virtual IOReturn commandSleep(void *event, 211*043036a2SApple OSS Distributions UInt32 interruptible = THREAD_ABORTSAFE); 212*043036a2SApple OSS Distributions 213*043036a2SApple OSS Distributions /*! @function commandWakeup 214*043036a2SApple OSS Distributions * @abstract Wakeup one or more threads that are asleep on an event. 215*043036a2SApple OSS Distributions * @param event Pointer to an address. 216*043036a2SApple OSS Distributions * @param oneThread true to only wake up at most one thread, false otherwise. */ 217*043036a2SApple OSS Distributions virtual void commandWakeup(void *event, bool oneThread = false); 218*043036a2SApple OSS Distributions 219*043036a2SApple OSS Distributions /*! @function disable 220*043036a2SApple OSS Distributions * @abstract Disable the command gate 221*043036a2SApple OSS Distributions * @discussion When a command gate is disabled all future calls to runAction and runCommand will stall until the gate is enable()d later. This can be used to block client threads when a system sleep is requested. The IOWorkLoop thread itself will never stall, even when making runAction/runCommand calls. This call must be made from a gated context, to clear potential race conditions. */ 222*043036a2SApple OSS Distributions virtual void disable() APPLE_KEXT_OVERRIDE; 223*043036a2SApple OSS Distributions 224*043036a2SApple OSS Distributions /*! @function enable 225*043036a2SApple OSS Distributions * @abstract Enable command gate, this will unblock any blocked Commands and Actions. 226*043036a2SApple OSS Distributions * @discussion Enable the command gate. The attemptAction/attemptCommand calls will now be enabled and can succeeed. Stalled runCommand/runAction calls will be woken up. */ 227*043036a2SApple OSS Distributions virtual void enable() APPLE_KEXT_OVERRIDE; 228*043036a2SApple OSS Distributions 229*043036a2SApple OSS Distributions /*! @function commandSleep 230*043036a2SApple OSS Distributions * @abstract Put a thread that is currently holding the command gate to sleep. 231*043036a2SApple OSS Distributions * @discussion Put a thread to sleep waiting for an event but release the gate first. If the event occurs or timeout occurs then the commandGate is closed before the function returns. If the thread does not hold the gate, panic. 232*043036a2SApple OSS Distributions * @param event Pointer to an address. 233*043036a2SApple OSS Distributions * @param deadline Clock deadline to timeout the sleep. 234*043036a2SApple OSS Distributions * @param interruptible THREAD_UNINT, THREAD_INTERRUPTIBLE or THREAD_ABORTSAFE. THREAD_UNINT specifies that the sleep cannot be interrupted by a signal. THREAD_INTERRUPTIBLE specifies that the sleep may be interrupted by a "kill -9" signal. THREAD_ABORTSAFE specifies that the sleep may be interrupted by any user signal. 235*043036a2SApple OSS Distributions * @result THREAD_AWAKENED - normal wakeup, THREAD_TIMED_OUT - timeout expired, THREAD_INTERRUPTED - interrupted, THREAD_RESTART - restart operation entirely. */ 236*043036a2SApple OSS Distributions virtual IOReturn commandSleep(void *event, 237*043036a2SApple OSS Distributions AbsoluteTime deadline, 238*043036a2SApple OSS Distributions UInt32 interruptible); 239*043036a2SApple OSS Distributions 240*043036a2SApple OSS Distributions private: 241*043036a2SApple OSS Distributions #if __LP64__ 242*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 0); 243*043036a2SApple OSS Distributions #else 244*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUsedX86(IOCommandGate, 0); 245*043036a2SApple OSS Distributions #endif 246*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 1); 247*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 2); 248*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 3); 249*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 4); 250*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 5); 251*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 6); 252*043036a2SApple OSS Distributions OSMetaClassDeclareReservedUnused(IOCommandGate, 7); 253*043036a2SApple OSS Distributions }; 254*043036a2SApple OSS Distributions 255*043036a2SApple OSS Distributions #endif /* !_IOKIT_IOCOMMANDGATE_H */ 256