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 make_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
);
104 timer
->when
.tv_sec
= sec
;
105 timer
->when
.tv_usec
= usec
;
106 timer
->period
= period
;
107 timer
->callback
= callback
;
109 timer
->timeout
= add_timeout_user( &timer
->when
, timer_callback
, timer
);
112 /* cancel a running timer */
113 static void cancel_timer( struct timer
*timer
)
117 remove_timeout_user( timer
->timeout
);
118 timer
->timeout
= NULL
;
122 static void timer_dump( struct object
*obj
, int verbose
)
124 struct timer
*timer
= (struct timer
*)obj
;
125 assert( obj
->ops
== &timer_ops
);
126 fprintf( stderr
, "Timer manual=%d when=%ld.%06ld period=%d ",
127 timer
->manual
, timer
->when
.tv_sec
, timer
->when
.tv_usec
, timer
->period
);
128 dump_object_name( &timer
->obj
);
129 fputc( '\n', stderr
);
132 static int timer_signaled( struct object
*obj
, struct thread
*thread
)
134 struct timer
*timer
= (struct timer
*)obj
;
135 assert( obj
->ops
== &timer_ops
);
136 return timer
->signaled
;
139 static int timer_satisfied( struct object
*obj
, struct thread
*thread
)
141 struct timer
*timer
= (struct timer
*)obj
;
142 assert( obj
->ops
== &timer_ops
);
143 if (!timer
->manual
) timer
->signaled
= 0;
147 static void timer_destroy( struct object
*obj
)
149 struct timer
*timer
= (struct timer
*)obj
;
150 assert( obj
->ops
== &timer_ops
);
152 if (timer
->timeout
) remove_timeout_user( timer
->timeout
);
156 DECL_HANDLER(create_timer
)
158 size_t len
= get_req_strlenW( req
->name
);
162 if ((timer
= create_timer( req
->name
, len
, req
->manual
)))
164 req
->handle
= alloc_handle( current
->process
, timer
, TIMER_ALL_ACCESS
, req
->inherit
);
165 release_object( timer
);
169 /* open a handle to a timer */
170 DECL_HANDLER(open_timer
)
172 size_t len
= get_req_strlenW( req
->name
);
173 req
->handle
= open_object( req
->name
, len
, &timer_ops
, req
->access
, req
->inherit
);
176 /* set a waitable timer */
177 DECL_HANDLER(set_timer
)
181 if ((timer
= (struct timer
*)get_handle_obj( current
->process
, req
->handle
,
182 TIMER_MODIFY_STATE
, &timer_ops
)))
184 set_timer( timer
, req
->sec
, req
->usec
, req
->period
, req
->callback
, req
->arg
);
185 release_object( timer
);
189 /* cancel a waitable timer */
190 DECL_HANDLER(cancel_timer
)
194 if ((timer
= (struct timer
*)get_handle_obj( current
->process
, req
->handle
,
195 TIMER_MODIFY_STATE
, &timer_ops
)))
197 cancel_timer( timer
);
198 release_object( timer
);