aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/iocall.c
blob: d9cf9d04eeee76ee27a2057c03c88ffc61cfcc7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "threadimpl.h"

long
iocall(Ioproc *io, long (*op)(va_list*), ...)
{
	int ret, inted;
	Ioproc *msg;

	if(send(io->c, &io) == -1){
		werrstr("interrupted");
		return -1;
	}
	assert(!io->inuse);
	io->inuse = 1;
	io->op = op;
	va_start(io->arg, op);
	msg = io;
	inted = 0;
	while(send(io->creply, &msg) == -1){
		msg = nil;
		inted = 1;
	}
	if(inted){
		werrstr("interrupted");
		return -1;
	}

	/*
	 * If we get interrupted, we have stick around so that
	 * the IO proc has someone to talk to.  Send it an interrupt
	 * and try again.
	 */
	inted = 0;
	while(recv(io->creply, nil) == -1){
		inted = 1;
		iointerrupt(io);
	}
	USED(inted);
	va_end(io->arg);
	ret = io->ret;
	if(ret < 0)
		errstr(io->err, sizeof io->err);
	io->inuse = 0;

	/* release resources */
	while(send(io->creply, &io) == -1)
		;
	return ret;
}