xref: /plan9/sys/src/libthread/ioproc.c (revision 7fd46167d91ac0c2e35d4b71179b3ebdd8b6621a)
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5 
6 enum
7 {
8 	STACK = 8192,
9 };
10 
11 void
iointerrupt(Ioproc * io)12 iointerrupt(Ioproc *io)
13 {
14 	if(!io->inuse)
15 		return;
16 	threadint(io->tid);
17 }
18 
19 static void
xioproc(void * a)20 xioproc(void *a)
21 {
22 	Ioproc *io, *x;
23 	io = a;
24 	/*
25 	 * first recvp acquires the ioproc.
26 	 * second tells us that the data is ready.
27 	 */
28 	for(;;){
29 		while(recv(io->c, &x) == -1)
30 			;
31 		if(x == 0)	/* our cue to leave */
32 			break;
33 		assert(x == io);
34 
35 		/* caller is now committed -- even if interrupted he'll return */
36 		while(recv(io->creply, &x) == -1)
37 			;
38 		if(x == 0)	/* caller backed out */
39 			continue;
40 		assert(x == io);
41 
42 		io->ret = io->op(&io->arg);
43 		if(io->ret < 0)
44 			rerrstr(io->err, sizeof io->err);
45 		while(send(io->creply, &io) == -1)
46 			;
47 		while(recv(io->creply, &x) == -1)
48 			;
49 	}
50 }
51 
52 Ioproc*
ioproc(void)53 ioproc(void)
54 {
55 	Ioproc *io;
56 
57 	io = mallocz(sizeof(*io), 1);
58 	if(io == nil)
59 		sysfatal("ioproc malloc: %r");
60 	io->c = chancreate(sizeof(void*), 0);
61 	io->creply = chancreate(sizeof(void*), 0);
62 	io->tid = proccreate(xioproc, io, STACK);
63 	return io;
64 }
65 
66 void
closeioproc(Ioproc * io)67 closeioproc(Ioproc *io)
68 {
69 	if(io == nil)
70 		return;
71 	iointerrupt(io);
72 	while(send(io->c, 0) == -1)
73 		;
74 	chanfree(io->c);
75 	chanfree(io->creply);
76 	free(io);
77 }
78