2 * Waitable timers management
4 * Copyright (C) 1999 Alexandre Julliard
11 #include <sys/types.h>
18 /* FIXME: check values and move to standard header */
19 #define TIMER_MODIFY_STATE 0x0001
20 #define TIMER_QUERY_STATE 0x0002
21 #define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
25 struct object obj; /* object header */
26 int manual; /* manual reset */
27 int signaled; /* current signaled state */
28 int period; /* timer period in ms */
29 struct timeval when; /* next expiration */
30 struct timeout_user *timeout; /* timeout user */
31 void *callback; /* callback APC function */
32 void *arg; /* callback argument */
35 static void timer_dump( struct object *obj, int verbose );
36 static int timer_signaled( struct object *obj, struct thread *thread );
37 static int timer_satisfied( struct object *obj, struct thread *thread );
38 static void timer_destroy( struct object *obj );
40 static const struct object_ops timer_ops =
56 /* create a timer object */
57 static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
61 if ((timer = create_named_object( &timer_ops, name, len )))
63 if (get_error() != ERROR_ALREADY_EXISTS)
65 /* initialize it if it didn't already exist */
66 timer->manual = manual;
68 timer->when.tv_sec = 0;
69 timer->when.tv_usec = 0;
71 timer->timeout = NULL;
77 /* callback on timer expiration */
78 static void timer_callback( void *private )
80 struct timer *timer = (struct timer *)private;
82 if (timer->period) /* schedule the next expiration */
84 add_timeout( &timer->when, timer->period );
85 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
87 else timer->timeout = NULL;
91 wake_up( &timer->obj, 0 );
94 /* set the timer expiration and period */
95 static void set_timer( struct timer *timer, int sec, int usec, int period,
96 void *callback, void *arg )
100 period = 0; /* period doesn't make any sense for a manual timer */
103 if (timer->timeout) remove_timeout_user( timer->timeout );
106 /* special case: use now + period as first expiration */
107 gettimeofday( &timer->when, 0 );
108 add_timeout( &timer->when, period );
112 timer->when.tv_sec = sec;
113 timer->when.tv_usec = usec;
115 timer->period = period;
116 timer->callback = callback;
118 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
121 /* cancel a running timer */
122 static void cancel_timer( struct timer *timer )
126 remove_timeout_user( timer->timeout );
127 timer->timeout = NULL;
131 static void timer_dump( struct object *obj, int verbose )
133 struct timer *timer = (struct timer *)obj;
134 assert( obj->ops == &timer_ops );
135 fprintf( stderr, "Timer manual=%d when=%ld.%06ld period=%d ",
136 timer->manual, timer->when.tv_sec, timer->when.tv_usec, timer->period );
137 dump_object_name( &timer->obj );
138 fputc( '\n', stderr );
141 static int timer_signaled( struct object *obj, struct thread *thread )
143 struct timer *timer = (struct timer *)obj;
144 assert( obj->ops == &timer_ops );
145 return timer->signaled;
148 static int timer_satisfied( struct object *obj, struct thread *thread )
150 struct timer *timer = (struct timer *)obj;
151 assert( obj->ops == &timer_ops );
152 if (!timer->manual) timer->signaled = 0;
156 static void timer_destroy( struct object *obj )
158 struct timer *timer = (struct timer *)obj;
159 assert( obj->ops == &timer_ops );
161 if (timer->timeout) remove_timeout_user( timer->timeout );
165 DECL_HANDLER(create_timer)
167 size_t len = get_req_strlenW( req->name );
171 if ((timer = create_timer( req->name, len, req->manual )))
173 req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
174 release_object( timer );
178 /* open a handle to a timer */
179 DECL_HANDLER(open_timer)
181 size_t len = get_req_strlenW( req->name );
182 req->handle = open_object( req->name, len, &timer_ops, req->access, req->inherit );
185 /* set a waitable timer */
186 DECL_HANDLER(set_timer)
190 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
191 TIMER_MODIFY_STATE, &timer_ops )))
193 set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg );
194 release_object( timer );
198 /* cancel a waitable timer */
199 DECL_HANDLER(cancel_timer)
203 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
204 TIMER_MODIFY_STATE, &timer_ops )))
206 cancel_timer( timer );
207 release_object( timer );