DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦d7d43a123⟧ TextFile

    Length: 8427 (0x20eb)
    Types: TextFile
    Notes: UNIX file
    Names: »proc.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦2d53db1df⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »sys/coh/proc.c« 

TextFile

/* (-lgl
 * 	The information contained herein is a trade secret of Mark Williams
 * 	Company, and  is confidential information.  It is provided  under a
 * 	license agreement,  and may be  copied or disclosed  only under the
 * 	terms of  that agreement.  Any  reproduction or disclosure  of this
 * 	material without the express written authorization of Mark Williams
 * 	Company or persuant to the license agreement is unlawful.
 * 
 * 	COHERENT Version 0.7.3
 * 	Copyright (c) 1982, 1983, 1984.
 * 	An unpublished work by Mark Williams Company, Chicago.
 * 	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Process handling and scheduling.
 */
#include <coherent.h>
#include <acct.h>
#include <errno.h>
#include <inode.h>
#include <proc.h>
#include <ptrace.h>
#include <sched.h>
#include <seg.h>
#include <signal.h>
#include <stat.h>
#include <uproc.h>

/*
 * Initialisation.
 * Set up the hash table queues.
 */
pcsinit()
{
	register PROC *pp;
	register PLINK *lp;

	pp = &procq;
	SELF = pp;
	procq.p_nforw = pp;
	procq.p_nback = pp;
	procq.p_lforw = pp;
	procq.p_lback = pp;
	for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
		lp->p_lforw = lp;
		lp->p_lback = lp;
	}
}

/*
 * Initiate a process.  `f' is a kernel function that is associated with
 * the process.
 */
PROC *
process(f)
int (*f)();
{
	register PROC *pp1;
	register PROC *pp;
	register SEG *sp;
	MCON mcon;

	if ((pp=kalloc(sizeof(PROC))) == NULL)
		return (NULL);
	pp->p_flags = PFCORE;
	pp->p_state = PSRUN;
	pp->p_ttdev = NODEV;
	if (f != NULL) {
		pp->p_flags |= PFKERN;
		sp = salloc((size_t)UPASIZE, SFSYST|SFHIGH|SFNSWP);
		if (sp == NULL) {
			kfree(pp);
			return (NULL);
		}
		pp->p_segp[SIUSERP] = sp;
		msetsys(&mcon, f, sp->s_mbase);
		kscopy((char *)&mcon, sp, offset(uproc, u_syscon),
			sizeof(mcon));
	}
	lock(pnxgate);
next:
	pp->p_pid = cpid++;
	if (cpid >= NPID)
		cpid = 2;
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid < pp->p_pid)
			break;
		if (pp1->p_pid == pp->p_pid)
			goto next;
	}
	pp->p_nback = pp1->p_nback;
	pp1->p_nback->p_nforw = pp;
	pp->p_nforw = pp1;
	pp1->p_nback = pp;
	unlock(pnxgate);
	return (pp);
}

/*
 * Remove a process from the next queue and release and space.
 */
relproc(pp)
register PROC *pp;
{
	lock(pnxgate);
	pp->p_nback->p_nforw = pp->p_nforw;
	pp->p_nforw->p_nback = pp->p_nback;
	unlock(pnxgate);
	kfree(pp);
}

/*
 * Create a clone of ourselves.
 *	N.B. - consave(&mcon) returns twice; anything not initialized
 *	in automatic storage before the call to segadup() will not be
 *	initialized when the second return from consave() commences.
 */
pfork()
{
	register PROC *cpp;
	register PROC *pp;
	register int i;
	register int s;
	MCON mcon;

	if ((cpp=process(NULL)) == NULL)
		return;
	s = sphi();	/* Make usave a null macro if unnecessary */
	usave();	/* Put the current copy of uarea into its segment */
	spl(s);
	if (segadup(cpp) == 0) {
		u.u_error = EAGAIN;
		relproc(cpp);
		return;
	}
	u.u_rdir->i_refc++;
	u.u_cdir->i_refc++;
	fdadupl();
	pp = SELF;
	cpp->p_uid = pp->p_uid;
	cpp->p_ruid = pp->p_ruid;
	cpp->p_rgid = pp->p_rgid;
	cpp->p_ppid = pp->p_pid;
	cpp->p_ttdev = pp->p_ttdev;
	cpp->p_group = pp->p_group;
	cpp->p_ssig = pp->p_ssig;
	cpp->p_isig = pp->p_isig;
	cpp->p_cval = CVCHILD;
	cpp->p_ival = IVCHILD;
	cpp->p_sval = SVCHILD;
	cpp->p_rval = RVCHILD;
	s = sphi();	/* Added for IBMSWAP */
	consave(&mcon);
	spl(s);		/* Added for IBMSWAP */
	if ((pp=SELF) != cpp) {
		segfinm(cpp->p_segp[SIUSERP]);
		kscopy((char *)&mcon, cpp->p_segp[SIUSERP],
			offset(uproc, u_syscon), sizeof(mcon));
		mfixcon(cpp);
		s = sphi();
		setrun(cpp);
		spl(s);
		return (cpp->p_pid);
	} else {
		u.u_btime = timer.t_time;
		u.u_flag = AFORK;
		for (i=0; i<NUSEG; i++)
			u.u_segl[i].sr_segp = pp->p_segp[i];
		pp->p_flags |= PFSPROTO;
		segload();
		return (0);
	}
}

/*
 * Die.
 */
