#include "threadimpl.h"

long
iocall(Ioproc *io, long (*op)(va_list*), ...)
{
	char e[ERRMAX];
	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)
		strecpy(e, e+sizeof e, io->err);
	io->inuse = 0;

	/* release resources */
	while(send(io->creply, &io) == -1)
		;
	if(ret < 0)
		errstr(e, sizeof e);
	return ret;
}
