Made the service thread instanciable in every process.

This commit is contained in:
Eric Pouech 1999-06-12 08:24:23 +00:00 committed by Alexandre Julliard
parent ffe6b7679a
commit 63c7cdf196
5 changed files with 129 additions and 100 deletions

View File

@ -95,6 +95,7 @@ typedef struct _PDB
struct _PDB *next; /* List reference - list of PDB's */ struct _PDB *next; /* List reference - list of PDB's */
WORD hInstance; /* hInstance on startup */ WORD hInstance; /* hInstance on startup */
WORD hPrevInstance; /* hPrevInstance on startup */ WORD hPrevInstance; /* hPrevInstance on startup */
struct _SERVICETABLE *service_table; /* Service table for service thread */
} PDB; } PDB;
/* Process flags */ /* Process flags */

View File

@ -9,8 +9,6 @@
#include "winbase.h" #include "winbase.h"
BOOL SERVICE_Init( void );
HANDLE SERVICE_AddObject( HANDLE object, HANDLE SERVICE_AddObject( HANDLE object,
PAPCFUNC callback, ULONG_PTR callback_arg ); PAPCFUNC callback, ULONG_PTR callback_arg );

View File

@ -68,9 +68,6 @@ BOOL MAIN_MainInit(void)
/* Initialize signal handling */ /* Initialize signal handling */
if (!SIGNAL_Init()) return FALSE; if (!SIGNAL_Init()) return FALSE;
/* Initialize kernel services thread */
if (!SERVICE_Init()) return FALSE;
/* Load the configuration file */ /* Load the configuration file */
if (!PROFILE_LoadWineIni()) return FALSE; if (!PROFILE_LoadWineIni()) return FALSE;

View File

