xref: /plan9/sys/src/libthread/ioproc.c (revision 7fd46167d91ac0c2e35d4b71179b3ebdd8b6621a)
13ff48bf5SDavid du Colombier #include <u.h>
23ff48bf5SDavid du Colombier #include <libc.h>
33ff48bf5SDavid du Colombier #include <thread.h>
43ff48bf5SDavid du Colombier #include "threadimpl.h"
53ff48bf5SDavid du Colombier 
63ff48bf5SDavid du Colombier enum
73ff48bf5SDavid du Colombier {
83ff48bf5SDavid du Colombier 	STACK = 8192,
93ff48bf5SDavid du Colombier };
103ff48bf5SDavid du Colombier 
113ff48bf5SDavid du Colombier void
iointerrupt(Ioproc * io)123ff48bf5SDavid du Colombier iointerrupt(Ioproc *io)
133ff48bf5SDavid du Colombier {
143ff48bf5SDavid du Colombier 	if(!io->inuse)
153ff48bf5SDavid du Colombier 		return;
16*7fd46167SDavid du Colombier 	threadint(io->tid);
173ff48bf5SDavid du Colombier }
183ff48bf5SDavid du Colombier 
193ff48bf5SDavid du Colombier static void
xioproc(void * a)203ff48bf5SDavid du Colombier xioproc(void *a)
213ff48bf5SDavid du Colombier {
22*7fd46167SDavid du Colombier 	Ioproc *io, *x;
233ff48bf5SDavid du Colombier 	io = a;
24*7fd46167SDavid du Colombier 	/*
25*7fd46167SDavid du Colombier 	 * first recvp acquires the ioproc.
26*7fd46167SDavid du Colombier 	 * second tells us that the data is ready.
27*7fd46167SDavid du Colombier 	 */
28*7fd46167SDavid du Colombier 	for(;;){
29*7fd46167SDavid du Colombier 		while(recv(io->c, &x) == -1)
30*7fd46167SDavid du Colombier 			;
31*7fd46167SDavid du Colombier 		if(x == 0)	/* our cue to leave */
32*7fd46167SDavid du Colombier 			break;
33*7fd46167SDavid du Colombier 		assert(x == io);
34*7fd46167SDavid du Colombier 
35*7fd46167SDavid du Colombier 		/* caller is now committed -- even if interrupted he'll return */
36*7fd46167SDavid du Colombier 		while(recv(io->creply, &x) == -1)
37*7fd46167SDavid du Colombier 			;
38*7fd46167SDavid du Colombier 		if(x == 0)	/* caller backed out */
39*7fd46167SDavid du Colombier 			continue;
40*7fd46167SDavid du Colombier 		assert(x == io);
41*7fd46167SDavid du Colombier 
423ff48bf5SDavid du Colombier 		io->ret = io->op(&io->arg);
433ff48bf5SDavid du Colombier 		if(io->ret < 0)
443ff48bf5SDavid du Colombier 			rerrstr(io->err, sizeof io->err);
45*7fd46167SDavid du Colombier 		while(send(io->creply, &io) == -1)
46*7fd46167SDavid du Colombier 			;
47*7fd46167SDavid du Colombier 		while(recv(io->creply, &x) == -1)
48*7fd46167SDavid du Colombier 			;
493ff48bf5SDavid du Colombier 	}
503ff48bf5SDavid du Colombier }
513ff48bf5SDavid du Colombier 
523ff48bf5SDavid du Colombier Ioproc*
ioproc(void)533ff48bf5SDavid du Colombier ioproc(void)
543ff48bf5SDavid du Colombier {
553ff48bf5SDavid du Colombier 	Ioproc *io;
563ff48bf5SDavid du Colombier 
573ff48bf5SDavid du Colombier 	io = mallocz(sizeof(*io), 1);
583ff48bf5SDavid du Colombier 	if(io == nil)
593ff48bf5SDavid du Colombier 		sysfatal("ioproc malloc: %r");
603ff48bf5SDavid du Colombier 	io->c = chancreate(sizeof(void*), 0);
61*7fd46167SDavid du Colombier 	io->creply = chancreate(sizeof(void*), 0);
62*7fd46167SDavid du Colombier 	io->tid = proccreate(xioproc, io, STACK);
633ff48bf5SDavid du Colombier 	return io;
643ff48bf5SDavid du Colombier }
653ff48bf5SDavid du Colombier 
663ff48bf5SDavid du Colombier void
closeioproc(Ioproc * io)673ff48bf5SDavid du Colombier closeioproc(Ioproc *io)
683ff48bf5SDavid du Colombier {
693ff48bf5SDavid du Colombier 	if(io == nil)
703ff48bf5SDavid du Colombier 		return;
713ff48bf5SDavid du Colombier 	iointerrupt(io);
72*7fd46167SDavid du Colombier 	while(send(io->c, 0) == -1)
73*7fd46167SDavid du Colombier 		;
74*7fd46167SDavid du Colombier 	chanfree(io->c);
75*7fd46167SDavid du Colombier 	chanfree(io->creply);
76*7fd46167SDavid du Colombier 	free(io);
773ff48bf5SDavid du Colombier }
78