Initial revision
This commit is contained in:
		
							parent
							
								
									bc94559e4d
								
							
						
					
					
						commit
						2eeacf071a
					
				
					 17 changed files with 1034 additions and 0 deletions
				
			
		
							
								
								
									
										11
									
								
								lang/occam/lib/AR2
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								lang/occam/lib/AR2
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
case $# in
 | 
			
		||||
	0)	ar ru /user0/bot/lib/lib2.a *.o
 | 
			
		||||
		ranlib /user0/bot/lib/lib2.a
 | 
			
		||||
		rm -f *.o
 | 
			
		||||
	;;
 | 
			
		||||
	*)	keys=$1
 | 
			
		||||
		shift
 | 
			
		||||
		ar $keys /user0/bot/lib/lib2.a $*
 | 
			
		||||
	;;
 | 
			
		||||
esac
 | 
			
		||||
							
								
								
									
										11
									
								
								lang/occam/lib/AR4
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								lang/occam/lib/AR4
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
case $# in
 | 
			
		||||
	0)	ar ru /user0/bot/lib/lib4.a *.o
 | 
			
		||||
		ranlib /user0/bot/lib/lib4.a
 | 
			
		||||
		rm -f *.o
 | 
			
		||||
	;;
 | 
			
		||||
	*)	keys=$1
 | 
			
		||||
		shift
 | 
			
		||||
		ar $keys /user0/bot/lib/lib4.a $*
 | 
			
		||||
	;;
 | 
			
		||||
esac
 | 
			
		||||
							
								
								
									
										28
									
								
								lang/occam/lib/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								lang/occam/lib/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
PRIMITIVES=	par_vax.s
 | 
			
		||||
PARALLEL=	parco.c par.c co.c
 | 
			
		||||
OCRT=		ocrt.c builtin.c channel.c chan_struct.c
 | 
			
		||||
 | 
			
		||||
COMMON=		$(PRIMITIVES) $(PARALLEL) $(OCRT)
 | 
			
		||||
 | 
			
		||||
SIZE2=	em2.e
 | 
			
		||||
SIZE4=	em4.e
 | 
			
		||||
 | 
			
		||||
LIB2=	/user0/bot/lib/lib2.a
 | 
			
		||||
LIB4=	/user0/bot/lib/lib4.a
 | 
			
		||||
 | 
			
		||||
ACK2=	vax2
 | 
			
		||||
ACK4=	vax4
 | 
			
		||||
 | 
			
		||||
all:	lib2 lib4
 | 
			
		||||
 | 
			
		||||
lib2:	$(COMMON) $(SIZE2)
 | 
			
		||||
	rm -f *.o $(LIB2)
 | 
			
		||||
	$(ACK2) -c.o -L -Dvoid=char -Dptrdiff=long $(COMMON) $(SIZE2)
 | 
			
		||||
	ar cq $(LIB2) *.o
 | 
			
		||||
	rm -f *.o
 | 
			
		||||
 | 
			
		||||
lib4:	$(COMMON) $(SIZE4)
 | 
			
		||||
	rm -f *.o $(LIB4)
 | 
			
		||||
	$(ACK4) -c.o -L -Dvoid=char $(COMMON) $(SIZE4)
 | 
			
		||||
	ar cq $(LIB4) *.o
 | 
			
		||||
	rm -f *.o
 | 
			
		||||
							
								
								
									
										75
									
								
								lang/occam/lib/builtin.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								lang/occam/lib/builtin.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
/*	builtin.c - built in named processes */
 | 
			
		||||
#include "channel.h"
 | 
			
		||||
#ifndef nil
 | 
			
		||||
#define nil 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern int errno;
 | 
			
		||||
 | 
			
		||||
static void nullterm(s) register char *s;
 | 
			
		||||