@ -8,45 +8,41 @@
#include <unistd.h> #include <unistd.h>
#include "services.h" #include "services.h"
#include "process.h"
#include "debugtools.h" #include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(timer) DEFAULT_DEBUG_CHANNEL(timer)
#define SERVICE_USE_OBJECT 0x0001 #define SERVICE_USE_OBJECT 0x0001
#define SERVICE_USE_TIMEOUT 0x0002 #define SERVICE_USE_TIMEOUT 0x0002
#define SERVICE_DISABLED 0x8000 #define SERVICE_DISABLED 0x8000
typedef struct _SERVICE typedef struct _SERVICE
{ {
struct _SERVICE *next; struct _SERVICE *next;
HANDLE self; HANDLE self;
PAPCFUNC callback; PAPCFUNC callback;
ULONG_PTR callback_arg; ULONG_PTR callback_arg;
int flags; int flags;
HANDLE object; HANDLE object;
long rate; long rate;
struct timeval expire; struct timeval expire;
} SERVICE; } SERVICE;
typedef struct typedef struct _SERVICETABLE
{ {
HANDLE heap; HANDLE thread;
HANDLE thread;
SERVICE *first; SERVICE *first;
DWORD counter; DWORD counter;
} SERVICETABLE; } SERVICETABLE;
static SERVICETABLE *Service = NULL;
/*********************************************************************** /***********************************************************************
* SERVICE_AddTimeval * SERVICE_AddTimeval
*/ */
@ -71,10 +67,10 @@ static long SERVICE_DiffTimeval( struct timeval *time1, struct timeval *time2 )
*/ */
static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service ) static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
{ {
HANDLE handles[MAXIMUM_WAIT_OBJECTS]; HANDLE handles[MAXIMUM_WAIT_OBJECTS];
int count = 0; int count = 0;
DWORD timeout = INFINITE; DWORD timeout = INFINITE;
DWORD retval = WAIT_FAILED; DWORD retval = WAIT_FAILED;
while ( TRUE ) while ( TRUE )
{ {
@ -87,7 +83,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
struct timeval curTime; struct timeval curTime;
gettimeofday( &curTime, NULL ); gettimeofday( &curTime, NULL );
HeapLock( service->heap ); HeapLock( GetProcessHeap() );
callback = NULL; callback = NULL;
callback_arg = 0L; callback_arg = 0L;
@ -96,8 +92,10 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
if ( s->flags & SERVICE_DISABLED ) if ( s->flags & SERVICE_DISABLED )
continue; continue;
if ( s->flags & SERVICE_USE_OBJECT ) if ( s->flags & SERVICE_USE_OBJECT )
{
if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count ) if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count )
{
if ( handles[retval - WAIT_OBJECT_0] == s->object ) if ( handles[retval - WAIT_OBJECT_0] == s->object )
{ {
retval = WAIT_TIMEOUT; retval = WAIT_TIMEOUT;
@ -105,8 +103,11 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
callback_arg = s->callback_arg; callback_arg = s->callback_arg;
break; break;
} }
}
}
if ( s->flags & SERVICE_USE_TIMEOUT ) if ( s->flags & SERVICE_USE_TIMEOUT )
{
if ((s->expire.tv_sec < curTime.tv_sec) || if ((s->expire.tv_sec < curTime.tv_sec) ||
((s->expire.tv_sec == curTime.tv_sec) && ((s->expire.tv_sec == curTime.tv_sec) &&
(s->expire.tv_usec <= curTime.tv_usec))) (s->expire.tv_usec <= curTime.tv_usec)))
@ -116,23 +117,22 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
callback_arg = s->callback_arg; callback_arg = s->callback_arg;
break; break;
} }
}
} }
HeapUnlock( service->heap ); HeapUnlock( GetProcessHeap() );
/* If found, call callback routine */ /* If found, call callback routine */
if ( callback ) if ( callback )
{ {
callback( callback_arg ); callback( callback_arg );
continue; continue;
} }
/* If not found, determine wait condition */ /* If not found, determine wait condition */
HeapLock( service->heap ); HeapLock( GetProcessHeap() );
count = 0; count = 0;
timeout = INFINITE; timeout = INFINITE;
@ -154,7 +154,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
} }
} }
HeapUnlock( service->heap ); HeapUnlock( GetProcessHeap() );
/* Wait until some condition satisfied */ /* 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 ); service_table = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) );
if ( !heap ) return FALSE; if ( !service_table )
Service = HeapAlloc( heap, HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) );
if ( !Service )
{ {
HeapDestroy( heap );
return FALSE; 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, thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SERVICE_Loop,
Service, 0, NULL ); service_table, 0, NULL );
if ( thread == INVALID_HANDLE_VALUE ) if ( thread == INVALID_HANDLE_VALUE )
{ {
HeapDestroy( heap ); pdb->service_table = 0;
HeapFree( GetProcessHeap(), 0, service_table );
return FALSE; return FALSE;
} }
Service->thread = ConvertToGlobalHandle( thread ); service_table->thread = thread;
return TRUE; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* SERVICE_AddObject * 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, HANDLE SERVICE_AddObject( HANDLE object,
PAPCFUNC callback, ULONG_PTR callback_arg ) PAPCFUNC callback, ULONG_PTR callback_arg )
{ {
SERVICE *s; SERVICE *s;
HANDLE handle; SERVICETABLE *service_table;
HANDLE handle;
object = ConvertToGlobalHandle( object ); /* FIXME */ if ( object == INVALID_HANDLE_VALUE || !callback )
if ( !Service || object == INVALID_HANDLE_VALUE || !callback )
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) ); if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable())
if ( !s ) return INVALID_HANDLE_VALUE; 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 = callback;
s->callback_arg = callback_arg; s->callback_arg = callback_arg;
s->object = object; s->object = object;
s->flags = SERVICE_USE_OBJECT; s->flags = SERVICE_USE_OBJECT;
s->self = handle = (HANDLE)++Service->counter; HeapLock( GetProcessHeap() );
s->next = Service->first;
Service->first = s;
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; return handle;
} }
@ -244,16 +254,19 @@ HANDLE SERVICE_AddObject( HANDLE object,
HANDLE SERVICE_AddTimer( LONG rate, HANDLE SERVICE_AddTimer( LONG rate,
PAPCFUNC callback, ULONG_PTR callback_arg ) PAPCFUNC callback, ULONG_PTR callback_arg )
{ {
SERVICE *s; SERVICE *s;
HANDLE handle; SERVICETABLE *service_table;
HANDLE handle;
if ( !Service || !rate || !callback ) if ( !rate || !callback )
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) ); if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable())
if ( !s ) return INVALID_HANDLE_VALUE; 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 = callback;
s->callback_arg = callback_arg; s->callback_arg = callback_arg;
@ -263,13 +276,15 @@ HANDLE SERVICE_AddTimer( LONG rate,
gettimeofday( &s->expire, NULL ); gettimeofday( &s->expire, NULL );
SERVICE_AddTimeval( &s->expire, s->rate ); SERVICE_AddTimeval( &s->expire, s->rate );
s->self = handle = (HANDLE)++Service->counter; HeapLock( GetProcessHeap() );
s->next = Service->first;
Service->first = s;
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; return handle;
} }
@ -279,33 +294,38 @@ HANDLE SERVICE_AddTimer( LONG rate,
*/ */
BOOL SERVICE_Delete( HANDLE service ) BOOL SERVICE_Delete( HANDLE service )
{ {
HANDLE handle = INVALID_HANDLE_VALUE; HANDLE handle = INVALID_HANDLE_VALUE;
BOOL retv = TRUE; BOOL retv = FALSE;
SERVICE **s, *next; 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)->self == service )
{ {
if ( (*s)->flags & SERVICE_USE_OBJECT ) if ( (*s)->flags & SERVICE_USE_OBJECT )
handle = (*s)->object; handle = (*s)->object;
next = (*s)->next; next = (*s)->next;
HeapFree( Service->heap, 0, *s ); HeapFree( GetProcessHeap(), 0, *s );
*s = next; *s = next;
retv = FALSE; retv = TRUE;
break; break;
} }
}
HeapUnlock( Service->heap ); HeapUnlock( GetProcessHeap() );
if ( handle != INVALID_HANDLE_VALUE ) if ( handle != INVALID_HANDLE_VALUE )
CloseHandle( handle ); CloseHandle( handle );
QueueUserAPC( NULL, Service->thread, 0L ); QueueUserAPC( NULL, service_table->thread, 0L );
return retv; return retv;
} }
@ -315,14 +335,18 @@ BOOL SERVICE_Delete( HANDLE service )
*/ */
BOOL SERVICE_Enable( HANDLE service ) BOOL SERVICE_Enable( HANDLE service )
{ {
BOOL retv = TRUE; BOOL retv = FALSE;
SERVICE *s; 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->self == service )
{ {
if ( s->flags & SERVICE_DISABLED ) if ( s->flags & SERVICE_DISABLED )
@ -341,13 +365,14 @@ BOOL SERVICE_Enable( HANDLE service )
(delta / s->rate) * s->rate ); (delta / s->rate) * s->rate );
} }
} }
retv = FALSE; retv = TRUE;
break; break;
} }
}
HeapUnlock( Service->heap ); HeapUnlock( GetProcessHeap() );
QueueUserAPC( NULL, Service->thread, 0L ); QueueUserAPC( NULL, service_table->thread, 0L );
return retv; return retv;
} }
@ -357,24 +382,29 @@ BOOL SERVICE_Enable( HANDLE service )
*/ */
BOOL SERVICE_Disable( HANDLE service ) BOOL SERVICE_Disable( HANDLE service )
{ {
BOOL retv = TRUE; BOOL retv = TRUE;
SERVICE *s; 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->self == service )
{ {
s->flags |= SERVICE_DISABLED; s->flags |= SERVICE_DISABLED;
retv = FALSE; retv = TRUE;
break; break;
} }
}
HeapUnlock( Service->heap ); HeapUnlock( GetProcessHeap() );
QueueUserAPC( NULL, Service->thread, 0L ); QueueUserAPC( NULL, service_table->thread, 0L );
return retv; return retv;
} }

View File

@ -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_request request;
struct new_thread_reply reply = { NULL, -1 }; struct new_thread_reply reply = { NULL, -1 };
int fd[2]; int fd[2];
HANDLE cleanup_object;
THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) ); THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
if (!thdb) return NULL; if (!thdb) return NULL;
@ -250,9 +251,11 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
THREAD_First = thdb; THREAD_First = thdb;
/* Install cleanup handler */ /* 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; return thdb;
error: error: