2 * Waitable timers management
4 * Copyright (C) 1999 Alexandre Julliard
11 #include <sys/types.h>
16 /* FIXME: check values and move to standard header */
17 #define TIMER_MODIFY_STATE 0x0001
18 #define TIMER_QUERY_STATE 0x0002
19 #define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
23 struct object obj; /* object header */
24 int manual; /* manual reset */
25 int signaled; /* current signaled state */
26 int period; /* timer period in ms */
27 struct timeval when; /* next expiration */
28 struct timeout_user *timeout; /* timeout user */
29 void *callback; /* callback APC function */
30 void *arg; /* callback argument */
33 static void timer_dump( struct object *obj, int verbose );
34 static int timer_signaled( struct object *obj, struct thread *thread );
35 static int timer_satisfied( struct object *obj, struct thread *thread );
36 static void timer_destroy( struct object *obj );
38 static const struct object_ops timer_ops =
40 sizeof(struct timer), /* size */
41 timer_dump, /* dump */
42 add_queue, /* add_queue */
43 remove_queue, /* remove_queue */
44 timer_signaled, /* signaled */
45 timer_satisfied, /* satisfied */
46 NULL, /* get_poll_events */
47 NULL, /* poll_event */
48 no_read_fd, /* get_read_fd */
49 no_write_fd, /* get_write_fd */
51 no_get_file_info, /* get_file_info */
52 timer_destroy /* destroy */
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() != STATUS_OBJECT_NAME_COLLISION)
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, 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, 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 );