/* Change Occam string to C string */
 | 
			
		||||
{
 | 
			
		||||
	register len= (*s & 0377);
 | 
			
		||||
	register char *p;
 | 
			
		||||
 | 
			
		||||
	while (--len>=0) {
 | 
			
		||||
		p=s++;
 | 
			
		||||
		*p = *s;
 | 
			
		||||
	}
 | 
			
		||||
	*s=0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void lenterm(s) register char *s;
 | 
			
		||||
/* Change C string to Occam string */
 | 
			
		||||
{
 | 
			
		||||
	register i=0;
 | 
			
		||||
	register c0, c1;
 | 
			
		||||
 | 
			
		||||
	c0=0;
 | 
			
		||||
	do {
 | 
			
		||||
		c1=s[i];
 | 
			
		||||
		s[i++]=c0;
 | 
			
		||||
		c0=c1;
 | 
			
		||||
	} while (c0!=0);
 | 
			
		||||
	*s= i-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void b_open(mode, name, index) register char *mode, *name; long *index;
 | 
			
		||||
/* PROC open(VAR index, VALUE name[], mode[])=	*/
 | 
			
		||||
{
 | 
			
		||||
	register FILE *fp;
 | 
			
		||||
	register i;
 | 
			
		||||
 | 
			
		||||
	nullterm(name);
 | 
			
		||||
	nullterm(mode);
 | 
			
		||||
 | 
			
		||||
	fp=fopen(name, mode);
 | 
			
		||||
 | 
			
		||||
	lenterm(name);
 | 
			
		||||
	lenterm(mode);
 | 
			
		||||
 | 
			
		||||
	if (fp==nil)
 | 
			
		||||
		*index= -errno;
 | 
			
		||||
	else {
 | 
			
		||||
		/* Find free file channel, there must be one free! */
 | 
			
		||||
 | 
			
		||||
		for (i=0; (file[i].f.flgs&C_F_INUSE)!=0; i++) ;
 | 
			
		||||
 | 
			
		||||
		file[i].f.flgs|=C_F_INUSE;
 | 
			
		||||
		unix_file[i]=fp;
 | 
			
		||||
		*index=i;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void b_close(index) long index;
 | 
			
		||||
/* PROC close(VALUE index)=	*/
 | 
			
		||||
{
 | 
			
		||||
	fclose(unix_file[index]);
 | 
			
		||||
	file[index].f.flgs&= ~C_F_INUSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void b_exit(code) long code;
 | 
			
		||||
/* PROC exit(VALUE code)=	*/
 | 
			
		||||
{
 | 
			
		||||
	exit((int) code);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										152
									
								
								lang/occam/lib/channel.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								lang/occam/lib/channel.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
/*	channel.c - basic channel handling routines */
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sgtty.h>
 | 
			
		||||
#include "channel.h"
 | 
			
		||||
 | 
			
		||||
static void disaster();
 | 
			
		||||
 | 
			
		||||
void c_init(c, z) register chan *c; register unsigned z;
 | 
			
		||||
/* Initialise an array of interprocess channels declared as: CHAN c[z]. */
 | 
			
		||||
{
 | 
			
		||||
	do {
 | 
			
		||||
		c->type=C_T_CHAN;
 | 
			
		||||
		(c++)->c.synch=C_S_FREE;
 | 
			
		||||
	} while (--z!=0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chan_in(v, c) long *v; register chan *c;
 | 
			
		||||
/* Reads a value from channel c and returns it through v. */
 | 
			
		||||
{
 | 
			
		||||
	switch(c->type) {
 | 
			
		||||
	case C_T_FILE:
 | 
			
		||||
		if ((c->f.flgs&C_F_READAHEAD)!=0) {
 | 
			
		||||
			*v=(c->f.preread&0377);
 | 
			
		||||
			c->f.flgs&= ~C_F_READAHEAD;
 | 
			
		||||
		} else {
 | 
			
		||||
			register FILE *fp= unix_file[c->f.index];
 | 
			
		||||
 | 
			
		||||
			*v= feof(fp) ? C_F_EOF : getc(fp);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case C_T_CHAN:
 | 
			
		||||
		deadlock=0;		/* Wait for value to arrive */
 | 
			
		||||
		while (c->c.synch!=C_S_ANY) resumenext();
 | 
			
		||||
 | 
			
		||||
		*v=c->c.val;
 | 
			
		||||
		c->c.synch=C_S_ACK;	/* Acknowledge receipt */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		disaster();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chan_out(v, c) long v; register chan *c;
 | 
			
		||||
/* Send value v through channel c. */
 | 
			
		||||
{
 | 
			
		||||
	switch(c->type) {
 | 
			
		||||
	case C_T_FILE: {
 | 
			
		||||
		register FILE *fp= unix_file[c->f.index];
 | 
			
		||||
		struct sgttyb tty;
 | 
			
		||||
 | 
			
		||||
		if ((v& ~0xff)==0)	/* Plain character */
 | 
			
		||||
			putc( (int) v, fp);
 | 
			
		||||
		else
 | 
			
		||||
		if (v==C_F_TEXT) {
 | 
			
		||||
			ioctl(fileno(fp), TIOCGETP, &tty);
 | 
			
		||||
			tty.sg_flags&= ~CBREAK;
 | 
			
		||||
			tty.sg_flags|= ECHO|CRMOD;
 | 
			
		||||
			ioctl(fileno(fp), TIOCSETN, &tty);
 | 
			
		||||
		} else
 | 
			
		||||
		if (v==C_F_RAW) {
 | 
			
		||||
			ioctl(fileno(fp), TIOCGETP, &tty);
 | 
			
		||||
			tty.sg_flags|= CBREAK;
 | 
			
		||||
			tty.sg_flags&= ~(ECHO|CRMOD);
 | 
			
		||||
			ioctl(fileno(fp), TIOCSETN, &tty);
 | 
			
		||||
		}
 | 
			
		||||
	}	break;
 | 
			
		||||
	case C_T_CHAN:
 | 
			
		||||
		deadlock=0;		/* Wait until channel is free */
 | 
			
		||||
		while (c->c.synch!=C_S_FREE) resumenext();
 | 
			
		||||
 | 
			
		||||
		c->c.val=v;
 | 
			
		||||
		c->c.synch=C_S_ANY;	/* Channel has data */
 | 
			
		||||
 | 
			
		||||
		deadlock=0;		/* Wait for acknowledgement */
 | 
			
		||||
		while (c->c.synch!=C_S_ACK) resumenext();
 | 
			
		||||
 | 
			
		||||
		c->c.synch=C_S_FREE;	/* Back to normal */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		disaster();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int timeout();
 | 
			
		||||
 | 
			
		||||
int chan_any(c) register chan *c;
 | 
			
		||||
{
 | 
			
		||||
	switch (c->type) {
 | 
			
		||||
	case C_T_FILE:
 | 
			
		||||
		if ((c->f.flgs&C_F_READAHEAD)!=0)
 | 
			
		||||
			return 1;
 | 
			
		||||
		else {
 | 
			
		||||
			register FILE *fp= unix_file[c->f.index];
 | 
			
		||||
			
 | 
			
		||||
			if (feof(fp))
 | 
			
		||||
				return 1;
 | 
			
		||||
			else {
 | 
			
		||||
				extern int errno;
 | 
			
		||||
				register ch;
 | 
			
		||||
 | 
			
		||||
				deadlock=0;
 | 
			
		||||
					/* No deadlock while waiting for key */
 | 
			
		||||
 | 
			
		||||
				signal(SIGALRM, timeout);
 | 
			
		||||
				alarm(1);
 | 
			
		||||
 | 
			
		||||
				errno=0;
 | 
			
		||||
				ch=getc(fp);
 | 
			
		||||
 | 
			
		||||
				signal(SIGALRM, SIG_IGN);
 | 
			
		||||
				alarm(0);
 | 
			
		||||
 | 
			
		||||
				if (errno==EINTR)
 | 
			
		||||
					return 0;
 | 
			
		||||
				else {
 | 
			
		||||
					if (!feof(fp)) {
 | 
			
		||||
						c->f.flgs|=C_F_READAHEAD;
 | 
			
		||||
						c->f.preread=ch;
 | 
			
		||||
					}
 | 
			
		||||
					return 1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case C_T_CHAN:
 | 
			
		||||
		return c->c.synch==C_S_ANY;
 | 
			
		||||
	default:
 | 
			
		||||
		disaster();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The ch=getc(fp) in the above function calls read(2) to do its task, but if
 | 
			
		||||
 * there's no input on the file (pipe or terminal) then the read will block.
 | 
			
		||||
 * To stop this read from blocking, we use the fact that if the read is
 | 
			
		||||
 * interrupted by a signal that is caught by the program, then the read returns
 | 
			
		||||
 * error EINTR after the signal is processed. Thus we use a one second alarm
 | 
			
		||||
 * to interrupt the read with a trap to timeout(). But since the alarm signal
 | 
			
		||||
 * may occur *before* the read is called, it is continuously restarted in
 | 
			
		||||
 * timeout() to prevent it from getting lost.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int timeout(sig)
 | 
			
		||||
{
 | 
			
		||||
	signal(SIGALRM, timeout);
 | 
			
		||||
	alarm(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void disaster()
 | 
			
		||||
{
 | 
			
		||||
	write(2, "Fatal error: Channel variable corrupted\n", 40);
 | 
			
		||||
	abort();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										115
									
								
								lang/occam/lib/co.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								lang/occam/lib/co.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,115 @@
 | 
			
		|||
/*	co.c - Routines to handle coroutines */
 | 
			
		||||
#include "process.h"
 | 
			
		||||
 | 
			
		||||
static void search(), RESUMERR();
 | 
			
		||||
 | 
			
		||||
void resume(id) identification id;
 | 
			
		||||
/* Stops the current process, by saving its stack, and searches for the
 | 
			
		||||
 * process with identification 'id' in the group the running process
 | 
			
		||||
 * belongs to. If 'id' cannot be found then repeat these actions with
 | 
			
		||||
 * the running process' parent. If 'id' is found it is activated. It
 | 
			
		||||
 * is a fatal error if 'id' cannot be found.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	if (group!=nil) {
 | 
			
		||||
		register wordsize size;
 | 
			
		||||
 | 
			
		||||
		size=top_size(group->s_brk);
 | 
			
		||||
		(*group->active)->stack=alloc((unsigned) size);
 | 
			
		||||
 | 
			
		||||
		if (top_save(size, (*group->active)->stack))
 | 
			
		||||
			search(id);
 | 
			
		||||
		else {
 | 
			
		||||
			free((*group->active)->stack);
 | 
			
		||||
			load_betweens();
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		RESUMERR();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void search(id) identification id;
 | 
			
		||||
/* Searches for the process with identification 'id'.
 | 
			
		||||
 * If the process is found it is activated and its process tree is
 | 
			
		||||
 * traversed to find the running process.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	register struct process **aproc, *proc;
 | 
			
		||||
 | 
			
		||||
	for(;;) {
 | 
			
		||||
		aproc= &group->first;
 | 
			
		||||
 | 
			
		||||
		while (*aproc!=nil && (*aproc)->id!=id)
 | 
			
		||||
			aproc= &(*aproc)->next;
 | 
			
		||||
 | 
			
		||||
		if (*aproc!=nil) break;
 | 
			
		||||
 | 
			
		||||
		save_between(group);
 | 
			
		||||
 | 
			
		||||
		if ((group=group->up)==nil)
 | 
			
		||||
			RESUMERR();
 | 
			
		||||
	}
 | 
			
		||||
	group->active=aproc;
 | 
			
		||||
	proc= *aproc;
 | 
			
		||||
	highest_group=group;
 | 
			
		||||
 | 
			
		||||
	while (proc->down!=nil) {
 | 
			
		||||
		group=proc->down;
 | 
			
		||||
		proc= *group->active;
 | 
			
		||||
	}
 | 
			
		||||
	top_load(proc->stack);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void delete_group(group) struct procgroup *group;
 | 
			
		||||
/* Removes the whole group and sub-groups recursively from the running
 | 
			
		||||
 * process.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	register struct process *proc, *next;
 | 
			
		||||
 | 
			
		||||
	proc=group->first;
 | 
			
		||||
 | 
			
		||||
	while (proc!=nil) {
 | 
			
		||||
		if (proc->down!=nil)
 | 
			
		||||
			delete_group(proc->down);
 | 
			
		||||
		else
 | 
			
		||||
			free(proc->stack);
 | 
			
		||||
		next=proc->next;
 | 
			
		||||
		free( (void *) proc);
 | 
			
		||||
		proc=next;
 | 
			
		||||
	}
 | 
			
		||||
	delete_between(group);
 | 
			
		||||
	free( (void *) group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void coend()
 | 
			
		||||
{
 | 
			
		||||
	register struct process *proc, *next;
 | 
			
		||||
	register struct procgroup *junk;
 | 
			
		||||
 | 
			
		||||
	proc=group->first;
 | 
			
		||||
 | 
			
		||||
	while (proc!=nil) {
 | 
			
		||||
		if (proc!= *group->active) {
 | 
			
		||||
			if (proc->down!=nil)
 | 
			
		||||
				delete_group(proc->down);
 | 
			
		||||
			else
 | 
			
		||||
				free(proc->stack);
 | 
			
		||||
		}
 | 
			
		||||
		next=proc->next;
 | 
			
		||||
		free( (void *) proc);
 | 
			
		||||
		proc=next;
 | 
			
		||||
	}
 | 
			
		||||
	delete_between(group);
 | 
			
		||||
	junk=group;
 | 
			
		||||
	group=group->up;
 | 
			
		||||
	free( (void *) junk);
 | 
			
		||||
 | 
			
		||||
	if (group!=nil)
 | 
			
		||||
		(*group->active)->down=nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void RESUMERR()
 | 
			
		||||
{
 | 
			
		||||
	write(2, "RESUMERR\n", 9);
 | 
			
		||||
	abort();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								lang/occam/lib/em2.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lang/occam/lib/em2.e
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
 mes 2,2,4
 | 
			
		||||
 | 
			
		||||
oldtrp
 | 
			
		||||
 bss 4, 0, 0
 | 
			
		||||
 | 
			
		||||
 exp $init
 | 
			
		||||
 pro $init, 0
 | 
			
		||||
 loc -321-1
 | 
			
		||||
 sim
 | 
			
		||||
 lpi $catch1
 | 
			
		||||
 sig
 | 
			
		||||
 sde oldtrp
 | 
			
		||||
 cal $initfile
 | 
			
		||||
 ret 0
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 pro $catch1, 0
 | 
			
		||||
 lde oldtrp
 | 
			
		||||
 sig
 | 
			
		||||
 asp 4
 | 
			
		||||
 loe 0
 | 
			
		||||
 lde 4
 | 
			
		||||
 lol 0
 | 
			
		||||
 cal $catch
 | 
			
		||||
 asp 8
 | 
			
		||||
 lol 0
 | 
			
		||||
 trp
 | 
			
		||||
 rtt
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 exp $now
 | 
			
		||||
 pro $now, 12
 | 
			
		||||
 zre deadlock
 | 
			
		||||
 lal -12
 | 
			
		||||
 loc 35
 | 
			
		||||
 mon
 | 
			
		||||
 asp 2
 | 
			
		||||
 ldl -12
 | 
			
		||||
 ret 4
 | 
			
		||||
 end 12
 | 
			
		||||
 | 
			
		||||
 exp $block_mo
 | 
			
		||||
 pro $block_mo, 0
 | 
			
		||||
 ldl 4
 | 
			
		||||
 ldl 8
 | 
			
		||||
 ldl 0
 | 
			
		||||
 loc 4
 | 
			
		||||
 loc 2
 | 
			
		||||
 cuu
 | 
			
		||||
 bls 2
 | 
			
		||||
 ret 0
 | 
			
		||||
 end 0
 | 
			
		||||
							
								
								
									
										49
									
								
								lang/occam/lib/em4.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lang/occam/lib/em4.e
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
 mes 2,4,4
 | 
			
		||||
 | 
			
		||||
oldtrp
 | 
			
		||||
 bss 4, 0, 0
 | 
			
		||||
 | 
			
		||||
 exp $init
 | 
			
		||||
 pro $init, 0
 | 
			
		||||
 loc -321-1
 | 
			
		||||
 sim
 | 
			
		||||
 lpi $catch1
 | 
			
		||||
 sig
 | 
			
		||||
 ste oldtrp
 | 
			
		||||
 cal $initfile
 | 
			
		||||
 ret 0
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 pro $catch1, 0
 | 
			
		||||
 loe oldtrp
 | 
			
		||||
 sig
 | 
			
		||||
 asp 4
 | 
			
		||||
 loe 0
 | 
			
		||||
 loe 4
 | 
			
		||||
 lol 0
 | 
			
		||||
 cal $catch
 | 
			
		||||
 asp 12
 | 
			
		||||
 lol 0
 | 
			
		||||
 trp
 | 
			
		||||
 rtt
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 exp $now
 | 
			
		||||
 pro $now, 12
 | 
			
		||||
 zre deadlock
 | 
			
		||||
 lal -12
 | 
			
		||||
 loc 35
 | 
			
		||||
 mon
 | 
			
		||||
 asp 4
 | 
			
		||||
 lol -12
 | 
			
		||||
 ret 4
 | 
			
		||||
 end 12
 | 
			
		||||
 | 
			
		||||
 exp $block_mo
 | 
			
		||||
 pro $block_mo, 0
 | 
			
		||||
 lol 4
 | 
			
		||||
 lol 8
 | 
			
		||||
 lol 0
 | 
			
		||||
 bls 4
 | 
			
		||||
 ret 0
 | 
			
		||||
 end 0
 | 
			
		||||
							
								
								
									
										47
									
								
								lang/occam/lib/ocm_chan.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lang/occam/lib/ocm_chan.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
/*	channel.h - channel definitions */
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "parco.h"
 | 
			
		||||
 | 
			
		||||
typedef union channel {
 | 
			
		||||
	struct {		/* Interprocess channel */
 | 
			
		||||
		char _type;	/* Channel type, see note */
 | 
			
		||||
		char synch;	/* State in channel synchronization */
 | 
			
		||||
		long val;	/* Transmitted value */
 | 
			
		||||
	} c;
 | 
			
		||||
	struct {		/* File channel */
 | 
			
		||||
		char _type;	/* Dummy field, see note */
 | 
			
		||||
		char index;	/* Index in the file array */
 | 
			
		||||
		char flgs;	/* Status flags: in use & readahead */
 | 
			
		||||
		char preread;	/* Possible preread character */
 | 
			
		||||
	} f;
 | 
			
		||||
} chan;
 | 
			
		||||
#define type		c._type	/* Channel type */
 | 
			
		||||
/* Note: The channel type should not be part of each structure in chan. But
 | 
			
		||||
 * the C alignment rules would make chan about 50% bigger if we had done it
 | 
			
		||||
 * the right way. Note that the order of fields in a struct cannot be a problem
 | 
			
		||||
 * as long as struct c is the largest within the union.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define C_T_CHAN	0	/* Type of a interprocess channel */
 | 
			
		||||
#define C_T_FILE	1	/* Type of a file channel */
 | 
			
		||||
 | 
			
		||||
#define C_S_FREE	0	/* IP channel is free */
 | 
			
		||||
#define C_S_ANY		1	/* IP channel contains data */
 | 
			
		||||
#define C_S_ACK		2	/* IP channel data is removed */
 | 
			
		||||
 | 
			
		||||
#define C_F_EOF		(-1L)	/* File channel returns EOF */
 | 
			
		||||
#define C_F_TEXT	(-2L)	/* File channel becomes line oriented */
 | 
			
		||||
#define C_F_RAW		(-3L)	/* File channel becomes character oriented */
 | 
			
		||||
 | 
			
		||||
#define C_F_INUSE	0x01	/* File channel is connected to a UNIX file */
 | 
			
		||||
#define C_F_READAHEAD	0x02	/* File channel has a preread character */
 | 
			
		||||
 | 
			
		||||
extern chan file[_NFILE];	/* Array of file channels */
 | 
			
		||||
extern FILE *unix_file[_NFILE];	/* Pointers to buffered UNIX files */
 | 
			
		||||
 | 
			
		||||
void c_init();
 | 
			
		||||
 | 
			
		||||
void chan_in(), cbyte_in(), c_wa_in(), c_ba_in();
 | 
			
		||||
void chan_out(), c_wa_out(), c_ba_out();
 | 
			
		||||
 | 
			
		||||
int chan_any();
 | 
			
		||||
							
								
								
									
										18
									
								
								lang/occam/lib/ocm_parco.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lang/occam/lib/ocm_parco.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
/*	parco.h - Define names for simulation routines
 | 
			
		||||
 *
 | 
			
		||||
 *      This file is to be included by users of the higher-level routines
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void pc_begin(), resumenext(), parend(), resume(), coend();
 | 
			
		||||
int pc_fork();
 | 
			
		||||
 | 
			
		||||
#define nullid	((int *) 0 - (int *) 0)
 | 
			
		||||
	/* I.e. a 0 of type "pointer difference" */
 | 
			
		||||
 | 
			
		||||
#define parbegin(sbrk)		pc_begin(sbrk, nullid)
 | 
			
		||||
#define parfork()		pc_fork(nullid)
 | 
			
		||||
#define cobegin(sbrk, id)	pc_begin(sbrk, id)
 | 
			
		||||
#define cofork(id)		pc_fork(id)
 | 
			
		||||
 | 
			
		||||
extern int deadlock;
 | 
			
		||||
							
								
								
									
										52
									
								
								lang/occam/lib/ocm_proc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lang/occam/lib/ocm_proc.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/*	process.h - Define administration types and functions
 | 
			
		||||
 *
 | 
			
		||||
 *      This file is to be included by implementors of the higher
 | 
			
		||||
 *      level routines
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include "parco.h"
 | 
			
		||||
 | 
			
		||||
#ifndef ptrdiff	/* This type must be able to hold a pointer difference */
 | 
			
		||||
#define ptrdiff int	/* Define as long int if necessary */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define nil	0
 | 
			
		||||
void *alloc(), free();
 | 
			
		||||
 | 
			
		||||
typedef ptrdiff wordsize, identification;
 | 
			
		||||
 | 
			
		||||
wordsize top_size();
 | 
			
		||||
int top_save();
 | 
			
		||||
void top_load();		/* Primitives */
 | 
			
		||||
 | 
			
		||||
struct procgroup;
 | 
			
		||||
 | 
			
		||||
struct process {
 | 
			
		||||
	struct process *next;	/* Next process in the same group */
 | 
			
		||||
	struct procgroup *down;	/* Process group running under this process */
 | 
			
		||||
	void *stack;		/* Pointer to the saved stack top */
 | 
			
		||||
	identification id;	/* Coroutine identification */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define init_between	__i_b__	/* These names are hidden */
 | 
			
		||||
#define save_between	__s_b__
 | 
			
		||||
#define load_betweens	__l_b__
 | 
			
		||||
#define delete_between	__d_b__
 | 
			
		||||
 | 
			
		||||
void init_between(), save_between(), load_betweens(), delete_between();
 | 
			
		||||
 | 
			
		||||
struct procgroup {
 | 
			
		||||
	struct process **active;/* Active process within this group */
 | 
			
		||||
	struct procgroup *up;	/* The group that this group belongs to */
 | 
			
		||||
	struct process *first;	/* List of processes belonging to this group */
 | 
			
		||||
	void *s_brk;		/* Point where the stack is split */
 | 
			
		||||
	void *between;		/* Stack space between s_brk and up->s_brk */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define group		__grp__	/* Ignore this please */
 | 
			
		||||
#define highest_group	__hgrp__
 | 
			
		||||
 | 
			
		||||
extern struct procgroup *group;		/* Current running group */
 | 
			
		||||
extern struct procgroup *highest_group;	/* highest group that has been seen
 | 
			
		||||
					 * while searching for a process
 | 
			
		||||
					 */
 | 
			
		||||
							
								
								
									
										52
									
								
								lang/occam/lib/ocrt.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lang/occam/lib/ocrt.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/*	ocrt.c - Occam runtime support */
 | 
			
		||||
#include "channel.h"
 | 
			
		||||
 | 
			
		||||
int chandes[]= { 0, 0, sizeof(int)+sizeof(long) };
 | 
			
		||||
int worddes[]= { 0, 0, sizeof(long) };
 | 
			
		||||
int bytedes[]= { 0, 0, 1 };
 | 
			
		||||
long any;
 | 
			
		||||
 | 
			
		||||
void catch(sig, file, line) int sig; char *file; int line;
 | 
			
		||||
/* Catches traps in the occam program */
 | 
			
		||||
{
 | 
			
		||||
	register char *mes;
 | 
			
		||||
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		mes="array bound error";
 | 
			
		||||
		break;
 | 
			
		||||
	case 6:
 | 
			
		||||
		mes="division by zero";
 | 
			
		||||
		break;
 | 
			
		||||
	case 8:
 | 
			
		||||
		mes="undefined variable";
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(stderr, "%s (%d) F: %s\n", file, line, mes);
 | 
			
		||||
	abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
chan file[_NFILE];
 | 
			
		||||
FILE *unix_file[_NFILE];
 | 
			
		||||
 | 
			
		||||
void initfile()
 | 
			
		||||
{
 | 
			
		||||
	register i;
 | 
			
		||||
	register chan *c=file;
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<_NFILE; i++) {
 | 
			
		||||
		c->type=C_T_FILE;
 | 
			
		||||
		c->f.flgs=0;
 | 
			
		||||
		(c++)->f.index=i;
 | 
			
		||||
	}
 | 
			
		||||
	file[0].f.flgs|=C_F_INUSE;
 | 
			
		||||
	unix_file[0]=stdin;
 | 
			
		||||
 | 
			
		||||
	file[1].f.flgs|=C_F_INUSE;
 | 
			
		||||
	unix_file[1]=stdout;
 | 
			
		||||
 | 
			
		||||
	file[2].f.flgs|=C_F_INUSE;
 | 
			
		||||
	unix_file[2]=stderr;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										92
									
								
								lang/occam/lib/par.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								lang/occam/lib/par.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
/*	par.c - Routines to simulate parallelism */
 | 
			
		||||
#include "process.h"
 | 
			
		||||
 | 
			
		||||
static void search_next(), DEADLOCK();
 | 
			
		||||
 | 
			
		||||
void resumenext()
 | 
			
		||||
/* Stops the current process, by saving its stack,  and determines a new one
 | 
			
		||||
 * to restart. In case the root of the process tree is passed more then once,
 | 
			
		||||
 * without a process  having done something useful, we'll have a deadlock.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	if (group!=nil) {
 | 
			
		||||
		register struct process *proc= *group->active;
 | 
			
		||||
		register wordsize size;
 | 
			
		||||
 | 
			
		||||
		size=top_size(group->s_brk);
 | 
			
		||||
		proc->stack=alloc((unsigned) size);
 | 
			
		||||
 | 
			
		||||
		if (top_save(size, proc->stack)) {
 | 
			
		||||
			group->active= &proc->next;
 | 
			
		||||
			search_next();
 | 
			
		||||
		} else {
 | 
			
		||||
			free(proc->stack);
 | 
			
		||||
			load_betweens();
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		if (++deadlock>1) DEADLOCK();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void search_next()
 | 
			
		||||
/* Tries to resume the active process, if this is not possible, the process
 | 
			
		||||
 * tree will be searched for another process. If the process tree is fully
 | 
			
		||||
 * traversed, search will restart at the root of the tree.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	while (*group->active==nil && group->up!=nil) {
 | 
			
		||||
		save_between(group);
 | 
			
		||||
 | 
			
		||||
		group=group->up;
 | 
			
		||||
 | 
			
		||||
		group->active= &(*group->active)->next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (*group->active==nil) {
 | 
			
		||||
		if (++deadlock>1) DEADLOCK();
 | 
			
		||||
		group->active= &group->first;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	highest_group=group;
 | 
			
		||||
 | 
			
		||||
	while ((*group->active)->down!=nil) {
 | 
			
		||||
		group=(*group->active)->down;
 | 
			
		||||
		group->active= &group->first;
 | 
			
		||||
	}
 | 
			
		||||
	top_load((*group->active)->stack);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void parend()
 | 
			
		||||
/* Deletes the current process from its process group and searches for a new
 | 
			
		||||
 * process to run. The entire group is removed if this is the last process in
 | 
			
		||||
 * the group, execution then continues with the process that set up this group
 | 
			
		||||
 * in the first place.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	register struct process *junk;
 | 
			
		||||
 | 
			
		||||
	junk= *group->active;
 | 
			
		||||
	*group->active=junk->next;
 | 
			
		||||
	free((void *) junk);
 | 
			
		||||
 | 
			
		||||
	if (group->first==nil) {
 | 
			
		||||
		register struct procgroup *junk;
 | 
			
		||||
 | 
			
		||||
		delete_between(group);
 | 
			
		||||
 | 
			
		||||
		junk=group;
 | 
			
		||||
		group=group->up;
 | 
			
		||||
		free((void *) junk);
 | 
			
		||||
 | 
			
		||||
		if (group!=nil)
 | 
			
		||||
			(*group->active)->down=nil;
 | 
			
		||||
	} else {
 | 
			
		||||
		deadlock=0;
 | 
			
		||||
		search_next();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void DEADLOCK()
 | 
			
		||||
{
 | 
			
		||||
	write(2, "DEADLOCK\n", 9);
 | 
			
		||||
	abort();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								lang/occam/lib/par_em2.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								lang/occam/lib/par_em2.e
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
 mes 2,2,4
 | 
			
		||||
 exp $top_size
 | 
			
		||||
 pro $top_size, 14
 | 
			
		||||
 ldl 0			; s_brk
 | 
			
		||||
 lor 1			; s_brk  SP
 | 
			
		||||
 sbs 4			; s_brk-SP
 | 
			
		||||
 ret 4			; return size of block to be saved
 | 
			
		||||
 end 14
 | 
			
		||||
 | 
			
		||||
 exp $top_save
 | 
			
		||||
 pro $top_save, 0
 | 
			
		||||
 loe 0
 | 
			
		||||
 lde 4			; load line number and file name
 | 
			
		||||
 lim			; ignore mask
 | 
			
		||||
 lor 0			; LB
 | 
			
		||||
 ldl 0			; size of block
 | 
			
		||||
 loc 4
 | 
			
		||||
 loc 2
 | 
			
		||||
 cuu
 | 
			
		||||
 dup 2
 | 
			
		||||
 stl 0			; push & store size in 2 bytes
 | 
			
		||||
 lor 1			; SP (the SP BEFORE pushing)
 | 
			
		||||
 lor 1			; SP (address of stack top to save)
 | 
			
		||||
 ldl 4			; area
 | 
			
		||||
 lol 0			; size
 | 
			
		||||
 bls 2			; move whole block
 | 
			
		||||
 asp 18			; remove the lot from the stack
 | 
			
		||||
 loc 1
 | 
			
		||||
 ret 2			; return 1
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 exp $top_load
 | 
			
		||||
 pro $top_load, 0
 | 
			
		||||
 ldl 0
 | 
			
		||||
 dup 4
 | 
			
		||||
 sde area		; copy area pointer from argument 0
 | 
			
		||||
 loi 4			; load indirect to
 | 
			
		||||
 str 1			; restore SP
 | 
			
		||||
 lde area		; load area, note that the SP is now correct
 | 
			
		||||
 lor 1			; SP (the SP AFTER, see above)
 | 
			
		||||
 lde area
 | 
			
		||||
 lof 4			; size of block
 | 
			
		||||
 bls 2			; move block back (SP becomes the SP BEFORE again!)
 | 
			
		||||
 asp 2			; drop size
 | 
			
		||||
 str 0			; LB
 | 
			
		||||
 sim			; ignore mask
 | 
			
		||||
 sde 4
 | 
			
		||||
 ste 0			; line and file
 | 
			
		||||
 loc 0
 | 
			
		||||
 ret 2			; return 0
 | 
			
		||||
 end 0
 | 
			
		||||
area
 | 
			
		||||
 bss 4,0,0
 | 
			
		||||
							
								
								
									
										46
									
								
								lang/occam/lib/par_em4.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								lang/occam/lib/par_em4.e
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
 mes 2,4,4
 | 
			
		||||
 exp $top_size
 | 
			
		||||
 pro $top_size, 20
 | 
			
		||||
 lol 0			; s_brk
 | 
			
		||||
 lor 1			; s_brk  SP
 | 
			
		||||
 sbs 4			; s_brk-SP
 | 
			
		||||
 ret 4			; return size of block to be saved
 | 
			
		||||
 end 20
 | 
			
		||||
 | 
			
		||||
 exp $top_save
 | 
			
		||||
 pro $top_save, 0
 | 
			
		||||
 lde 0			; load line number and file name
 | 
			
		||||
 lim			; ignore mask
 | 
			
		||||
 lor 0			; LB
 | 
			
		||||
 lol 0			; size of block
 | 
			
		||||
 lor 1			; SP (the SP BEFORE pushing)
 | 
			
		||||
 lor 1			; SP (address of stack top to save)
 | 
			
		||||
 lol 4			; area
 | 
			
		||||
 lol 0			; size
 | 
			
		||||
 bls 4			; move whole block
 | 
			
		||||
 asp 24			; remove the lot from the stack
 | 
			
		||||
 loc 1
 | 
			
		||||
 ret 4			; return 1
 | 
			
		||||
 end 0
 | 
			
		||||
 | 
			
		||||
 exp $top_load
 | 
			
		||||
 pro $top_load, 0
 | 
			
		||||
 lol 0
 | 
			
		||||
 dup 4
 | 
			
		||||
 ste area		; copy area pointer from argument 0
 | 
			
		||||
 loi 4			; load indirect to
 | 
			
		||||
 str 1			; restore sp
 | 
			
		||||
 loe area		; load area, note that the SP is now correct
 | 
			
		||||
 lor 1			; SP (the SP AFTER, see above)
 | 
			
		||||
 loe area
 | 
			
		||||
 lof 4			; size of block
 | 
			
		||||
 bls 4			; move block back (SP becomes the SP BEFORE again!)
 | 
			
		||||
 asp 4			; drop size
 | 
			
		||||
 str 0			; LB
 | 
			
		||||
 sim			; ignore mask
 | 
			
		||||
 sde 0			; line and file
 | 
			
		||||
 loc 0
 | 
			
		||||
 ret 4			; return 0
 | 
			
		||||
 end 0
 | 
			
		||||
area
 | 
			
		||||
 bss 4,0,0
 | 
			
		||||
							
								
								
									
										51
									
								
								lang/occam/lib/par_vax.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								lang/occam/lib/par_vax.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
 # VAX code for the top_* primitives
 | 
			
		||||
 | 
			
		||||
	.set	BIG, 0x8000	# 32K chunk per movc3
 | 
			
		||||
	.text
 | 
			
		||||
	.align 1
 | 
			
		||||
	.globl _top_size
 | 
			
		||||
	.globl _top_save
 | 
			
		||||
	.globl _top_load
 | 
			
		||||
 | 
			
		||||
_top_size: .word 0x0000
 | 
			
		||||
	subl3	sp, 4(ap), r0	# bytes between stack pointer and break
 | 
			
		||||
	addl2	$(8+6+1)*4, r0	# add 8 regs, 6 pushed longwords (line, file,
 | 
			
		||||
	ret			# ap, fp, size, sp) and 1 extra argument
 | 
			
		||||
 | 
			
		||||
_top_save: .word 0x0ff0		# save regs r4-r11
 | 
			
		||||
	movq	hol0, -(sp)	# push line number and file name
 | 
			
		||||
	movq	ap, -(sp)	# push LB equivalents ap and fp
 | 
			
		||||
	pushl	4(ap)		# push size
 | 
			
		||||
	pushal	-4(sp)		# push sp (the sp AFTER pushing)
 | 
			
		||||
	movl	$BIG, r6	# chunk size in r6
 | 
			
		||||
	movl	4(ap), r7	# size of block to move
 | 
			
		||||
	movl	sp, r1		# source address
 | 
			
		||||
	movl	8(ap), r3	# destination address
 | 
			
		||||
	cmpl	r7, r6
 | 
			
		||||
	jlequ	0f
 | 
			
		||||
1:	movc3	r6, (r1), (r3)	# move chunk of the block, add r6 to r1 and r3
 | 
			
		||||
	subl2	r6, r7
 | 
			
		||||
	cmpl	r7, r6
 | 
			
		||||
	jgtru	1b
 | 
			
		||||
0:	movc3	r7, (r1), (r3)	# move what's left
 | 
			
		||||
	movl	$1, r0		# return 1
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
_top_load: .word 0x0000
 | 
			
		||||
	movl	4(ap), r1	# source
 | 
			
		||||
	movl	(r1), sp	# restore sp
 | 
			
		||||
	movl	$BIG, r6	# chunk size
 | 
			
		||||
	movl	4(r1), r7	# size
 | 
			
		||||
	movl	sp, r3		# destination
 | 
			
		||||
	cmpl	r7, r6
 | 
			
		||||
	jlequ	0f
 | 
			
		||||
1:	movc3	r6, (r1), (r3)	# move chunk of the block back
 | 
			
		||||
	subl2	r6, r7
 | 
			
		||||
	cmpl	r7, r6
 | 
			
		||||
	jgtru	1b
 | 
			
		||||
0:	movc3	r7, (r1), (r3)	# move what's left back
 | 
			
		||||
	addl2	$8, sp		# pop saved sp and size
 | 
			
		||||
	movq	(sp)+, ap	# pop LB's
 | 
			
		||||
	movq	(sp)+, hol0	# pop line and file
 | 
			
		||||
	clrl	r0		# return 0
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										130
									
								
								lang/occam/lib/parco.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								lang/occam/lib/parco.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
/*	parco.c	- Common routines for simulating parallelism or coroutines on
 | 
			
		||||
 *		  machines with downward growing stacks
 | 
			
		||||
 */
 | 
			
		||||
#include "process.h"
 | 
			
		||||
 | 
			
		||||
struct procgroup *group=nil, *highest_group;
 | 
			
		||||
 | 
			
		||||
int deadlock=0;
 | 
			
		||||
 | 
			
		||||
void pc_begin(s_brk, id)
 | 
			
		||||
	register void *s_brk;
 | 
			
		||||
	identification id;
 | 
			
		||||
/* Sets up a group of processes and puts the current process in it */
 | 
			
		||||
{
 | 
			
		||||
	register struct procgroup *pg;
 | 
			
		||||
	register struct process *p;
 | 
			
		||||
 | 
			
		||||
	pg= (struct procgroup *) alloc(sizeof *pg);
 | 
			
		||||
	p= (struct process *) alloc(sizeof *p);
 | 
			
		||||
 | 
			
		||||
	pg->s_brk= s_brk==nil ? (void *) (&id +1) : s_brk;
 | 
			
		||||
	pg->up=group;
 | 
			
		||||
	pg->first=p;
 | 
			
		||||
	pg->active= &pg->first;
 | 
			
		||||
 | 
			
		||||
	p->next=nil;
 | 
			
		||||
	p->down=nil;
 | 
			
		||||
	p->id=id;
 | 
			
		||||
 | 
			
		||||
	if (group!=nil)
 | 
			
		||||
		(*group->active)->down=pg;
 | 
			
		||||
 | 
			
		||||
	group=pg;
 | 
			
		||||
	init_between(group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pc_fork(id) identification id;
 | 
			
		||||
/* Makes a copy of the stack top of the calling function and creates an
 | 
			
		||||
 * entry for it in the current process group.  Pc_fork() returns 1 in the
 | 
			
		||||
 * current process, 0 in the copied process. The current process runs first.
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	register struct process *newp;
 | 
			
		||||
	register wordsize size;
 | 
			
		||||
 | 
			
		||||
	newp= (struct process *) alloc(sizeof *newp);
 | 
			
		||||
 | 
			
		||||
	newp->down=nil;
 | 
			
		||||
	newp->id=id;
 | 
			
		||||
 | 
			
		||||
	newp->next= *group->active;
 | 
			
		||||
	*group->active= newp;
 | 
			
		||||
	group->active= &newp->next;
 | 
			
		||||
 | 
			
		||||
	size=top_size(group->s_brk);
 | 
			
		||||
	newp->stack=alloc((unsigned) size);
 | 
			
		||||
 | 
			
		||||
	if (top_save(size, newp->stack))
 | 
			
		||||
		return 1;
 | 
			
		||||
	else {
 | 
			
		||||
		free(newp->stack);
 | 
			
		||||
		load_betweens();
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_between(group) register struct procgroup *group;
 | 
			
		||||
/* Allocates memory to hold the stack space between s_brk and up->s_brk. */
 | 
			
		||||
{
 | 
			
		||||
	register wordsize size;
 | 
			
		||||
 | 
			
		||||
	if (group->up==nil
 | 
			
		||||
	    || (size= (wordsize) group->up->s_brk - (wordsize) group->s_brk)==0)
 | 
			
		||||
		group->between=nil;
 | 
			
		||||
	else
 | 
			
		||||
		group->between=alloc((unsigned) size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void block_move();
 | 
			
		||||
 | 
			
		||||
void save_between(group) register struct procgroup *group;
 | 
			
		||||
/* Saves the stack space between  s_brk and up->s_brk. */
 | 
			
		||||
{
 | 
			
		||||
	register wordsize size;
 | 
			
		||||
 | 
			
		||||
	if (group->between!=nil) {
 | 
			
		||||
	    	size= (wordsize) group->up->s_brk - (wordsize) group->s_brk;
 | 
			
		||||
		block_move(size, group->s_brk, group->between);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void load_betweens()
 | 
			
		||||
/* All stack pieces between s_brk and up->s_brk from the current group
 | 
			
		||||
 * upto the 'highest_group' are loaded onto the stack at the right
 | 
			
		||||
 * place (i.e. s_brk).
 | 
			
		||||
 */
 | 
			
		||||
{
 | 
			
		||||
	register struct procgroup *gr=group, *up;
 | 
			
		||||
	register wordsize size;
 | 
			
		||||
 | 
			
		||||
	while (gr!=highest_group) {
 | 
			
		||||
		up=gr->up;
 | 
			
		||||
		if (gr->between!=nil) {
 | 
			
		||||
			size= (wordsize) up->s_brk - (wordsize) gr->s_brk;
 | 
			
		||||
 | 
			
		||||
			block_move(size, gr->between, gr->s_brk);
 | 
			
		||||
		}
 | 
			
		||||
		gr=up;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void delete_between(group) register struct procgroup *group;
 | 
			
		||||
/* Deallocates the stack space between s_brk and up->s_brk. */
 | 
			
		||||
{
 | 
			
		||||
	if (group->between!=nil)
 | 
			
		||||
		free(group->between);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *malloc();
 | 
			
		||||
 | 
			
		||||
void *alloc(size) unsigned size;
 | 
			
		||||
{
 | 
			
		||||
	register void *mem;
 | 
			
		||||
 | 
			
		||||
	if ((mem=malloc(size))==nil) {
 | 
			
		||||
		write(2, "Heap error\n", 14);
 | 
			
		||||
		abort();
 | 
			
		||||
	}
 | 
			
		||||
	return mem;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue