/*
 * jam 841030-1101-02
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"
#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"

caddr_t
prpc_call(clientClassp, serverConn, serverClass, operation, param)
   rpc_clientClass_t *clientClassp;
   connection_t *serverConn;
   u_short serverClass;
   u_short operation;
   caddr_t param;
{
	register struct proc *p = u.u_procp;
	caddr_t result;
	int s;

	/*
	 * Indicate that we are the client of an RPC
	 * and make the call request.  We will be
	 * awakened when a return or error is
	 * received.
	 */
	p->p_rpcerror = 0;
	p->p_rpcresults = NULL;
	p->p_rpcflags &= ~RPCFLAG_SIGNAL;
	p->p_rpcflags |= RPCFLAG_CLIENT;
	rpc_call((u_long)p, clientClassp, serverConn, serverClass,
							operation, param);

	/*
	 * Sleep until we receive a response or
	 * get an error.  Also, wait until any
	 * outstanding signal calls have gotten
	 * responses.
	 */
	s = RPC_SPL();
	while (p->p_rpcflags & (RPCFLAG_CLIENT | RPCFLAG_SIGNAL))
		/* BUG should sleep at PRIPRPC_CLIENT */
		sleep((caddr_t)&p->p_rpcresults, PZERO-1);
	splx(s);

	result = p->p_rpcresults;
	if (p->p_rpcerror)
		u.u_error = p->p_rpcerror;

	return(result);
}

prpc_return(clientId, result)
   u_long clientId;
   caddr_t result;
{
	register struct proc *p = clientproc(clientId);

	p->p_rpcresults = result;
	prpc_wakeup(p);
}

prpc_error(clientId, error)
   u_long clientId;
   int error;
{
	register struct proc *p = clientproc(clientId);

	p->p_rpcerror = error;
	prpc_wakeup(p);
}

/*
 * Wakeup the client process.  If it is
 * stopped then what happened is that the
 * remote server process was stopped and
 * then some error occurred (such as the
 * connection going down) so that the
 * server was never continued or we never
 * got word that it was; in any event we
 * leave the stopped state.
 */
prpc_wakeup(p)
   register struct proc *p;
{
	p->p_rpcflags &= ~RPCFLAG_CLIENT;
	if (p->p_stat == SSTOP)
		p->p_stat = SSLEEP;

	/*
	 * If there is an outstanding signal
	 * for this call then we do not wake
	 * the process up yet; the rpc signal
	 * module will do that when the signal
	 * has completed.
	 */
	if (!(p->p_rpcflags & RPCFLAG_SIGNAL))
		wakeup((caddr_t)&p->p_rpcresults);
}
