2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
33 * IOTimerEventSource.cpp
36 * 2-Feb-1999 Joe Liu (jliu) created.
37 * 1999-10-14 Godfrey van der Linden(gvdl)
38 * Revamped to use thread_call APIs
42 #include <sys/cdefs.h>
45 #include <kern/thread_call.h>
48 #include <IOKit/assert.h>
49 #include <IOKit/system.h>
51 #include <IOKit/IOLib.h>
52 #include <IOKit/IOTimerEventSource.h>
53 #include <IOKit/IOWorkLoop.h>
55 #include <IOKit/IOTimeStamp.h>
57 #define super IOEventSource
58 OSDefineMetaClassAndStructors(IOTimerEventSource
, IOEventSource
)
59 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 0);
60 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 1);
61 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 2);
62 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 3);
63 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 4);
64 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 5);
65 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 6);
66 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 7);
69 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
70 // not a subclassed implementation.
73 bool IOTimerEventSource::checkForWork() { return false; }
75 // Timeout handler function. This function is called by the kernel when
76 // the timeout interval expires.
78 void IOTimerEventSource::timeout(void *self
)
80 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
82 if (me
->enabled
&& me
->action
)
90 doit
= (Action
) me
->action
;
91 if (doit
&& me
->enabled
&& AbsoluteTime_to_scalar(&me
->abstime
))
93 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
94 (unsigned int) doit
, (unsigned int) me
->owner
);
95 (*doit
)(me
->owner
, me
);
102 void IOTimerEventSource::timeoutAndRelease(void * self
, void * count
)
104 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
106 if (me
->enabled
&& me
->action
)
109 wl
= me
->reserved
->workLoop
;
114 doit
= (Action
) me
->action
;
115 if (doit
&& (me
->reserved
->calloutGeneration
== (SInt32
) count
))
117 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
118 (unsigned int) doit
, (unsigned int) me
->owner
);
119 (*doit
)(me
->owner
, me
);
125 me
->reserved
->workLoop
->release();
129 void IOTimerEventSource::setTimeoutFunc()
131 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
132 // not a subclassed implementation
133 reserved
= IONew(ExpansionData
, 1);
134 calloutEntry
= (void *) thread_call_allocate((thread_call_func_t
) &IOTimerEventSource::timeoutAndRelease
,
135 (thread_call_param_t
) this);
138 bool IOTimerEventSource::init(OSObject
*inOwner
, Action inAction
)
140 if (!super::init(inOwner
, (IOEventSource::Action
) inAction
) )
151 IOTimerEventSource::timerEventSource(OSObject
*inOwner
, Action inAction
)
153 IOTimerEventSource
*me
= new IOTimerEventSource
;
155 if (me
&& !me
->init(inOwner
, inAction
)) {
163 void IOTimerEventSource::free()
167 thread_call_free((thread_call_t
) calloutEntry
);
171 IODelete(reserved
, ExpansionData
, 1);
176 void IOTimerEventSource::cancelTimeout()
179 reserved
->calloutGeneration
++;
180 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
181 AbsoluteTime_to_scalar(&abstime
) = 0;
182 if (active
&& reserved
)
189 void IOTimerEventSource::enable()
192 if (kIOReturnSuccess
!= wakeAtTime(abstime
))
193 super::disable(); // Problem re-scheduling timeout ignore enable
196 void IOTimerEventSource::disable()
199 reserved
->calloutGeneration
++;
200 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
202 if (active
&& reserved
)
209 IOReturn
IOTimerEventSource::setTimeoutTicks(UInt32 ticks
)
211 return setTimeout(ticks
, kTickScale
);
214 IOReturn
IOTimerEventSource::setTimeoutMS(UInt32 ms
)
216 return setTimeout(ms
, kMillisecondScale
);
219 IOReturn
IOTimerEventSource::setTimeoutUS(UInt32 us
)
221 return setTimeout(us
, kMicrosecondScale
);
224 IOReturn
IOTimerEventSource::setTimeout(UInt32 interval
, UInt32 scale_factor
)
228 clock_interval_to_deadline(interval
, scale_factor
, &end
);
229 return wakeAtTime(end
);
232 IOReturn
IOTimerEventSource::setTimeout(mach_timespec_t interval
)
234 AbsoluteTime end
, nsecs
;
236 clock_interval_to_absolutetime_interval
237 (interval
.tv_nsec
, kNanosecondScale
, &nsecs
);
238 clock_interval_to_deadline
239 (interval
.tv_sec
, NSEC_PER_SEC
, &end
);
240 ADD_ABSOLUTETIME(&end
, &nsecs
);
242 return wakeAtTime(end
);
245 IOReturn
IOTimerEventSource::setTimeout(AbsoluteTime interval
)
249 clock_get_uptime(&end
);
250 ADD_ABSOLUTETIME(&end
, &interval
);
252 return wakeAtTime(end
);
255 IOReturn
IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks
)
257 return wakeAtTime(ticks
, kTickScale
);
260 IOReturn
IOTimerEventSource::wakeAtTimeMS(UInt32 ms
)
262 return wakeAtTime(ms
, kMillisecondScale
);
265 IOReturn
IOTimerEventSource::wakeAtTimeUS(UInt32 us
)
267 return wakeAtTime(us
, kMicrosecondScale
);
270 IOReturn
IOTimerEventSource::wakeAtTime(UInt32 inAbstime
, UInt32 scale_factor
)
273 clock_interval_to_absolutetime_interval(inAbstime
, scale_factor
, &end
);
275 return wakeAtTime(end
);
278 IOReturn
IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime
)
280 AbsoluteTime end
, nsecs
;
282 clock_interval_to_absolutetime_interval
283 (inAbstime
.tv_nsec
, kNanosecondScale
, &nsecs
);
284 clock_interval_to_absolutetime_interval
285 (inAbstime
.tv_sec
, kSecondScale
, &end
);
286 ADD_ABSOLUTETIME(&end
, &nsecs
);
288 return wakeAtTime(end
);
291 void IOTimerEventSource::setWorkLoop(IOWorkLoop
*inWorkLoop
)
293 super::setWorkLoop(inWorkLoop
);
294 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
298 IOReturn
IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime
)
301 return kIOReturnNoResources
;
304 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
310 reserved
->workLoop
= workLoop
;
311 reserved
->calloutGeneration
++;
312 if (thread_call_enter1_delayed((thread_call_t
) calloutEntry
,
313 (void *) reserved
->calloutGeneration
, abstime
))
320 thread_call_enter_delayed((thread_call_t
) calloutEntry
, abstime
);
323 return kIOReturnSuccess
;