Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - kcc-4/lib/usys/wait.c
There are 9 other files named wait.c in the archive. Click here to see a list.
/* WAIT - simulation of wait(2) system call
**
**	Copyright (c) 1987 by Ken Harrenstien, SRI International
**
**	Returns -1 if no more forks or if interrupted.
*/

#include "c-env.h"
#include "sys/usysig.h"
#include "errno.h"

#if SYS_T20+SYS_10X
#if 0
	The miserable code here for T20 is necessary because of the
incredibly losing way that T20/10X handles forks.  For one thing,
WFORK% hangs forever if there are no inferiors!  For another, there is
no way to identify which fork has stopped other than by examining the
entire fork structure with GFRKS%!  And finally, GFRKS% can only work
within a single section, which is why extended-addressing code must
keep a temporary static buffer and copy it to the stack, hoping that
nothing else clobbers it in the meantime.  Barf, choke, puke.
#endif

#include "jsys.h"

#define MAXFRK 30		/* Max # of forks we expect to see */

struct frkblk {
	unsigned fk_parp : 18;	/* Parallel ptr */
	unsigned fk_infp : 18;	/* Inferior ptr */
	unsigned fk_supp : 18;	/* Superior ptr */
	unsigned fk_hand : 18;	/* Fork handle */
	union {
	    int wd;
	    struct {		/* Fork status word */
		unsigned rf_frz : 1;	/* Frozen bit */
		unsigned rf_sts : 17;	/* Status code */
		unsigned rf_sic : 18;	/* PSI channel causing termination */
	    } bits;
	} fk_stat;
};
#define fk_stafld fk_stat.bits		/* For getting at status bits */
#define fk_status fk_stat.wd		/* For getting at whole word */

struct frkarr {
	struct frkblk fb[MAXFRK];
};
#if SYS_T20			/* Stuff in case using extended addressing */
static int wrkflg = 0;
static struct frkarr wrkarr;	/* GFRKS% stores stuff here */
#endif
#endif /* T20+10X */
int
wait(status)
int *status;
{
#if SYS_T20+SYS_10X
    int acs[5], i;
    struct frkblk *fkp;
    struct frkarr stkarr;	/* Big array on stack */

    USYS_BEG();

    for (;;) {

	fkp = &stkarr.fb[0];		/* Get pointer to stack workspace */
#if SYS_T20
	if ((int)fkp & (-1<<18)) {	/* Check if extended addressing */
	    if (wrkflg) {
#define ERRMSG "\n?KCC runtime error - wait() trying to re-use storage!\n"
		write(2, ERRMSG, sizeof(ERRMSG)-1);
		abort();
	    }
	    wrkflg++;			/* Say storage blk now in use */
	    fkp = &wrkarr.fb[0];	/* Point to static block */
	}
#endif
	acs[1] = _FHSLF;
	acs[2] = GF_GFH|GF_GFS;		/* Get handle & status for each fork */
	acs[3] = (-(sizeof(wrkarr)/sizeof(int))<<18) + ((int)fkp & 0777777);
	if (jsys(GFRKS, acs) <= 0)
	    USYS_RETERR(EFAULT);	/* Shouldn't happen! */
#if SYS_T20
	if (wrkflg) {			/* If extended addressing, */
	    stkarr = wrkarr;		/* Copy results onto stack */
	    wrkflg = 0;			/* Then can release storage */
	    fkp = &stkarr.fb[0];
	}
#endif
	/* Now scan list of inferior forks */
	i = (int)fkp & (-1<<18);	/* Save section # of address */
	fkp = (struct frkblk *)fkp->fk_infp;	/* Start with 1st inferior */
	if (fkp == 0)			/* If no inferiors, */
	    USYS_RETERR(ECHILD);	/* WFORK lied, return failure! */
	for (; fkp; fkp = (struct frkblk *)fkp->fk_parp) {
	    fkp = (struct frkblk *)(i | (int)fkp);	/* Make global ptr */
	    switch (fkp->fk_stafld.rf_sts) {
		default:
		    continue;		/* Not status we want, keep looking */
		case _RFHLT:		/* Process halted? */
		case _RFFPT:		/* Forced process termination? */
		    break;		/* Found one!  Break out */
	    }
	    break;	/* Stop loop */
	}
	if (fkp == 0) {		/* If no stopped inferiors found, */
	    /* Then must wait for one! */
	    acs[1] = _FHINF;		/* All inferiors of current process */
	    i = jsys(WFORK|JSYS_OKINT, acs);	/* Wait */
	    if (i == 0)
		USYS_RETERR(ECHILD);	/* Assume no forks */
	    if (i < 0) {		/* Interrupted? */
		if (USYS_END() < 0) {	/* Yeah, take it, see if must fail */
		    errno = EINTR;	/* Fail, sigh */
		    return -1;
		}
		USYS_BEG();		/* Otherwise disable ints again */
		continue;		/* and re-try the call! */
	    }
	    continue;	/* A fork stopped!  Go try to identify it. */
	}

	/* Found a stopped fork!  Take care of it... */
	acs[1] = fkp->fk_hand;
	jsys(KFORK, acs);		/* Flush the fork */
	if (status) {			/* Return fork status? */
	    if (fkp->fk_stafld.rf_sts == _RFHLT)
		*status = 0;		/* Normal termination */
	    else *status = fkp->fk_status;	/* Return T20 status */
	}
	/* Now return fork handle as a USYS PID */
	jsys(GJINF, acs);		/* Get job # in AC3 */
	USYS_RET(((fkp->fk_hand & 0777)<<9)
			| (acs[3] & 0777));
    }
#else
#error wait() not supported for this system.
#endif
}