2 * Copyright (c) 2004,2007-2008 Apple 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@
31 * - timer source based on <kern/thread_call.h>
35 * Modification History:
37 * June 22, 2004 Dieter Siegmund (dieter@apple.com)
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <kern/thread_call.h>
44 #include <net/devtimer.h>
45 #include <os/refcnt.h>
48 #define _devtimer_printf printf
49 #else /* !DEVTIMER_DEBUG */
50 static __inline__
void
51 _devtimer_printf(__unused
const char * fmt
, ...)
54 #endif /* !DEVTIMER_DEBUG */
58 devtimer_timeout_func dt_timeout_func
;
59 devtimer_process_func dt_process_func
;
64 struct os_refcnt dt_retain_count
;
67 #define M_DEVTIMER M_DEVBUF
69 static __inline__
void
70 timeval_add(struct timeval tv1
, struct timeval tv2
,
71 struct timeval
* result
)
73 result
->tv_sec
= tv1
.tv_sec
+ tv2
.tv_sec
;
74 result
->tv_usec
= tv1
.tv_usec
+ tv2
.tv_usec
;
75 if (result
->tv_usec
> DEVTIMER_USECS_PER_SEC
) {
76 result
->tv_usec
-= DEVTIMER_USECS_PER_SEC
;
82 static __inline__
uint64_t
83 timeval_to_absolutetime(struct timeval tv
)
88 clock_interval_to_absolutetime_interval(tv
.tv_sec
, NSEC_PER_SEC
,
90 clock_interval_to_absolutetime_interval(tv
.tv_usec
, NSEC_PER_USEC
,
96 __private_extern__
int
97 devtimer_valid(devtimer_ref timer
)
99 return timer
->dt_callout
!= NULL
;
102 __private_extern__
void
103 devtimer_retain(devtimer_ref timer
)
105 os_ref_retain(&timer
->dt_retain_count
);
108 __private_extern__
void
109 devtimer_invalidate(devtimer_ref timer
)
111 devtimer_cancel(timer
);
112 timer
->dt_arg0
= NULL
;
113 if (timer
->dt_callout
!= NULL
) {
114 thread_call_free(timer
->dt_callout
);
115 timer
->dt_callout
= NULL
;
120 __private_extern__
void
121 devtimer_release(devtimer_ref timer
)
123 if (os_ref_release(&timer
->dt_retain_count
) == 0) {
124 devtimer_invalidate(timer
);
125 FREE(timer
, M_DEVTIMER
);
126 _devtimer_printf("devtimer: timer released\n");
131 devtimer_process(void * param0
, void * param1
)
133 int generation
= *(int*)param1
;
134 devtimer_process_func process_func
;
135 devtimer_timeout_func timeout_func
;
136 devtimer_ref timer
= (devtimer_ref
)param0
;
138 process_func
= timer
->dt_process_func
;
139 if (process_func
!= NULL
) {
140 (*process_func
)(timer
, devtimer_process_func_event_lock
);
142 timeout_func
= timer
->dt_timeout_func
;
143 if (timeout_func
!= NULL
) {
144 timer
->dt_timeout_func
= NULL
;
145 if (timer
->dt_generation
== generation
) {
146 (*timeout_func
)(timer
->dt_arg0
, timer
->dt_arg1
, timer
->dt_arg2
);
149 devtimer_release(timer
);
150 if (process_func
!= NULL
) {
151 (*process_func
)(timer
, devtimer_process_func_event_unlock
);
156 __private_extern__
void *
157 devtimer_arg0(devtimer_ref timer
)
159 return timer
->dt_arg0
;
162 __private_extern__ devtimer_ref
163 devtimer_create(devtimer_process_func process_func
, void * arg0
)
167 timer
= _MALLOC(sizeof(*timer
), M_DEVTIMER
, M_WAITOK
| M_ZERO
);
171 os_ref_init(&timer
->dt_retain_count
, NULL
);
172 timer
->dt_callout
= thread_call_allocate(devtimer_process
, timer
);
173 if (timer
->dt_callout
== NULL
) {
174 _devtimer_printf("devtimer: thread_call_allocate failed\n");
175 devtimer_release(timer
);
178 timer
->dt_process_func
= process_func
;
179 timer
->dt_arg0
= arg0
;
183 __private_extern__
void
184 devtimer_set_absolute(devtimer_ref timer
,
185 struct timeval abs_time
,
186 devtimer_timeout_func timeout_func
,
187 void * arg1
, void * arg2
)
189 if (timer
->dt_callout
== NULL
) {
190 printf("devtimer_set_absolute: uninitialized/freed timer\n");
193 devtimer_cancel(timer
);
194 if (timeout_func
== NULL
) {
197 timer
->dt_timeout_func
= timeout_func
;
198 timer
->dt_arg1
= arg1
;
199 timer
->dt_arg2
= arg2
;
200 _devtimer_printf("devtimer: wakeup time is (%d.%d)\n",
201 abs_time
.tv_sec
, abs_time
.tv_usec
);
202 timer
->dt_generation
++;
203 devtimer_retain(timer
);
204 thread_call_enter1_delayed(timer
->dt_callout
,
205 &timer
->dt_generation
,
206 timeval_to_absolutetime(abs_time
));
210 __private_extern__
void
211 devtimer_set_relative(devtimer_ref timer
,
212 struct timeval rel_time
,
213 devtimer_timeout_func timeout_func
,
214 void * arg1
, void * arg2
)
216 struct timeval abs_time
;
217 struct timeval current_time
;
219 current_time
= devtimer_current_time();
220 timeval_add(current_time
, rel_time
, &abs_time
);
221 devtimer_set_absolute(timer
, abs_time
, timeout_func
, arg1
, arg2
);
225 __private_extern__
void
226 devtimer_cancel(devtimer_ref timer
)
228 if (timer
->dt_timeout_func
!= NULL
) {
229 timer
->dt_timeout_func
= NULL
;
230 if (timer
->dt_callout
!= NULL
) {
231 _devtimer_printf("devtimer: cancelling timer source\n");
232 if (thread_call_cancel(timer
->dt_callout
)) {
233 devtimer_release(timer
);
235 _devtimer_printf("devtimer: delayed release\n");
242 __private_extern__
int
243 devtimer_enabled(devtimer_ref timer
)
245 return timer
->dt_timeout_func
!= NULL
;
248 __private_extern__
int32_t
249 devtimer_current_secs(void)
253 tv
= devtimer_current_time();
257 __private_extern__
struct timeval
258 devtimer_current_time(void)
264 clock_get_system_microtime(&sec
, &usec
);