130 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*	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;
 | 
						||
}
 |