1c1dac77fSApple OSS Distributions /*
2855239e5SApple OSS Distributions * Copyright (c) 1998-2000, 2009-2010 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions *
4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions *
6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions *
15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions *
18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions * limitations under the License.
25c1dac77fSApple OSS Distributions *
26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions */
28c1dac77fSApple OSS Distributions
29bb611c8fSApple OSS Distributions #include <ptrauth.h>
30c1dac77fSApple OSS Distributions #include <sys/cdefs.h>
31c1dac77fSApple OSS Distributions
32c1dac77fSApple OSS Distributions __BEGIN_DECLS
33c1dac77fSApple OSS Distributions #include <kern/thread_call.h>
34c1dac77fSApple OSS Distributions __END_DECLS
35c1dac77fSApple OSS Distributions
36c1dac77fSApple OSS Distributions #include <IOKit/assert.h>
37c1dac77fSApple OSS Distributions #include <IOKit/system.h>
38c1dac77fSApple OSS Distributions
39c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h>
40c1dac77fSApple OSS Distributions #include <IOKit/IOTimerEventSource.h>
41c1dac77fSApple OSS Distributions #include <IOKit/IOWorkLoop.h>
42c1dac77fSApple OSS Distributions
43c1dac77fSApple OSS Distributions #include <IOKit/IOTimeStamp.h>
44855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h>
45186b8fceSApple OSS Distributions #if CONFIG_DTRACE
46186b8fceSApple OSS Distributions #include <mach/sdt.h>
47186b8fceSApple OSS Distributions #endif
48c1dac77fSApple OSS Distributions
49cc9a6355SApple OSS Distributions #include <libkern/Block.h>
50bb611c8fSApple OSS Distributions #include <libkern/Block_private.h>
51cc9a6355SApple OSS Distributions
52cc9a6355SApple OSS Distributions
53c1dac77fSApple OSS Distributions #define super IOEventSource
54c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOTimerEventSource, IOEventSource)
55bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOTimerEventSource, 0);
56bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOTimerEventSource, 1);
57bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOTimerEventSource, 2);
58c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOTimerEventSource, 3);
59c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOTimerEventSource, 4);
60c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOTimerEventSource, 5);
61c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOTimerEventSource, 6);
62c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOTimerEventSource, 7);
63c1dac77fSApple OSS Distributions
64855239e5SApple OSS Distributions #if IOKITSTATS
65855239e5SApple OSS Distributions
66855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() \
67855239e5SApple OSS Distributions do { \
68855239e5SApple OSS Distributions IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsTimerEventSourceCounter); \
69855239e5SApple OSS Distributions } while (0)
70855239e5SApple OSS Distributions
71855239e5SApple OSS Distributions #define IOStatisticsOpenGate() \
72855239e5SApple OSS Distributions do { \
73855239e5SApple OSS Distributions IOStatistics::countOpenGate(me->IOEventSource::reserved->counter); \
74855239e5SApple OSS Distributions } while (0)
75855239e5SApple OSS Distributions
76855239e5SApple OSS Distributions #define IOStatisticsCloseGate() \
77855239e5SApple OSS Distributions do { \
78855239e5SApple OSS Distributions IOStatistics::countCloseGate(me->IOEventSource::reserved->counter); \
79855239e5SApple OSS Distributions } while (0)
80855239e5SApple OSS Distributions
81855239e5SApple OSS Distributions #define IOStatisticsTimeout() \
82855239e5SApple OSS Distributions do { \
83855239e5SApple OSS Distributions IOStatistics::countTimerTimeout(me->IOEventSource::reserved->counter); \
84855239e5SApple OSS Distributions } while (0)
85855239e5SApple OSS Distributions
86855239e5SApple OSS Distributions #else
87855239e5SApple OSS Distributions
88855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter()
89855239e5SApple OSS Distributions #define IOStatisticsOpenGate()
90855239e5SApple OSS Distributions #define IOStatisticsCloseGate()
91855239e5SApple OSS Distributions #define IOStatisticsTimeout()
92855239e5SApple OSS Distributions
93855239e5SApple OSS Distributions #endif /* IOKITSTATS */
94855239e5SApple OSS Distributions
9514e3d835SApple OSS Distributions //
9614e3d835SApple OSS Distributions // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
9714e3d835SApple OSS Distributions // not a subclassed implementation.
9814e3d835SApple OSS Distributions //
9914e3d835SApple OSS Distributions
100c1dac77fSApple OSS Distributions // Timeout handler function. This function is called by the kernel when
101c1dac77fSApple OSS Distributions // the timeout interval expires.
102c1dac77fSApple OSS Distributions //
10376e12aa3SApple OSS Distributions
104cc9a6355SApple OSS Distributions __inline__ void
invokeAction(IOEventSource::Action _action,IOTimerEventSource * ts,OSObject * _owner,IOWorkLoop * _workLoop)105bb611c8fSApple OSS Distributions IOTimerEventSource::invokeAction(IOEventSource::Action _action, IOTimerEventSource * ts,
106a5e72196SApple OSS Distributions OSObject * _owner, IOWorkLoop * _workLoop)
10776e12aa3SApple OSS Distributions {
10876e12aa3SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceTimers) ? true : false;
109bb611c8fSApple OSS Distributions void * address;
110bb611c8fSApple OSS Distributions
111bb611c8fSApple OSS Distributions if (kActionBlock & flags) {
112bb611c8fSApple OSS Distributions address = ptrauth_nop_cast(void *, _Block_get_invoke_fn((struct Block_layout *) actionBlock));
113bb611c8fSApple OSS Distributions } else {
114bb611c8fSApple OSS Distributions address = ptrauth_nop_cast(void *, _action);
115bb611c8fSApple OSS Distributions }
11676e12aa3SApple OSS Distributions
117a5e72196SApple OSS Distributions if (trace) {
11876e12aa3SApple OSS Distributions IOTimeStampStartConstant(IODBG_TIMES(IOTIMES_ACTION),
119bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(address),
120bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(_owner));
12176e12aa3SApple OSS Distributions }
12276e12aa3SApple OSS Distributions
123a5e72196SApple OSS Distributions if (kActionBlock & flags) {
124a5e72196SApple OSS Distributions ((IOTimerEventSource::ActionBlock) actionBlock)(ts);
125a5e72196SApple OSS Distributions } else {
126bb611c8fSApple OSS Distributions ((IOTimerEventSource::Action)_action)(_owner, ts);
127a5e72196SApple OSS Distributions }
128a5e72196SApple OSS Distributions
129a5e72196SApple OSS Distributions #if CONFIG_DTRACE
130bb611c8fSApple OSS Distributions DTRACE_TMR3(iotescallout__expire, Action, address, OSObject, _owner, void, _workLoop);
131a5e72196SApple OSS Distributions #endif
132a5e72196SApple OSS Distributions
133a5e72196SApple OSS Distributions if (trace) {
134a5e72196SApple OSS Distributions IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION),
135bb611c8fSApple OSS Distributions VM_KERNEL_UNSLIDE(address),
136bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(_owner));
137a5e72196SApple OSS Distributions }
138a5e72196SApple OSS Distributions }
139a5e72196SApple OSS Distributions
140a5e72196SApple OSS Distributions void
timeout(void * self)141a5e72196SApple OSS Distributions IOTimerEventSource::timeout(void *self)
142c1dac77fSApple OSS Distributions {
143c1dac77fSApple OSS Distributions IOTimerEventSource *me = (IOTimerEventSource *) self;
144c1dac77fSApple OSS Distributions
145855239e5SApple OSS Distributions IOStatisticsTimeout();
146855239e5SApple OSS Distributions
147a5e72196SApple OSS Distributions if (me->enabled && me->action) {
14814e3d835SApple OSS Distributions IOWorkLoop *
14914e3d835SApple OSS Distributions wl = me->workLoop;
150a5e72196SApple OSS Distributions if (wl) {
151bb611c8fSApple OSS Distributions IOEventSource::Action doit;
15214e3d835SApple OSS Distributions wl->closeGate();
153855239e5SApple OSS Distributions IOStatisticsCloseGate();
154bb611c8fSApple OSS Distributions doit = me->action;
155a5e72196SApple OSS Distributions if (doit && me->enabled && AbsoluteTime_to_scalar(&me->abstime)) {
156cc9a6355SApple OSS Distributions me->invokeAction(doit, me, me->owner, me->workLoop);
15714e3d835SApple OSS Distributions }
158855239e5SApple OSS Distributions IOStatisticsOpenGate();
15914e3d835SApple OSS Distributions wl->openGate();
160c1dac77fSApple OSS Distributions }
161c1dac77fSApple OSS Distributions }
162c1dac77fSApple OSS Distributions }
163c1dac77fSApple OSS Distributions
164a5e72196SApple OSS Distributions void
timeoutAndRelease(void * self,void * c)165a5e72196SApple OSS Distributions IOTimerEventSource::timeoutAndRelease(void * self, void * c)
16614e3d835SApple OSS Distributions {
16714e3d835SApple OSS Distributions IOTimerEventSource *me = (IOTimerEventSource *) self;
1683ca3bd55SApple OSS Distributions /* The second parameter (a pointer) gets abused to carry an SInt32, so on LP64, "count"
169a5e72196SApple OSS Distributions * must be cast to "long" before, in order to tell GCC we're not truncating a pointer. */
1703ca3bd55SApple OSS Distributions SInt32 count = (SInt32) (long) c;
17114e3d835SApple OSS Distributions
172855239e5SApple OSS Distributions IOStatisticsTimeout();
173855239e5SApple OSS Distributions
174a5e72196SApple OSS Distributions if (me->enabled && me->action) {
17514e3d835SApple OSS Distributions IOWorkLoop *
17614e3d835SApple OSS Distributions wl = me->reserved->workLoop;
177a5e72196SApple OSS Distributions if (wl) {
178bb611c8fSApple OSS Distributions IOEventSource::Action doit;
17914e3d835SApple OSS Distributions wl->closeGate();
180855239e5SApple OSS Distributions IOStatisticsCloseGate();
181bb611c8fSApple OSS Distributions doit = me->action;
182a5e72196SApple OSS Distributions if (doit && (me->reserved->calloutGeneration == count)) {
183bb611c8fSApple OSS Distributions thread_call_start_iotes_invocation((thread_call_t)me->calloutEntry);
184cc9a6355SApple OSS Distributions me->invokeAction(doit, me, me->owner, me->workLoop);
18514e3d835SApple OSS Distributions }
186855239e5SApple OSS Distributions IOStatisticsOpenGate();
18714e3d835SApple OSS Distributions wl->openGate();
18814e3d835SApple OSS Distributions }
18914e3d835SApple OSS Distributions }
190*e7776783SApple OSS Distributions if (me->reserved->workLoop) {
19114e3d835SApple OSS Distributions me->reserved->workLoop->release();
192*e7776783SApple OSS Distributions }
19314e3d835SApple OSS Distributions me->release();
19414e3d835SApple OSS Distributions }
19514e3d835SApple OSS Distributions
19676e12aa3SApple OSS Distributions // -- work loop delivery
19776e12aa3SApple OSS Distributions
198a5e72196SApple OSS Distributions bool
checkForWork()199a5e72196SApple OSS Distributions IOTimerEventSource::checkForWork()
20076e12aa3SApple OSS Distributions {
201bb611c8fSApple OSS Distributions IOEventSource::Action doit;
20276e12aa3SApple OSS Distributions
20376e12aa3SApple OSS Distributions if (reserved
20476e12aa3SApple OSS Distributions && (reserved->calloutGenerationSignaled == reserved->calloutGeneration)
205bb611c8fSApple OSS Distributions && enabled && (doit = action)) {
20676e12aa3SApple OSS Distributions reserved->calloutGenerationSignaled = ~reserved->calloutGeneration;
207cc9a6355SApple OSS Distributions invokeAction(doit, this, owner, workLoop);
20876e12aa3SApple OSS Distributions }
20976e12aa3SApple OSS Distributions
21076e12aa3SApple OSS Distributions return false;
21176e12aa3SApple OSS Distributions }
21276e12aa3SApple OSS Distributions
213a5e72196SApple OSS Distributions void
timeoutSignaled(void * self,void * c)214a5e72196SApple OSS Distributions IOTimerEventSource::timeoutSignaled(void * self, void * c)
21576e12aa3SApple OSS Distributions {
21676e12aa3SApple OSS Distributions IOTimerEventSource *me = (IOTimerEventSource *) self;
21776e12aa3SApple OSS Distributions
21876e12aa3SApple OSS Distributions me->reserved->calloutGenerationSignaled = (SInt32)(long) c;
219a5e72196SApple OSS Distributions if (me->enabled) {
220a5e72196SApple OSS Distributions me->signalWorkAvailable();
221a5e72196SApple OSS Distributions }
22276e12aa3SApple OSS Distributions }
22376e12aa3SApple OSS Distributions
22476e12aa3SApple OSS Distributions // --
22576e12aa3SApple OSS Distributions
226a5e72196SApple OSS Distributions void
setTimeoutFunc()227a5e72196SApple OSS Distributions IOTimerEventSource::setTimeoutFunc()
228c1dac77fSApple OSS Distributions {
22976e12aa3SApple OSS Distributions thread_call_priority_t pri;
23076e12aa3SApple OSS Distributions uint32_t options;
23176e12aa3SApple OSS Distributions
232a5e72196SApple OSS Distributions if (reserved) {
233a5e72196SApple OSS Distributions panic("setTimeoutFunc already %p, %p", this, reserved);
234a5e72196SApple OSS Distributions }
23576e12aa3SApple OSS Distributions
23614e3d835SApple OSS Distributions // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
23714e3d835SApple OSS Distributions // not a subclassed implementation
238e6231be0SApple OSS Distributions reserved = IOMallocType(ExpansionData);
239bb611c8fSApple OSS Distributions
24076e12aa3SApple OSS Distributions reserved->calloutGenerationSignaled = ~reserved->calloutGeneration;
241bb611c8fSApple OSS Distributions // make use of an existing ivar for parameter passing
242bb611c8fSApple OSS Distributions options = (uint32_t) abstime;
24376e12aa3SApple OSS Distributions abstime = 0;
24476e12aa3SApple OSS Distributions
24576e12aa3SApple OSS Distributions thread_call_options_t tcoptions = 0;
24676e12aa3SApple OSS Distributions thread_call_func_t func = NULL;
24776e12aa3SApple OSS Distributions
248a5e72196SApple OSS Distributions switch (kIOTimerEventSourceOptionsPriorityMask & options) {
24976e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityHigh:
25076e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_HIGH;
25176e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutAndRelease;
25276e12aa3SApple OSS Distributions break;
25376e12aa3SApple OSS Distributions
25476e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityKernel:
25576e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_KERNEL;
25676e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutAndRelease;
25776e12aa3SApple OSS Distributions break;
25876e12aa3SApple OSS Distributions
25976e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityKernelHigh:
26076e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_KERNEL_HIGH;
26176e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutAndRelease;
26276e12aa3SApple OSS Distributions break;
26376e12aa3SApple OSS Distributions
26476e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityUser:
26576e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_USER;
26676e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutAndRelease;
26776e12aa3SApple OSS Distributions break;
26876e12aa3SApple OSS Distributions
26976e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityLow:
27076e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_LOW;
27176e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutAndRelease;
27276e12aa3SApple OSS Distributions break;
27376e12aa3SApple OSS Distributions
27476e12aa3SApple OSS Distributions case kIOTimerEventSourceOptionsPriorityWorkLoop:
27576e12aa3SApple OSS Distributions pri = THREAD_CALL_PRIORITY_KERNEL;
27676e12aa3SApple OSS Distributions tcoptions |= THREAD_CALL_OPTIONS_SIGNAL;
277a5e72196SApple OSS Distributions if (kIOTimerEventSourceOptionsAllowReenter & options) {
278a5e72196SApple OSS Distributions break;
279a5e72196SApple OSS Distributions }
28076e12aa3SApple OSS Distributions func = &IOTimerEventSource::timeoutSignaled;
28176e12aa3SApple OSS Distributions break;
28276e12aa3SApple OSS Distributions
28376e12aa3SApple OSS Distributions default:
28476e12aa3SApple OSS Distributions break;
28576e12aa3SApple OSS Distributions }
28676e12aa3SApple OSS Distributions
28776e12aa3SApple OSS Distributions assertf(func, "IOTimerEventSource options 0x%x", options);
288a5e72196SApple OSS Distributions if (!func) {
289a5e72196SApple OSS Distributions return; // init will fail
290a5e72196SApple OSS Distributions }
291a5e72196SApple OSS Distributions if (THREAD_CALL_OPTIONS_SIGNAL & tcoptions) {
292a5e72196SApple OSS Distributions flags |= kActive;
293a5e72196SApple OSS Distributions } else {
294a5e72196SApple OSS Distributions flags |= kPassive;
295a5e72196SApple OSS Distributions }
29676e12aa3SApple OSS Distributions
297a5e72196SApple OSS Distributions if (!(kIOTimerEventSourceOptionsAllowReenter & options)) {
298a5e72196SApple OSS Distributions tcoptions |= THREAD_CALL_OPTIONS_ONCE;
299a5e72196SApple OSS Distributions }
30076e12aa3SApple OSS Distributions
30176e12aa3SApple OSS Distributions calloutEntry = (void *) thread_call_allocate_with_options(func,
30276e12aa3SApple OSS Distributions (thread_call_param_t) this, pri, tcoptions);
30376e12aa3SApple OSS Distributions assert(calloutEntry);
304c1dac77fSApple OSS Distributions }
305c1dac77fSApple OSS Distributions
306a5e72196SApple OSS Distributions bool
init(OSObject * inOwner,Action inAction)307a5e72196SApple OSS Distributions IOTimerEventSource::init(OSObject *inOwner, Action inAction)
308c1dac77fSApple OSS Distributions {
309a5e72196SApple OSS Distributions if (!super::init(inOwner, (IOEventSource::Action) inAction)) {
310c1dac77fSApple OSS Distributions return false;
311a5e72196SApple OSS Distributions }
312c1dac77fSApple OSS Distributions
313c1dac77fSApple OSS Distributions setTimeoutFunc();
314a5e72196SApple OSS Distributions if (!calloutEntry) {
315c1dac77fSApple OSS Distributions return false;
316a5e72196SApple OSS Distributions }
317c1dac77fSApple OSS Distributions
318855239e5SApple OSS Distributions IOStatisticsInitializeCounter();
319855239e5SApple OSS Distributions
320c1dac77fSApple OSS Distributions return true;
321c1dac77fSApple OSS Distributions }
322c1dac77fSApple OSS Distributions
323a5e72196SApple OSS Distributions bool
init(uint32_t options,OSObject * inOwner,Action inAction)324a5e72196SApple OSS Distributions IOTimerEventSource::init(uint32_t options, OSObject *inOwner, Action inAction)
32576e12aa3SApple OSS Distributions {
326bb611c8fSApple OSS Distributions // make use of an existing ivar for parameter passing
32776e12aa3SApple OSS Distributions abstime = options;
328a5e72196SApple OSS Distributions return init(inOwner, inAction);
32976e12aa3SApple OSS Distributions }
33076e12aa3SApple OSS Distributions
331c1dac77fSApple OSS Distributions IOTimerEventSource *
timerEventSource(uint32_t inOptions,OSObject * inOwner,Action inAction)33276e12aa3SApple OSS Distributions IOTimerEventSource::timerEventSource(uint32_t inOptions, OSObject *inOwner, Action inAction)
333c1dac77fSApple OSS Distributions {
334c1dac77fSApple OSS Distributions IOTimerEventSource *me = new IOTimerEventSource;
335c1dac77fSApple OSS Distributions
33676e12aa3SApple OSS Distributions if (me && !me->init(inOptions, inOwner, inAction)) {
337368ad365SApple OSS Distributions me->release();
338a5e72196SApple OSS Distributions return NULL;
339c1dac77fSApple OSS Distributions }
340c1dac77fSApple OSS Distributions
341c1dac77fSApple OSS Distributions return me;
342c1dac77fSApple OSS Distributions }
343c1dac77fSApple OSS Distributions
344cc9a6355SApple OSS Distributions IOTimerEventSource *
timerEventSource(uint32_t options,OSObject * inOwner,ActionBlock _action)345a5e72196SApple OSS Distributions IOTimerEventSource::timerEventSource(uint32_t options, OSObject *inOwner, ActionBlock _action)
346cc9a6355SApple OSS Distributions {
347cc9a6355SApple OSS Distributions IOTimerEventSource * tes;
348cc9a6355SApple OSS Distributions tes = IOTimerEventSource::timerEventSource(options, inOwner, (Action) NULL);
349a5e72196SApple OSS Distributions if (tes) {
350a5e72196SApple OSS Distributions tes->setActionBlock((IOEventSource::ActionBlock) _action);
351a5e72196SApple OSS Distributions }
352cc9a6355SApple OSS Distributions
353cc9a6355SApple OSS Distributions return tes;
354cc9a6355SApple OSS Distributions }
355cc9a6355SApple OSS Distributions
35676e12aa3SApple OSS Distributions #define _thread_call_cancel(tc) ((kActive & flags) ? thread_call_cancel_wait((tc)) : thread_call_cancel((tc)))
35776e12aa3SApple OSS Distributions
35876e12aa3SApple OSS Distributions IOTimerEventSource *
timerEventSource(OSObject * inOwner,Action inAction)35976e12aa3SApple OSS Distributions IOTimerEventSource::timerEventSource(OSObject *inOwner, Action inAction)
36076e12aa3SApple OSS Distributions {
361a5e72196SApple OSS Distributions return IOTimerEventSource::timerEventSource(
36276e12aa3SApple OSS Distributions kIOTimerEventSourceOptionsPriorityKernelHigh,
363a5e72196SApple OSS Distributions inOwner, inAction);
36476e12aa3SApple OSS Distributions }
36576e12aa3SApple OSS Distributions
366a5e72196SApple OSS Distributions void
free()367a5e72196SApple OSS Distributions IOTimerEventSource::free()
368c1dac77fSApple OSS Distributions {
369c1dac77fSApple OSS Distributions if (calloutEntry) {
37076e12aa3SApple OSS Distributions __assert_only bool freed;
37176e12aa3SApple OSS Distributions
372c1dac77fSApple OSS Distributions cancelTimeout();
37376e12aa3SApple OSS Distributions
37476e12aa3SApple OSS Distributions freed = thread_call_free((thread_call_t) calloutEntry);
37576e12aa3SApple OSS Distributions assert(freed);
376c1dac77fSApple OSS Distributions }
377c1dac77fSApple OSS Distributions
378a5e72196SApple OSS Distributions if (reserved) {
379e6231be0SApple OSS Distributions IOFreeType(reserved, ExpansionData);
380a5e72196SApple OSS Distributions }
38114e3d835SApple OSS Distributions
382c1dac77fSApple OSS Distributions super::free();
383c1dac77fSApple OSS Distributions }
384c1dac77fSApple OSS Distributions
385a5e72196SApple OSS Distributions void
cancelTimeout()386a5e72196SApple OSS Distributions IOTimerEventSource::cancelTimeout()
387c1dac77fSApple OSS Distributions {
388a5e72196SApple OSS Distributions if (reserved) {
38914e3d835SApple OSS Distributions reserved->calloutGeneration++;
390a5e72196SApple OSS Distributions }
39176e12aa3SApple OSS Distributions bool active = _thread_call_cancel((thread_call_t) calloutEntry);
392c1dac77fSApple OSS Distributions AbsoluteTime_to_scalar(&abstime) = 0;
393a5e72196SApple OSS Distributions if (active && reserved && (kPassive & flags)) {
39414e3d835SApple OSS Distributions release();
39514e3d835SApple OSS Distributions workLoop->release();
39614e3d835SApple OSS Distributions }
397c1dac77fSApple OSS Distributions }
398c1dac77fSApple OSS Distributions
399a5e72196SApple OSS Distributions void
enable()400a5e72196SApple OSS Distributions IOTimerEventSource::enable()
401c1dac77fSApple OSS Distributions {
402c1dac77fSApple OSS Distributions super::enable();
403a5e72196SApple OSS Distributions if (kIOReturnSuccess != wakeAtTime(abstime)) {
404c1dac77fSApple OSS Distributions super::disable(); // Problem re-scheduling timeout ignore enable
405c1dac77fSApple OSS Distributions }
406a5e72196SApple OSS Distributions }
407c1dac77fSApple OSS Distributions
408a5e72196SApple OSS Distributions void
disable()409a5e72196SApple OSS Distributions IOTimerEventSource::disable()
410c1dac77fSApple OSS Distributions {
411a5e72196SApple OSS Distributions if (reserved) {
41214e3d835SApple OSS Distributions reserved->calloutGeneration++;
413a5e72196SApple OSS Distributions }
41476e12aa3SApple OSS Distributions bool active = _thread_call_cancel((thread_call_t) calloutEntry);
415c1dac77fSApple OSS Distributions super::disable();
416a5e72196SApple OSS Distributions if (active && reserved && (kPassive & flags)) {
41714e3d835SApple OSS Distributions release();
41814e3d835SApple OSS Distributions workLoop->release();
41914e3d835SApple OSS Distributions }
420c1dac77fSApple OSS Distributions }
421c1dac77fSApple OSS Distributions
422a5e72196SApple OSS Distributions IOReturn
setTimeoutTicks(UInt32 ticks)423a5e72196SApple OSS Distributions IOTimerEventSource::setTimeoutTicks(UInt32 ticks)
424c1dac77fSApple OSS Distributions {
42514e3d835SApple OSS Distributions return setTimeout(ticks, kTickScale);
426c1dac77fSApple OSS Distributions }
427c1dac77fSApple OSS Distributions
428a5e72196SApple OSS Distributions IOReturn
setTimeoutMS(UInt32 ms)429a5e72196SApple OSS Distributions IOTimerEventSource::setTimeoutMS(UInt32 ms)
430c1dac77fSApple OSS Distributions {
431c1dac77fSApple OSS Distributions return setTimeout(ms, kMillisecondScale);
432c1dac77fSApple OSS Distributions }
433c1dac77fSApple OSS Distributions
434a5e72196SApple OSS Distributions IOReturn
setTimeoutUS(UInt32 us)435a5e72196SApple OSS Distributions IOTimerEventSource::setTimeoutUS(UInt32 us)
436c1dac77fSApple OSS Distributions {
437c1dac77fSApple OSS Distributions return setTimeout(us, kMicrosecondScale);
438c1dac77fSApple OSS Distributions }
439c1dac77fSApple OSS Distributions
440a5e72196SApple OSS Distributions IOReturn
setTimeout(UInt32 interval,UInt32 scale_factor)441a5e72196SApple OSS Distributions IOTimerEventSource::setTimeout(UInt32 interval, UInt32 scale_factor)
442c1dac77fSApple OSS Distributions {
443c1dac77fSApple OSS Distributions AbsoluteTime end;
444c1dac77fSApple OSS Distributions
445c1dac77fSApple OSS Distributions clock_interval_to_deadline(interval, scale_factor, &end);
446c1dac77fSApple OSS Distributions return wakeAtTime(end);
447c1dac77fSApple OSS Distributions }
448c1dac77fSApple OSS Distributions
4493ca3bd55SApple OSS Distributions #if !defined(__LP64__)
450a5e72196SApple OSS Distributions IOReturn
setTimeout(mach_timespec_t interval)451a5e72196SApple OSS Distributions IOTimerEventSource::setTimeout(mach_timespec_t interval)
452c1dac77fSApple OSS Distributions {
453c1dac77fSApple OSS Distributions AbsoluteTime end, nsecs;
454c1dac77fSApple OSS Distributions
455c1dac77fSApple OSS Distributions clock_interval_to_absolutetime_interval
456c1dac77fSApple OSS Distributions (interval.tv_nsec, kNanosecondScale, &nsecs);
457c1dac77fSApple OSS Distributions clock_interval_to_deadline
458c1dac77fSApple OSS Distributions (interval.tv_sec, NSEC_PER_SEC, &end);
459c1dac77fSApple OSS Distributions ADD_ABSOLUTETIME(&end, &nsecs);
460c1dac77fSApple OSS Distributions
461c1dac77fSApple OSS Distributions return wakeAtTime(end);
462c1dac77fSApple OSS Distributions }
4633ca3bd55SApple OSS Distributions #endif
464c1dac77fSApple OSS Distributions
465a5e72196SApple OSS Distributions IOReturn
setTimeout(AbsoluteTime interval)466a5e72196SApple OSS Distributions IOTimerEventSource::setTimeout(AbsoluteTime interval)
467c1dac77fSApple OSS Distributions {
468c1dac77fSApple OSS Distributions AbsoluteTime end;
46976e12aa3SApple OSS Distributions clock_absolutetime_interval_to_deadline(interval, &end);
470c1dac77fSApple OSS Distributions return wakeAtTime(end);
471c1dac77fSApple OSS Distributions }
472c1dac77fSApple OSS Distributions
473a5e72196SApple OSS Distributions IOReturn
setTimeout(uint32_t options,AbsoluteTime abstime,AbsoluteTime leeway)474a5e72196SApple OSS Distributions IOTimerEventSource::setTimeout(uint32_t options,
47576e12aa3SApple OSS Distributions AbsoluteTime abstime, AbsoluteTime leeway)
47676e12aa3SApple OSS Distributions {
47776e12aa3SApple OSS Distributions AbsoluteTime end;
478a5e72196SApple OSS Distributions if (options & kIOTimeOptionsContinuous) {
47976e12aa3SApple OSS Distributions clock_continuoustime_interval_to_deadline(abstime, &end);
480a5e72196SApple OSS Distributions } else {
481cc9a6355SApple OSS Distributions clock_absolutetime_interval_to_deadline(abstime, &end);
482a5e72196SApple OSS Distributions }
48376e12aa3SApple OSS Distributions
484cc9a6355SApple OSS Distributions return wakeAtTime(options, end, leeway);
48576e12aa3SApple OSS Distributions }
48676e12aa3SApple OSS Distributions
487a5e72196SApple OSS Distributions IOReturn
wakeAtTimeTicks(UInt32 ticks)488a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks)
489c1dac77fSApple OSS Distributions {
49014e3d835SApple OSS Distributions return wakeAtTime(ticks, kTickScale);
491c1dac77fSApple OSS Distributions }
492c1dac77fSApple OSS Distributions
493a5e72196SApple OSS Distributions IOReturn
wakeAtTimeMS(UInt32 ms)494a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTimeMS(UInt32 ms)
495c1dac77fSApple OSS Distributions {
496c1dac77fSApple OSS Distributions return wakeAtTime(ms, kMillisecondScale);
497c1dac77fSApple OSS Distributions }
498c1dac77fSApple OSS Distributions
499a5e72196SApple OSS Distributions IOReturn
wakeAtTimeUS(UInt32 us)500a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTimeUS(UInt32 us)
501c1dac77fSApple OSS Distributions {
502c1dac77fSApple OSS Distributions return wakeAtTime(us, kMicrosecondScale);
503c1dac77fSApple OSS Distributions }
504c1dac77fSApple OSS Distributions
505a5e72196SApple OSS Distributions IOReturn
wakeAtTime(UInt32 inAbstime,UInt32 scale_factor)506a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTime(UInt32 inAbstime, UInt32 scale_factor)
507c1dac77fSApple OSS Distributions {
508c1dac77fSApple OSS Distributions AbsoluteTime end;
50914e3d835SApple OSS Distributions clock_interval_to_absolutetime_interval(inAbstime, scale_factor, &end);
510c1dac77fSApple OSS Distributions
511c1dac77fSApple OSS Distributions return wakeAtTime(end);
512c1dac77fSApple OSS Distributions }
513c1dac77fSApple OSS Distributions
5143ca3bd55SApple OSS Distributions #if !defined(__LP64__)
515a5e72196SApple OSS Distributions IOReturn
wakeAtTime(mach_timespec_t inAbstime)516a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime)
517c1dac77fSApple OSS Distributions {
518c1dac77fSApple OSS Distributions AbsoluteTime end, nsecs;
519c1dac77fSApple OSS Distributions
520c1dac77fSApple OSS Distributions clock_interval_to_absolutetime_interval
52114e3d835SApple OSS Distributions (inAbstime.tv_nsec, kNanosecondScale, &nsecs);
522c1dac77fSApple OSS Distributions clock_interval_to_absolutetime_interval
52314e3d835SApple OSS Distributions (inAbstime.tv_sec, kSecondScale, &end);
524c1dac77fSApple OSS Distributions ADD_ABSOLUTETIME(&end, &nsecs);
525c1dac77fSApple OSS Distributions
526c1dac77fSApple OSS Distributions return wakeAtTime(end);
527c1dac77fSApple OSS Distributions }
5283ca3bd55SApple OSS Distributions #endif
529c1dac77fSApple OSS Distributions
530a5e72196SApple OSS Distributions void
setWorkLoop(IOWorkLoop * inWorkLoop)531a5e72196SApple OSS Distributions IOTimerEventSource::setWorkLoop(IOWorkLoop *inWorkLoop)
53214e3d835SApple OSS Distributions {
53314e3d835SApple OSS Distributions super::setWorkLoop(inWorkLoop);
534a5e72196SApple OSS Distributions if (enabled && AbsoluteTime_to_scalar(&abstime) && workLoop) {
53514e3d835SApple OSS Distributions wakeAtTime(abstime);
53614e3d835SApple OSS Distributions }
537a5e72196SApple OSS Distributions }
53814e3d835SApple OSS Distributions
539a5e72196SApple OSS Distributions IOReturn
wakeAtTime(AbsoluteTime inAbstime)540a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime)
541c1dac77fSApple OSS Distributions {
54276e12aa3SApple OSS Distributions return wakeAtTime(0, inAbstime, 0);
54376e12aa3SApple OSS Distributions }
54476e12aa3SApple OSS Distributions
545a5e72196SApple OSS Distributions IOReturn
wakeAtTime(uint32_t options,AbsoluteTime inAbstime,AbsoluteTime leeway)546a5e72196SApple OSS Distributions IOTimerEventSource::wakeAtTime(uint32_t options, AbsoluteTime inAbstime, AbsoluteTime leeway)
54776e12aa3SApple OSS Distributions {
548a5e72196SApple OSS Distributions if (!action) {
549c1dac77fSApple OSS Distributions return kIOReturnNoResources;
550a5e72196SApple OSS Distributions }
551c1dac77fSApple OSS Distributions
552c1dac77fSApple OSS Distributions abstime = inAbstime;
553a5e72196SApple OSS Distributions if (enabled && AbsoluteTime_to_scalar(&inAbstime) && AbsoluteTime_to_scalar(&abstime) && workLoop) {
55476e12aa3SApple OSS Distributions uint32_t tcoptions = 0;
55576e12aa3SApple OSS Distributions
556a5e72196SApple OSS Distributions if (kIOTimeOptionsWithLeeway & options) {
557a5e72196SApple OSS Distributions tcoptions |= THREAD_CALL_DELAY_LEEWAY;
558a5e72196SApple OSS Distributions }
559a5e72196SApple OSS Distributions if (kIOTimeOptionsContinuous & options) {
560a5e72196SApple OSS Distributions tcoptions |= THREAD_CALL_CONTINUOUS;
561a5e72196SApple OSS Distributions }
56276e12aa3SApple OSS Distributions
563a5e72196SApple OSS Distributions if (reserved) {
564a5e72196SApple OSS Distributions if (kPassive & flags) {
56514e3d835SApple OSS Distributions retain();
56614e3d835SApple OSS Distributions workLoop->retain();
56776e12aa3SApple OSS Distributions }
56814e3d835SApple OSS Distributions reserved->workLoop = workLoop;
56914e3d835SApple OSS Distributions reserved->calloutGeneration++;
57076e12aa3SApple OSS Distributions if (thread_call_enter_delayed_with_leeway((thread_call_t) calloutEntry,
57176e12aa3SApple OSS Distributions (void *)(uintptr_t) reserved->calloutGeneration, inAbstime, leeway, tcoptions)
572a5e72196SApple OSS Distributions && (kPassive & flags)) {
57314e3d835SApple OSS Distributions release();
57414e3d835SApple OSS Distributions workLoop->release();
57514e3d835SApple OSS Distributions }
576a5e72196SApple OSS Distributions } else {
57776e12aa3SApple OSS Distributions thread_call_enter_delayed_with_leeway((thread_call_t) calloutEntry,
57876e12aa3SApple OSS Distributions NULL, inAbstime, leeway, tcoptions);
57976e12aa3SApple OSS Distributions }
58014e3d835SApple OSS Distributions }
581c1dac77fSApple OSS Distributions
582c1dac77fSApple OSS Distributions return kIOReturnSuccess;
583c1dac77fSApple OSS Distributions }
584