xref: /plan9/sys/src/libthread/iocall.c (revision 5ab4dd4c205ee4af2f09166e9f81c4aec6598a6e)
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5 
6 long
iocall(Ioproc * io,long (* op)(va_list *),...)7 iocall(Ioproc *io, long (*op)(va_list*), ...)
8 {
9 	int ret, inted;
10 	Ioproc *msg;
11 
12 	if(send(io->c, &io) == -1){
13 		werrstr("interrupted");
14 		return -1;
15 	}
16 	assert(!io->inuse);
17 	io->inuse = 1;
18 	io->op = op;
19 	va_start(io->arg, op);
20 	msg = io;
21 	inted = 0;
22 	while(send(io->creply, &msg) == -1){
23 		msg = nil;
24 		inted = 1;
25 	}
26 	if(inted){
27 		werrstr("interrupted");
28 		return -1;
29 	}
30 
31 	/*
32 	 * If we get interrupted, we have to stick around so that
33 	 * the IO proc has someone to talk to.  Send it an interrupt
34 	 * and try again.
35 	 */
36 	inted = 0;
37 	while(recv(io->creply, nil) == -1){
38 		inted = 1;
39 		iointerrupt(io);
40 	}
41 	USED(inted);
42 	va_end(io->arg);
43 	ret = io->ret;
44 	if(ret < 0)
45 		errstr(io->err, sizeof io->err);
46 	io->inuse = 0;
47 
48 	/* release resources */
49 	while(send(io->creply, &io) == -1)
50 		;
51 	return ret;
52 }
53