- Correct RBN_CHILDSIZE rect value for CCS_VERT rebar.
[wine/gsoc_dplay.git] / scheduler / services.c
blobe29a137ee71a3c8380407dc2ecb3a3d3dc8f90be
1 /*
2 * Kernel Services Thread
4 * Copyright 1999 Ulrich Weigand
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sys/time.h>
22 #include <unistd.h>
24 #include "services.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(timer);
29 typedef struct _SERVICE
31 struct _SERVICE *next;
32 HANDLE self;
34 PAPCFUNC callback;
35 ULONG_PTR callback_arg;
37 BOOL disabled;
38 HANDLE object;
39 } SERVICE;
42 static HANDLE service_thread;
43 static SERVICE *service_first;
44 static DWORD service_counter;
46 /***********************************************************************
47 * SERVICE_Loop
49 static DWORD CALLBACK SERVICE_Loop( void *dummy )
51 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
52 int count = 0;
53 DWORD retval = WAIT_FAILED;
55 while ( TRUE )
57 PAPCFUNC callback;
58 ULONG_PTR callback_arg;
59 SERVICE *s;
61 /* Check whether some condition is fulfilled */
63 HeapLock( GetProcessHeap() );
65 callback = NULL;
66 callback_arg = 0L;
67 for ( s = service_first; s; s = s->next )
69 if (s->disabled) continue;
71 if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count )
73 if ( handles[retval - WAIT_OBJECT_0] == s->object )
75 retval = WAIT_TIMEOUT;
76 callback = s->callback;
77 callback_arg = s->callback_arg;
78 break;
83 HeapUnlock( GetProcessHeap() );
85 /* If found, call callback routine */
87 if ( callback )
89 callback( callback_arg );
90 continue;
93 /* If not found, determine wait condition */
95 HeapLock( GetProcessHeap() );
97 count = 0;
98 for ( s = service_first; s; s = s->next )
100 if (s->disabled) continue;
102 if ( count < MAXIMUM_WAIT_OBJECTS )
103 handles[count++] = s->object;
106 HeapUnlock( GetProcessHeap() );
109 /* Wait until some condition satisfied */
111 TRACE("Waiting for %d objects\n", count );
113 retval = WaitForMultipleObjectsEx( count, handles, FALSE, INFINITE, TRUE );
115 TRACE("Wait returned: %ld\n", retval );
118 return 0L;
121 /***********************************************************************
122 * SERVICE_CreateServiceTable
124 static BOOL SERVICE_CreateServiceTable( void )
126 /* service_thread must be set *BEFORE* calling CreateThread
127 * otherwise the thread cleanup service will cause an infinite recursion
128 * when installed
130 service_thread = INVALID_HANDLE_VALUE;
131 service_thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SERVICE_Loop,
132 NULL, 0, NULL );
133 return (service_thread != 0);
136 /***********************************************************************
137 * SERVICE_AddObject
139 * Warning: the object supplied by the caller must not be closed. It'll
140 * be destroyed when the service is deleted. It's up to the caller
141 * to ensure that object will not be destroyed in between.
143 HANDLE SERVICE_AddObject( HANDLE object,
144 PAPCFUNC callback, ULONG_PTR callback_arg )
146 SERVICE *s;
147 HANDLE handle;
149 if ( !object || object == INVALID_HANDLE_VALUE || !callback )
150 return INVALID_HANDLE_VALUE;
152 if (!service_thread && !SERVICE_CreateServiceTable()) return INVALID_HANDLE_VALUE;
154 s = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) );
155 if ( !s ) return INVALID_HANDLE_VALUE;
157 s->callback = callback;
158 s->callback_arg = callback_arg;
159 s->object = object;
160 s->disabled = FALSE;
162 HeapLock( GetProcessHeap() );
164 s->self = handle = (HANDLE)++service_counter;
165 s->next = service_first;
166 service_first = s;
168 HeapUnlock( GetProcessHeap() );
170 QueueUserAPC( NULL, service_thread, 0L );
172 return handle;
175 /***********************************************************************
176 * SERVICE_AddTimer
178 HANDLE SERVICE_AddTimer( LONG rate,
179 PAPCFUNC callback, ULONG_PTR callback_arg )
181 HANDLE handle, ret;
182 LARGE_INTEGER when;
184 if ( !rate || !callback )
185 return INVALID_HANDLE_VALUE;
187 handle = CreateWaitableTimerA( NULL, FALSE, NULL );
188 if (!handle) return INVALID_HANDLE_VALUE;
190 if (!rate) rate = 1;
191 when.s.LowPart = when.s.HighPart = 0;
192 if (!SetWaitableTimer( handle, &when, rate, NULL, NULL, FALSE ))
194 CloseHandle( handle );
195 return INVALID_HANDLE_VALUE;
198 if ((ret = SERVICE_AddObject( handle, callback, callback_arg )) == INVALID_HANDLE_VALUE)
200 CloseHandle( handle );
201 return INVALID_HANDLE_VALUE;
203 return ret;
206 /***********************************************************************
207 * SERVICE_Delete
209 BOOL SERVICE_Delete( HANDLE service )
211 HANDLE handle = INVALID_HANDLE_VALUE;
212 BOOL retv = FALSE;
213 SERVICE **s, *next;
215 HeapLock( GetProcessHeap() );
217 for ( s = &service_first; *s; s = &(*s)->next )
219 if ( (*s)->self == service )
221 handle = (*s)->object;
222 next = (*s)->next;
223 HeapFree( GetProcessHeap(), 0, *s );
224 *s = next;
225 retv = TRUE;
226 break;
230 HeapUnlock( GetProcessHeap() );
232 if ( handle != INVALID_HANDLE_VALUE )
233 CloseHandle( handle );
235 QueueUserAPC( NULL, service_thread, 0L );
237 return retv;
240 /***********************************************************************
241 * SERVICE_Enable
243 BOOL SERVICE_Enable( HANDLE service )
245 BOOL retv = FALSE;
246 SERVICE *s;
248 HeapLock( GetProcessHeap() );
250 for ( s = service_first; s; s = s->next )
252 if ( s->self == service )
254 s->disabled = FALSE;
255 retv = TRUE;
256 break;
260 HeapUnlock( GetProcessHeap() );
262 QueueUserAPC( NULL, service_thread, 0L );
264 return retv;
267 /***********************************************************************
268 * SERVICE_Disable
270 BOOL SERVICE_Disable( HANDLE service )
272 BOOL retv = TRUE;
273 SERVICE *s;
275 HeapLock( GetProcessHeap() );
277 for ( s = service_first; s; s = s->next )
279 if ( s->self == service )
281 s->disabled = TRUE;
282 retv = TRUE;
283 break;
287 HeapUnlock( GetProcessHeap() );
289 QueueUserAPC( NULL, service_thread, 0L );
291 return retv;