summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorArmin Novak <anovak@thinstuff.com>2013-08-16 15:51:44 +0200
committerBernhard Miklautz <bmiklautz@thinstuff.at>2013-08-26 20:19:03 +0200
commita91592bd68c027148007f09dc6d681eb55be722e (patch)
treee9d3e8a4b00a2d274a411b6b9011fac81d6d0e2f /channels
parent48ce36fd11b3c0d92a7a74137160327a2767e779 (diff)
downloadfreerdp-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.c64
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;