]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOTimerEventSource.cpp
xnu-792.25.20.tar.gz
[apple/xnu.git] / iokit / Kernel / IOTimerEventSource.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
8f6c56a5 11 *
6601e61a
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/*
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24 *
25 * IOTimerEventSource.cpp
26 *
27 * HISTORY
28 * 2-Feb-1999 Joe Liu (jliu) created.
29 * 1999-10-14 Godfrey van der Linden(gvdl)
30 * Revamped to use thread_call APIs
31 *
32 */
33
34#include <sys/cdefs.h>
35
36__BEGIN_DECLS
37#include <kern/thread_call.h>
38__END_DECLS
39
40#include <IOKit/assert.h>
41#include <IOKit/system.h>
42
43#include <IOKit/IOLib.h>
44#include <IOKit/IOTimerEventSource.h>
45#include <IOKit/IOWorkLoop.h>
46
47#include <IOKit/IOTimeStamp.h>
48
49#define super IOEventSource
50OSDefineMetaClassAndStructors(IOTimerEventSource, IOEventSource)
51OSMetaClassDefineReservedUnused(IOTimerEventSource, 0);
52OSMetaClassDefineReservedUnused(IOTimerEventSource, 1);
53OSMetaClassDefineReservedUnused(IOTimerEventSource, 2);
54OSMetaClassDefineReservedUnused(IOTimerEventSource, 3);
55OSMetaClassDefineReservedUnused(IOTimerEventSource, 4);
56OSMetaClassDefineReservedUnused(IOTimerEventSource, 5);
57OSMetaClassDefineReservedUnused(IOTimerEventSource, 6);
58OSMetaClassDefineReservedUnused(IOTimerEventSource, 7);
59
91447636
A
60//
61// reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
62// not a subclassed implementation.
63//
64
1c79356b
A
65bool IOTimerEventSource::checkForWork() { return false; }
66
67// Timeout handler function. This function is called by the kernel when
68// the timeout interval expires.
69//
70void IOTimerEventSource::timeout(void *self)
71{
72 IOTimerEventSource *me = (IOTimerEventSource *) self;
73
91447636
A
74 if (me->enabled && me->action)
75 {
76 IOWorkLoop *
77 wl = me->workLoop;
78 if (wl)
79 {
80 Action doit;
81 wl->closeGate();
82 doit = (Action) me->action;
83 if (doit && me->enabled && AbsoluteTime_to_scalar(&me->abstime))
84 {
85 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION),
86 (unsigned int) doit, (unsigned int) me->owner);
87 (*doit)(me->owner, me);
88 }
89 wl->openGate();
90 }
91 }
92}
1c79356b 93
91447636
A
94void IOTimerEventSource::timeoutAndRelease(void * self, void * count)
95{
96 IOTimerEventSource *me = (IOTimerEventSource *) self;
97
98 if (me->enabled && me->action)
99 {
100 IOWorkLoop *
101 wl = me->reserved->workLoop;
102 if (wl)
103 {
104 Action doit;
105 wl->closeGate();
106 doit = (Action) me->action;
107 if (doit && (me->reserved->calloutGeneration == (SInt32) count))
108 {
109 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION),
110 (unsigned int) doit, (unsigned int) me->owner);
111 (*doit)(me->owner, me);
112 }
113 wl->openGate();
1c79356b
A
114 }
115 }
91447636
A
116
117 me->reserved->workLoop->release();
118 me->release();
1c79356b
A
119}
120
121void IOTimerEventSource::setTimeoutFunc()
122{
91447636
A
123 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
124 // not a subclassed implementation
125 reserved = IONew(ExpansionData, 1);
126 calloutEntry = (void *) thread_call_allocate((thread_call_func_t) &IOTimerEventSource::timeoutAndRelease,
1c79356b
A
127 (thread_call_param_t) this);
128}
129
130bool IOTimerEventSource::init(OSObject *inOwner, Action inAction)
131{
132 if (!super::init(inOwner, (IOEventSource::Action) inAction) )
133 return false;
134
135 setTimeoutFunc();
136 if (!calloutEntry)
137 return false;
138
139 return true;
140}
141
142IOTimerEventSource *
143IOTimerEventSource::timerEventSource(OSObject *inOwner, Action inAction)
144{
145 IOTimerEventSource *me = new IOTimerEventSource;
146
147 if (me && !me->init(inOwner, inAction)) {
55e303ae 148 me->release();
1c79356b
A
149 return 0;
150 }
151
152 return me;
153}
154
155void IOTimerEventSource::free()
156{
157 if (calloutEntry) {
158 cancelTimeout();
159 thread_call_free((thread_call_t) calloutEntry);
160 }
161
91447636
A
162 if (reserved)
163 IODelete(reserved, ExpansionData, 1);
164
1c79356b
A
165 super::free();
166}
167
168void IOTimerEventSource::cancelTimeout()
169{
91447636
A
170 if (reserved)
171 reserved->calloutGeneration++;
172 bool active = thread_call_cancel((thread_call_t) calloutEntry);
1c79356b 173 AbsoluteTime_to_scalar(&abstime) = 0;
91447636
A
174 if (active && reserved)
175 {
176 release();
177 workLoop->release();
178 }
1c79356b
A
179}
180
181void IOTimerEventSource::enable()
182{
183 super::enable();
184 if (kIOReturnSuccess != wakeAtTime(abstime))
185 super::disable(); // Problem re-scheduling timeout ignore enable
186}
187
188void IOTimerEventSource::disable()
189{
91447636
A
190 if (reserved)
191 reserved->calloutGeneration++;
192 bool active = thread_call_cancel((thread_call_t) calloutEntry);
1c79356b 193 super::disable();
91447636
A
194 if (active && reserved)
195 {
196 release();
197 workLoop->release();
198 }
1c79356b
A
199}
200
201IOReturn IOTimerEventSource::setTimeoutTicks(UInt32 ticks)
202{
91447636 203 return setTimeout(ticks, kTickScale);
1c79356b
A
204}
205
206IOReturn IOTimerEventSource::setTimeoutMS(UInt32 ms)
207{
208 return setTimeout(ms, kMillisecondScale);
209}
210
211IOReturn IOTimerEventSource::setTimeoutUS(UInt32 us)
212{
213 return setTimeout(us, kMicrosecondScale);
214}
215
216IOReturn IOTimerEventSource::setTimeout(UInt32 interval, UInt32 scale_factor)
217{
218 AbsoluteTime end;
219
220 clock_interval_to_deadline(interval, scale_factor, &end);
221 return wakeAtTime(end);
222}
223
224IOReturn IOTimerEventSource::setTimeout(mach_timespec_t interval)
225{
226 AbsoluteTime end, nsecs;
227
228 clock_interval_to_absolutetime_interval
229 (interval.tv_nsec, kNanosecondScale, &nsecs);
230 clock_interval_to_deadline
231 (interval.tv_sec, NSEC_PER_SEC, &end);
232 ADD_ABSOLUTETIME(&end, &nsecs);
233
234 return wakeAtTime(end);
235}
236
237IOReturn IOTimerEventSource::setTimeout(AbsoluteTime interval)
238{
239 AbsoluteTime end;
240
241 clock_get_uptime(&end);
242 ADD_ABSOLUTETIME(&end, &interval);
243
244 return wakeAtTime(end);
245}
246
247IOReturn IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks)
248{
91447636 249 return wakeAtTime(ticks, kTickScale);
1c79356b
A
250}
251
252IOReturn IOTimerEventSource::wakeAtTimeMS(UInt32 ms)
253{
254 return wakeAtTime(ms, kMillisecondScale);
255}
256
257IOReturn IOTimerEventSource::wakeAtTimeUS(UInt32 us)
258{
259 return wakeAtTime(us, kMicrosecondScale);
260}
261
91447636 262IOReturn IOTimerEventSource::wakeAtTime(UInt32 inAbstime, UInt32 scale_factor)
1c79356b
A
263{
264 AbsoluteTime end;
91447636 265 clock_interval_to_absolutetime_interval(inAbstime, scale_factor, &end);
1c79356b
A
266
267 return wakeAtTime(end);
268}
269
91447636 270IOReturn IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime)
1c79356b
A
271{
272 AbsoluteTime end, nsecs;
273
274 clock_interval_to_absolutetime_interval
91447636 275 (inAbstime.tv_nsec, kNanosecondScale, &nsecs);
1c79356b 276 clock_interval_to_absolutetime_interval
91447636 277 (inAbstime.tv_sec, kSecondScale, &end);
1c79356b
A
278 ADD_ABSOLUTETIME(&end, &nsecs);
279
280 return wakeAtTime(end);
281}
282
91447636
A
283void IOTimerEventSource::setWorkLoop(IOWorkLoop *inWorkLoop)
284{
285 super::setWorkLoop(inWorkLoop);
286 if ( enabled && AbsoluteTime_to_scalar(&abstime) && workLoop )
287 wakeAtTime(abstime);
288}
289
1c79356b
A
290IOReturn IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime)
291{
292 if (!action)
293 return kIOReturnNoResources;
294
295 abstime = inAbstime;
91447636
A
296 if ( enabled && AbsoluteTime_to_scalar(&abstime) && workLoop )
297 {
298 if (reserved)
299 {
300 retain();
301 workLoop->retain();
302 reserved->workLoop = workLoop;
303 reserved->calloutGeneration++;
304 if (thread_call_enter1_delayed((thread_call_t) calloutEntry,
305 (void *) reserved->calloutGeneration, abstime))
306 {
307 release();
308 workLoop->release();
309 }
310 }
311 else
312 thread_call_enter_delayed((thread_call_t) calloutEntry, abstime);
313 }
1c79356b
A
314
315 return kIOReturnSuccess;
316}