2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
25 * IOTimerEventSource.cpp
28 * 2-Feb-1999 Joe Liu (jliu) created.
29 * 1999-10-14 Godfrey van der Linden(gvdl)
30 * Revamped to use thread_call APIs
34 #include <sys/cdefs.h>
37 #include <kern/thread_call.h>
40 #include <IOKit/assert.h>
41 #include <IOKit/system.h>
43 #include <IOKit/IOLib.h>
44 #include <IOKit/IOTimerEventSource.h>
45 #include <IOKit/IOWorkLoop.h>
47 #include <IOKit/IOTimeStamp.h>
49 #define super IOEventSource
50 OSDefineMetaClassAndStructors(IOTimerEventSource
, IOEventSource
)
51 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 0);
52 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 1);
53 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 2);
54 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 3);
55 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 4);
56 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 5);
57 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 6);
58 OSMetaClassDefineReservedUnused(IOTimerEventSource
, 7);
61 // reserved != 0 means IOTimerEventSource::timeoutAndRelease is being used,
62 // not a subclassed implementation.
65 bool IOTimerEventSource::checkForWork() { return false; }
67 // Timeout handler function. This function is called by the kernel when
68 // the timeout interval expires.
70 void IOTimerEventSource::timeout(void *self
)
72 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
74 if (me
->enabled
&& me
->action
)
82 doit
= (Action
) me
->action
;
83 if (doit
&& me
->enabled
&& AbsoluteTime_to_scalar(&me
->abstime
))
85 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
86 (unsigned int) doit
, (unsigned int) me
->owner
);
87 (*doit
)(me
->owner
, me
);
94 void IOTimerEventSource::timeoutAndRelease(void * self
, void * count
)
96 IOTimerEventSource
*me
= (IOTimerEventSource
*) self
;
98 if (me
->enabled
&& me
->action
)
101 wl
= me
->reserved
->workLoop
;
106 doit
= (Action
) me
->action
;
107 if (doit
&& (me
->reserved
->calloutGeneration
== (SInt32
) count
))
109 IOTimeStampConstant(IODBG_TIMES(IOTIMES_ACTION
),
110 (unsigned int) doit
, (unsigned int) me
->owner
);
111 (*doit
)(me
->owner
, me
);
117 me
->reserved
->workLoop
->release();
121 void IOTimerEventSource::setTimeoutFunc()
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
,
127 (thread_call_param_t
) this);
130 bool IOTimerEventSource::init(OSObject
*inOwner
, Action inAction
)
132 if (!super::init(inOwner
, (IOEventSource::Action
) inAction
) )
143 IOTimerEventSource::timerEventSource(OSObject
*inOwner
, Action inAction
)
145 IOTimerEventSource
*me
= new IOTimerEventSource
;
147 if (me
&& !me
->init(inOwner
, inAction
)) {
155 void IOTimerEventSource::free()
159 thread_call_free((thread_call_t
) calloutEntry
);
163 IODelete(reserved
, ExpansionData
, 1);
168 void IOTimerEventSource::cancelTimeout()
171 reserved
->calloutGeneration
++;
172 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
173 AbsoluteTime_to_scalar(&abstime
) = 0;
174 if (active
&& reserved
)
181 void IOTimerEventSource::enable()
184 if (kIOReturnSuccess
!= wakeAtTime(abstime
))
185 super::disable(); // Problem re-scheduling timeout ignore enable
188 void IOTimerEventSource::disable()
191 reserved
->calloutGeneration
++;
192 bool active
= thread_call_cancel((thread_call_t
) calloutEntry
);
194 if (active
&& reserved
)
201 IOReturn
IOTimerEventSource::setTimeoutTicks(UInt32 ticks
)
203 return setTimeout(ticks
, kTickScale
);
206 IOReturn
IOTimerEventSource::setTimeoutMS(UInt32 ms
)
208 return setTimeout(ms
, kMillisecondScale
);
211 IOReturn
IOTimerEventSource::setTimeoutUS(UInt32 us
)
213 return setTimeout(us
, kMicrosecondScale
);
216 IOReturn
IOTimerEventSource::setTimeout(UInt32 interval
, UInt32 scale_factor
)
220 clock_interval_to_deadline(interval
, scale_factor
, &end
);
221 return wakeAtTime(end
);
224 IOReturn
IOTimerEventSource::setTimeout(mach_timespec_t interval
)
226 AbsoluteTime end
, nsecs
;
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
);
234 return wakeAtTime(end
);
237 IOReturn
IOTimerEventSource::setTimeout(AbsoluteTime interval
)
241 clock_get_uptime(&end
);
242 ADD_ABSOLUTETIME(&end
, &interval
);
244 return wakeAtTime(end
);
247 IOReturn
IOTimerEventSource::wakeAtTimeTicks(UInt32 ticks
)
249 return wakeAtTime(ticks
, kTickScale
);
252 IOReturn
IOTimerEventSource::wakeAtTimeMS(UInt32 ms
)
254 return wakeAtTime(ms
, kMillisecondScale
);
257 IOReturn
IOTimerEventSource::wakeAtTimeUS(UInt32 us
)
259 return wakeAtTime(us
, kMicrosecondScale
);
262 IOReturn
IOTimerEventSource::wakeAtTime(UInt32 inAbstime
, UInt32 scale_factor
)
265 clock_interval_to_absolutetime_interval(inAbstime
, scale_factor
, &end
);
267 return wakeAtTime(end
);
270 IOReturn
IOTimerEventSource::wakeAtTime(mach_timespec_t inAbstime
)
272 AbsoluteTime end
, nsecs
;
274 clock_interval_to_absolutetime_interval
275 (inAbstime
.tv_nsec
, kNanosecondScale
, &nsecs
);
276 clock_interval_to_absolutetime_interval
277 (inAbstime
.tv_sec
, kSecondScale
, &end
);
278 ADD_ABSOLUTETIME(&end
, &nsecs
);
280 return wakeAtTime(end
);
283 void IOTimerEventSource::setWorkLoop(IOWorkLoop
*inWorkLoop
)
285 super::setWorkLoop(inWorkLoop
);
286 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
290 IOReturn
IOTimerEventSource::wakeAtTime(AbsoluteTime inAbstime
)
293 return kIOReturnNoResources
;
296 if ( enabled
&& AbsoluteTime_to_scalar(&abstime
) && workLoop
)
302 reserved
->workLoop
= workLoop
;
303 reserved
->calloutGeneration
++;
304 if (thread_call_enter1_delayed((thread_call_t
) calloutEntry
,
305 (void *) reserved
->calloutGeneration
, abstime
))
312 thread_call_enter_delayed((thread_call_t
) calloutEntry
, abstime
);
315 return kIOReturnSuccess
;