131 lines
2.8 KiB
C
131 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;
|
|||
|
}
|