1 /* 2 * Copyright (c) 1998-2019 Apple 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 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. 30 * HISTORY 31 * 1998-7-13 Godfrey van der Linden(gvdl) 32 * Created. 33 * 1998-10-30 Godfrey van der Linden(gvdl) 34 * Converted to C++ 35 */ 36 #ifndef _IOKIT_IOEVENTSOURCE_H 37 #define _IOKIT_IOEVENTSOURCE_H 38 39 #include <sys/cdefs.h> 40 41 #include <libkern/c++/OSObject.h> 42 43 #include <IOKit/IOLib.h> 44 #include <IOKit/system.h> 45 #include <IOKit/IOWorkLoop.h> 46 47 #if IOKITSTATS 48 #include <IOKit/IOStatisticsPrivate.h> 49 #endif 50 51 __BEGIN_DECLS 52 #include <mach/clock_types.h> 53 #include <kern/clock.h> 54 __END_DECLS 55 56 /*! 57 * @class IOEventSource : public OSObject 58 * @abstract Abstract class for all work-loop event sources. 59 * @discussion The IOEventSource declares the abstract super class that all 60 * event sources must inherit from if an IOWorkLoop is to receive events from them. 61 * <br><br> 62 * An event source can represent any event that should cause the work-loop of a 63 * device to wake up and perform work. Two examples of event sources are the 64 * IOInterruptEventSource which delivers interrupt notifications and IOCommandGate 65 * which delivers command requests. 66 * <br><br> 67 * A kernel module can always use the work-loop model for serialising access to 68 * anything at all. The IOEventSource is used for communicating events to the 69 * work-loop, and the chain of event sources should be used to walk the possible 70 * event sources and demultipex them. Note a particular instance of an event 71 * source may only be a member of 1 linked list chain. If you need to move it 72 * between chains than make sure it is removed from the original chain before 73 * attempting to move it. 74 * <br><br> 75 * The IOEventSource makes no attempt to maintain the consistency of its internal data across multi-threading. It is assumed that the user of these basic tools will protect the data that these objects represent in some sort of device wide instance lock. For example the IOWorkLoop maintains the event chain by using an IOCommandGate and thus single threading access to its state. 76 * <br><br> 77 * All subclasses of IOEventSource that wish to perform work on the work-loop thread are expected to implement the checkForWork() member function. As of Mac OS X, 10.7 (Darwin 11), checkForWork is no longer pure virtual, and should not be overridden if there is no work to be done. 78 * 79 * <br><br> 80 * checkForWork() is the key method in this class. It is called by some work-loop when convienient and is expected to evaluate its internal state and determine if an event has occurred since the last call. In the case of an event having occurred then the instance defined target(owner)/action will be called. The action is stored as an ordinary C function pointer but the first parameter is always the owner. This means that a C++ member function can be used as an action function though this depends on the ABI. 81 * <br><br> 82 * Although the eventChainNext variable contains a reference to the next event source in the chain this reference is not retained. The list 'owner' i.e. the client that creates the event, not the work-loop, is expected to retain the source. 83 */ 84 class IOEventSource : public OSObject 85 { 86 OSDeclareAbstractStructors(IOEventSource); 87 friend class IOWorkLoop; 88 #if IOKITSTATS 89 friend class IOStatistics; 90 #endif 91 92 public: 93 /*! 94 * @typedef Action 95 * @discussion Placeholder type for C++ function overloading discrimination. 96 * As the all event sources require an action and it has to be stored somewhere 97 * and be of some type, this is that type. 98 * @param owner 99 * Target of the function, can be used as a refcon. The owner is set 100 * during initialisation. Note if a C++ function was specified this parameter 101 * is implicitly the first paramter in the target member function's parameter list. 102 */ 103 typedef void (*Action)(OSObject *owner, ...); 104 105 /*! @defined IOEventSourceAction 106 * @discussion Backward compatibilty define for the old non-class scoped type definition. See $link IOEventSource::Action */ 107 #define IOEventSourceAction IOEventSource::Action 108 109 #ifdef __BLOCKS__ 110 typedef IOReturn (^ActionBlock)(); 111 #endif /* __BLOCKS__ */ 112 113 protected: 114 /*! @var eventChainNext 115 * The next event source in the event chain. nil at end of chain. */ 116 IOEventSource *eventChainNext; 117 118 /*! @var owner The owner object called when an event has been delivered. */ 119 OSObject *owner; 120 121 /*! @var action 122 * The action method called when an event has been delivered */ 123 124 #if XNU_KERNEL_PRIVATE 125 union { Action action; ActionBlock actionBlock; }; 126 #else /* XNU_KERNEL_PRIVATE */ 127 Action action; 128 #endif /* !XNU_KERNEL_PRIVATE */ 129 130 /*! @var enabled 131 * Is this event source enabled to deliver requests to the work-loop. */ 132 bool enabled; 133 134 #if XNU_KERNEL_PRIVATE 135 enum{ 136 kPassive = 0x0001, 137 kActive = 0x0002, 138 kActionBlock = 0x0004, 139 kSubClass0 = 0x0008, 140 }; 141 uint8_t eventSourceReserved1[1]; 142 uint16_t flags; 143 #if __LP64__ 144 uint8_t eventSourceReserved2[4]; 145 #endif /* __LP64__ */ 146 147 #endif /* XNU_KERNEL_PRIVATE */ 148 149 /*! @var workLoop What is the work-loop for this event source. */ 150 IOWorkLoop *workLoop; 151 152 /*! @var refcon What ever the client wants to do, see $link setRefcon. */ 153 void *refcon; 154 155 /*! @struct ExpansionData 156 * @discussion This structure will be used to expand the capablilties of the IOEventSource in the future. 157 */ 158 struct ExpansionData { 159 #if IOKITSTATS 160 struct IOEventSourceCounter *counter; 161 #else 162 void *iokitstatsReserved; 163 #endif 164 }; 165 166 /*! @var reserved 167 * Reserved for future use. (Internal use only) */ 168 ExpansionData *reserved; 169 170 /*! @function init 171 * @abstract Primary initialiser for the IOEventSource class. 172 * @param owner 173 * Owner of this instance of an event source. Used as the first parameter 174 * of the action callout. Owner must be an OSObject. 175 * @param action 176 * Pointer to C call out function. Action is a pointer to a C function 177 * that gets called when this event source has outstanding work. It will usually 178 * be called by the checkForWork member function. The first parameter of the 179 * action call out will always be the owner, this allows C++ member functions to 180 * be used as actions. Defaults to 0. 181 * @result true if the inherited classes and this instance initialise 182 * successfully. 183 */ 184 virtual bool init(OSObject *owner, IOEventSource::Action action = NULL); 185 186 virtual void free( void ) APPLE_KEXT_OVERRIDE; 187 188 /*! @function checkForWork 189 * @abstract Virtual member function used by IOWorkLoop for work 190 * scheduling. 191 * @discussion This function will be called to request a subclass to check 192 * its internal state for any work to do and then to call out the owner/action. 193 * If this event source never performs any work (e.g. IOCommandGate), this 194 * method should not be overridden. NOTE: This method is no longer declared pure 195 * virtual. A default implementation is provided in IOEventSource. 196 * @result Return true if this function needs to be called again before all its outstanding events have been processed. 197 */ 198 virtual bool checkForWork(); 199 200 /*! @function setWorkLoop 201 * @abstract Set'ter for $link workLoop variable. 202 * @param workLoop 203 * Target work-loop of this event source instance. A subclass of 204 * IOWorkLoop that at least reacts to signalWorkAvailable() and onThread functions. 205 */ 206 virtual void setWorkLoop(IOWorkLoop *workLoop); 207 208 /*! @function setNext 209 * @abstract Set'ter for $link eventChainNext variable. 210 * @param next 211 * Pointer to another IOEventSource instance. 212 */ 213 virtual void setNext(IOEventSource *next); 214 215 /*! @function getNext 216 * @abstract Get'ter for $link eventChainNext variable. 217 * @result value of eventChainNext. 218 */ 219 virtual IOEventSource *getNext() const; 220 221 222 protected: 223 // Methods to access the IOWorkLoop exported fields 224 void signalWorkAvailable(); 225 void openGate(); 226 void closeGate(); 227 bool tryCloseGate(); 228 int sleepGate(void *event, UInt32 type); 229 int sleepGate(void *event, AbsoluteTime deadline, UInt32 type); 230 void wakeupGate(void *event, bool oneThread); 231 232 public: 233 /*! @function setAction 234 * @abstract Set'ter for $link action variable. 235 * @param action Pointer to a C function of type IOEventSource::Action. */ 236 virtual void setAction(IOEventSource::Action action); 237 238 /*! @function getAction 239 * @abstract Get'ter for $link action variable. 240 * @result value of action. */ 241 virtual IOEventSource::Action getAction() const; 242 243 #ifdef __BLOCKS__ 244 /*! @function setActionBlock 245 * @abstract Setter for action ivar. The current block is released, & the new block is retained. 246 * @param block Block pointer of type IOEventSource::ActionBlock. */ 247 void setActionBlock(ActionBlock block); 248 /*! @function getActionBlock 249 * @abstract Getter for action ivar. 250 * @result Block pointer of type IOEventSource::ActionBlock, if set, or NULL. */ 251 ActionBlock getActionBlock(ActionBlock) const; 252 #endif /* __BLOCKS__ */ 253 254 /*! @function setRefcon 255 * @abstract Setter for refcon ivar. This function will assert if a block action has been set. 256 * @param refcon Refcon. */ 257 void setRefcon(void *refcon); 258 /*! @function getRefcon 259 * @abstract Getter for refcon ivar. 260 * @result The refcon. This function will assert if a block action has been set. */ 261 void * getRefcon() const; 262 263 /*! @function enable 264 * @abstract Enable event source. 265 * @discussion A subclass implementation is expected to respect the enabled 266 * state when checkForWork is called. Calling this function will cause the 267 * work-loop to be signalled so that a checkForWork is performed. */ 268 virtual void enable(); 269 270 /*! @function disable 271 * @abstract Disable event source. 272 * @discussion A subclass implementation is expected to respect the enabled 273 * state when checkForWork is called. */ 274 virtual void disable(); 275 276 /*! @function isEnabled 277 * @abstract Get'ter for $link enable variable. 278 * @result true if enabled. */ 279 virtual bool isEnabled() const; 280 281 /*! @function getWorkLoop 282 * @abstract Get'ter for $link workLoop variable. 283 * @result value of workLoop. */ 284 virtual IOWorkLoop *getWorkLoop() const; 285 286 /*! @function onThread 287 * @abstract Convenience function for workLoop->onThread. 288 * @result true if called on the work-loop thread. 289 */ 290 virtual bool onThread() const; 291 292 private: 293 OSMetaClassDeclareReservedUnused(IOEventSource, 0); 294 OSMetaClassDeclareReservedUnused(IOEventSource, 1); 295 OSMetaClassDeclareReservedUnused(IOEventSource, 2); 296 OSMetaClassDeclareReservedUnused(IOEventSource, 3); 297 OSMetaClassDeclareReservedUnused(IOEventSource, 4); 298 OSMetaClassDeclareReservedUnused(IOEventSource, 5); 299 OSMetaClassDeclareReservedUnused(IOEventSource, 6); 300 OSMetaClassDeclareReservedUnused(IOEventSource, 7); 301 }; 302 303 #endif /* !_IOKIT_IOEVENTSOURCE_H */ 304