]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOTimerEventSource.cpp
3c86e67090c91405814dfb5e706466d57ede6579
[apple/xnu.git] / iokit / Kernel / IOTimerEventSource.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
27 *
28 * IOTimerEventSource.cpp
29 *
30 * HISTORY
31 * 2-Feb-1999 Joe Liu (jliu) created.
32 * 1999-10-14 Godfrey van der Linden(gvdl)
33 * Revamped to use thread_call APIs
34 *
35 */
36
37 #include <sys/cdefs.h>
38
39 __BEGIN_DECLS
40 #include <kern/thread_call.h>
41 __END_DECLS
42
43 #include <IOKit/assert.h>
44 #include <IOKit/system.h>
45
46 #include <IOKit/IOLib.h>
47 #include <IOKit/IOTimerEventSource.h>
48 #include <IOKit/IOWorkLoop.h>
49
50 #include <IOKit/IOTimeStamp.h>
51
52 #define super IOEventSource
53 OSDefineMetaClassAndStructors(IOTimerEventSource, IOEventSource)
54 OSMetaClassDefineReservedUnused(IOTimerEventSource, 0);
55 OSMetaClassDefineReservedUnused(IOTimerEventSource, 1);
56 OSMetaClassDefineReservedUnused(IOTimerEventSource, 2);
57 OSMetaClassDefineReservedUnused(IOTimerEventSource, 3);
58 OSMetaClassDefineReservedUnused(IOTimerEventSource, 4);
59 OSMetaClassDefineReservedUnused(IOTimerEventSource, 5);
60 OSMetaClassDefineReservedUnused(IOTimerEventSource, 6);
61 OSMetaClassDefineReservedUnused(IOTimerEventSource, 7);
62
63 bool IOTimerEventSource::checkForWork() { return false; }
64
65 // Timeout handler function. This function is called by the kernel when
66 // the timeout interval expires.
67 //
68 void IOTimerEventSource::timeout(void *self)
69 {
70 IOTimerEventSource *me = (IOTimerEventSource *) self;
71
72 if (me->enabled) {
73 Action doit = (Action) me->action;
74
75 if (doit) {
76 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION),
77 (unsigned int) doit, (unsigned int) me->owner);
78 me->closeGate();
79 (*doit)(me->owner, me);
80 me->openGate();
81 }
82 }
83 }
84
85 void IOTimerEventSource::setTimeoutFunc()
86 {
87 calloutEntry = (void *) thread_call_allocate((thread_call_func_t) timeout,
88 (thread_call_param_t) this);
89 }
90
91 bool IOTimerEventSource::init(OSObject *inOwner, Action inAction)
92 {
93 if (!super::init(inOwner, (IOEventSource::Action) inAction) )
94 return false;
95
96 setTimeoutFunc();
97 if (!calloutEntry)
98 return false;
99
100 return true;
101 }
102
103 IOTimerEventSource *
104 IOTimerEventSource::timerEventSource(OSObject *inOwner, Action inAction)
105 {
106 IOTimerEventSource *me = new IOTimerEventSource;
107
108 if (me && !me->init(inOwner, inAction)) {
109 me->free();
110 return 0;
111 }
112
113 return me;
114 }
115
116 void IOTimerEventSource::free()
117 {
118 if (calloutEntry) {
119 cancelTimeout();
120 thread_call_free((thread_call_t) calloutEntry);
121 }
122
123 super::free();
124 }
125
126 void IOTimerEventSource::cancelTimeout()
127 {
128 thread_call_cancel((thread_call_t) calloutEntry);
129 AbsoluteTime_to_scalar(&abstime) = 0;
130 }
131
132 void IOTimerEventSource::enable()
133 {
134 super::enable();
135 if (kIOReturnSuccess != wakeAtTime(abstime))
136 super::disable(); // Problem re-scheduling timeout ignore enable
137 }
138
139 void IOTimerEventSource::disable()
140 {
141 thread_call_cancel((thread_call_t) calloutEntry);
142 super::disable();
143 }
144
145 IOReturn IOTimerEventSource::setTimeoutTicks(UInt32 ticks)
146 {
147 return setTimeout(ticks, NSEC_PER_SEC/hz);
148 }
149
150 IOReturn IOTimerEventSource::setTimeoutMS(UInt32 ms)
151 {
152 return setTimeout(ms, kMillisecondScale);
153 }
154
155 IOReturn IOTimerEventSource::setTimeoutUS(UInt32 us)
156 {
157 return setTimeout(us, kMicrosecondScale);
158 }
159
160 IOReturn IOTimerEventSource::setTimeout(UInt32 interval, UInt32 scale_factor)
161 {
162 AbsoluteTime end;
163
164 clock_interval_to_deadline(interval, scale_factor, &end);
165 return wakeAtTime(end);
166 }
167
168 IOReturn IOTimerEventSource::setTimeout(mach_timespec_t interval)
169 {
170 AbsoluteTime end, nsecs;
171
172 clock_interval_to_absolutetime_interval
173 (interval.tv_nsec, kNanosecondScale, &nsecs);
174 clock_interval_to_deadline
175 (interval.tv_sec, NSEC_PER_SEC, &end);
176 ADD_ABSOLUTETIME(&end, &nsecs);
177
178 return wakeAtTime(end);
179 }
180
181 IOReturn IOTimerEventSource::setTimeout(AbsoluteTime interval)
182 {
183 AbsoluteTime end;
184
185 clock_get_uptime(&end);
186 ADD_ABSOLUTETIME(&end, &interval);
187
188 return wakeAtTime(end);
189 }
190
191 IOReturn IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks)
192 {
193 return wakeAtTime(ticks, NSEC_PER_SEC/hz);
194 }
195
196 IOReturn IOTimerEventSource::wakeAtTimeMS(UInt32 ms)
197 {
198 return wakeAtTime(ms, kMillisecondScale);
199 }
200
201 IOReturn IOTimerEventSource::wakeAtTimeUS(UInt32 us)
202 {
203 return wakeAtTime(us, kMicrosecondScale);
204 }
205
206 IOReturn IOTimerEventSource::wakeAtTime(UInt32 abstime, UInt32 scale_factor)
207 {
208 AbsoluteTime end;
209 clock_interval_to_absolutetime_interval(abstime, scale_factor, &end);
210
211 return wakeAtTime(end);
212 }
213
214 IOReturn IOTimerEventSource::wakeAtTime(mach_timespec_t abstime)
215 {
216 AbsoluteTime end, nsecs;
217
218 clock_interval_to_absolutetime_interval
219 (abstime.tv_nsec, kNanosecondScale, &nsecs);
220 clock_interval_to_absolutetime_interval
221 (abstime.tv_sec, kSecondScale, &end);
222 ADD_ABSOLUTETIME(&end, &nsecs);
223
224 return wakeAtTime(end);
225 }
226
227 IOReturn IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime)
228 {
229 if (!action)
230 return kIOReturnNoResources;
231
232 abstime = inAbstime;
233 if ( enabled && AbsoluteTime_to_scalar(&abstime) )
234 thread_call_enter_delayed((thread_call_t) calloutEntry, abstime);
235
236 return kIOReturnSuccess;
237 }