aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/ioproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libthread/ioproc.c')
-rw-r--r--src/libthread/ioproc.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/libthread/ioproc.c b/src/libthread/ioproc.c
new file mode 100644
index 00000000..2b2a6025
--- /dev/null
+++ b/src/libthread/ioproc.c
@@ -0,0 +1,74 @@
+#include "threadimpl.h"
+
+enum
+{
+ STACK = 8192,
+};
+
+void
+iointerrupt(Ioproc *io)
+{
+ if(!io->inuse)
+ return;
+ threadint(io->tid);
+}
+
+static void
+xioproc(void *a)
+{
+ Ioproc *io, *x;
+ io = a;
+ /*
+ * first recvp acquires the ioproc.
+ * second tells us that the data is ready.
+ */
+ for(;;){
+ while(recv(io->c, &x) == -1)
+ ;
+ if(x == 0) /* our cue to leave */
+ break;
+ assert(x == io);
+
+ /* caller is now committed -- even if interrupted he'll return */
+ while(recv(io->creply, &x) == -1)
+ ;
+ if(x == 0) /* caller backed out */
+ continue;
+ assert(x == io);
+
+ io->ret = io->op(&io->arg);
+ if(io->ret < 0)
+ rerrstr(io->err, sizeof io->err);
+ while(send(io->creply, &io) == -1)
+ ;
+ while(recv(io->creply, &x) == -1)
+ ;
+ }
+}
+
+Ioproc*
+ioproc(void)
+{
+ Ioproc *io;
+
+ io = mallocz(sizeof(*io), 1);
+ if(io == nil)
+ sysfatal("ioproc malloc: %r");
+ io->c = chancreate(sizeof(void*), 0);
+ io->creply = chancreate(sizeof(void*), 0);
+ io->tid = proccreate(xioproc, io, STACK);
+ return io;
+}
+
+void
+closeioproc(Ioproc *io)
+{
+ if(io == nil)
+ return;
+ iointerrupt(io);
+ while(send(io->c, 0) == -1)
+ ;
+ chanfree(io->c);
+ chanfree(io->creply);
+ free(io);
+}