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,
|
||||
HQUEUE16 hQueue, BOOL remove );
|
||||
|
||||
#define EVENT_IO_READ 0
|
||||
#define EVENT_IO_WRITE 1
|
||||
#define EVENT_IO_EXCEPT 2
|
||||
|
||||
/* event.c */
|
||||
typedef struct tagEVENT_DRIVER {
|
||||
BOOL (*pInit)(void);
|
||||
|
@ -40,15 +36,11 @@ typedef struct tagEVENT_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 void EVENT_WaitNetEvent( void );
|
||||
extern void EVENT_Synchronize( BOOL bProcessEvents );
|
||||
extern BOOL EVENT_CheckFocus( void );
|
||||
extern BOOL EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state);
|
||||
extern void EVENT_DummyMotionNotify(void);
|
||||
extern void EVENT_WakeUp(void);
|
||||
|
||||
/* input.c */
|
||||
|
||||
|
|
|
@ -581,8 +581,8 @@ 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_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] );
|
||||
void WINSOCK_Shutdown(void);
|
||||
BOOL WINSOCK_Init(void);
|
||||
void WINSOCK_Shutdown(void);
|
||||
UINT16 wsaErrno(void);
|
||||
UINT16 wsaHerrno(void);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "winproc.h"
|
||||
#include "syslevel.h"
|
||||
#include "services.h"
|
||||
#include "winsock.h"
|
||||
#include "thread.h"
|
||||
#include "task.h"
|
||||
#include "debug.h"
|
||||
|
@ -59,7 +60,6 @@ int __winelib = 1; /* Winelib run-time flag */
|
|||
BOOL MAIN_MainInit(void)
|
||||
{
|
||||
/* Set server debug level */
|
||||
/* To fool make_debug: TRACE(server) */
|
||||
CLIENT_SetDebug( TRACE_ON(server) );
|
||||
|
||||
/* Initialize syslevel handling */
|
||||
|
@ -86,9 +86,12 @@ BOOL MAIN_MainInit(void)
|
|||
/* Initialise DOS directories */
|
||||
if (!DIR_Init()) return FALSE;
|
||||
|
||||
/* Initialize event handling */
|
||||
/* Initialize event handling */
|
||||
if (!EVENT_Init()) return FALSE;
|
||||
|
||||
/* Initialise WINSOCK handling */
|
||||
if (!WINSOCK_Init()) return FALSE;
|
||||
|
||||
/* Initialize communications */
|
||||
COMM_Init();
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ THHOOK *pThhook = &DefaultThhook;
|
|||
static HTASK16 hTaskToKill = 0;
|
||||
static UINT16 nTaskCount = 0;
|
||||
|
||||
static HANDLE TASK_ScheduleEvent = INVALID_HANDLE_VALUE;
|
||||
|
||||
static void TASK_YieldToSystem( void );
|
||||
|
||||
extern BOOL THREAD_InitDone;
|
||||
|
@ -486,15 +488,12 @@ void TASK_StartTask( HTASK16 hTask )
|
|||
|
||||
if ( THREAD_IsWin16( pTask->thdb ) )
|
||||
{
|
||||
pTask->nEvents++;
|
||||
|
||||
/* If we ourselves are a 16-bit task, we simply Yield().
|
||||
If we are 32-bit however, we need to signal the scheduler. */
|
||||
/* Post event to start the task */
|
||||
PostEvent16( hTask );
|
||||
|
||||
/* If we ourselves are a 16-bit task, we Yield() directly. */
|
||||
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||
OldYield16();
|
||||
else
|
||||
EVENT_WakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,6 +682,13 @@ BOOL TASK_Reschedule(void)
|
|||
HTASK16 hTask = 0;
|
||||
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 */
|
||||
if (!hCurrentTask && GetCurrentTask())
|
||||
{
|
||||
|
@ -766,8 +772,9 @@ BOOL TASK_Reschedule(void)
|
|||
tasks won't execute and Win32 threads are not allowed to enter
|
||||
TASK_Reschedule anyway, there should be no re-entrancy problem ... */
|
||||
|
||||
ResetEvent( TASK_ScheduleEvent );
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
EVENT_WaitNetEvent( );
|
||||
WaitForSingleObject( TASK_ScheduleEvent, INFINITE );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
}
|
||||
|
||||
|
@ -964,12 +971,7 @@ void WINAPI PostEvent16( HTASK16 hTask )
|
|||
}
|
||||
|
||||
pTask->nEvents++;
|
||||
|
||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
||||
{
|
||||
/* wake-up the scheduler waiting in EVENT_WaitNetEvent */
|
||||
EVENT_WakeUp();
|
||||
}
|
||||
SetEvent( TASK_ScheduleEvent );
|
||||
}
|
||||
|
||||
|
||||
|
|
156
misc/winsock.c
156
misc/winsock.c
|
@ -317,6 +317,158 @@ void __ws_memfree(void* 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 -----
|
||||
*
|
||||
* Init / cleanup / error checking.
|
||||
|
@ -422,10 +574,6 @@ INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
|
|||
*
|
||||
* 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 )
|
||||
{
|
||||
|
|
106
windows/event.c
106
windows/event.c
|
@ -5,9 +5,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "message.h"
|
||||
#include "winsock.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DECLARE_DEBUG_CHANNEL(event)
|
||||
|
@ -16,118 +14,16 @@ DECLARE_DEBUG_CHANNEL(event)
|
|||
|
||||
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
|
||||
*
|
||||
* Initialize network IO.
|
||||
* Initialize input event handling
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue