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) 1999 Apple Computer, Inc. All rights reserved. 30 * 31 * IOTimerEventSource.h 32 * 33 * HISTORY 34 * 2-Feb-1999 Joe Liu (jliu) created. 35 * 36 */ 37 38 #ifndef _IOTIMEREVENTSOURCE 39 #define _IOTIMEREVENTSOURCE 40 41 #include <sys/cdefs.h> 42 43 __BEGIN_DECLS 44 #include <kern/clock.h> 45 __END_DECLS 46 47 #include <libkern/c++/OSPtr.h> 48 #include <IOKit/IOEventSource.h> 49 #include <IOKit/IOTypes.h> 50 51 /*! 52 * @enum IOTimerEventSource constructor options 53 * @abstract Constants defining behavior of the IOTimerEventSource. 54 * @constant kIOTimerEventSourceOptionsPriorityHigh Importance above everything but realtime. 55 * Thread calls allocated with this priority execute at extremely high priority, 56 * above everything but realtime threads. They are generally executed in serial. 57 * Though they may execute concurrently under some circumstances, no fan-out is implied. 58 * These work items should do very small amounts of work or risk disrupting system 59 * responsiveness. 60 * @constant kIOTimerEventSourceOptionsPriorityKernelHigh Importance higher than most kernel 61 * threads. 62 * @constant kIOTimerEventSourceOptionsPriorityKernel Importance similar to that of normal kernel 63 * threads. 64 * @constant kIOTimerEventSourceOptionsPriorityUser Importance similar to that of normal user threads. 65 * @constant kIOTimerEventSourceOptionsPriorityLow Very low importance. 66 * @constant kIOTimerEventSourceOptionsPriorityWorkLoop Run the callout on the thread of the IOWorkLoop 67 * the event source has been added to. 68 * @constant kIOTimerEventSourceOptionsAllowReenter Allow the callout to be rescheduled and potentially 69 * re-entered, if the IOWorkLoop lock has been released (eg. with commandSleep) during its invocation. 70 * @constant kIOTimerEventSourceOptionsDefault Recommended default options. 71 */ 72 enum{ 73 kIOTimerEventSourceOptionsPriorityMask = 0x000000ff, 74 kIOTimerEventSourceOptionsPriorityHigh = 0x00000000, 75 kIOTimerEventSourceOptionsPriorityKernelHigh = 0x00000001, 76 kIOTimerEventSourceOptionsPriorityKernel = 0x00000002, 77 kIOTimerEventSourceOptionsPriorityUser = 0x00000003, 78 kIOTimerEventSourceOptionsPriorityLow = 0x00000004, 79 kIOTimerEventSourceOptionsPriorityWorkLoop = 0x000000ff, 80 81 kIOTimerEventSourceOptionsAllowReenter = 0x00000100, 82 83 kIOTimerEventSourceOptionsDefault = kIOTimerEventSourceOptionsPriorityKernelHigh 84 }; 85 86 #define IOTIMEREVENTSOURCEOPTIONS_DEFINED 1 87 88 /*! 89 * @enum IOTimerEventSource setTimeout/wakeAtTime options 90 * @abstract Constants defining behavior of a scheduled call from IOTimerEventSource. 91 * @constant kIOTimeOptionsWithLeeway Use the leeway parameter to the call. 92 * @constant kIOTimeOptionsContinuous Use mach_continuous_time() to generate the callback. 93 */ 94 enum{ 95 kIOTimeOptionsWithLeeway = 0x00000020, 96 kIOTimeOptionsContinuous = 0x00000100, 97 }; 98 99 /*! 100 * @class IOTimerEventSource : public IOEventSource 101 * @abstract Time based event source mechanism. 102 * @discussion An event source that implements a simple timer. A timeout handler is called once the timeout period expires. This timeout handler will be called by the work-loop that this event source is attached to. 103 * <br><br> 104 * Usually a timer event source will be used to implement a timeout. In general when a driver makes a request it will need to setup a call to keep track of when the I/O doesn't complete. This class is designed to make that somewhat easier. 105 * <br><br> 106 * Remember the system doesn't guarantee the accuracy of the callout. It is possible that a higher priority thread is running which will delay the execution of the action routine. In fact the thread will be made runable at the exact requested time, within the accuracy of the CPU's decrementer based interrupt, but the scheduler will then control execution. 107 */ 108 109 class IOTimerEventSource : public IOEventSource 110 { 111 OSDeclareDefaultStructors(IOTimerEventSource); 112 113 protected: 114 /*! @var calloutEntry thread_call entry for preregistered thread callouts */ 115 void *calloutEntry; 116 117 /*! @var abstime time to wake up next, see enable. */ 118 AbsoluteTime abstime; 119 120 /*! @struct ExpansionData 121 * @discussion This structure is private to the IOTimerEventSource implementation. 122 */ 123 struct ExpansionData { 124 SInt32 calloutGeneration; 125 SInt32 calloutGenerationSignaled; 126 IOWorkLoop * workLoop; 127 }; 128 129 /*! @var reserved 130 * Reserved for future use. (Internal use only) */ 131 APPLE_KEXT_WSHADOW_PUSH; 132 ExpansionData *reserved; 133 APPLE_KEXT_WSHADOW_POP; 134 135 /*! @function timeout 136 * @abstract Function that routes the call from the OS' timeout mechanism into a work-loop context. 137 * @discussion timeout will normally not be called nor overridden by a subclass. If the event source is enabled then close the work-loop's gate and call the action routine. 138 * @param self This argument will be cast to an IOTimerEventSource. */ 139 static void timeout(void *self); 140 141 /*! @function setTimeoutFunc 142 * @abstract Set's timeout as the function of calloutEntry. 143 * @discussion IOTimerEventSource is based upon the kern/thread_call.h APIs currently. This function allocates the calloutEntry member variable by using thread_call_allocate(timeout, this). If you need to write your own subclass of IOTimerEventSource you probably should override this method to allocate an entry that points to your own timeout routine. */ 144 virtual void setTimeoutFunc(); 145 146 /*! @function free 147 * @abstract Sub-class implementation of free method, frees calloutEntry */ 148 virtual void free() APPLE_KEXT_OVERRIDE; 149 150 virtual void setWorkLoop(IOWorkLoop *workLoop) APPLE_KEXT_OVERRIDE; 151 152 public: 153 154 /*! @typedef Action 155 * @discussion 'C' Function pointer defining the callout routine of this event source. 156 * @param owner Owning target object. Note by a startling coincidence the first parameter in a C callout is currently used to define the target of a C++ member function. 157 * @param sender The object that timed out. */ 158 typedef void (*Action)(OSObject *owner, IOTimerEventSource *sender); 159 160 #ifdef __BLOCKS__ 161 typedef void (^ActionBlock)(IOTimerEventSource *sender); 162 #endif /* __BLOCKS__ */ 163 164 static OSPtr<IOTimerEventSource> 165 timerEventSource(OSObject *owner, Action action = NULL); 166 167 /*! @function timerEventSource 168 * @abstract Allocates and returns an initialized timer instance. 169 * @param options Mask of kIOTimerEventSourceOptions* options. 170 * @param owner The object that that will be passed to the Action callback. 171 * @param action 'C' Function pointer for the callout routine of this event source. 172 */ 173 static OSPtr<IOTimerEventSource> 174 timerEventSource(uint32_t options, OSObject *owner, Action action = NULL); 175 176 #ifdef __BLOCKS__ 177 /*! @function timerEventSource 178 * @abstract Allocates and returns an initialized timer instance. 179 * @param options Mask of kIOTimerEventSourceOptions* options. 180 * @param inOwner The object that that will be passed to the Action callback. 181 * @param action Block for the callout routine of this event source. 182 */ 183 static OSPtr<IOTimerEventSource> 184 timerEventSource(uint32_t options, OSObject *inOwner, ActionBlock action); 185 #endif /* __BLOCKS__ */ 186 187 #if XNU_KERNEL_PRIVATE 188 __inline__ void invokeAction(IOEventSource::Action action, IOTimerEventSource * ts, 189 OSObject * owner, IOWorkLoop * workLoop); 190 #endif /* XNU_KERNEL_PRIVATE */ 191 192 /*! @function init 193 * @abstract Initializes the timer with an owner, and a handler to call when the timeout expires. 194 */ 195 virtual bool init(OSObject *owner, Action action = NULL); 196 197 /*! @function enable 198 * @abstract Enables a call to the action. 199 * @discussion Allows the action function to be called. If the timer event source was disabled while a call was outstanding and the call wasn't cancelled then it will be rescheduled. So a disable/enable pair will disable calls from this event source. */ 200 virtual void enable() APPLE_KEXT_OVERRIDE; 201 202 /*! @function disable 203 * @abstract Disable a timed callout. 204 * @discussion When disable returns the action will not be called until the next time enable(qv) is called. */ 205 virtual void disable() APPLE_KEXT_OVERRIDE; 206 207 /*! @function checkForWork 208 * @abstract Pure Virtual member function used by IOWorkLoop for issuing a client calls. 209 * @discussion This function called when the work-loop is ready to check for any work to do and then to call out the owner/action. 210 * @result Return true if this function needs to be called again before all its outstanding events have been processed. */ 211 virtual bool checkForWork() APPLE_KEXT_OVERRIDE; 212 213 /*! @function setTimeoutTicks 214 * @abstract Setup a callback at after the delay in scheduler ticks. See wakeAtTime(AbsoluteTime). 215 * @param ticks Delay from now to wake up, in scheduler ticks, whatever that may be. 216 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 217 virtual IOReturn setTimeoutTicks(UInt32 ticks); 218 219 /*! @function setTimeoutMS 220 * @abstract Setup a callback at after the delay in milliseconds. See wakeAtTime(AbsoluteTime). 221 * @param ms Delay from now to wake up, time in milliseconds. 222 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 223 virtual IOReturn setTimeoutMS(UInt32 ms); 224 225 /*! @function setTimeoutUS 226 * @abstract Setup a callback at after the delay in microseconds. See wakeAtTime(AbsoluteTime). 227 * @param us Delay from now to wake up, time in microseconds. 228 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 229 virtual IOReturn setTimeoutUS(UInt32 us); 230 231 /*! @function setTimeout 232 * @abstract Setup a callback at after the delay in some unit. See wakeAtTime(AbsoluteTime). 233 * @param interval Delay from now to wake up in some defined unit. 234 * @param scale_factor Define the unit of interval, default to nanoseconds. 235 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 236 virtual IOReturn setTimeout(UInt32 interval, 237 UInt32 scale_factor = kNanosecondScale); 238 239 #if !defined(__LP64__) 240 virtual IOReturn setTimeout(mach_timespec_t interval) 241 APPLE_KEXT_DEPRECATED; 242 #endif 243 244 /*! @function setTimeout 245 * @abstract Setup a callback at after the delay in decrementer ticks. See wakeAtTime(AbsoluteTime). 246 * @param interval Delay from now to wake up in decrementer ticks. 247 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 248 virtual IOReturn setTimeout(AbsoluteTime interval); 249 250 /*! @function wakeAtTimeTicks 251 * @abstract Setup a callback at this absolute time. See wakeAtTime(AbsoluteTime). 252 * @param ticks Time to wake up in scheduler quantums, whatever that is? 253 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 254 virtual IOReturn wakeAtTimeTicks(UInt32 ticks); 255 256 /*! @function wakeAtTimeMS 257 * @abstract Setup a callback at this absolute time. See wakeAtTime(AbsoluteTime). 258 * @param ms Time to wake up in milliseconds. 259 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 260 virtual IOReturn wakeAtTimeMS(UInt32 ms); 261 262 /*! @function wakeAtTimeUS 263 * @abstract Setup a callback at this absolute time. See wakeAtTime(AbsoluteTime). 264 * @param us Time to wake up in microseconds. 265 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 266 virtual IOReturn wakeAtTimeUS(UInt32 us); 267 268 /*! @function wakeAtTime 269 * @abstract Setup a callback at this absolute time. See wakeAtTime(AbsoluteTime). 270 * @param abstime Time to wake up in some unit. 271 * @param scale_factor Define the unit of abstime, default to nanoseconds. 272 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 273 virtual IOReturn wakeAtTime(UInt32 abstime, 274 UInt32 scale_factor = kNanosecondScale); 275 276 #if !defined(__LP64__) 277 virtual IOReturn wakeAtTime(mach_timespec_t abstime) 278 APPLE_KEXT_DEPRECATED; 279 #endif 280 281 /*! @function wakeAtTime 282 * @abstract Setup a callback at this absolute time. 283 * @discussion Starts the timer, which will expire at abstime. After it expires, the timer will call the 'action' registered in the init() function. This timer is not periodic, a further call is needed to reset and restart the timer after it expires. 284 * @param abstime Absolute Time when to wake up, counted in 'decrementer' units and starts at zero when system boots. 285 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared by init or IOEventSource::setAction (qqv). */ 286 virtual IOReturn wakeAtTime(AbsoluteTime abstime); 287 288 /*! @function cancelTimeout 289 * @abstract Disable any outstanding calls to this event source. 290 * @discussion Clear down any oustanding calls. By the time this function completes it is guaranteed that the action will not be called again. */ 291 virtual void cancelTimeout(); 292 293 /*! @function init 294 * @abstract Initializes the timer with an owner, and a handler to call when the timeout expires. 295 */ 296 virtual bool init(uint32_t options, OSObject *inOwner, Action inAction); 297 298 /*! @function setTimeout 299 * @abstract Setup a callback at after the delay in decrementer ticks. See wakeAtTime(AbsoluteTime). 300 * @param options see kIOTimeOptionsWithLeeway and kIOTimeOptionsContinuous 301 * @param interval Delay from now to wake up in decrementer ticks. 302 * @param leeway Allowable leeway to wake time, if the kIOTimeOptionsWithLeeway option is set 303 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared. */ 304 virtual IOReturn setTimeout(uint32_t options, AbsoluteTime interval, AbsoluteTime leeway); 305 306 /*! @function wakeAtTime 307 * @abstract Setup a callback at this absolute time. 308 * @discussion Starts the timer, which will expire at abstime. After it expires, the timer will call the 'action' registered in the init() function. This timer is not periodic, a further call is needed to reset and restart the timer after it expires. 309 * @param options see kIOTimeOptionsWithLeeway and kIOTimeOptionsContinuous 310 * @param abstime Absolute Time when to wake up, counted in 'decrementer' units and starts at zero when system boots. 311 * @param leeway Allowable leeway to wake time, if the kIOTimeOptionsWithLeeway option is set 312 * @result kIOReturnSuccess if everything is fine, kIOReturnNoResources if action hasn't been declared by init or IOEventSource::setAction (qqv). */ 313 virtual IOReturn wakeAtTime(uint32_t options, AbsoluteTime abstime, AbsoluteTime leeway); 314 315 private: 316 static void timeoutAndRelease(void *self, void *c); 317 static void timeoutSignaled(void *self, void *c); 318 319 private: 320 OSMetaClassDeclareReservedUsedX86(IOTimerEventSource, 0); 321 OSMetaClassDeclareReservedUsedX86(IOTimerEventSource, 1); 322 OSMetaClassDeclareReservedUsedX86(IOTimerEventSource, 2); 323 OSMetaClassDeclareReservedUnused(IOTimerEventSource, 3); 324 OSMetaClassDeclareReservedUnused(IOTimerEventSource, 4); 325 OSMetaClassDeclareReservedUnused(IOTimerEventSource, 5); 326 OSMetaClassDeclareReservedUnused(IOTimerEventSource, 6); 327 OSMetaClassDeclareReservedUnused(IOTimerEventSource, 7); 328 }; 329 330 #endif /* !_IOTIMEREVENTSOURCE */ 331