ack/lang/occam/lib/parco.c

131 lines
2.8 KiB
C
Raw Normal View History

1987-02-24 18:36:02 +00:00
/* 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;
}