Commit 89fc6fda authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Moved WINSOCK network IO event handling to special thread.

Removed EVENT_WaitNetEvent, introduced a global scheduler event.
parent a1957c4d
......@@ -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 );
}
......
......@@ -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 )
{
......
......@@ -5,9 +5,7 @@
*
*/
#include <unistd.h>
#include "message.h"
#include "winsock.h"
#include "debugtools.h"
DECLARE_DEBUG_CHANNEL(event)
......@@ -16,119 +14,17 @@ 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
*
* Synchronize with the X server. Should not be used too often.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment