Removed client-side wait functions; all waiting is now done through
the server.
This commit is contained in:
parent
63cb0f8b99
commit
55443878fc
21 changed files with 303 additions and 1371 deletions
|
@ -15,22 +15,13 @@
|
|||
#include "process.h"
|
||||
#include "thread.h"
|
||||
#include "heap.h"
|
||||
#include "server.h"
|
||||
#include "debug.h"
|
||||
|
||||
static BOOL32 CHANGE_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 CHANGE_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void CHANGE_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void CHANGE_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void CHANGE_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS CHANGE_Ops =
|
||||
{
|
||||
CHANGE_Signaled, /* signaled */
|
||||
CHANGE_Satisfied, /* satisfied */
|
||||
CHANGE_AddWait, /* add_wait */
|
||||
CHANGE_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
CHANGE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -48,51 +39,6 @@ typedef struct
|
|||
|
||||
} CHANGE_OBJECT;
|
||||
|
||||
/***********************************************************************
|
||||
* CHANGE_Signaled
|
||||
*/
|
||||
static BOOL32 CHANGE_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj;
|
||||
assert( obj->type == K32OBJ_CHANGE );
|
||||
return change->notify;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CHANGE_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 CHANGE_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
assert( obj->type == K32OBJ_CHANGE );
|
||||
return FALSE; /* Not abandoned */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CHANGE_AddWait
|
||||
*
|
||||
* Add thread to object wait queue.
|
||||
*/
|
||||
static void CHANGE_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj;
|
||||
assert( obj->type == K32OBJ_CHANGE );
|
||||
THREAD_AddQueue( &change->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CHANGE_RemoveWait
|
||||
*
|
||||
* Remove thread from object wait queue.
|
||||
*/
|
||||
static void CHANGE_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj;
|
||||
assert( obj->type == K32OBJ_CHANGE );
|
||||
THREAD_RemoveQueue( &change->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CHANGE_Destroy
|
||||
*/
|
||||
|
@ -118,11 +64,24 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName,
|
|||
BOOL32 bWatchSubtree,
|
||||
DWORD dwNotifyFilter )
|
||||
{
|
||||
HANDLE32 handle;
|
||||
CHANGE_OBJECT *change;
|
||||
struct create_change_notification_request req;
|
||||
struct create_change_notification_reply reply;
|
||||
int len;
|
||||
|
||||
req.subtree = bWatchSubtree;
|
||||
req.filter = dwNotifyFilter;
|
||||
CLIENT_SendRequest( REQ_CREATE_CHANGE_NOTIFICATION, -1, 1, &req, sizeof(req) );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
|
||||
|
||||
change = HeapAlloc( SystemHeap, 0, sizeof(CHANGE_OBJECT) );
|
||||
if (!change) return INVALID_HANDLE_VALUE32;
|
||||
if (!change)
|
||||
{
|
||||
CLIENT_CloseHandle( reply.handle );
|
||||
return INVALID_HANDLE_VALUE32;
|
||||
}
|
||||
|
||||
change->header.type = K32OBJ_CHANGE;
|
||||
change->header.refcount = 1;
|
||||
|
@ -134,11 +93,9 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName,
|
|||
change->wait_queue = NULL;
|
||||
change->notify = FALSE;
|
||||
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), &change->header,
|
||||
FILE_ALL_ACCESS /*FIXME*/, TRUE, -1 );
|
||||
/* If the allocation failed, the object is already destroyed */
|
||||
if (handle == INVALID_HANDLE_VALUE32) change = NULL;
|
||||
return handle;
|
||||
return HANDLE_Alloc( PROCESS_Current(), &change->header,
|
||||
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE /*FIXME*/,
|
||||
FALSE, reply.handle );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
139
files/file.c
139
files/file.c
|
@ -45,29 +45,10 @@
|
|||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static BOOL32 FILE_Signaled(K32OBJ *ptr, DWORD tid);
|
||||
static BOOL32 FILE_Satisfied(K32OBJ *ptr, DWORD thread_id);
|
||||
static void FILE_AddWait(K32OBJ *ptr, DWORD tid);
|
||||
static void FILE_RemoveWait(K32OBJ *ptr, DWORD thread_id);
|
||||
#endif
|
||||
static void FILE_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS FILE_Ops =
|
||||
{
|
||||
#if 0
|
||||
FILE_Signaled, /* signaled */
|
||||
FILE_Satisfied, /* satisfied */
|
||||
FILE_AddWait, /* add_wait */
|
||||
FILE_RemoveWait, /* remove_wait */
|
||||
#else
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
#endif
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
FILE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -126,58 +107,6 @@ HFILE32 FILE_Alloc( FILE_OBJECT **file, int unix_handle )
|
|||
return handle;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_async_handler [internal]
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
FILE_async_handler(int unixfd,void *private) {
|
||||
FILE_OBJECT *file = (FILE_OBJECT*)private;
|
||||
|
||||
SYNC_WakeUp(&file->wait_queue,INFINITE32);
|
||||
}
|
||||
|
||||
static BOOL32 FILE_Signaled(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
fd_set fds,*readfds = NULL,*writefds = NULL;
|
||||
struct timeval tv;
|
||||
FILE_OBJECT *file = (FILE_OBJECT *)ptr;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(file->unix_handle,&fds);
|
||||
if (file->mode == OF_READ) readfds = &fds;
|
||||
if (file->mode == OF_WRITE) writefds = &fds;
|
||||
if (file->mode == OF_READWRITE) {writefds = &fds; readfds = &fds;}
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
assert(readfds || writefds);
|
||||
if (select(file->unix_handle+1,readfds,writefds,NULL,&tv)>0)
|
||||
return TRUE; /* we triggered one fd. Whereever. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void FILE_AddWait(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
FILE_OBJECT *file = (FILE_OBJECT*)ptr;
|
||||
if (!file->wait_queue)
|
||||
ASYNC_RegisterFD(file->unix_handle,FILE_async_handler,file);
|
||||
THREAD_AddQueue(&file->wait_queue,thread_id);
|
||||
}
|
||||
|
||||
static void FILE_RemoveWait(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
FILE_OBJECT *file = (FILE_OBJECT*)ptr;
|
||||
THREAD_RemoveQueue(&file->wait_queue,thread_id);
|
||||
if (!file->wait_queue)
|
||||
ASYNC_UnregisterFD(file->unix_handle,FILE_async_handler);
|
||||
}
|
||||
|
||||
static BOOL32 FILE_Satisfied(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
return FALSE; /* not abandoned. Hmm? */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_Destroy
|
||||
|
@ -1248,6 +1177,7 @@ BOOL32 WINAPI ReadFile( HANDLE32 hFile, LPVOID buffer, DWORD bytesToRead,
|
|||
{
|
||||
K32OBJ *ptr;
|
||||
struct get_read_fd_request req;
|
||||
int unix_handle, result;
|
||||
|
||||
TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToRead );
|
||||
|
||||
|
@ -1258,29 +1188,25 @@ BOOL32 WINAPI ReadFile( HANDLE32 hFile, LPVOID buffer, DWORD bytesToRead,
|
|||
K32OBJ_UNKNOWN, GENERIC_READ, &req.handle )))
|
||||
return FALSE;
|
||||
|
||||
if (req.handle != -1) /* We have a server handle */
|
||||
if (req.handle == -1) /* We need a server handle */
|
||||
{
|
||||
int unix_handle, result;
|
||||
|
||||
CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
|
||||
CLIENT_WaitReply( NULL, &unix_handle, 0 );
|
||||
if (unix_handle == -1) return FALSE;
|
||||
if ((result = read( unix_handle, buffer, bytesToRead )) == -1)
|
||||
FILE_SetDosError();
|
||||
close( unix_handle );
|
||||
K32OBJ_DecCount( ptr );
|
||||
if (result == -1) return FALSE;
|
||||
if (bytesRead) *bytesRead = result;
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
|
||||
CLIENT_WaitReply( NULL, &unix_handle, 0 );
|
||||
K32OBJ_DecCount( ptr );
|
||||
if (unix_handle == -1) return FALSE;
|
||||
while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
|
||||
{
|
||||
BOOL32 status = FALSE;
|
||||
if (K32OBJ_OPS(ptr)->read)
|
||||
status = K32OBJ_OPS(ptr)->read(ptr, buffer, bytesToRead, bytesRead, overlapped );
|
||||
K32OBJ_DecCount( ptr );
|
||||
return status;
|
||||
if ((errno == EAGAIN) || (errno == EINTR)) continue;
|
||||
FILE_SetDosError();
|
||||
break;
|
||||
}
|
||||
close( unix_handle );
|
||||
if (result == -1) return FALSE;
|
||||
if (bytesRead) *bytesRead = result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1292,6 +1218,7 @@ BOOL32 WINAPI WriteFile( HANDLE32 hFile, LPCVOID buffer, DWORD bytesToWrite,
|
|||
{
|
||||
K32OBJ *ptr;
|
||||
struct get_write_fd_request req;
|
||||
int unix_handle, result;
|
||||
|
||||
TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToWrite );
|
||||
|
||||
|
@ -1302,31 +1229,25 @@ BOOL32 WINAPI WriteFile( HANDLE32 hFile, LPCVOID buffer, DWORD bytesToWrite,
|
|||
K32OBJ_UNKNOWN, GENERIC_WRITE, &req.handle )))
|
||||
return FALSE;
|
||||
|
||||
if (req.handle != -1) /* We have a server handle */
|
||||
if (req.handle == -1) /* We need a server handle */
|
||||
{
|
||||
int unix_handle, result;
|
||||
|
||||
CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
|
||||
CLIENT_WaitReply( NULL, &unix_handle, 0 );
|
||||
if (unix_handle == -1) return FALSE;
|
||||
|
||||
if ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
|
||||
FILE_SetDosError();
|
||||
close( unix_handle );
|
||||
K32OBJ_DecCount( ptr );
|
||||
if (result == -1) return FALSE;
|
||||
if (bytesWritten) *bytesWritten = result;
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
|
||||
CLIENT_WaitReply( NULL, &unix_handle, 0 );
|
||||
K32OBJ_DecCount( ptr );
|
||||
if (unix_handle == -1) return FALSE;
|
||||
while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
|
||||
{
|
||||
BOOL32 status = FALSE;
|
||||
if (K32OBJ_OPS(ptr)->write)
|
||||
status = K32OBJ_OPS(ptr)->write( ptr, buffer, bytesToWrite,
|
||||
bytesWritten, overlapped );
|
||||
K32OBJ_DecCount( ptr );
|
||||
return status;
|
||||
if ((errno == EAGAIN) || (errno == EINTR)) continue;
|
||||
FILE_SetDosError();
|
||||
break;
|
||||
}
|
||||
close( unix_handle );
|
||||
if (result == -1) return FALSE;
|
||||
if (bytesWritten) *bytesWritten = result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,12 +44,6 @@ typedef struct
|
|||
/* Kernel object operations */
|
||||
typedef struct
|
||||
{
|
||||
BOOL32 (*signaled)(K32OBJ*,DWORD); /* Is object signaled? */
|
||||
BOOL32 (*satisfied)(K32OBJ*,DWORD); /* Wait on object is satisfied */
|
||||
void (*add_wait)(K32OBJ*,DWORD); /* Add thread to wait queue */
|
||||
void (*remove_wait)(K32OBJ*,DWORD); /* Remove thread from wait queue */
|
||||
BOOL32 (*read)(K32OBJ*,LPVOID,DWORD,LPDWORD,LPOVERLAPPED);
|
||||
BOOL32 (*write)(K32OBJ*,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED);
|
||||
void (*destroy)(K32OBJ *); /* Destroy object on refcount==0 */
|
||||
} K32OBJ_OPS;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef struct _PDB32
|
|||
{
|
||||
K32OBJ header; /* 00 Kernel object header */
|
||||
DWORD unknown1; /* 08 Unknown */
|
||||
K32OBJ *event; /* 0c Pointer to an event object */
|
||||
K32OBJ *event; /* 0c Pointer to an event object (unused) */
|
||||
DWORD exit_code; /* 10 Process exit code */
|
||||
DWORD unknown2; /* 14 Unknown */
|
||||
HANDLE32 heap; /* 18 Default process heap */
|
||||
|
@ -102,7 +102,7 @@ typedef struct _PDB32
|
|||
K32OBJ *console_provider; /* b0 Console provider (??) */
|
||||
WORD env_selector; /* b4 Selector to process environment */
|
||||
WORD error_mode; /* b6 Error mode */
|
||||
K32OBJ *load_done_evt; /* b8 Event for process loading done */
|
||||
HANDLE32 load_done_evt; /* b8 Event for process loading done */
|
||||
DWORD unknown7; /* bc Unknown */
|
||||
DWORD unknown8; /* c0 Unknown (NT) */
|
||||
LCID locale; /* c4 Locale to be queried by GetThreadLocale (NT) */
|
||||
|
@ -136,6 +136,8 @@ extern HANDLE32 HANDLE_Alloc( PDB32 *pdb, K32OBJ *ptr, DWORD access,
|
|||
extern K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle,
|
||||
K32OBJ_TYPE type, DWORD access,
|
||||
int *server_handle );
|
||||
extern int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
|
||||
K32OBJ_TYPE type, DWORD access );
|
||||
extern BOOL32 HANDLE_SetObjPtr( PDB32 *pdb, HANDLE32 handle,
|
||||
K32OBJ *ptr, DWORD access );
|
||||
extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
|
||||
|
|
|
@ -64,7 +64,6 @@ typedef struct
|
|||
DWORD signaled; /* Index of signaled object (or WAIT_FAILED)*/
|
||||
BOOL32 wait_all; /* Wait for all objects flag */
|
||||
BOOL32 wait_msg; /* Wait for message flag */
|
||||
BOOL32 use_server; /* Use server call for waiting */
|
||||
K32OBJ *objs[MAXIMUM_WAIT_OBJECTS]; /* Object pointers */
|
||||
int server[MAXIMUM_WAIT_OBJECTS]; /* Server handles */
|
||||
} WAIT_STRUCT;
|
||||
|
@ -107,8 +106,7 @@ typedef struct _THDB
|
|||
void *entry_point; /* 1c0 Thread entry point (was: unknown) */
|
||||
void *entry_arg; /* 1c4 Entry point arg (was: unknown) */
|
||||
int unix_pid; /* 1c8 Unix thread pid (was: unknown) */
|
||||
K32OBJ *mutex_list; /* 1cc List of owned mutex (was: unknown)*/
|
||||
DWORD unknown5[2]; /* 1d0 Unknown */
|
||||
DWORD unknown5[3]; /* 1cc Unknown */
|
||||
DWORD sys_count[4]; /* 1d8 Syslevel mutex entry counters */
|
||||
CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */
|
||||
DWORD unknown6[2]; /* 1f8 Unknown */
|
||||
|
@ -162,18 +160,7 @@ extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread );
|
|||
extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
|
||||
extern DWORD THREAD_TlsAlloc( THDB *thread );
|
||||
|
||||
/* scheduler/event.c */
|
||||
extern void EVENT_Set( K32OBJ *obj );
|
||||
extern K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state );
|
||||
|
||||
/* scheduler/mutex.c */
|
||||
extern void MUTEX_Abandon( K32OBJ *obj );
|
||||
|
||||
/* scheduler/synchro.c */
|
||||
extern void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout );
|
||||
extern void SYNC_WakeUp( THREAD_QUEUE *queue, DWORD max );
|
||||
extern void SYNC_MsgWakeUp( THDB *thdb );
|
||||
extern void SYNC_SetupSignals(void);
|
||||
extern DWORD SYNC_DoWait( DWORD count, const HANDLE32 *handles,
|
||||
BOOL32 wait_all, DWORD timeout,
|
||||
BOOL32 alertable, BOOL32 wait_msg );
|
||||
|
|
|
@ -156,8 +156,6 @@ extern void ASYNC_sigio(int a);
|
|||
*/
|
||||
BOOL32 SIGNAL_Init(void)
|
||||
{
|
||||
extern void SYNC_SetupSignals(void);
|
||||
|
||||
#ifdef HAVE_WORKING_SIGALTSTACK
|
||||
struct sigaltstack ss;
|
||||
ss.ss_sp = SIGNAL_Stack;
|
||||
|
@ -187,8 +185,6 @@ BOOL32 SIGNAL_Init(void)
|
|||
|
||||
/* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */
|
||||
signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
SYNC_SetupSignals();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,13 +110,6 @@ static void VIRTUAL_DestroyMapping( K32OBJ *obj );
|
|||
|
||||
const K32OBJ_OPS MEM_MAPPED_FILE_Ops =
|
||||
{
|
||||
/* Object cannot be waited upon, so we don't need these (except destroy) */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
VIRTUAL_DestroyMapping /* destroy */
|
||||
};
|
||||
|
||||
|
|
|
@ -29,12 +29,6 @@ static void SNAPSHOT_Destroy( K32OBJ *obj );
|
|||
|
||||
const K32OBJ_OPS SNAPSHOT_Ops =
|
||||
{
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
SNAPSHOT_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
|
|
@ -327,32 +327,6 @@ int CLIENT_SetDebug( int level )
|
|||
return CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_TerminateProcess
|
||||
*
|
||||
* Send a terminate process request. Return 0 if OK.
|
||||
*/
|
||||
int CLIENT_TerminateProcess( int handle, int exit_code )
|
||||
{
|
||||
CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 2,
|
||||
&handle, sizeof(handle),
|
||||
&exit_code, sizeof(exit_code) );
|
||||
return CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_TerminateThread
|
||||
*
|
||||
* Send a terminate thread request. Return 0 if OK.
|
||||
*/
|
||||
int CLIENT_TerminateThread( int handle, int exit_code )
|
||||
{
|
||||
CLIENT_SendRequest( REQ_TERMINATE_THREAD, -1, 2,
|
||||
&handle, sizeof(handle),
|
||||
&exit_code, sizeof(exit_code) );
|
||||
return CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_CloseHandle
|
||||
*
|
||||
|
|
|
@ -18,68 +18,16 @@
|
|||
typedef struct
|
||||
{
|
||||
K32OBJ header;
|
||||
THREAD_QUEUE wait_queue;
|
||||
BOOL32 manual_reset;
|
||||
BOOL32 signaled;
|
||||
} EVENT;
|
||||
|
||||
static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void EVENT_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS EVENT_Ops =
|
||||
{
|
||||
EVENT_Signaled, /* signaled */
|
||||
EVENT_Satisfied, /* satisfied */
|
||||
EVENT_AddWait, /* add_wait */
|
||||
EVENT_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
EVENT_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Set
|
||||
*
|
||||
* Implementation of SetEvent. Used by ExitThread and ExitProcess.
|
||||
*/
|
||||
void EVENT_Set( K32OBJ *obj )
|
||||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
SYSTEM_LOCK();
|
||||
event->signaled = TRUE;
|
||||
SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Create
|
||||
*
|
||||
* Partial implementation of CreateEvent.
|
||||
* Used internally by processes and threads.
|
||||
*/
|
||||
K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state )
|
||||
{
|
||||
EVENT *event;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
if ((event = HeapAlloc( SystemHeap, 0, sizeof(*event) )))
|
||||
{
|
||||
event->header.type = K32OBJ_EVENT;
|
||||
event->header.refcount = 1;
|
||||
event->wait_queue = NULL;
|
||||
event->manual_reset = manual_reset;
|
||||
event->signaled = initial_state;
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return event ? &event->header : NULL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CreateEvent32A (KERNEL32.156)
|
||||
*/
|
||||
|
@ -99,20 +47,15 @@ HANDLE32 WINAPI CreateEvent32A( SECURITY_ATTRIBUTES *sa, BOOL32 manual_reset,
|
|||
CLIENT_SendRequest( REQ_CREATE_EVENT, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle == -1) return NULL;
|
||||
if (reply.handle == -1) return 0;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
event = (EVENT *)K32OBJ_Create( K32OBJ_EVENT, sizeof(*event), name,
|
||||
reply.handle, EVENT_ALL_ACCESS, sa, &handle );
|
||||
if (event)
|
||||
{
|
||||
/* Finish initializing it */
|
||||
event->wait_queue = NULL;
|
||||
event->manual_reset = manual_reset;
|
||||
event->signaled = initial_state;
|
||||
K32OBJ_DecCount( &event->header );
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
if (handle == INVALID_HANDLE_VALUE32) handle = 0;
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -145,13 +88,29 @@ HANDLE32 WINAPI OpenEvent32A( DWORD access, BOOL32 inherit, LPCSTR name )
|
|||
{
|
||||
HANDLE32 handle = 0;
|
||||
K32OBJ *obj;
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_EVENT )) != NULL)
|
||||
struct open_named_obj_request req;
|
||||
struct open_named_obj_reply reply;
|
||||
int len = name ? strlen(name) + 1 : 0;
|
||||
|
||||
req.type = OPEN_EVENT;
|
||||
req.access = access;
|
||||
req.inherit = inherit;
|
||||
CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle != -1)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, -1 );
|
||||
K32OBJ_DecCount( obj );
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_EVENT )) != NULL)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, reply.handle );
|
||||
K32OBJ_DecCount( obj );
|
||||
if (handle == INVALID_HANDLE_VALUE32)
|
||||
handle = 0; /* must return 0 on failure, not -1 */
|
||||
}
|
||||
else CLIENT_CloseHandle( reply.handle );
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -168,34 +127,30 @@ HANDLE32 WINAPI OpenEvent32W( DWORD access, BOOL32 inherit, LPCWSTR name )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Operation
|
||||
*
|
||||
* Execute an event operation (set,reset,pulse).
|
||||
*/
|
||||
static BOOL32 EVENT_Operation( HANDLE32 handle, enum event_op op )
|
||||
{
|
||||
struct event_op_request req;
|
||||
|
||||
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
|
||||
K32OBJ_EVENT, EVENT_MODIFY_STATE );
|
||||
if (req.handle == -1) return FALSE;
|
||||
req.op = op;
|
||||
CLIENT_SendRequest( REQ_EVENT_OP, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PulseEvent (KERNEL32.557)
|
||||
*/
|
||||
BOOL32 WINAPI PulseEvent( HANDLE32 handle )
|
||||
{
|
||||
struct event_op_request req;
|
||||
EVENT *event;
|
||||
SYSTEM_LOCK();
|
||||
if (!(event = (EVENT *)HANDLE_GetObjPtr(PROCESS_Current(), handle,
|
||||
K32OBJ_EVENT, EVENT_MODIFY_STATE,
|
||||
&req.handle )))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
if (req.handle != -1)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
req.op = PULSE_EVENT;
|
||||
CLIENT_SendRequest( REQ_EVENT_OP, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
event->signaled = TRUE;
|
||||
SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
|
||||
event->signaled = FALSE;
|
||||
K32OBJ_DecCount( &event->header );
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
return EVENT_Operation( handle, PULSE_EVENT );
|
||||
}
|
||||
|
||||
|
||||
|
@ -204,28 +159,7 @@ BOOL32 WINAPI PulseEvent( HANDLE32 handle )
|
|||
*/
|
||||
BOOL32 WINAPI SetEvent( HANDLE32 handle )
|
||||
{
|
||||
struct event_op_request req;
|
||||
EVENT *event;
|
||||
SYSTEM_LOCK();
|
||||
if (!(event = (EVENT *)HANDLE_GetObjPtr(PROCESS_Current(), handle,
|
||||
K32OBJ_EVENT, EVENT_MODIFY_STATE,
|
||||
&req.handle )))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
if (req.handle != -1)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
req.op = SET_EVENT;
|
||||
CLIENT_SendRequest( REQ_EVENT_OP, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
event->signaled = TRUE;
|
||||
SYNC_WakeUp( &event->wait_queue, event->manual_reset ? INFINITE32 : 1 );
|
||||
K32OBJ_DecCount( &event->header );
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
return EVENT_Operation( handle, SET_EVENT );
|
||||
}
|
||||
|
||||
|
||||
|
@ -234,79 +168,7 @@ BOOL32 WINAPI SetEvent( HANDLE32 handle )
|
|||
*/
|
||||
BOOL32 WINAPI ResetEvent( HANDLE32 handle )
|
||||
{
|
||||
struct event_op_request req;
|
||||
EVENT *event;
|
||||
SYSTEM_LOCK();
|
||||
if (!(event = (EVENT *)HANDLE_GetObjPtr(PROCESS_Current(), handle,
|
||||
K32OBJ_EVENT, EVENT_MODIFY_STATE,
|
||||
&req.handle )))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
if (req.handle != -1)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
req.op = RESET_EVENT;
|
||||
CLIENT_SendRequest( REQ_EVENT_OP, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
event->signaled = FALSE;
|
||||
K32OBJ_DecCount( &event->header );
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Signaled
|
||||
*/
|
||||
static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
return event->signaled;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
/* Reset if it's an auto-reset event */
|
||||
if (!event->manual_reset) event->signaled = FALSE;
|
||||
return FALSE; /* Not abandoned */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_AddWait
|
||||
*
|
||||
* Add thread to object wait queue.
|
||||
*/
|
||||
static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
THREAD_AddQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_RemoveWait
|
||||
*
|
||||
* Remove thread from object wait queue.
|
||||
*/
|
||||
static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
THREAD_RemoveQueue( &event->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
return EVENT_Operation( handle, RESET_EVENT );
|
||||
}
|
||||
|
||||
|
||||
|
@ -317,8 +179,6 @@ static void EVENT_Destroy( K32OBJ *obj )
|
|||
{
|
||||
EVENT *event = (EVENT *)obj;
|
||||
assert( obj->type == K32OBJ_EVENT );
|
||||
/* There cannot be any thread on the list since the ref count is 0 */
|
||||
assert( event->wait_queue == NULL );
|
||||
obj->type = K32OBJ_UNKNOWN;
|
||||
HeapFree( SystemHeap, 0, event );
|
||||
}
|
||||
|
|
|
@ -191,6 +191,27 @@ K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle,
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* HANDLE_GetServerHandle
|
||||
*
|
||||
* Retrieve the server handle associated to an object.
|
||||
*/
|
||||
int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
|
||||
K32OBJ_TYPE type, DWORD access )
|
||||
{
|
||||
int server_handle;
|
||||
K32OBJ *obj;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = HANDLE_GetObjPtr( pdb, handle, type, access, &server_handle )))
|
||||
K32OBJ_DecCount( obj );
|
||||
else
|
||||
server_handle = -1;
|
||||
SYSTEM_UNLOCK();
|
||||
return server_handle;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* HANDLE_SetObjPtr
|
||||
*
|
||||
|
@ -413,3 +434,38 @@ done:
|
|||
SYSTEM_UNLOCK();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ConvertToGlobalHandle (KERNEL32)
|
||||
*/
|
||||
HANDLE32 WINAPI ConvertToGlobalHandle(HANDLE32 hSrc)
|
||||
{
|
||||
int src_handle, dst_handle;
|
||||
HANDLE32 handle;
|
||||
K32OBJ *obj = NULL;
|
||||
DWORD access;
|
||||
|
||||
if (HANDLE_IS_GLOBAL(hSrc))
|
||||
return hSrc;
|
||||
|
||||
if (!(obj = HANDLE_GetObjPtr( PROCESS_Current(), hSrc, K32OBJ_UNKNOWN, 0, &src_handle )))
|
||||
return 0;
|
||||
|
||||
HANDLE_GetAccess( PROCESS_Current(), hSrc, &access );
|
||||
|
||||
if (src_handle != -1)
|
||||
dst_handle = CLIENT_DuplicateHandle( GetCurrentProcess(), src_handle, -1, -1, 0, FALSE,
|
||||
DUP_HANDLE_MAKE_GLOBAL | DUP_HANDLE_SAME_ACCESS );
|
||||
else
|
||||
dst_handle = -1;
|
||||
|
||||
if ((handle = HANDLE_Alloc( PROCESS_Initial(), obj, access, FALSE,
|
||||
dst_handle )) != INVALID_HANDLE_VALUE32)
|
||||
handle = HANDLE_LOCAL_TO_GLOBAL(handle);
|
||||
else
|
||||
handle = 0;
|
||||
|
||||
CloseHandle( hSrc );
|
||||
return handle;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
|
||||
/* The declarations are here to avoid including a lot of unnecessary files */
|
||||
extern const K32OBJ_OPS CRITICAL_SECTION_Ops;
|
||||
extern const K32OBJ_OPS PROCESS_Ops;
|
||||
extern const K32OBJ_OPS THREAD_Ops;
|
||||
extern const K32OBJ_OPS FILE_Ops;
|
||||
|
@ -30,12 +29,6 @@ extern const K32OBJ_OPS PIPE_Ops;
|
|||
|
||||
static const K32OBJ_OPS K32OBJ_NullOps =
|
||||
{
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
NULL /* destroy */
|
||||
};
|
||||
|
||||
|
@ -45,7 +38,7 @@ const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
|
|||
&SEMAPHORE_Ops, /* K32OBJ_SEMAPHORE */
|
||||
&EVENT_Ops, /* K32OBJ_EVENT */
|
||||
&MUTEX_Ops, /* K32OBJ_MUTEX */
|
||||
&CRITICAL_SECTION_Ops, /* K32OBJ_CRITICAL_SECTION */
|
||||
&K32OBJ_NullOps, /* K32OBJ_CRITICAL_SECTION */
|
||||
&PROCESS_Ops, /* K32OBJ_PROCESS */
|
||||
&THREAD_Ops, /* K32OBJ_THREAD */
|
||||
&FILE_Ops, /* K32OBJ_FILE */
|
||||
|
|
|
@ -17,66 +17,16 @@
|
|||
typedef struct _MUTEX
|
||||
{
|
||||
K32OBJ header;
|
||||
THREAD_QUEUE wait_queue;
|
||||
DWORD owner;
|
||||
DWORD count;
|
||||
BOOL32 abandoned;
|
||||
struct _MUTEX *next;
|
||||
struct _MUTEX *prev;
|
||||
} MUTEX;
|
||||
|
||||
static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void MUTEX_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS MUTEX_Ops =
|
||||
{
|
||||
MUTEX_Signaled, /* signaled */
|
||||
MUTEX_Satisfied, /* satisfied */
|
||||
MUTEX_AddWait, /* add_wait */
|
||||
MUTEX_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
MUTEX_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_Release
|
||||
*
|
||||
* Release a mutex once the count is 0.
|
||||
* Helper function for MUTEX_Abandon and ReleaseMutex.
|
||||
*/
|
||||
static void MUTEX_Release( MUTEX *mutex )
|
||||
{
|
||||
/* Remove the mutex from the thread list of owned mutexes */
|
||||
if (mutex->next) mutex->next->prev = mutex->prev;
|
||||
if (mutex->prev) mutex->prev->next = mutex->next;
|
||||
else THREAD_Current()->mutex_list = &mutex->next->header;
|
||||
mutex->next = mutex->prev = NULL;
|
||||
mutex->owner = 0;
|
||||
SYNC_WakeUp( &mutex->wait_queue, INFINITE32 );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_Abandon
|
||||
*
|
||||
* Abandon a mutex.
|
||||
*/
|
||||
void MUTEX_Abandon( K32OBJ *obj )
|
||||
{
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
assert( mutex->count && (mutex->owner == GetCurrentThreadId()) );
|
||||
mutex->count = 0;
|
||||
mutex->abandoned = TRUE;
|
||||
MUTEX_Release( mutex );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CreateMutex32A (KERNEL32.166)
|
||||
*/
|
||||
|
@ -95,37 +45,14 @@ HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
|
|||
CLIENT_SendRequest( REQ_CREATE_MUTEX, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle == -1) return NULL;
|
||||
if (reply.handle == -1) return 0;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
mutex = (MUTEX *)K32OBJ_Create( K32OBJ_MUTEX, sizeof(*mutex),
|
||||
name, reply.handle, MUTEX_ALL_ACCESS,
|
||||
sa, &handle );
|
||||
if (mutex)
|
||||
{
|
||||
/* Finish initializing it */
|
||||
mutex->wait_queue = NULL;
|
||||
mutex->abandoned = FALSE;
|
||||
mutex->prev = NULL;
|
||||
if (owner)
|
||||
{
|
||||
K32OBJ **list;
|
||||
mutex->owner = GetCurrentThreadId();
|
||||
mutex->count = 1;
|
||||
/* Add the mutex in the thread list of owned mutexes */
|
||||
list = &THREAD_Current()->mutex_list;
|
||||
if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
|
||||
*list = &mutex->header;
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->owner = 0;
|
||||
mutex->count = 0;
|
||||
mutex->next = NULL;
|
||||
}
|
||||
K32OBJ_DecCount( &mutex->header );
|
||||
}
|
||||
SetLastError(0); /* FIXME */
|
||||
if (mutex) K32OBJ_DecCount( &mutex->header );
|
||||
if (handle == INVALID_HANDLE_VALUE32) handle = 0;
|
||||
SYSTEM_UNLOCK();
|
||||
return handle;
|
||||
}
|
||||
|
@ -151,13 +78,29 @@ HANDLE32 WINAPI OpenMutex32A( DWORD access, BOOL32 inherit, LPCSTR name )
|
|||
{
|
||||
HANDLE32 handle = 0;
|
||||
K32OBJ *obj;
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_MUTEX )) != NULL)
|
||||
struct open_named_obj_request req;
|
||||
struct open_named_obj_reply reply;
|
||||
int len = name ? strlen(name) + 1 : 0;
|
||||
|
||||
req.type = OPEN_MUTEX;
|
||||
req.access = access;
|
||||
req.inherit = inherit;
|
||||
CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle != -1)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, -1 );
|
||||
K32OBJ_DecCount( obj );
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_MUTEX )) != NULL)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, reply.handle );
|
||||
K32OBJ_DecCount( obj );
|
||||
if (handle == INVALID_HANDLE_VALUE32)
|
||||
handle = 0; /* must return 0 on failure, not -1 */
|
||||
}
|
||||
else CLIENT_CloseHandle( reply.handle );
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -180,95 +123,12 @@ HANDLE32 WINAPI OpenMutex32W( DWORD access, BOOL32 inherit, LPCWSTR name )
|
|||
BOOL32 WINAPI ReleaseMutex( HANDLE32 handle )
|
||||
{
|
||||
struct release_mutex_request req;
|
||||
MUTEX *mutex;
|
||||
SYSTEM_LOCK();
|
||||
if (!(mutex = (MUTEX *)HANDLE_GetObjPtr(PROCESS_Current(), handle,
|
||||
K32OBJ_MUTEX, MUTEX_MODIFY_STATE,
|
||||
&req.handle )))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
if (req.handle != -1)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
CLIENT_SendRequest( REQ_RELEASE_MUTEX, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
if (!mutex->count || (mutex->owner != GetCurrentThreadId()))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
SetLastError( ERROR_NOT_OWNER );
|
||||
return FALSE;
|
||||
}
|
||||
if (!--mutex->count) MUTEX_Release( mutex );
|
||||
K32OBJ_DecCount( &mutex->header );
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_Signaled
|
||||
*/
|
||||
static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
return (!mutex->count || (mutex->owner == thread_id));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
BOOL32 ret;
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
assert( !mutex->count || (mutex->owner == thread_id) );
|
||||
mutex->owner = thread_id;
|
||||
if (!mutex->count++)
|
||||
{
|
||||
/* Add the mutex in the thread list of owned mutexes */
|
||||
K32OBJ **list = &THREAD_ID_TO_THDB( thread_id )->mutex_list;
|
||||
assert( !mutex->next );
|
||||
if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
|
||||
*list = &mutex->header;
|
||||
mutex->prev = NULL;
|
||||
}
|
||||
ret = mutex->abandoned;
|
||||
mutex->abandoned = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_AddWait
|
||||
*
|
||||
* Add a thread to the object wait queue.
|
||||
*/
|
||||
static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
THREAD_AddQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MUTEX_RemoveWait
|
||||
*
|
||||
* Remove a thread from the object wait queue.
|
||||
*/
|
||||
static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
THREAD_RemoveQueue( &mutex->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
|
||||
K32OBJ_MUTEX, MUTEX_MODIFY_STATE );
|
||||
if (req.handle == -1) return FALSE;
|
||||
CLIENT_SendRequest( REQ_RELEASE_MUTEX, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,8 +139,6 @@ static void MUTEX_Destroy( K32OBJ *obj )
|
|||
{
|
||||
MUTEX *mutex = (MUTEX *)obj;
|
||||
assert( obj->type == K32OBJ_MUTEX );
|
||||
/* There cannot be any thread on the list since the ref count is 0 */
|
||||
assert( mutex->wait_queue == NULL );
|
||||
obj->type = K32OBJ_UNKNOWN;
|
||||
HeapFree( SystemHeap, 0, mutex );
|
||||
}
|
||||
|
|
|
@ -23,12 +23,6 @@ static void PIPE_Destroy( K32OBJ *obj );
|
|||
|
||||
const K32OBJ_OPS PIPE_Ops =
|
||||
{
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
PIPE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
|
|
@ -23,20 +23,10 @@
|
|||
#include "server.h"
|
||||
#include "debug.h"
|
||||
|
||||
static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void PROCESS_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS PROCESS_Ops =
|
||||
{
|
||||
PROCESS_Signaled, /* signaled */
|
||||
PROCESS_Satisfied, /* satisfied */
|
||||
PROCESS_AddWait, /* add_wait */
|
||||
PROCESS_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
PROCESS_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -295,8 +285,6 @@ static void PROCESS_FreePDB( PDB32 *pdb )
|
|||
if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
|
||||
ENV_FreeEnvironment( pdb );
|
||||
if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
|
||||
if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
|
||||
if (pdb->event) K32OBJ_DecCount( pdb->event );
|
||||
DeleteCriticalSection( &pdb->crit_section );
|
||||
HeapFree( SystemHeap, 0, pdb );
|
||||
}
|
||||
|
@ -325,19 +313,11 @@ static PDB32 *PROCESS_CreatePDB( PDB32 *parent )
|
|||
pdb->priority = 8; /* Normal */
|
||||
pdb->heap = pdb->system_heap; /* will be changed later on */
|
||||
|
||||
InitializeCriticalSection( &pdb->crit_section );
|
||||
|
||||
/* Allocate the events */
|
||||
|
||||
if (!(pdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
|
||||
if (!(pdb->load_done_evt = EVENT_Create( TRUE, FALSE ))) goto error;
|
||||
|
||||
/* Create the handle table */
|
||||
|
||||
if (!HANDLE_CreateTable( pdb, TRUE )) goto error;
|
||||
|
||||
PROCESS_PDBList_Insert (pdb);
|
||||
|
||||
return pdb;
|
||||
|
||||
error:
|
||||
|
@ -346,6 +326,21 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_FinishCreatePDB
|
||||
*
|
||||
* Second part of CreatePDB
|
||||
*/
|
||||
static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
|
||||
{
|
||||
InitializeCriticalSection( &pdb->crit_section );
|
||||
/* Allocate the event */
|
||||
if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Init
|
||||
*/
|
||||
|
@ -357,9 +352,8 @@ BOOL32 PROCESS_Init(void)
|
|||
/* Initialize virtual memory management */
|
||||
if (!VIRTUAL_Init()) return FALSE;
|
||||
|
||||
/* Create the system and SEGPTR heaps */
|
||||
/* Create the system heaps */
|
||||
if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
|
||||
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
||||
|
||||
/* Create the initial process and thread structures */
|
||||
if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
|
||||
|
@ -376,6 +370,10 @@ BOOL32 PROCESS_Init(void)
|
|||
|
||||
/* Initialize the first thread */
|
||||
if (CLIENT_InitThread()) return FALSE;
|
||||
if (!PROCESS_FinishCreatePDB( pdb )) return FALSE;
|
||||
|
||||
/* Create the SEGPTR heap */
|
||||
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -400,6 +398,7 @@ PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
|
|||
|
||||
if (!pdb) return NULL;
|
||||
info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
|
||||
if (!PROCESS_FinishCreatePDB( pdb )) goto error;
|
||||
|
||||
/* Create the heap */
|
||||
|
||||
|
@ -472,56 +471,6 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Signaled
|
||||
*/
|
||||
static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
PDB32 *pdb = (PDB32 *)obj;
|
||||
assert( obj->type == K32OBJ_PROCESS );
|
||||
return K32OBJ_OPS( pdb->event )->signaled( pdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
PDB32 *pdb = (PDB32 *)obj;
|
||||
assert( obj->type == K32OBJ_PROCESS );
|
||||
return K32OBJ_OPS( pdb->event )->satisfied( pdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_AddWait
|
||||
*
|
||||
* Add thread to object wait queue.
|
||||
*/
|
||||
static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
PDB32 *pdb = (PDB32 *)obj;
|
||||
assert( obj->type == K32OBJ_PROCESS );
|
||||
return K32OBJ_OPS( pdb->event )->add_wait( pdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_RemoveWait
|
||||
*
|
||||
* Remove thread from object wait queue.
|
||||
*/
|
||||
static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
PDB32 *pdb = (PDB32 *)obj;
|
||||
assert( obj->type == K32OBJ_PROCESS );
|
||||
return K32OBJ_OPS( pdb->event )->remove_wait( pdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Destroy
|
||||
*/
|
||||
|
@ -552,7 +501,6 @@ void WINAPI ExitProcess( DWORD status )
|
|||
SYSTEM_LOCK();
|
||||
/* FIXME: should kill all running threads of this process */
|
||||
pdb->exit_code = status;
|
||||
EVENT_Set( pdb->event );
|
||||
if (pdb->console) FreeConsole();
|
||||
SYSTEM_UNLOCK();
|
||||
|
||||
|
@ -566,13 +514,13 @@ void WINAPI ExitProcess( DWORD status )
|
|||
*/
|
||||
BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
|
||||
{
|
||||
int server_handle;
|
||||
BOOL32 ret;
|
||||
PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_TERMINATE, &server_handle );
|
||||
if (!pdb) return FALSE;
|
||||
ret = !CLIENT_TerminateProcess( server_handle, exit_code );
|
||||
K32OBJ_DecCount( &pdb->header );
|
||||
return ret;
|
||||
struct terminate_process_request req;
|
||||
|
||||
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
|
||||
K32OBJ_PROCESS, PROCESS_TERMINATE );
|
||||
req.exit_code = exit_code;
|
||||
CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -832,8 +780,8 @@ BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
|
|||
* It really shouldn't be here, but I'll move it when it's been checked!
|
||||
*/
|
||||
#define SHUTDOWN_NORETRY 1
|
||||
extern unsigned int shutdown_noretry = 0;
|
||||
extern unsigned int shutdown_priority = 0x280L;
|
||||
static unsigned int shutdown_noretry = 0;
|
||||
static unsigned int shutdown_priority = 0x280L;
|
||||
BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
|
||||
{
|
||||
if (flags & SHUTDOWN_NORETRY)
|
||||
|
@ -900,28 +848,6 @@ BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ConvertToGlobalHandle (KERNEL32)
|
||||
*/
|
||||
HANDLE32 WINAPI ConvertToGlobalHandle(HANDLE32 hSrc)
|
||||
{
|
||||
HANDLE32 hProcessInit, hDest;
|
||||
|
||||
/* Get a handle to the initial process */
|
||||
hProcessInit = OpenProcess( PROCESS_ALL_ACCESS, FALSE, PROCESS_InitialProcessID );
|
||||
|
||||
/* Duplicate the handle into the initial process */
|
||||
if ( !DuplicateHandle( GetCurrentProcess(), hSrc, hProcessInit, &hDest,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ) )
|
||||
hDest = 0;
|
||||
|
||||
/* Close initial process handle */
|
||||
CloseHandle( hProcessInit );
|
||||
|
||||
/* Return obfuscated global handle */
|
||||
return hDest? HANDLE_LOCAL_TO_GLOBAL( hDest ) : 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RegisterServiceProcess (KERNEL, KERNEL32)
|
||||
*
|
||||
|
@ -942,28 +868,17 @@ DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
|
|||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*
|
||||
* FIXME
|
||||
* Should call SetLastError (but doesn't).
|
||||
*/
|
||||
BOOL32 WINAPI GetExitCodeProcess(
|
||||
HANDLE32 hProcess, /* [I] handle to the process */
|
||||
LPDWORD lpExitCode) /* [O] address to receive termination status */
|
||||
{
|
||||
PDB32 *process;
|
||||
int server_handle;
|
||||
struct get_process_info_reply info;
|
||||
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
|
||||
K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
|
||||
|
||||
if (!(process = PROCESS_GetPtr( hProcess, PROCESS_QUERY_INFORMATION,
|
||||
&server_handle )))
|
||||
return FALSE;
|
||||
if (server_handle != -1)
|
||||
{
|
||||
CLIENT_GetProcessInfo( server_handle, &info );
|
||||
if (lpExitCode) *lpExitCode = info.exit_code;
|
||||
}
|
||||
else if (lpExitCode) *lpExitCode = process->exit_code;
|
||||
K32OBJ_DecCount( &process->header );
|
||||
if (CLIENT_GetProcessInfo( handle, &info )) return FALSE;
|
||||
if (lpExitCode) *lpExitCode = info.exit_code;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,25 +17,12 @@
|
|||
typedef struct
|
||||
{
|
||||
K32OBJ header;
|
||||
THREAD_QUEUE wait_queue;
|
||||
LONG count;
|
||||
LONG max;
|
||||
} SEMAPHORE;
|
||||
|
||||
static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void SEMAPHORE_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS SEMAPHORE_Ops =
|
||||
{
|
||||
SEMAPHORE_Signaled, /* signaled */
|
||||
SEMAPHORE_Satisfied, /* satisfied */
|
||||
SEMAPHORE_AddWait, /* add_wait */
|
||||
SEMAPHORE_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
SEMAPHORE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -57,7 +44,7 @@ HANDLE32 WINAPI CreateSemaphore32A( SECURITY_ATTRIBUTES *sa, LONG initial,
|
|||
if ((max <= 0) || (initial < 0) || (initial > max))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return INVALID_HANDLE_VALUE32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
req.initial = (unsigned int)initial;
|
||||
|
@ -67,21 +54,15 @@ HANDLE32 WINAPI CreateSemaphore32A( SECURITY_ATTRIBUTES *sa, LONG initial,
|
|||
CLIENT_SendRequest( REQ_CREATE_SEMAPHORE, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle == -1) return NULL;
|
||||
if (reply.handle == -1) return 0;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
sem = (SEMAPHORE *)K32OBJ_Create( K32OBJ_SEMAPHORE, sizeof(*sem),
|
||||
name, reply.handle, SEMAPHORE_ALL_ACCESS,
|
||||
sa, &handle);
|
||||
if (sem)
|
||||
{
|
||||
/* Finish initializing it */
|
||||
sem->wait_queue = NULL;
|
||||
sem->count = initial;
|
||||
sem->max = max;
|
||||
K32OBJ_DecCount( &sem->header );
|
||||
}
|
||||
if (sem) K32OBJ_DecCount( &sem->header );
|
||||
SYSTEM_UNLOCK();
|
||||
if (handle == INVALID_HANDLE_VALUE32) handle = 0;
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -106,13 +87,29 @@ HANDLE32 WINAPI OpenSemaphore32A( DWORD access, BOOL32 inherit, LPCSTR name )
|
|||
{
|
||||
HANDLE32 handle = 0;
|
||||
K32OBJ *obj;
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_SEMAPHORE )) != NULL)
|
||||
struct open_named_obj_request req;
|
||||
struct open_named_obj_reply reply;
|
||||
int len = name ? strlen(name) + 1 : 0;
|
||||
|
||||
req.type = OPEN_SEMAPHORE;
|
||||
req.access = access;
|
||||
req.inherit = inherit;
|
||||
CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len );
|
||||
CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (reply.handle != -1)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, -1 );
|
||||
K32OBJ_DecCount( obj );
|
||||
SYSTEM_LOCK();
|
||||
if ((obj = K32OBJ_FindNameType( name, K32OBJ_SEMAPHORE )) != NULL)
|
||||
{
|
||||
handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, reply.handle );
|
||||
K32OBJ_DecCount( obj );
|
||||
if (handle == INVALID_HANDLE_VALUE32)
|
||||
handle = 0; /* must return 0 on failure, not -1 */
|
||||
}
|
||||
else CLIENT_CloseHandle( reply.handle );
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -135,110 +132,26 @@ HANDLE32 WINAPI OpenSemaphore32W( DWORD access, BOOL32 inherit, LPCWSTR name )
|
|||
BOOL32 WINAPI ReleaseSemaphore( HANDLE32 handle, LONG count, LONG *previous )
|
||||
{
|
||||
struct release_semaphore_request req;
|
||||
SEMAPHORE *sem;
|
||||
struct release_semaphore_reply reply;
|
||||
int len;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
SYSTEM_LOCK();
|
||||
if (!(sem = (SEMAPHORE *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
|
||||
K32OBJ_SEMAPHORE,
|
||||
SEMAPHORE_MODIFY_STATE, &req.handle )))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
if (req.handle != -1)
|
||||
{
|
||||
struct release_semaphore_reply reply;
|
||||
int len;
|
||||
|
||||
SYSTEM_UNLOCK();
|
||||
req.count = (unsigned int)count;
|
||||
CLIENT_SendRequest( REQ_RELEASE_SEMAPHORE, -1, 1, &req, sizeof(req) );
|
||||
if (CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) )) return FALSE;
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (previous) *previous = reply.prev_count;
|
||||
return TRUE;
|
||||
}
|
||||
if (previous) *previous = sem->count;
|
||||
if (sem->count + count > sem->max)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
SetLastError( ERROR_TOO_MANY_POSTS );
|
||||
return FALSE;
|
||||
}
|
||||
if (sem->count > 0)
|
||||
{
|
||||
/* There cannot be any thread waiting if the count is > 0 */
|
||||
assert( sem->wait_queue == NULL );
|
||||
sem->count += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
sem->count = count;
|
||||
SYNC_WakeUp( &sem->wait_queue, count );
|
||||
}
|
||||
K32OBJ_DecCount( &sem->header );
|
||||
SYSTEM_UNLOCK();
|
||||
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
|
||||
K32OBJ_SEMAPHORE, SEMAPHORE_MODIFY_STATE );
|
||||
if (req.handle == -1) return FALSE;
|
||||
req.count = (unsigned int)count;
|
||||
CLIENT_SendRequest( REQ_RELEASE_SEMAPHORE, -1, 1, &req, sizeof(req) );
|
||||
if (CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) )) return FALSE;
|
||||
CHECK_LEN( len, sizeof(reply) );
|
||||
if (previous) *previous = reply.prev_count;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SEMAPHORE_Signaled
|
||||
*/
|
||||
static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
SEMAPHORE *sem = (SEMAPHORE *)obj;
|
||||
assert( obj->type == K32OBJ_SEMAPHORE );
|
||||
return (sem->count > 0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SEMAPHORE_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
SEMAPHORE *sem = (SEMAPHORE *)obj;
|
||||
assert( obj->type == K32OBJ_SEMAPHORE );
|
||||
assert( sem->count > 0 );
|
||||
sem->count--;
|
||||
return FALSE; /* Not abandoned */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SEMAPHORE_AddWait
|
||||
*
|
||||
* Add current thread to object wait queue.
|
||||
*/
|
||||
static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
SEMAPHORE *sem = (SEMAPHORE *)obj;
|
||||
assert( obj->type == K32OBJ_SEMAPHORE );
|
||||
THREAD_AddQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SEMAPHORE_RemoveWait
|
||||
*
|
||||
* Remove thread from object wait queue.
|
||||
*/
|
||||
static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
SEMAPHORE *sem = (SEMAPHORE *)obj;
|
||||
assert( obj->type == K32OBJ_SEMAPHORE );
|
||||
THREAD_RemoveQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SEMAPHORE_Destroy
|
||||
*/
|
||||
|
@ -247,7 +160,6 @@ static void SEMAPHORE_Destroy( K32OBJ *obj )
|
|||
SEMAPHORE *sem = (SEMAPHORE *)obj;
|
||||
assert( obj->type == K32OBJ_SEMAPHORE );
|
||||
/* There cannot be any thread on the list since the ref count is 0 */
|
||||
assert( sem->wait_queue == NULL );
|
||||
obj->type = K32OBJ_UNKNOWN;
|
||||
HeapFree( SystemHeap, 0, sem );
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
|
|||
BOOL32 wait_all, BOOL32 wait_msg,
|
||||
WAIT_STRUCT *wait )
|
||||
{
|
||||
DWORD i, j;
|
||||
DWORD i;
|
||||
K32OBJ **ptr;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
|
@ -32,7 +32,6 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
|
|||
wait->signaled = WAIT_FAILED;
|
||||
wait->wait_all = wait_all;
|
||||
wait->wait_msg = wait_msg;
|
||||
wait->use_server = TRUE;
|
||||
for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
|
||||
{
|
||||
if (!(*ptr = HANDLE_GetObjPtr( PROCESS_Current(), handles[i],
|
||||
|
@ -43,28 +42,11 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
|
|||
break;
|
||||
}
|
||||
if (wait->server[i] == -1)
|
||||
{
|
||||
WARN(win32,"No server handle for %08x (type %d)\n",
|
||||
handles[i], (*ptr)->type );
|
||||
wait->use_server = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wait->use_server)
|
||||
{
|
||||
for (j = 0, ptr = wait->objs; j < i; j++, ptr++)
|
||||
{
|
||||
if (!K32OBJ_OPS( *ptr )->signaled)
|
||||
{
|
||||
/* This object type cannot be waited upon */
|
||||
ERR(win32, "Cannot wait on handle %08x\n", handles[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else j = count;
|
||||
|
||||
if ((i != count) || (j != count))
|
||||
if (i != count)
|
||||
{
|
||||
/* There was an error */
|
||||
wait->wait_msg = FALSE;
|
||||
|
@ -90,224 +72,6 @@ static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_CheckCondition
|
||||
*/
|
||||
static BOOL32 SYNC_CheckCondition( WAIT_STRUCT *wait, DWORD thread_id )
|
||||
{
|
||||
DWORD i;
|
||||
K32OBJ **ptr;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
if (wait->wait_all)
|
||||
{
|
||||
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
|
||||
{
|
||||
if (!K32OBJ_OPS( *ptr )->signaled( *ptr, thread_id ))
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/* Wait satisfied: tell it to all objects */
|
||||
wait->signaled = WAIT_OBJECT_0;
|
||||
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
|
||||
if (K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id ))
|
||||
wait->signaled = WAIT_ABANDONED_0;
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
|
||||
{
|
||||
if (K32OBJ_OPS( *ptr )->signaled( *ptr, thread_id ))
|
||||
{
|
||||
/* Wait satisfied: tell it to the object */
|
||||
wait->signaled = WAIT_OBJECT_0 + i;
|
||||
if (K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id ))
|
||||
wait->signaled = WAIT_ABANDONED_0 + i;
|
||||
SYSTEM_UNLOCK();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_WaitForCondition
|
||||
*/
|
||||
void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout )
|
||||
{
|
||||
DWORD i, thread_id = GetCurrentThreadId();
|
||||
LONG count;
|
||||
K32OBJ **ptr;
|
||||
sigset_t set;
|
||||
|
||||
SYSTEM_LOCK();
|
||||
if (SYNC_CheckCondition( wait, thread_id ))
|
||||
goto done; /* Condition already satisfied */
|
||||
if (!timeout)
|
||||
{
|
||||
/* No need to wait */
|
||||
wait->signaled = WAIT_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Add ourselves to the waiting list of all objects */
|
||||
|
||||
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
|
||||
K32OBJ_OPS( *ptr )->add_wait( *ptr, thread_id );
|
||||
|
||||
/* Release the system lock completely */
|
||||
|
||||
count = SYSTEM_LOCK_COUNT();
|
||||
for (i = count; i > 0; i--) SYSTEM_UNLOCK();
|
||||
|
||||
/* Now wait for it */
|
||||
|
||||
TRACE(win32, "starting wait (%p %04x)\n",
|
||||
THREAD_Current(), THREAD_Current()->teb_sel );
|
||||
|
||||
sigprocmask( SIG_SETMASK, NULL, &set );
|
||||
sigdelset( &set, SIGUSR1 );
|
||||
sigdelset( &set, SIGALRM );
|
||||
if (timeout != INFINITE32)
|
||||
{
|
||||
while (wait->signaled == WAIT_FAILED)
|
||||
{
|
||||
struct itimerval timer;
|
||||
DWORD start_ticks, elapsed;
|
||||
timer.it_interval.tv_sec = timer.it_interval.tv_usec = 0;
|
||||
timer.it_value.tv_sec = timeout / 1000;
|
||||
timer.it_value.tv_usec = (timeout % 1000) * 1000;
|
||||
start_ticks = GetTickCount();
|
||||
setitimer( ITIMER_REAL, &timer, NULL );
|
||||
sigsuspend( &set );
|
||||
if (wait->signaled != WAIT_FAILED) break;
|
||||
/* Recompute the timer value */
|
||||
elapsed = GetTickCount() - start_ticks;
|
||||
if (elapsed >= timeout) wait->signaled = WAIT_TIMEOUT;
|
||||
else timeout -= elapsed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (wait->signaled == WAIT_FAILED)
|
||||
{
|
||||
sigsuspend( &set );
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab the system lock again */
|
||||
|
||||
while (count--) SYSTEM_LOCK();
|
||||
TRACE(win32, "wait finished (%p %04x)\n",
|
||||
THREAD_Current(), THREAD_Current()->teb_sel );
|
||||
|
||||
/* Remove ourselves from the lists */
|
||||
|
||||
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
|
||||
K32OBJ_OPS( *ptr )->remove_wait( *ptr, thread_id );
|
||||
|
||||
done:
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_DummySigHandler
|
||||
*
|
||||
* Dummy signal handler
|
||||
*/
|
||||
static void SYNC_DummySigHandler(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_SetupSignals
|
||||
*
|
||||
* Setup signal handlers for a new thread.
|
||||
* FIXME: should merge with SIGNAL_Init.
|
||||
*/
|
||||
void SYNC_SetupSignals(void)
|
||||
{
|
||||
sigset_t set;
|
||||
SIGNAL_SetHandler( SIGUSR1, SYNC_DummySigHandler, 0 );
|
||||
/* FIXME: conflicts with system timers */
|
||||
SIGNAL_SetHandler( SIGALRM, SYNC_DummySigHandler, 0 );
|
||||
sigemptyset( &set );
|
||||
/* Make sure these are blocked by default */
|
||||
sigaddset( &set, SIGUSR1 );
|
||||
sigaddset( &set, SIGALRM );
|
||||
sigprocmask( SIG_BLOCK , &set, NULL);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_WakeUp
|
||||
*/
|
||||
void SYNC_WakeUp( THREAD_QUEUE *wait_queue, DWORD max )
|
||||
{
|
||||
THREAD_ENTRY *entry;
|
||||
|
||||
if (!max) max = INFINITE32;
|
||||
SYSTEM_LOCK();
|
||||
if (!*wait_queue)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return;
|
||||
}
|
||||
entry = (*wait_queue)->next;
|
||||
for (;;)
|
||||
{
|
||||
THDB *thdb = entry->thread;
|
||||
if (SYNC_CheckCondition( &thdb->wait_struct, THDB_TO_THREAD_ID(thdb) ))
|
||||
{
|
||||
TRACE(win32, "waking up %04x (pid %d)\n", thdb->teb_sel, thdb->unix_pid );
|
||||
if (thdb->unix_pid)
|
||||
kill( thdb->unix_pid, SIGUSR1 );
|
||||
else
|
||||
FIXME(win32,"have got unix_pid 0\n");
|
||||
if (!--max) break;
|
||||
}
|
||||
if (entry == *wait_queue) break;
|
||||
entry = entry->next;
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_MsgWakeUp
|
||||
*/
|
||||
void SYNC_MsgWakeUp( THDB *thdb )
|
||||
{
|
||||
SYSTEM_LOCK();
|
||||
|
||||
if (!thdb)
|
||||
{
|
||||
SYSTEM_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
if (thdb->wait_struct.wait_msg)
|
||||
{
|
||||
thdb->wait_struct.signaled = thdb->wait_struct.count;
|
||||
|
||||
TRACE(win32, "waking up %04x for message\n", thdb->teb_sel );
|
||||
if (thdb->unix_pid)
|
||||
kill( thdb->unix_pid, SIGUSR1 );
|
||||
else
|
||||
FIXME(win32,"have got unix_pid 0\n");
|
||||
}
|
||||
|
||||
SYSTEM_UNLOCK();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_DoWait
|
||||
*/
|
||||
|
@ -326,30 +90,18 @@ DWORD SYNC_DoWait( DWORD count, const HANDLE32 *handles,
|
|||
if (alertable)
|
||||
FIXME(win32, "alertable not implemented\n" );
|
||||
|
||||
SYSTEM_LOCK();
|
||||
if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait_msg, wait ))
|
||||
wait->signaled = WAIT_FAILED;
|
||||
else
|
||||
{
|
||||
/* Check if we can use a server wait */
|
||||
if (wait->use_server)
|
||||
{
|
||||
int flags = 0;
|
||||
SYSTEM_UNLOCK();
|
||||
if (wait_all) flags |= SELECT_ALL;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
if (wait_msg) flags |= SELECT_MSG;
|
||||
if (timeout != INFINITE32) flags |= SELECT_TIMEOUT;
|
||||
return CLIENT_Select( count, wait->server, flags, timeout );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now wait for it */
|
||||
SYNC_WaitForCondition( wait, timeout );
|
||||
SYNC_FreeWaitStruct( wait );
|
||||
}
|
||||
int flags = 0;
|
||||
if (wait_all) flags |= SELECT_ALL;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
if (wait_msg) flags |= SELECT_MSG;
|
||||
if (timeout != INFINITE32) flags |= SELECT_TIMEOUT;
|
||||
wait->signaled = CLIENT_Select( count, wait->server, flags, timeout );
|
||||
SYNC_FreeWaitStruct( wait );
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
return wait->signaled;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,20 +25,10 @@
|
|||
THDB *pCurrentThread;
|
||||
#endif
|
||||
|
||||
static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id );
|
||||
static BOOL32 THREAD_Satisfied( K32OBJ *obj, DWORD thread_id );
|
||||
static void THREAD_AddWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void THREAD_RemoveWait( K32OBJ *obj, DWORD thread_id );
|
||||
static void THREAD_Destroy( K32OBJ *obj );
|
||||
|
||||
const K32OBJ_OPS THREAD_Ops =
|
||||
{
|
||||
THREAD_Signaled, /* signaled */
|
||||
THREAD_Satisfied, /* satisfied */
|
||||
THREAD_AddWait, /* add_wait */
|
||||
THREAD_RemoveWait, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
THREAD_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -234,10 +224,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
|
|||
0x10000 - sizeof(STACK16FRAME) );
|
||||
}
|
||||
|
||||
/* Allocate the event */
|
||||
|
||||
if (!(thdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
|
||||
|
||||
/* Create the thread socket */
|
||||
|
||||
if (CLIENT_NewThread( thdb, server_thandle, server_phandle )) goto error;
|
||||
|
@ -273,56 +259,6 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THREAD_Signaled
|
||||
*/
|
||||
static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
THDB *thdb = (THDB *)obj;
|
||||
assert( obj->type == K32OBJ_THREAD );
|
||||
return K32OBJ_OPS( thdb->event )->signaled( thdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THREAD_Satisfied
|
||||
*
|
||||
* Wait on this object has been satisfied.
|
||||
*/
|
||||
static BOOL32 THREAD_Satisfied( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
THDB *thdb = (THDB *)obj;
|
||||
assert( obj->type == K32OBJ_THREAD );
|
||||
return K32OBJ_OPS( thdb->event )->satisfied( thdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THREAD_AddWait
|
||||
*
|
||||
* Add thread to object wait queue.
|
||||
*/
|
||||
static void THREAD_AddWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
THDB *thdb = (THDB *)obj;
|
||||
assert( obj->type == K32OBJ_THREAD );
|
||||
return K32OBJ_OPS( thdb->event )->add_wait( thdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THREAD_RemoveWait
|
||||
*
|
||||
* Remove thread from object wait queue.
|
||||
*/
|
||||
static void THREAD_RemoveWait( K32OBJ *obj, DWORD thread_id )
|
||||
{
|
||||
THDB *thdb = (THDB *)obj;
|
||||
assert( obj->type == K32OBJ_THREAD );
|
||||
return K32OBJ_OPS( thdb->event )->remove_wait( thdb->event, thread_id );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THREAD_Destroy
|
||||
*/
|
||||
|
@ -348,7 +284,6 @@ static void THREAD_Destroy( K32OBJ *ptr )
|
|||
}
|
||||
#endif
|
||||
close( thdb->socket );
|
||||
K32OBJ_DecCount( thdb->event );
|
||||
SELECTOR_FreeBlock( thdb->teb_sel, 1 );
|
||||
if (thdb->teb.stack_sel) SELECTOR_FreeBlock( thdb->teb.stack_sel, 1 );
|
||||
HeapFree( SystemHeap, 0, thdb );
|
||||
|
@ -418,10 +353,6 @@ void WINAPI ExitThread(
|
|||
|
||||
SYSTEM_LOCK();
|
||||
thdb->exit_code = code;
|
||||
EVENT_Set( thdb->event );
|
||||
|
||||
/* Abandon all owned mutexes */
|
||||
while (thdb->mutex_list) MUTEX_Abandon( thdb->mutex_list );
|
||||
|
||||
/* FIXME: should free the stack somehow */
|
||||
#if 0
|
||||
|
@ -731,15 +662,13 @@ BOOL32 WINAPI TerminateThread(
|
|||
HANDLE32 handle, /* [in] Handle to thread */
|
||||
DWORD exitcode) /* [in] Exit code for thread */
|
||||
{
|
||||
int server_handle;
|
||||
BOOL32 ret;
|
||||
THDB *thread;
|
||||
|
||||
if (!(thread = THREAD_GetPtr( handle, THREAD_TERMINATE, &server_handle )))
|
||||
return FALSE;
|
||||
ret = !CLIENT_TerminateThread( server_handle, exitcode );
|
||||
K32OBJ_DecCount( &thread->header );
|
||||
return ret;
|
||||
struct terminate_thread_request req;
|
||||
|
||||
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
|
||||
K32OBJ_THREAD, THREAD_TERMINATE );
|
||||
req.exit_code = exitcode;
|
||||
CLIENT_SendRequest( REQ_TERMINATE_THREAD, -1, 1, &req, sizeof(req) );
|
||||
return !CLIENT_WaitReply( NULL, NULL, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -754,19 +683,11 @@ BOOL32 WINAPI GetExitCodeThread(
|
|||
HANDLE32 hthread, /* [in] Handle to thread */
|
||||
LPDWORD exitcode) /* [out] Address to receive termination status */
|
||||
{
|
||||
THDB *thread;
|
||||
int server_handle;
|
||||
|
||||
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, &server_handle )))
|
||||
return FALSE;
|
||||
if (server_handle != -1)
|
||||
{
|
||||
struct get_thread_info_reply info;
|
||||
CLIENT_GetThreadInfo( server_handle, &info );
|
||||
if (exitcode) *exitcode = info.exit_code;
|
||||
}
|
||||
else if (exitcode) *exitcode = thread->exit_code;
|
||||
K32OBJ_DecCount( &thread->header );
|
||||
struct get_thread_info_reply info;
|
||||
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
|
||||
K32OBJ_THREAD, THREAD_QUERY_INFORMATION );
|
||||
if (CLIENT_GetThreadInfo( handle, &info )) return FALSE;
|
||||
if (exitcode) *exitcode = info.exit_code;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
195
win32/console.c
195
win32/console.c
|
@ -63,26 +63,10 @@ typedef struct _CONSOLE {
|
|||
THREAD_QUEUE wait_queue;
|
||||
} CONSOLE;
|
||||
|
||||
static void CONSOLE_AddWait(K32OBJ *ptr, DWORD thread_id);
|
||||
static void CONSOLE_RemoveWait(K32OBJ *ptr, DWORD thread_id);
|
||||
static BOOL32 CONSOLE_Satisfied(K32OBJ *ptr, DWORD thread_id);
|
||||
static BOOL32 CONSOLE_Signaled(K32OBJ *ptr, DWORD thread_id);
|
||||
static void CONSOLE_Destroy( K32OBJ *obj );
|
||||
static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer,
|
||||
DWORD nNumberOfChars, LPDWORD lpNumberOfChars,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer,
|
||||
DWORD nNumberOfChars, LPDWORD lpNumberOfChars,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
const K32OBJ_OPS CONSOLE_Ops =
|
||||
{
|
||||
CONSOLE_Signaled, /* signaled */
|
||||
CONSOLE_Satisfied, /* satisfied */
|
||||
CONSOLE_AddWait, /* add_wait */
|
||||
CONSOLE_RemoveWait, /* remove_wait */
|
||||
CONSOLE_Read, /* read */
|
||||
CONSOLE_Write, /* write */
|
||||
CONSOLE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
@ -106,63 +90,6 @@ static void CONSOLE_Destroy(K32OBJ *obj)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_Read
|
||||
*
|
||||
* NOTES
|
||||
* lpOverlapped is ignored
|
||||
*/
|
||||
static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
|
||||
LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
CONSOLE *console = (CONSOLE *)ptr;
|
||||
int result;
|
||||
|
||||
TRACE(console, "%p %p %ld\n", ptr, lpBuffer, nNumberOfChars);
|
||||
*lpNumberOfChars = 0;
|
||||
if ((result = read(console->infd, lpBuffer, nNumberOfChars)) == -1) {
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
*lpNumberOfChars = result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_Write
|
||||
*
|
||||
* NOTES
|
||||
* lpOverlapped is ignored
|
||||
*/
|
||||
static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer,
|
||||
DWORD nNumberOfChars,
|
||||
LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
CONSOLE *console = (CONSOLE *)ptr;
|
||||
int result;
|
||||
|
||||
TRACE(console, "%p %p %ld\n", ptr, lpBuffer, nNumberOfChars);
|
||||
*lpNumberOfChars = 0;
|
||||
/*
|
||||
* I assume this loop around EAGAIN is here because
|
||||
* win32 doesn't have interrupted system calls
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
result = write(console->outfd, lpBuffer, nNumberOfChars);
|
||||
if (result != -1) {
|
||||
*lpNumberOfChars = result;
|
||||
return TRUE;
|
||||
}
|
||||
if (errno != EINTR) {
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CONSOLE_add_input_record [internal]
|
||||
*
|
||||
|
@ -181,9 +108,11 @@ CONSOLE_add_input_record(CONSOLE *console,INPUT_RECORD *inp) {
|
|||
* queue. Does translation of vt100 style function keys and xterm-mouse clicks.
|
||||
*/
|
||||
static void
|
||||
CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
|
||||
CONSOLE_string_to_IR( HANDLE32 hConsoleInput,unsigned char *buf,int len) {
|
||||
int j,k;
|
||||
INPUT_RECORD ir;
|
||||
CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput,
|
||||
K32OBJ_CONSOLE, 0, NULL);
|
||||
|
||||
for (j=0;j<len;j++) {
|
||||
unsigned char inchar = buf[j];
|
||||
|
@ -326,39 +255,31 @@ CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
|
|||
}
|
||||
}
|
||||
}
|
||||
K32OBJ_DecCount(&console->header);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CONSOLE_get_input (internal)
|
||||
*
|
||||
* Reads (nonblocking) as much input events as possible and stores them
|
||||
* in an internal queue.
|
||||
* (not necessarily XTERM dependend, but UNIX filedescriptor...)
|
||||
*/
|
||||
static void
|
||||
CONSOLE_get_input(CONSOLE *console) {
|
||||
CONSOLE_get_input( HANDLE32 handle )
|
||||
{
|
||||
char *buf = HeapAlloc(GetProcessHeap(),0,1);
|
||||
int len = 0;
|
||||
|
||||
while (1) {
|
||||
fd_set infds;
|
||||
DWORD res;
|
||||
struct timeval tv;
|
||||
char inchar;
|
||||
|
||||
FD_ZERO(&infds);
|
||||
FD_SET(console->infd,&infds);
|
||||
memset(&tv,0,sizeof(tv));
|
||||
if (select(console->infd+1,&infds,NULL,NULL,&tv)<1)
|
||||
break; /* no input there */
|
||||
|
||||
if (!FD_ISSET(console->infd,&infds))
|
||||
break;
|
||||
if (!CONSOLE_Read((K32OBJ*)console,&inchar,1,&res,NULL))
|
||||
break;
|
||||
while (1)
|
||||
{
|
||||
DWORD res;
|
||||
char inchar;
|
||||
if (!WaitForSingleObject( handle, 0 )) break;
|
||||
if (!ReadFile( handle, &inchar, 1, &res, NULL )) break;
|
||||
buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
|
||||
buf[len++]=inchar;
|
||||
}
|
||||
CONSOLE_string_to_IR(console,buf,len);
|
||||
CONSOLE_string_to_IR(handle,buf,len);
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
}
|
||||
|
||||
|
@ -385,73 +306,6 @@ CONSOLE_drain_input(CONSOLE *console,int n) {
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_async_handler [internal]
|
||||
*/
|
||||
static void
|
||||
CONSOLE_async_handler(int unixfd,void *private) {
|
||||
CONSOLE *console = (CONSOLE*)private;
|
||||
|
||||
SYNC_WakeUp(&console->wait_queue,INFINITE32);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_Signaled [internal]
|
||||
*
|
||||
* Checks if we can read something. (Hmm, what about writing ?)
|
||||
*/
|
||||
static BOOL32
|
||||
CONSOLE_Signaled(K32OBJ *ptr,DWORD tid) {
|
||||
CONSOLE *console =(CONSOLE*)ptr;
|
||||
|
||||
if (ptr->type!= K32OBJ_CONSOLE)
|
||||
return FALSE;
|
||||
CONSOLE_get_input(console);
|
||||
if (console->nrofirs!=0)
|
||||
return TRUE;
|
||||
/* addref console */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_AddWait [internal]
|
||||
*
|
||||
* Add thread to our waitqueue (so we can signal it if we have input).
|
||||
*/
|
||||
static void CONSOLE_AddWait(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
CONSOLE *console = (CONSOLE *)ptr;
|
||||
|
||||
/* register our unix filedescriptors for async IO */
|
||||
if (!console->wait_queue)
|
||||
ASYNC_RegisterFD(console->infd,CONSOLE_async_handler,console);
|
||||
THREAD_AddQueue( &console->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_RemoveWait [internal]
|
||||
*
|
||||
* Remove thread from our waitqueue.
|
||||
*/
|
||||
static void CONSOLE_RemoveWait(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
CONSOLE *console = (CONSOLE *)ptr;
|
||||
|
||||
THREAD_RemoveQueue( &console->wait_queue, THREAD_ID_TO_THDB(thread_id) );
|
||||
if (!console->wait_queue)
|
||||
ASYNC_UnregisterFD(console->infd,CONSOLE_async_handler);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CONSOLE_Satisfied [internal]
|
||||
*
|
||||
* Condition from last Signaled is satisfied and will be used now.
|
||||
*/
|
||||
static BOOL32 CONSOLE_Satisfied(K32OBJ *ptr, DWORD thread_id)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SetConsoleCtrlHandler [KERNEL32.459] Adds function to calling process list
|
||||
|
@ -711,7 +565,7 @@ static int CONSOLE_openpty(CONSOLE *console, char *name,
|
|||
*
|
||||
* To test for complex console: pid == -1 -> simple, otherwise complex.
|
||||
*/
|
||||
static BOOL32 CONSOLE_make_complex(CONSOLE *console)
|
||||
static BOOL32 CONSOLE_make_complex(HANDLE32 handle,CONSOLE *console)
|
||||
{
|
||||
struct termios term;
|
||||
char buf[30];
|
||||
|
@ -757,7 +611,7 @@ static BOOL32 CONSOLE_make_complex(CONSOLE *console)
|
|||
}
|
||||
/* enable mouseclicks */
|
||||
sprintf(buf,"%c[?1001s%c[?1000h",27,27);
|
||||
CONSOLE_Write(&console->header,buf,strlen(buf),&xlen,NULL);
|
||||
WriteFile(handle,buf,strlen(buf),&xlen,NULL);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
@ -1033,7 +887,7 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
|
|||
FIXME(console,"(%d,...): no console handle!\n",hConsoleOutput);
|
||||
return FALSE;
|
||||
}
|
||||
CONSOLE_make_complex(console);
|
||||
CONSOLE_make_complex(hConsoleOutput,console);
|
||||
buffer = HeapAlloc(GetProcessHeap(),0,100);;
|
||||
curbufsize = 100;
|
||||
|
||||
|
@ -1114,7 +968,7 @@ BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
|
|||
hConsoleInput,lpBuffer,nNumberOfCharsToRead,
|
||||
lpNumberOfCharsRead,lpReserved
|
||||
);
|
||||
CONSOLE_get_input(console);
|
||||
CONSOLE_get_input(hConsoleInput);
|
||||
|
||||
/* FIXME: should this drain everything from the input queue and just
|
||||
* put the keypresses in the buffer? Needs further thought.
|
||||
|
@ -1186,7 +1040,7 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
|
|||
lpBuffer, nLength, lpNumberOfEventsRead);
|
||||
return FALSE;
|
||||
}
|
||||
CONSOLE_get_input(console);
|
||||
CONSOLE_get_input(hConsoleInput);
|
||||
if (nLength>console->nrofirs)
|
||||
nLength = console->nrofirs;
|
||||
memcpy(lpBuffer,console->irs,sizeof(INPUT_RECORD)*nLength);
|
||||
|
@ -1232,7 +1086,8 @@ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
|
|||
|
||||
sprintf(titlestring,titleformat,title);
|
||||
/* FIXME: hmm, should use WriteFile probably... */
|
||||
CONSOLE_Write(&console->header,titlestring,strlen(titlestring),&written,NULL);
|
||||
/*CONSOLE_Write(&console->header,titlestring,strlen(titlestring),&written,NULL);*/
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),titlestring,strlen(titlestring),&written,NULL);
|
||||
if (written == strlen(titlestring))
|
||||
ret =TRUE;
|
||||
HeapFree( GetProcessHeap(), 0, titlestring );
|
||||
|
@ -1311,7 +1166,7 @@ BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos )
|
|||
FIXME(console,"(%d,...), no console handle!\n",hcon);
|
||||
return FALSE;
|
||||
}
|
||||
CONSOLE_make_complex(console);
|
||||
CONSOLE_make_complex(hcon,console);
|
||||
TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
|
||||
/* x are columns, y rows */
|
||||
sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
|
||||
|
@ -1332,7 +1187,7 @@ BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
|
|||
FIXME(console,"(%d,%p), no console handle!\n",hcon,nrofevents);
|
||||
return FALSE;
|
||||
}
|
||||
CONSOLE_get_input(console);
|
||||
CONSOLE_get_input(hcon);
|
||||
*nrofevents = console->nrofirs;
|
||||
K32OBJ_DecCount(&console->header);
|
||||
return TRUE;
|
||||
|
@ -1367,7 +1222,7 @@ BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
|
|||
return FALSE;
|
||||
}
|
||||
TRACE(console,"(%d,%p,%ld,%p)\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
|
||||
CONSOLE_get_input(console);
|
||||
CONSOLE_get_input(hConsoleInput);
|
||||
if (cInRecords>console->nrofirs)
|
||||
cInRecords = console->nrofirs;
|
||||
if (pirBuffer)
|
||||
|
@ -1438,7 +1293,7 @@ BOOL32 WINAPI SetConsoleCursorInfo32(
|
|||
TRACE(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible);
|
||||
if (!console)
|
||||
return FALSE;
|
||||
CONSOLE_make_complex(console);
|
||||
CONSOLE_make_complex(hcon,console);
|
||||
sprintf(buf,"%c[?25%c",27,cinfo->bVisible?'h':'l');
|
||||
WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
|
||||
console->cinfo = *cinfo;
|
||||
|
|
|
@ -32,14 +32,9 @@
|
|||
#include "miscemu.h"
|
||||
|
||||
static void DEVICE_Destroy(K32OBJ *dev);
|
||||
|
||||
const K32OBJ_OPS DEVICE_Ops =
|
||||
{
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
NULL, /* add_wait */
|
||||
NULL, /* remove_wait */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
DEVICE_Destroy /* destroy */
|
||||
};
|
||||
|
||||
|
|
|
@ -235,6 +235,8 @@ void QUEUE_Signal( HTASK16 hTask )
|
|||
/* NOTE: This should really wake up *the* thread that owns
|
||||
the queue. Since we dont't have thread-local message
|
||||
queues yet, we wake up all waiting threads ... */
|
||||
#if 0
|
||||
/* FIXME: should be replaced by a server event */
|
||||
SYSTEM_LOCK();
|
||||
pdb = pTask->thdb->process;
|
||||
entry = pdb? pdb->thread_list->next : NULL;
|
||||
|
@ -251,6 +253,7 @@ void QUEUE_Signal( HTASK16 hTask )
|
|||
entry = entry->next;
|
||||
}
|
||||
SYSTEM_UNLOCK();
|
||||
#endif
|
||||
|
||||
/* if ( !wakeup )*/
|
||||
PostEvent( hTask );
|
||||
|
|
Loading…
Add table
Reference in a new issue