Moved WINSOCK network IO event handling to special thread.
Removed EVENT_WaitNetEvent, introduced a global scheduler event.
This commit is contained in:
parent
a1957c4d64
commit
89fc6fda97
|
@ -24,10 +24,6 @@ extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue );
|
||||||
extern BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
|
extern BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
|
||||||
HQUEUE16 hQueue, BOOL remove );
|
HQUEUE16 hQueue, BOOL remove );
|
||||||
|
|
||||||
#define EVENT_IO_READ 0
|
|
||||||
#define EVENT_IO_WRITE 1
|
|
||||||
#define EVENT_IO_EXCEPT 2
|
|
||||||
|
|
||||||
/* event.c */
|
/* event.c */
|
||||||
typedef struct tagEVENT_DRIVER {
|
typedef struct tagEVENT_DRIVER {
|
||||||
BOOL (*pInit)(void);
|
BOOL (*pInit)(void);
|
||||||
|
@ -40,15 +36,11 @@ typedef struct tagEVENT_DRIVER {
|
||||||
|
|
||||||
extern EVENT_DRIVER *EVENT_Driver;
|
extern EVENT_DRIVER *EVENT_Driver;
|
||||||
|
|
||||||
extern void EVENT_AddIO( int fd, unsigned flag );
|
|
||||||
extern void EVENT_DeleteIO( int fd, unsigned flag );
|
|
||||||
extern BOOL EVENT_Init( void );
|
extern BOOL EVENT_Init( void );
|
||||||
extern void EVENT_WaitNetEvent( void );
|
|
||||||
extern void EVENT_Synchronize( BOOL bProcessEvents );
|
extern void EVENT_Synchronize( BOOL bProcessEvents );
|
||||||
extern BOOL EVENT_CheckFocus( void );
|
extern BOOL EVENT_CheckFocus( void );
|
||||||
extern BOOL EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state);
|
extern BOOL EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state);
|
||||||
extern void EVENT_DummyMotionNotify(void);
|
extern void EVENT_DummyMotionNotify(void);
|
||||||
extern void EVENT_WakeUp(void);
|
|
||||||
|
|
||||||
/* input.c */
|
/* input.c */
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,7 @@ int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
|
||||||
int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
|
int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
|
||||||
int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
|
int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
|
||||||
|
|
||||||
BOOL WINSOCK_HandleIO(int* fd_max, int num_pending, fd_set pending_set[3], fd_set master_set[3] );
|
BOOL WINSOCK_Init(void);
|
||||||
void WINSOCK_Shutdown(void);
|
void WINSOCK_Shutdown(void);
|
||||||
UINT16 wsaErrno(void);
|
UINT16 wsaErrno(void);
|
||||||
UINT16 wsaHerrno(void);
|
UINT16 wsaHerrno(void);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "winproc.h"
|
#include "winproc.h"
|
||||||
#include "syslevel.h"
|
#include "syslevel.h"
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
|
#include "winsock.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -59,7 +60,6 @@ int __winelib = 1; /* Winelib run-time flag */
|
||||||
BOOL MAIN_MainInit(void)
|
BOOL MAIN_MainInit(void)
|
||||||
{
|
{
|
||||||
/* Set server debug level */
|
/* Set server debug level */
|
||||||
/* To fool make_debug: TRACE(server) */
|
|
||||||
CLIENT_SetDebug( TRACE_ON(server) );
|
CLIENT_SetDebug( TRACE_ON(server) );
|
||||||
|
|
||||||
/* Initialize syslevel handling */
|
/* Initialize syslevel handling */
|
||||||
|
@ -89,6 +89,9 @@ BOOL MAIN_MainInit(void)
|
||||||
/* Initialize event handling */
|
/* Initialize event handling */
|
||||||
if (!EVENT_Init()) return FALSE;
|
if (!EVENT_Init()) return FALSE;
|
||||||
|
|
||||||
|
/* Initialise WINSOCK handling */
|
||||||
|
if (!WINSOCK_Init()) return FALSE;
|
||||||
|
|
||||||
/* Initialize communications */
|
/* Initialize communications */
|
||||||
COMM_Init();
|
COMM_Init();
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@ THHOOK *pThhook = &DefaultThhook;
|
||||||
static HTASK16 hTaskToKill = 0;
|
static HTASK16 hTaskToKill = 0;
|
||||||
static UINT16 nTaskCount = 0;
|
static UINT16 nTaskCount = 0;
|
||||||
|
|
||||||
|
static HANDLE TASK_ScheduleEvent = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
static void TASK_YieldToSystem( void );
|
static void TASK_YieldToSystem( void );
|
||||||
|
|
||||||
extern BOOL THREAD_InitDone;
|
extern BOOL THREAD_InitDone;
|
||||||
|
@ -486,15 +488,12 @@ void TASK_StartTask( HTASK16 hTask )
|
||||||
|
|
||||||
if ( THREAD_IsWin16( pTask->thdb ) )
|
if ( THREAD_IsWin16( pTask->thdb ) )
|
||||||
{
|
{
|
||||||
pTask->nEvents++;
|
/* Post event to start the task */
|
||||||
|
PostEvent16( hTask );
|
||||||
/* If we ourselves are a 16-bit task, we simply Yield().
|
|
||||||
If we are 32-bit however, we need to signal the scheduler. */
|
|
||||||
|
|
||||||
|
/* If we ourselves are a 16-bit task, we Yield() directly. */
|
||||||
if ( THREAD_IsWin16( THREAD_Current() ) )
|
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||||
OldYield16();
|
OldYield16();
|
||||||
else
|
|
||||||
EVENT_WakeUp();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,6 +682,13 @@ BOOL TASK_Reschedule(void)
|
||||||
HTASK16 hTask = 0;
|
HTASK16 hTask = 0;
|
||||||
STACK16FRAME *newframe16;
|
STACK16FRAME *newframe16;
|
||||||
|
|
||||||
|
/* Create scheduler event */
|
||||||
|
if ( TASK_ScheduleEvent == INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
TASK_ScheduleEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
|
||||||
|
TASK_ScheduleEvent = ConvertToGlobalHandle( TASK_ScheduleEvent );
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the initial task up and running */
|
/* Get the initial task up and running */
|
||||||
if (!hCurrentTask && GetCurrentTask())
|
if (!hCurrentTask && GetCurrentTask())
|
||||||
{
|
{
|
||||||
|
@ -766,8 +772,9 @@ BOOL TASK_Reschedule(void)
|
||||||
tasks won't execute and Win32 threads are not allowed to enter
|
tasks won't execute and Win32 threads are not allowed to enter
|
||||||
TASK_Reschedule anyway, there should be no re-entrancy problem ... */
|
TASK_Reschedule anyway, there should be no re-entrancy problem ... */
|
||||||
|
|
||||||
|
ResetEvent( TASK_ScheduleEvent );
|
||||||
SYSLEVEL_ReleaseWin16Lock();
|
SYSLEVEL_ReleaseWin16Lock();
|
||||||
EVENT_WaitNetEvent( );
|
WaitForSingleObject( TASK_ScheduleEvent, INFINITE );
|
||||||
SYSLEVEL_RestoreWin16Lock();
|
SYSLEVEL_RestoreWin16Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,12 +971,7 @@ void WINAPI PostEvent16( HTASK16 hTask )
|
||||||
}
|
}
|
||||||
|
|
||||||
pTask->nEvents++;
|
pTask->nEvents++;
|
||||||
|
SetEvent( TASK_ScheduleEvent );
|
||||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
|
||||||
{
|
|
||||||
/* wake-up the scheduler waiting in EVENT_WaitNetEvent */
|
|
||||||
EVENT_WakeUp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
156
misc/winsock.c
156
misc/winsock.c
|
@ -317,6 +317,158 @@ void __ws_memfree(void* ptr)
|
||||||
WS_FREE(ptr);
|
WS_FREE(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event handling helper routines
|
||||||
|
*
|
||||||
|
* FIXME: This is all a hack; winsock event handling should be moved
|
||||||
|
* to the services thread ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EVENT_IO_READ 0
|
||||||
|
#define EVENT_IO_WRITE 1
|
||||||
|
#define EVENT_IO_EXCEPT 2
|
||||||
|
|
||||||
|
static fd_set __winsock_io_set[3];
|
||||||
|
static int __winsock_max_fd = 0;
|
||||||
|
static int __wakeup_pipe[2];
|
||||||
|
|
||||||
|
static CRITICAL_SECTION __winsock_crst;
|
||||||
|
static HANDLE __winsock_thread = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
BOOL WINSOCK_HandleIO( int* max_fd, int num_pending,
|
||||||
|
fd_set pending_set[3], fd_set event_set[3] );
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* WINSOCK_Init
|
||||||
|
*
|
||||||
|
* Initialize network IO.
|
||||||
|
*/
|
||||||
|
BOOL WINSOCK_Init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for( i = 0; i < 3; i++ )
|
||||||
|
FD_ZERO( __winsock_io_set + i );
|
||||||
|
|
||||||
|
/* pipe used to wake up the winsock thread */
|
||||||
|
pipe(__wakeup_pipe);
|
||||||
|
|
||||||
|
/* make the pipe non-blocking */
|
||||||
|
fcntl(__wakeup_pipe[0], F_SETFL, O_NONBLOCK);
|
||||||
|
fcntl(__wakeup_pipe[1], F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
FD_SET( __wakeup_pipe[0], &__winsock_io_set[EVENT_IO_READ] );
|
||||||
|
__winsock_max_fd = __wakeup_pipe[0];
|
||||||
|
__winsock_max_fd++;
|
||||||
|
|
||||||
|
/* Inititalize critical section */
|
||||||
|
InitializeCriticalSection( &__winsock_crst );
|
||||||
|
MakeCriticalSectionGlobal( &__winsock_crst );
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* WINSOCK_Shutdown
|
||||||
|
*/
|
||||||
|
void WINSOCK_Shutdown()
|
||||||
|
{
|
||||||
|
/* Called on exit(), has to remove all outstanding async DNS processes. */
|
||||||
|
|
||||||
|
if ( __winsock_thread != INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
TerminateThread( __winsock_thread, 0 );
|
||||||
|
__winsock_thread = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* WINSOCK_Thread
|
||||||
|
*/
|
||||||
|
static DWORD CALLBACK WINSOCK_Thread( LPVOID arg )
|
||||||
|
{
|
||||||
|
while ( TRUE )
|
||||||
|
{
|
||||||
|
int num_pending, max_fd;
|
||||||
|
fd_set io_set[3];
|
||||||
|
|
||||||
|
EnterCriticalSection( &__winsock_crst );
|
||||||
|
memcpy( io_set, __winsock_io_set, sizeof(io_set) );
|
||||||
|
max_fd = __winsock_max_fd;
|
||||||
|
LeaveCriticalSection( &__winsock_crst );
|
||||||
|
|
||||||
|
num_pending = select( max_fd, &io_set[EVENT_IO_READ],
|
||||||
|
&io_set[EVENT_IO_WRITE],
|
||||||
|
&io_set[EVENT_IO_EXCEPT], NULL );
|
||||||
|
|
||||||
|
if ( num_pending == -1 )
|
||||||
|
{
|
||||||
|
/* Error - signal, invalid arguments, out of memory */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the wake-up pipe */
|
||||||
|
if ( FD_ISSET( __wakeup_pipe[0], &io_set[EVENT_IO_READ] ) )
|
||||||
|
{
|
||||||
|
char tmpBuf[10];
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
while ( (ret = read(__wakeup_pipe[0], &tmpBuf, 10)) == 10 );
|
||||||
|
num_pending--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle actual IO */
|
||||||
|
if ( num_pending > 0 )
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &__winsock_crst );
|
||||||
|
WINSOCK_HandleIO( &__winsock_max_fd, num_pending, io_set, __winsock_io_set );
|
||||||
|
LeaveCriticalSection( &__winsock_crst );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* WINSOCK_WakeUp
|
||||||
|
*
|
||||||
|
* Wake up the winsock thread.
|
||||||
|
*/
|
||||||
|
static void WINSOCK_WakeUp(void)
|
||||||
|
{
|
||||||
|
if ( __winsock_thread == INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
__winsock_thread = CreateThread( NULL, 0, WINSOCK_Thread, NULL, 0, NULL );
|
||||||
|
__winsock_thread = ConvertToGlobalHandle( __winsock_thread );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write (__wakeup_pipe[1], "A", 1) != 1)
|
||||||
|
ERR(winsock, "unable to write in wakeup_pipe\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* EVENT_AddIO
|
||||||
|
*/
|
||||||
|
static void EVENT_AddIO(int fd, unsigned io_type)
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &__winsock_crst );
|
||||||
|
FD_SET( fd, &__winsock_io_set[io_type] );
|
||||||
|
if( __winsock_max_fd <= fd ) __winsock_max_fd = fd + 1;
|
||||||
|
LeaveCriticalSection( &__winsock_crst );
|
||||||
|
|
||||||
|
WINSOCK_WakeUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* EVENT_DeleteIO
|
||||||
|
*/
|
||||||
|
static void EVENT_DeleteIO(int fd, unsigned io_type)
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &__winsock_crst );
|
||||||
|
FD_CLR( fd, &__winsock_io_set[io_type] );
|
||||||
|
LeaveCriticalSection( &__winsock_crst );
|
||||||
|
|
||||||
|
WINSOCK_WakeUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------- API -----
|
/* ----------------------------------- API -----
|
||||||
*
|
*
|
||||||
* Init / cleanup / error checking.
|
* Init / cleanup / error checking.
|
||||||
|
@ -422,10 +574,6 @@ INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
|
||||||
*
|
*
|
||||||
* Cleanup functions of varying impact.
|
* Cleanup functions of varying impact.
|
||||||
*/
|
*/
|
||||||
void WINSOCK_Shutdown()
|
|
||||||
{
|
|
||||||
/* Called on exit(), has to remove all outstanding async DNS processes. */
|
|
||||||
}
|
|
||||||
|
|
||||||
INT WINSOCK_DeleteTaskWSI( TDB* pTask, LPWSINFO pwsi )
|
INT WINSOCK_DeleteTaskWSI( TDB* pTask, LPWSINFO pwsi )
|
||||||
{
|
{
|
||||||
|
|
106
windows/event.c
106
windows/event.c
|
@ -5,9 +5,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "winsock.h"
|
|
||||||
#include "debugtools.h"
|
#include "debugtools.h"
|
||||||
|
|
||||||
DECLARE_DEBUG_CHANNEL(event)
|
DECLARE_DEBUG_CHANNEL(event)
|
||||||
|
@ -16,118 +14,16 @@ DECLARE_DEBUG_CHANNEL(event)
|
||||||
|
|
||||||
EVENT_DRIVER *EVENT_Driver = NULL;
|
EVENT_DRIVER *EVENT_Driver = NULL;
|
||||||
|
|
||||||
/* EVENT_WaitNetEvent() master fd sets */
|
|
||||||
static fd_set __event_io_set[3];
|
|
||||||
static int __event_max_fd = 0;
|
|
||||||
static int __wakeup_pipe[2];
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* EVENT_Init
|
* EVENT_Init
|
||||||
*
|
*
|
||||||
* Initialize network IO.
|
* Initialize input event handling
|
||||||
*/
|
*/
|
||||||
BOOL EVENT_Init(void)
|
BOOL EVENT_Init(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
for( i = 0; i < 3; i++ )
|
|
||||||
FD_ZERO( __event_io_set + i );
|
|
||||||
|
|
||||||
/* this pipe is used to be able to wake-up the scheduler(WaitNetEvent) by
|
|
||||||
a 32 bit thread, this will become obsolete when the input thread will be
|
|
||||||
implemented */
|
|
||||||
pipe(__wakeup_pipe);
|
|
||||||
|
|
||||||
/* make the pipe non-blocking */
|
|
||||||
fcntl(__wakeup_pipe[0], F_SETFL, O_NONBLOCK);
|
|
||||||
fcntl(__wakeup_pipe[1], F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
FD_SET( __wakeup_pipe[0], &__event_io_set[EVENT_IO_READ] );
|
|
||||||
__event_max_fd = __wakeup_pipe[0];
|
|
||||||
__event_max_fd++;
|
|
||||||
|
|
||||||
return EVENT_Driver->pInit();
|
return EVENT_Driver->pInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* EVENT_AddIO
|
|
||||||
*/
|
|
||||||
void EVENT_AddIO(int fd, unsigned io_type)
|
|
||||||
{
|
|
||||||
FD_SET( fd, &__event_io_set[io_type] );
|
|
||||||
if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* EVENT_DeleteIO
|
|
||||||
*/
|
|
||||||
void EVENT_DeleteIO(int fd, unsigned io_type)
|
|
||||||
{
|
|
||||||
FD_CLR( fd, &__event_io_set[io_type] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* EVENT_WakeUp
|
|
||||||
*
|
|
||||||
* Wake up the scheduler (EVENT_WaitNetEvent). Use by 32 bit thread
|
|
||||||
* when thew want signaled an event to a 16 bit task. This function
|
|
||||||
* will become obsolete when an Asynchronous thread will be implemented
|
|
||||||
*/
|
|
||||||
void EVENT_WakeUp(void)
|
|
||||||
{
|
|
||||||
if (write (__wakeup_pipe[1], "A", 1) != 1)
|
|
||||||
ERR_(event)("unable to write in wakeup_pipe\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* EVENT_ReadWakeUpPipe
|
|
||||||
*
|
|
||||||
* Empty the wake up pipe
|
|
||||||
*/
|
|
||||||
void EVENT_ReadWakeUpPipe(void)
|
|
||||||
{
|
|
||||||
char tmpBuf[10];
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
/* Flush the wake-up pipe, it's just dummy data for waking-up this
|
|
||||||
thread. This will be obsolete when the input thread will be done */
|
|
||||||
while ( (ret = read(__wakeup_pipe[0], &tmpBuf, 10)) == 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* EVENT_WaitNetEvent
|
|
||||||
*
|
|
||||||
* Sleep until a network event arrives, or until woken.
|
|
||||||
*/
|
|
||||||
void EVENT_WaitNetEvent( void )
|
|
||||||
{
|
|
||||||
int num_pending;
|
|
||||||
fd_set io_set[3];
|
|
||||||
|
|
||||||
memcpy( io_set, __event_io_set, sizeof(io_set) );
|
|
||||||
|
|
||||||
num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
|
|
||||||
&io_set[EVENT_IO_WRITE],
|
|
||||||
&io_set[EVENT_IO_EXCEPT], NULL );
|
|
||||||
|
|
||||||
if ( num_pending == -1 )
|
|
||||||
{
|
|
||||||
/* Error - signal, invalid arguments, out of memory */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush the wake-up pipe, it's just dummy data for waking-up this
|
|
||||||
thread. This will be obsolete when the input thread will be done */
|
|
||||||
if ( FD_ISSET( __wakeup_pipe[0], &io_set[EVENT_IO_READ] ) )
|
|
||||||
{
|
|
||||||
num_pending--;
|
|
||||||
EVENT_ReadWakeUpPipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Winsock asynchronous services */
|
|
||||||
WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* EVENT_Synchronize
|
* EVENT_Synchronize
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue