diff options
author | Armin Novak <anovak@thinstuff.com> | 2013-08-16 15:51:44 +0200 |
---|---|---|
committer | Bernhard Miklautz <bmiklautz@thinstuff.at> | 2013-08-26 20:19:03 +0200 |
commit | a91592bd68c027148007f09dc6d681eb55be722e (patch) | |
tree | e9d3e8a4b00a2d274a411b6b9011fac81d6d0e2f /channels | |
parent | 48ce36fd11b3c0d92a7a74137160327a2767e779 (diff) | |
download | freerdp-a91592bd68c027148007f09dc6d681eb55be722e.tar.gz freerdp-a91592bd68c027148007f09dc6d681eb55be722e.tar.bz2 freerdp-a91592bd68c027148007f09dc6d681eb55be722e.zip |
Using a monitor thread for tty input now to work around a WaitForMultipleObjects
limitation of winpr.
Using infinite timeout now in threads to reduce CPU usage to nearly zero.
Diffstat (limited to 'channels')
-rw-r--r-- | channels/serial/client/serial_main.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index d34dd7a0a..5f8002008 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -63,7 +63,9 @@ struct _SERIAL_DEVICE SERIAL_TTY* tty; HANDLE thread; + HANDLE mthread; HANDLE stopEvent; + HANDLE newEvent; wQueue* queue; LIST* pending_irps; @@ -80,6 +82,7 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32 static void serial_check_for_events(SERIAL_DEVICE* serial); static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp); static BOOL serial_check_fds(SERIAL_DEVICE* serial); +static void* serial_thread_mfunc(void* arg); static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { @@ -121,6 +124,10 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED); + serial->mthread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) serial_thread_mfunc, (void*) serial, + 0, NULL); + DEBUG_SVC("%s(%d) created.", serial->path, FileId); } @@ -147,6 +154,11 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) { DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); + TerminateThread(serial->mthread, 0); + WaitForSingleObject(serial->mthread, INFINITE); + CloseHandle(serial->mthread); + serial->mthread = NULL; + serial_tty_free(tty); serial->tty = NULL; } @@ -326,21 +338,51 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) serial_check_for_events(serial); } +/* This thread is used as a workaround for the missing serial event + * support in WaitForMultipleObjects. + * It monitors the terminal for events and posts it in a supported + * form that WaitForMultipleObjects can use it. */ +void* serial_thread_mfunc(void* arg) +{ + SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; + + while(1) + { + int sl; + fd_set rd; + + if(!serial->tty || serial->tty->fd <= 0) + { + DEBUG_WARN("Monitor thread still running, but no terminal opened!"); + sleep(1); + } + else + { + FD_ZERO(&rd); + FD_SET(serial->tty->fd, &rd); + sl = select(serial->tty->fd + 1, &rd, NULL, NULL, NULL); + if( sl > 0 ) + SetEvent(serial->newEvent); + } + } + + return NULL; +} + static void* serial_thread_func(void* arg) { IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; - HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)}; + HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent}; while (1) { - status = WaitForMultipleObjects(2, ev, FALSE, 1); - + status = WaitForMultipleObjects(3, ev, FALSE, INFINITE); + if (WAIT_OBJECT_0 == status) break; - - if (status == WAIT_OBJECT_0 + 1) + else if (status == WAIT_OBJECT_0 + 1) { FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); @@ -351,8 +393,9 @@ static void* serial_thread_func(void* arg) if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); - continue; } + else if (status == WAIT_OBJECT_0 + 2) + ResetEvent(serial->newEvent); if(serial->tty) serial_check_fds(serial); @@ -376,6 +419,12 @@ static void serial_free(DEVICE* device) /* Stop thread */ SetEvent(serial->stopEvent); + if(serial->mthread) + { + TerminateThread(serial->mthread, 0); + WaitForSingleObject(serial->mthread, INFINITE); + CloseHandle(serial->mthread); + } WaitForSingleObject(serial->thread, INFINITE); serial_tty_free(serial->tty); @@ -385,6 +434,7 @@ static void serial_free(DEVICE* device) Queue_Free(serial->queue); list_free(serial->pending_irps); CloseHandle(serial->stopEvent); + CloseHandle(serial->newEvent); CloseHandle(serial->thread); free(serial); } @@ -754,11 +804,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) serial->pending_irps = list_new(); serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + serial->newEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial); serial->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL); + serial->mthread = NULL; } return 0; |