pexit(s)
{
	register PROC *pp1;
	register PROC *pp;
	register int n;

	pp = SELF;

	/*
	 * Write out accounting directory and close all files associated with
	 * this process.
	 */
	setacct();
	ldetach(u.u_rdir);
	ldetach(u.u_cdir);
	fdaclose();
	if (pp == slprocp)
		slprocp = NULL;

	/*
	 * This must be done in backwards order to prevent freeing the
	 * user area before we free the shared text segment.
	 */
	n = NUSEG;
	while (n--) {
		if (pp->p_segp[n] == NULL)
			continue;
		sfree(pp->p_segp[n]);
		pp->p_segp[n] = NULL;
	}

	/*
	 * Wakeup our parent.  If we have any children, init will become the
	 * new parent.  If there are any children we are tracing who are
	 * waiting for us, we wake them up.
	 */
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid == pp->p_ppid) {
			if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1)
				wakeup((char *)pp1);
		}
		if (pp1->p_ppid == pp->p_pid) {
			pp1->p_ppid = 1;
			if (pp1->p_state == PSDEAD)
				wakeup((char *)eprocp);
			if ((pp1->p_flags&PFTRAC) != 0)
				wakeup((char *)&pts.pt_req);
		}
	}

	/*
	 * And finally mark us as dead and give up the processor forever.
	 */
	pp->p_exit = s;
	pp->p_state = PSDEAD;
	dispatch();
}

/*
 * Sleep on the event `e'.  This gives up the processor until someone
 * wakes us up.  Since it is possible for many people to sleep on the
 * same event, the caller when awakened should make sure that what he
 * was waiting for has completed and if not, go to sleep again.  `cl'
 * is the cpu value we get to get the cpu as soon as we are woken up.
 * `sl' is the swap value we get to keep us in memory for the duration
 * of the sleep.  `sr' is the swap value that allows us to get swapped
 * in if we have been swapped out.
 */
sleep(e, cl, sl, sr)
char *e;
{
	register PROC *bp;
	register PROC *fp;
	register PROC *pp;
	register int s;

	pp = SELF;

	/*
	 * See if we have a signal awaiting.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}

	/*
	 * Get ready to go to sleep and do so.
	 */
	s = sphi();
	pp->p_state = PSSLEEP;
	pp->p_event = e;
	pp->p_lctim = utimer;
	addu(pp->p_cval, cl);
	pp->p_ival = sl;
	pp->p_rval = sr;
	fp = &linkq[hash(e)];
	bp = fp->p_lback;
	pp->p_lforw = fp;
	fp->p_lback = pp;
	pp->p_lback = bp;
	bp->p_lforw = pp;
	spl(s);
	dispatch();

	/*
	 * We have just woken up.  Get ready to return.
	 */
	subu(pp->p_cval, cl);
	pp->p_ival = 0;
	pp->p_rval = 0;

	/*
	 * Check for an interrupted system call.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}
}

/*
 * Wake up all processes sleeping on the event `e'.
 */
wakeup(e)
char *e;
{
	register PROC *pp;
	register PROC *pp1;
	register int s;

	pp1 = &linkq[hash(e)];
	pp = pp1;
	s = sphi();
	while ((pp=pp->p_lforw) != pp1) {
		if (pp->p_event == e) {
			pp->p_lback->p_lforw = pp->p_lforw;
			pp->p_lforw->p_lback = pp->p_lback;
			addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
			setrun(pp);
			pp = pp1;
			spl(s);
			s = sphi();
		}
	}
	spl(s);
}

/*
 * Reschedule the processor.
 */
dispatch()
{
	register PROC *pp1;
	register PROC *pp2;
	register unsigned v;
	register int s;

	s = sphi();
	pp1 = iprocp;
	pp2 = &procq;
	v = 0;
	while ((pp2=pp2->p_lforw) != &procq) {
		v -= pp2->p_cval;
		if ((pp2->p_flags&PFCORE) == 0)
			continue;
		pp1 = pp2->p_lforw;
		pp1->p_cval += pp2->p_cval;
		pp2->p_cval = v;
		pp1->p_lback = pp2->p_lback;
		pp1->p_lback->p_lforw = pp1;
		pp1 = pp2;
		break;
	}
	spl(s);
	quantum = NCRTICK;
	disflag = 0;
	if (pp1 != SELF) {
		s = sphi();
		SELF = pp1;
		if (consave(&u.u_syscon) == 0)
			conrest(pp1->p_u->s_mbase, offset(uproc, u_syscon));
		else if ((SELF->p_flags&PFKERN) == 0)
			segload();
		spl(s);
	}
}

/*
 * Add a process to the run queue.
 * This routine must be called at high priority.
 */
setrun(pp1)
register PROC *pp1;
{
	register PROC *pp2;
	register unsigned v;

	v = 0;
	pp2 = &procq;
	for (;;) {
		pp2 = pp2->p_lback;
		if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval)
			break;
		if (pp2 == &procq)
			break;
	}
	pp2->p_lforw->p_lback = pp1;
	pp1->p_lforw = pp2->p_lforw;
	pp2->p_lforw = pp1;
	pp1->p_lback = pp2;
	v -= pp1->p_cval;
	pp1->p_cval = v;
	pp1->p_lforw->p_cval -= v;
	pp1->p_state = PSRUN;
}

/*
 * Wait for the gate `g' to unlock, and then lock it.
 */
lock(g)
register GATE g;
{
	register int s;

	s = sphi();
	while (g[0]) {
		g[1]++;
		sleep((char *)g, CVGATE, IVGATE, SVGATE);
		g[1]--;
	}
	g[0] = 1;
	spl(s);
}

/*
 * Unlock the gate `g'.
 */
unlock(g)
register GATE g;
{
	g[0] = 0;
	if (g[1]) {
		disflag = 1;
		wakeup((char *)g);
	}
}