2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
31 * IOTimerEventSource.cpp
34 * 2-Feb-1999 Joe Liu (jliu) created.
35 * 1999-10-14 Godfrey van der Linden(gvdl)
36 * Revamped to use thread_call APIs
40 #include <sys/cdefs.h>
43 #include <kern/thread_call.h>
46 #include <IOKit/assert.h>
47 #include <IOKit/system.h>
49 #include <IOKit/IOLib.h>
50 #include <IOKit/IOTimerEventSource.h>
51 #include <IOKit/IOWorkLoop.h>
53 #include <IOKit/IOTimeStamp.h>
55 #define super IOEventSource
56 OSDefineMetaClassAndStructors(IOTimerEventSource
, IOEventSource
)
57 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 0);
58 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 1);
59 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 2);
60 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 3);
61 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 4);
62 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 5);
63 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 6);
64 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 7);
67 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
68 // not a subclassed implementation.
71 bool IOTimerEventSource::checkForWork() { return false; }
73 // Timeout handler function. This function is called by the kernel when
74 // the timeout interval expires.
76 void IOTimerEventSource::timeout(void *self
)
78 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
80 if (me
->enabled
&& me
->action
)
88 doit
= (Action
) me
->action
;
89 if (doit
&& me
->enabled
&& AbsoluteTime_to_scalar(&me
->abstime
))
91 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
92 (unsigned int) doit
, (unsigned int) me
->owner
);
93 (*doit
)(me
->owner
, me
);
100 void IOTimerEventSource::timeoutAndRelease(void * self
, void * count
)
102 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
104 if (me
->enabled
&& me
->action
)
107 wl
= me
->reserved
->workLoop
;
112 doit
= (Action
) me
->action
;
113 if (doit
&& (me
->reserved
->calloutGeneration
== (SInt32
) count
))
115 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
116 (unsigned int) doit
, (unsigned int) me
->owner
);
117 (*doit
)(me
->owner
, me
);
123 me
->reserved
->workLoop
->release();
127 void IOTimerEventSource::setTimeoutFunc()
129 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
130 // not a subclassed implementation
131 reserved
= IONew(ExpansionData
, 1);
132 calloutEntry
= (void *) thread_call_allocate((thread_call_func_t
) &IOTimerEventSource::timeoutAndRelease
,
133 (thread_call_param_t
) this);
136 bool IOTimerEventSource::init(OSObject
*inOwner
, Action inAction
)
138 if (!super::init(inOwner
, (IOEventSource::Action
) inAction
) )
149 IOTimerEventSource::timerEventSource(OSObject
*inOwner
, Action inAction
)
151 IOTimerEventSource
*me
= new IOTimerEventSource
;
153 if (me
&& !me
->init(inOwner
, inAction
)) {
161 void IOTimerEventSource::free()
165 thread_call_free((thread_call_t
) calloutEntry
);
169 IODelete(reserved
, ExpansionData
, 1);
174 void IOTimerEventSource::cancelTimeout()
177 reserved
->calloutGeneration
++;
178 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
179 AbsoluteTime_to_scalar(&abstime
) = 0;
180 if (active
&& reserved
)
187 void IOTimerEventSource::enable()
190 if (kIOReturnSuccess
!= wakeAtTime(abstime
))
191 super::disable(); // Problem re-scheduling timeout ignore enable
194 void IOTimerEventSource::disable()
197 reserved
->calloutGeneration
++;
198 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
200 if (active
&& reserved
)
207 IOReturn
IOTimerEventSource::setTimeoutTicks(UInt32 ticks
)
209 return setTimeout(ticks
, kTickScale
);
212 IOReturn
IOTimerEventSource::setTimeoutMS(UInt32 ms
)
214 return setTimeout(ms
, kMillisecondScale
);
217 IOReturn
IOTimerEventSource::setTimeoutUS(UInt32 us
)
219 return setTimeout(us
, kMicrosecondScale
);
222 IOReturn
IOTimerEventSource::setTimeout(UInt32 interval
, UInt32 scale_factor
)
226 clock_interval_to_deadline(interval
, scale_factor
, &end
);
227 return wakeAtTime(end
);
230 IOReturn
IOTimerEventSource::setTimeout(mach_timespec_t interval
)
232 AbsoluteTime end
, nsecs
;
234 clock_interval_to_absolutetime_interval
235 (interval
.tv_nsec
, kNanosecondScale
, &nsecs
);
236 clock_interval_to_deadline
237 (interval
.tv_sec
, NSEC_PER_SEC
, &end
);
238 ADD_ABSOLUTETIME(&end
, &nsecs
);
240 return wakeAtTime(end
);
243 IOReturn
IOTimerEventSource::setTimeout(AbsoluteTime interval
)
247 clock_get_uptime(&end
);
248 ADD_ABSOLUTETIME(&end
, &interval
);
250 return wakeAtTime(end
);
253 IOReturn
IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks
)
255 return wakeAtTime(ticks
, kTickScale
);
258 IOReturn
IOTimerEventSource::wakeAtTimeMS(UInt32 ms
)
260 return wakeAtTime(ms
, kMillisecondScale
);
263 IOReturn
IOTimerEventSource::wakeAtTimeUS(UInt32 us
)
265 return wakeAtTime(us
, kMicrosecondScale
);
268 IOReturn
IOTimerEventSource::wakeAtTime(UInt32 inAbstime
, UInt32 scale_factor
)
271 clock_interval_to_absolutetime_interval(inAbstime
, scale_factor
, &end
);
273 return wakeAtTime(end
);
276 IOReturn
IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime
)
278 AbsoluteTime end
, nsecs
;
280 clock_interval_to_absolutetime_interval
281 (inAbstime
.tv_nsec
, kNanosecondScale
, &nsecs
);
282 clock_interval_to_absolutetime_interval
283 (inAbstime
.tv_sec
, kSecondScale
, &end
);
284 ADD_ABSOLUTETIME(&end
, &nsecs
);
286 return wakeAtTime(end
);
289 void IOTimerEventSource::setWorkLoop(IOWorkLoop
*inWorkLoop
)
291 super::setWorkLoop(inWorkLoop
);
292 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
296 IOReturn
IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime
)
299 return kIOReturnNoResources
;
302 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
308 reserved
->workLoop
= workLoop
;
309 reserved
->calloutGeneration
++;
310 if (thread_call_enter1_delayed((thread_call_t
) calloutEntry
,
311 (void *) reserved
->calloutGeneration
, abstime
))
318 thread_call_enter_delayed((thread_call_t
) calloutEntry
, abstime
);
321 return kIOReturnSuccess
;