From 63c7cdf19655fbbd613a65a5f5983f83140ead8b Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sat, 12 Jun 1999 08:24:23 +0000 Subject: [PATCH] Made the service thread instanciable in every process. --- include/process.h | 1 + include/services.h | 2 - loader/main.c | 3 - scheduler/services.c | 216 ++++++++++++++++++++++++------------------- scheduler/thread.c | 7 +- 5 files changed, 129 insertions(+), 100 deletions(-) diff --git a/include/process.h b/include/process.h index 453dc19260f..224f352ea4b 100644 --- a/include/process.h +++ b/include/process.h @@ -95,6 +95,7 @@ typedef struct _PDB struct _PDB *next; /* List reference - list of PDB's */ WORD hInstance; /* hInstance on startup */ WORD hPrevInstance; /* hPrevInstance on startup */ + struct _SERVICETABLE *service_table; /* Service table for service thread */ } PDB; /* Process flags */ diff --git a/include/services.h b/include/services.h index 4f8f054dd4f..4e00dad6b5c 100644 --- a/include/services.h +++ b/include/services.h @@ -9,8 +9,6 @@ #include "winbase.h" -BOOL SERVICE_Init( void ); - HANDLE SERVICE_AddObject( HANDLE object, PAPCFUNC callback, ULONG_PTR callback_arg ); diff --git a/loader/main.c b/loader/main.c index 63bf6df517f..a7b361bf227 100644 --- a/loader/main.c +++ b/loader/main.c @@ -68,9 +68,6 @@ BOOL MAIN_MainInit(void) /* Initialize signal handling */ if (!SIGNAL_Init()) return FALSE; - /* Initialize kernel services thread */ - if (!SERVICE_Init()) return FALSE; - /* Load the configuration file */ if (!PROFILE_LoadWineIni()) return FALSE; diff --git a/scheduler/services.c b/scheduler/services.c index a01bd3f34e2..43bab2d5db4 100644 --- a/scheduler/services.c +++ b/scheduler/services.c @@ -8,45 +8,41 @@ #include #include "services.h" +#include "process.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(timer) - #define SERVICE_USE_OBJECT 0x0001 #define SERVICE_USE_TIMEOUT 0x0002 #define SERVICE_DISABLED 0x8000 typedef struct _SERVICE { - struct _SERVICE *next; - HANDLE self; + struct _SERVICE *next; + HANDLE self; - PAPCFUNC callback; - ULONG_PTR callback_arg; + PAPCFUNC callback; + ULONG_PTR callback_arg; - int flags; + int flags; - HANDLE object; - long rate; + HANDLE object; + long rate; - struct timeval expire; + struct timeval expire; } SERVICE; -typedef struct +typedef struct _SERVICETABLE { - HANDLE heap; - HANDLE thread; + HANDLE thread; - SERVICE *first; - DWORD counter; + SERVICE *first; + DWORD counter; } SERVICETABLE; -static SERVICETABLE *Service = NULL; - - /*********************************************************************** * SERVICE_AddTimeval */ @@ -71,10 +67,10 @@ static long SERVICE_DiffTimeval( struct timeval *time1, struct timeval *time2 ) */ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) { - HANDLE handles[MAXIMUM_WAIT_OBJECTS]; - int count = 0; - DWORD timeout = INFINITE; - DWORD retval = WAIT_FAILED; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + int count = 0; + DWORD timeout = INFINITE; + DWORD retval = WAIT_FAILED; while ( TRUE ) { @@ -87,7 +83,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) struct timeval curTime; gettimeofday( &curTime, NULL ); - HeapLock( service->heap ); + HeapLock( GetProcessHeap() ); callback = NULL; callback_arg = 0L; @@ -96,8 +92,10 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) if ( s->flags & SERVICE_DISABLED ) continue; - if ( s->flags & SERVICE_USE_OBJECT ) + if ( s->flags & SERVICE_USE_OBJECT ) + { if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count ) + { if ( handles[retval - WAIT_OBJECT_0] == s->object ) { retval = WAIT_TIMEOUT; @@ -105,8 +103,11 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) callback_arg = s->callback_arg; break; } + } + } if ( s->flags & SERVICE_USE_TIMEOUT ) + { if ((s->expire.tv_sec < curTime.tv_sec) || ((s->expire.tv_sec == curTime.tv_sec) && (s->expire.tv_usec <= curTime.tv_usec))) @@ -116,23 +117,22 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) callback_arg = s->callback_arg; break; } + } } - HeapUnlock( service->heap ); - + HeapUnlock( GetProcessHeap() ); /* If found, call callback routine */ if ( callback ) { - callback( callback_arg ); + callback( callback_arg ); continue; } - /* If not found, determine wait condition */ - HeapLock( service->heap ); + HeapLock( GetProcessHeap() ); count = 0; timeout = INFINITE; @@ -154,7 +154,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) } } - HeapUnlock( service->heap ); + HeapUnlock( GetProcessHeap() ); /* Wait until some condition satisfied */ @@ -172,68 +172,78 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) } /*********************************************************************** - * SERVICE_Init + * SERVICE_CreateServiceTable */ -BOOL SERVICE_Init( void ) +static BOOL SERVICE_CreateServiceTable( void ) { - HANDLE heap, thread; + HANDLE thread; + SERVICETABLE *service_table; + PDB *pdb = PROCESS_Current(); - heap = HeapCreate( HEAP_GROWABLE, 0x1000, 0 ); - if ( !heap ) return FALSE; - - Service = HeapAlloc( heap, HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) ); - if ( !Service ) + service_table = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) ); + if ( !service_table ) { - HeapDestroy( heap ); return FALSE; } - Service->heap = heap; + /* service_table field in PDB must be set *BEFORE* calling CreateThread + * otherwise the thread cleanup service will cause an infinite recursion + * when installed + */ + pdb->service_table = service_table; thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SERVICE_Loop, - Service, 0, NULL ); + service_table, 0, NULL ); if ( thread == INVALID_HANDLE_VALUE ) { - HeapDestroy( heap ); + pdb->service_table = 0; + HeapFree( GetProcessHeap(), 0, service_table ); return FALSE; } - - Service->thread = ConvertToGlobalHandle( thread ); + + service_table->thread = thread; return TRUE; } /*********************************************************************** * SERVICE_AddObject + * + * Warning: the object supplied by the caller must not be closed. It'll + * be destroyed when the service is deleted. It's up to the caller + * to ensure that object will not be destroyed in between. */ HANDLE SERVICE_AddObject( HANDLE object, PAPCFUNC callback, ULONG_PTR callback_arg ) { - SERVICE *s; - HANDLE handle; + SERVICE *s; + SERVICETABLE *service_table; + HANDLE handle; - object = ConvertToGlobalHandle( object ); /* FIXME */ - - if ( !Service || object == INVALID_HANDLE_VALUE || !callback ) + if ( object == INVALID_HANDLE_VALUE || !callback ) return INVALID_HANDLE_VALUE; - s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) ); - if ( !s ) return INVALID_HANDLE_VALUE; + if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable()) + return INVALID_HANDLE_VALUE; + service_table = PROCESS_Current()->service_table; - HeapLock( Service->heap ); + s = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) ); + if ( !s ) return INVALID_HANDLE_VALUE; s->callback = callback; s->callback_arg = callback_arg; s->object = object; s->flags = SERVICE_USE_OBJECT; - s->self = handle = (HANDLE)++Service->counter; - s->next = Service->first; - Service->first = s; + HeapLock( GetProcessHeap() ); - HeapUnlock( Service->heap ); + s->self = handle = (HANDLE)++service_table->counter; + s->next = service_table->first; + service_table->first = s; - QueueUserAPC( NULL, Service->thread, 0L ); + HeapUnlock( GetProcessHeap() ); + + QueueUserAPC( NULL, service_table->thread, 0L ); return handle; } @@ -244,16 +254,19 @@ HANDLE SERVICE_AddObject( HANDLE object, HANDLE SERVICE_AddTimer( LONG rate, PAPCFUNC callback, ULONG_PTR callback_arg ) { - SERVICE *s; - HANDLE handle; + SERVICE *s; + SERVICETABLE *service_table; + HANDLE handle; - if ( !Service || !rate || !callback ) + if ( !rate || !callback ) return INVALID_HANDLE_VALUE; - s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) ); - if ( !s ) return INVALID_HANDLE_VALUE; + if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable()) + return INVALID_HANDLE_VALUE; + service_table = PROCESS_Current()->service_table; - HeapLock( Service->heap ); + s = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) ); + if ( !s ) return INVALID_HANDLE_VALUE; s->callback = callback; s->callback_arg = callback_arg; @@ -263,13 +276,15 @@ HANDLE SERVICE_AddTimer( LONG rate, gettimeofday( &s->expire, NULL ); SERVICE_AddTimeval( &s->expire, s->rate ); - s->self = handle = (HANDLE)++Service->counter; - s->next = Service->first; - Service->first = s; + HeapLock( GetProcessHeap() ); - HeapUnlock( Service->heap ); + s->self = handle = (HANDLE)++service_table->counter; + s->next = service_table->first; + service_table->first = s; - QueueUserAPC( NULL, Service->thread, 0L ); + HeapUnlock( GetProcessHeap() ); + + QueueUserAPC( NULL, service_table->thread, 0L ); return handle; } @@ -279,33 +294,38 @@ HANDLE SERVICE_AddTimer( LONG rate, */ BOOL SERVICE_Delete( HANDLE service ) { - HANDLE handle = INVALID_HANDLE_VALUE; - BOOL retv = TRUE; - SERVICE **s, *next; + HANDLE handle = INVALID_HANDLE_VALUE; + BOOL retv = FALSE; + SERVICE **s, *next; + SERVICETABLE *service_table; - if ( !Service ) return retv; + /* service table must have been created on previous SERVICE_Add??? call */ + if ((service_table = PROCESS_Current()->service_table) == 0) + return retv; - HeapLock( Service->heap ); + HeapLock( GetProcessHeap() ); - for ( s = &Service->first; *s; s = &(*s)->next ) + for ( s = &service_table->first; *s; s = &(*s)->next ) + { if ( (*s)->self == service ) { if ( (*s)->flags & SERVICE_USE_OBJECT ) handle = (*s)->object; next = (*s)->next; - HeapFree( Service->heap, 0, *s ); + HeapFree( GetProcessHeap(), 0, *s ); *s = next; - retv = FALSE; + retv = TRUE; break; } + } - HeapUnlock( Service->heap ); + HeapUnlock( GetProcessHeap() ); if ( handle != INVALID_HANDLE_VALUE ) CloseHandle( handle ); - QueueUserAPC( NULL, Service->thread, 0L ); + QueueUserAPC( NULL, service_table->thread, 0L ); return retv; } @@ -315,14 +335,18 @@ BOOL SERVICE_Delete( HANDLE service ) */ BOOL SERVICE_Enable( HANDLE service ) { - BOOL retv = TRUE; - SERVICE *s; + BOOL retv = FALSE; + SERVICE *s; + SERVICETABLE *service_table; - if ( !Service ) return retv; + /* service table must have been created on previous SERVICE_Add??? call */ + if ((service_table = PROCESS_Current()->service_table) == 0) + return retv; - HeapLock( Service->heap ); + HeapLock( GetProcessHeap() ); - for ( s = Service->first; s; s = s->next ) + for ( s = service_table->first; s; s = s->next ) + { if ( s->self == service ) { if ( s->flags & SERVICE_DISABLED ) @@ -341,13 +365,14 @@ BOOL SERVICE_Enable( HANDLE service ) (delta / s->rate) * s->rate ); } } - retv = FALSE; + retv = TRUE; break; } + } - HeapUnlock( Service->heap ); + HeapUnlock( GetProcessHeap() ); - QueueUserAPC( NULL, Service->thread, 0L ); + QueueUserAPC( NULL, service_table->thread, 0L ); return retv; } @@ -357,24 +382,29 @@ BOOL SERVICE_Enable( HANDLE service ) */ BOOL SERVICE_Disable( HANDLE service ) { - BOOL retv = TRUE; - SERVICE *s; + BOOL retv = TRUE; + SERVICE *s; + SERVICETABLE *service_table; - if ( !Service ) return retv; + /* service table must have been created on previous SERVICE_Add??? call */ + if ((service_table = PROCESS_Current()->service_table) == 0) + return retv; - HeapLock( Service->heap ); + HeapLock( GetProcessHeap() ); - for ( s = Service->first; s; s = s->next ) + for ( s = service_table->first; s; s = s->next ) + { if ( s->self == service ) { s->flags |= SERVICE_DISABLED; - retv = FALSE; + retv = TRUE; break; } + } - HeapUnlock( Service->heap ); + HeapUnlock( GetProcessHeap() ); - QueueUserAPC( NULL, Service->thread, 0L ); + QueueUserAPC( NULL, service_table->thread, 0L ); return retv; } diff --git a/scheduler/thread.c b/scheduler/thread.c index 6c184b14ae9..d86295affe2 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -203,6 +203,7 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16 struct new_thread_request request; struct new_thread_reply reply = { NULL, -1 }; int fd[2]; + HANDLE cleanup_object; THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) ); if (!thdb) return NULL; @@ -250,9 +251,11 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16 THREAD_First = thdb; /* Install cleanup handler */ + if ( !DuplicateHandle( GetCurrentProcess(), *server_handle, + GetCurrentProcess(), &cleanup_object, + 0, FALSE, DUPLICATE_SAME_ACCESS ) ) goto error; + thdb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTHDB, (ULONG_PTR)thdb ); - thdb->cleanup = SERVICE_AddObject( *server_handle, - THREAD_FreeTHDB, (ULONG_PTR)thdb ); return thdb; error: