summaryrefslogtreecommitdiffstats
path: root/auto-virtserial-guest.c
diff options
context:
space:
mode:
Diffstat (limited to 'auto-virtserial-guest.c')
-rw-r--r--auto-virtserial-guest.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/auto-virtserial-guest.c b/auto-virtserial-guest.c
index eebf1f0..2c84c27 100644
--- a/auto-virtserial-guest.c
+++ b/auto-virtserial-guest.c
@@ -24,6 +24,7 @@
#include <error.h>
#include <fcntl.h>
#include <poll.h>
+#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -44,6 +45,8 @@ static int g_bigfile_fd;
static int g_length;
/* The 'name' field in the sysfs port info */
static char g_sysfs_name[1024];
+/* The thread that performs a blocking read operation */
+static pthread_t g_read_thread_id;
static ssize_t safewrite(int fd, const void *buf, size_t count)
@@ -413,6 +416,50 @@ out:
return ret;
}
+static void *t_blocked_read(void *arg)
+{
+ int port_nr = *(int *)arg;
+ int *ret;
+
+ ret = malloc(sizeof(int));
+ if (!ret)
+ return NULL;
+
+ *ret = read_port(port_nr);
+
+ return ret;
+}
+
+static int create_read_thread(int nr)
+{
+ int ret;
+
+ ret = pthread_create(&g_read_thread_id, NULL, &t_blocked_read, &nr);
+ if (ret)
+ return -errno;
+
+ /* Give a chance to the thread to start and block */
+ sleep(2);
+
+ return 0;
+}
+
+static int join_read_thread(int nr)
+{
+ int ret;
+ void *ret2;
+
+ ret = pthread_join(g_read_thread_id, &ret2);
+ if (ret)
+ return ret;
+
+ ret = *(int *)ret2;
+
+ free(ret2);
+
+ return ret;
+}
+
static void send_report(int cfd, int ret)
{
struct guest_packet gpkt;
@@ -539,6 +586,14 @@ back_to_open:
ret = send_guest_csum(gpkt.value);
send_report(cfd, ret);
break;
+ case KEY_CREATE_READ_THREAD:
+ ret = create_read_thread(gpkt.value);
+ send_report(cfd, ret);
+ break;
+ case KEY_JOIN_READ_THREAD:
+ ret = join_read_thread(gpkt.value);
+ send_report(cfd, ret);
+ break;
}
}
return 0;