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
->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
);