+
+__inline__ void
+IOTimerEventSource::invokeAction(IOEventSource::Action _action, IOTimerEventSource * ts,
+ OSObject * _owner, IOWorkLoop * _workLoop)
+{
+ bool trace = (gIOKitTrace & kIOTraceTimers) ? true : false;
+ void * address;
+
+ if (kActionBlock & flags) {
+ address = ptrauth_nop_cast(void *, _Block_get_invoke_fn((struct Block_layout *) actionBlock));
+ } else {
+ address = ptrauth_nop_cast(void *, _action);
+ }
+
+ if (trace) {
+ IOTimeStampStartConstant(IODBG_TIMES(IOTIMES_ACTION),
+ VM_KERNEL_ADDRHIDE(address),
+ VM_KERNEL_ADDRHIDE(_owner));
+ }
+
+ if (kActionBlock & flags) {
+ ((IOTimerEventSource::ActionBlock) actionBlock)(ts);
+ } else {
+ ((IOTimerEventSource::Action)_action)(_owner, ts);
+ }
+
+#if CONFIG_DTRACE
+ DTRACE_TMR3(iotescallout__expire, Action, address, OSObject, _owner, void, _workLoop);
+#endif
+
+ if (trace) {
+ IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION),
+ VM_KERNEL_UNSLIDE(address),
+ VM_KERNEL_ADDRHIDE(_owner));
+ }
+}
+
+void
+IOTimerEventSource::timeout(void *self)
+{
+ IOTimerEventSource *me = (IOTimerEventSource *) self;
+
+ IOStatisticsTimeout();
+
+ if (me->enabled && me->action) {
+ IOWorkLoop *
+ wl = me->workLoop;
+ if (wl) {
+ IOEventSource::Action doit;
+ wl->closeGate();
+ IOStatisticsCloseGate();
+ doit = me->action;
+ if (doit && me->enabled && AbsoluteTime_to_scalar(&me->abstime)) {
+ me->invokeAction(doit, me, me->owner, me->workLoop);
+ }
+ IOStatisticsOpenGate();
+ wl->openGate();
+ }
+ }
+}
+
+void
+IOTimerEventSource::timeoutAndRelease(void * self, void * c)
+{
+ IOTimerEventSource *me = (IOTimerEventSource *) self;
+ /* The second parameter (a pointer) gets abused to carry an SInt32, so on LP64, "count"
+ * must be cast to "long" before, in order to tell GCC we're not truncating a pointer. */
+ SInt32 count = (SInt32) (long) c;
+
+ IOStatisticsTimeout();
+
+ if (me->enabled && me->action) {
+ IOWorkLoop *
+ wl = me->reserved->workLoop;
+ if (wl) {
+ IOEventSource::Action doit;
+ wl->closeGate();
+ IOStatisticsCloseGate();
+ doit = me->action;
+ if (doit && (me->reserved->calloutGeneration == count)) {
+ thread_call_start_iotes_invocation((thread_call_t)me->calloutEntry);
+ me->invokeAction(doit, me, me->owner, me->workLoop);
+ }
+ IOStatisticsOpenGate();
+ wl->openGate();
+ }
+ }
+
+ me->reserved->workLoop->release();
+ me->release();
+}
+
+// -- work loop delivery
+
+bool
+IOTimerEventSource::checkForWork()