Skip to content
Snippets Groups Projects
Commit 63c7cdf1 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard
Browse files

Made the service thread instanciable in every process.

parent ffe6b767
No related branches found
No related tags found
No related merge requests found
......@@ -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 */
......
......@@ -9,8 +9,6 @@
#include "winbase.h"
BOOL SERVICE_Init( void );
HANDLE SERVICE_AddObject( HANDLE object,
PAPCFUNC callback, ULONG_PTR callback_arg );
......
......@@ -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;
......
......@@ -8,45 +8,41 @@
#include <unistd.h>
#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;
heap = HeapCreate( HEAP_GROWABLE, 0x1000, 0 );
if ( !heap ) return FALSE;
HANDLE thread;
SERVICETABLE *service_table;
PDB *pdb = PROCESS_Current();
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;
object = ConvertToGlobalHandle( object ); /* FIXME */
SERVICE *s;
SERVICETABLE *service_table;
HANDLE handle;
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() );
s->self = handle = (HANDLE)++service_table->counter;
s->next = service_table->first;
service_table->first = s;
HeapUnlock( Service->heap );
HeapUnlock( GetProcessHeap() );
QueueUserAPC( NULL, Service->thread, 0L );
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() );
s->self = handle = (HANDLE)++service_table->counter;
s->next = service_table->first;
service_table->first = s;
HeapUnlock( Service->heap );
HeapUnlock( GetProcessHeap() );
QueueUserAPC( NULL, Service->thread, 0L );
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;
}
......
......@@ -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:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment