2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
26 * IOTimerEventSource.cpp
29 * 2-Feb-1999 Joe Liu (jliu) created.
30 * 1999-10-14 Godfrey van der Linden(gvdl)
31 * Revamped to use thread_call APIs
35 #include <sys/cdefs.h>
38 #include <kern/thread_call.h>
41 #include <IOKit/assert.h>
42 #include <IOKit/system.h>
44 #include <IOKit/IOLib.h>
45 #include <IOKit/IOTimerEventSource.h>
46 #include <IOKit/IOWorkLoop.h>
48 #include <IOKit/IOTimeStamp.h>
50 #define super IOEventSource
51 OSDefineMetaClassAndStructors(IOTimerEventSource
, IOEventSource
)
52 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 0);
53 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 1);
54 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 2);
55 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 3);
56 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 4);
57 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 5);
58 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 6);
59 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 7);
62 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
63 // not a subclassed implementation.
66 bool IOTimerEventSource::checkForWork() { return false; }
68 // Timeout handler function. This function is called by the kernel when
69 // the timeout interval expires.
71 void IOTimerEventSource::timeout(void *self
)
73 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
75 if (me
->enabled
&& me
->action
)
83 doit
= (Action
) me
->action
;
84 if (doit
&& me
->enabled
&& AbsoluteTime_to_scalar(&me
->abstime
))
86 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
87 (unsigned int) doit
, (unsigned int) me
->owner
);
88 (*doit
)(me
->owner
, me
);
95 void IOTimerEventSource::timeoutAndRelease(void * self
, void * count
)
97 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
99 if (me
->enabled
&& me
->action
)
102 wl
= me
->reserved
->workLoop
;
107 doit
= (Action
) me
->action
;
108 if (doit
&& (me
->reserved
->calloutGeneration
== (SInt32
) count
))
110 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
111 (unsigned int) doit
, (unsigned int) me
->owner
);
112 (*doit
)(me
->owner
, me
);
118 me
->reserved
->workLoop
->release();
122 void IOTimerEventSource::setTimeoutFunc()
124 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
125 // not a subclassed implementation
126 reserved
= IONew(ExpansionData
, 1);
127 calloutEntry
= (void *) thread_call_allocate((thread_call_func_t
) &IOTimerEventSource::timeoutAndRelease
,
128 (thread_call_param_t
) this);
131 bool IOTimerEventSource::init(OSObject
*inOwner
, Action inAction
)
133 if (!super::init(inOwner
, (IOEventSource::Action
) inAction
) )
144 IOTimerEventSource::timerEventSource(OSObject
*inOwner
, Action inAction
)
146 IOTimerEventSource
*me
= new IOTimerEventSource
;
148 if (me
&& !me
->init(inOwner
, inAction
)) {
156 void IOTimerEventSource::free()
160 thread_call_free((thread_call_t
) calloutEntry
);
164 IODelete(reserved
, ExpansionData
, 1);
169 void IOTimerEventSource::cancelTimeout()
172 reserved
->calloutGeneration
++;
173 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
174 AbsoluteTime_to_scalar(&abstime
) = 0;
175 if (active
&& reserved
)
182 void IOTimerEventSource::enable()
185 if (kIOReturnSuccess
!= wakeAtTime(abstime
))
186 super::disable(); // Problem re-scheduling timeout ignore enable
189 void IOTimerEventSource::disable()
192 reserved
->calloutGeneration
++;
193 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
195 if (active
&& reserved
)
202 IOReturn
IOTimerEventSource::setTimeoutTicks(UInt32 ticks
)
204 return setTimeout(ticks
, kTickScale
);
207 IOReturn
IOTimerEventSource::setTimeoutMS(UInt32 ms
)
209 return setTimeout(ms
, kMillisecondScale
);
212 IOReturn
IOTimerEventSource::setTimeoutUS(UInt32 us
)
214 return setTimeout(us
, kMicrosecondScale
);
217 IOReturn
IOTimerEventSource::setTimeout(UInt32 interval
, UInt32 scale_factor
)
221 clock_interval_to_deadline(interval
, scale_factor
, &end
);
222 return wakeAtTime(end
);
225 IOReturn
IOTimerEventSource::setTimeout(mach_timespec_t interval
)
227 AbsoluteTime end
, nsecs
;
229 clock_interval_to_absolutetime_interval
230 (interval
.tv_nsec
, kNanosecondScale
, &nsecs
);
231 clock_interval_to_deadline
232 (interval
.tv_sec
, NSEC_PER_SEC
, &end
);
233 ADD_ABSOLUTETIME(&end
, &nsecs
);
235 return wakeAtTime(end
);
238 IOReturn
IOTimerEventSource::setTimeout(AbsoluteTime interval
)
242 clock_get_uptime(&end
);
243 ADD_ABSOLUTETIME(&end
, &interval
);
245 return wakeAtTime(end
);
248 IOReturn
IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks
)
250 return wakeAtTime(ticks
, kTickScale
);
253 IOReturn
IOTimerEventSource::wakeAtTimeMS(UInt32 ms
)
255 return wakeAtTime(ms
, kMillisecondScale
);
258 IOReturn
IOTimerEventSource::wakeAtTimeUS(UInt32 us
)
260 return wakeAtTime(us
, kMicrosecondScale
);
263 IOReturn
IOTimerEventSource::wakeAtTime(UInt32 inAbstime
, UInt32 scale_factor
)
266 clock_interval_to_absolutetime_interval(inAbstime
, scale_factor
, &end
);
268 return wakeAtTime(end
);
271 IOReturn
IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime
)
273 AbsoluteTime end
, nsecs
;
275 clock_interval_to_absolutetime_interval
276 (inAbstime
.tv_nsec
, kNanosecondScale
, &nsecs
);
277 clock_interval_to_absolutetime_interval
278 (inAbstime
.tv_sec
, kSecondScale
, &end
);
279 ADD_ABSOLUTETIME(&end
, &nsecs
);
281 return wakeAtTime(end
);
284 void IOTimerEventSource::setWorkLoop(IOWorkLoop
*inWorkLoop
)
286 super::setWorkLoop(inWorkLoop
);
287 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
291 IOReturn
IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime
)
294 return kIOReturnNoResources
;
297 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
303 reserved
->workLoop
= workLoop
;
304 reserved
->calloutGeneration
++;
305 if (thread_call_enter1_delayed((thread_call_t
) calloutEntry
,
306 (void *) reserved
->calloutGeneration
, abstime
))
313 thread_call_enter_delayed((thread_call_t
) calloutEntry
, abstime
);
316 return kIOReturnSuccess
;