Initial revision
This commit is contained in:
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;
|
||||
}
|
||||
Reference in New Issue
Block a user