parco.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* $Header$ */
  2. /* parco.c - Common routines for simulating parallelism or coroutines on
  3. * machines with downward growing stacks
  4. */
  5. #include "ocm_proc.h"
  6. struct procgroup *group=nil, *highest_group;
  7. int deadlock=0;
  8. void pc_begin(s_brk, id)
  9. register void *s_brk;
  10. identification id;
  11. /* Sets up a group of processes and puts the current process in it */
  12. {
  13. register struct procgroup *pg;
  14. register struct process *p;
  15. pg= (struct procgroup *) alloc(sizeof *pg);
  16. p= (struct process *) alloc(sizeof *p);
  17. pg->s_brk= s_brk==nil ? (void *) (&id +1) : s_brk;
  18. pg->up=group;
  19. pg->first=p;
  20. pg->active= &pg->first;
  21. p->next=nil;
  22. p->down=nil;
  23. p->id=id;
  24. if (group!=nil)
  25. (*group->active)->down=pg;
  26. group=pg;
  27. init_between(group);
  28. }
  29. int pc_fork(id) identification id;
  30. /* Makes a copy of the stack top of the calling function and creates an
  31. * entry for it in the current process group. Pc_fork() returns 1 in the
  32. * current process, 0 in the copied process. The current process runs first.
  33. */
  34. {
  35. register struct process *newp;
  36. register wordsize size;
  37. newp= (struct process *) alloc(sizeof *newp);
  38. newp->down=nil;
  39. newp->id=id;
  40. newp->next= *group->active;
  41. *group->active= newp;
  42. group->active= &newp->next;
  43. size=top_size(group->s_brk);
  44. newp->stack=alloc((unsigned) size);
  45. if (top_save(size, newp->stack))
  46. return 1;
  47. else {
  48. free(newp->stack);
  49. load_betweens();
  50. return 0;
  51. }
  52. }
  53. void init_between(group) register struct procgroup *group;
  54. /* Allocates memory to hold the stack space between s_brk and up->s_brk. */
  55. {
  56. register wordsize size;
  57. if (group->up==nil
  58. || (size= (wordsize) group->up->s_brk - (wordsize) group->s_brk)==0)
  59. group->between=nil;
  60. else
  61. group->between=alloc((unsigned) size);
  62. }
  63. void block_move();
  64. void save_between(group) register struct procgroup *group;
  65. /* Saves the stack space between s_brk and up->s_brk. */
  66. {
  67. register wordsize size;
  68. if (group->between!=nil) {
  69. size= (wordsize) group->up->s_brk - (wordsize) group->s_brk;
  70. block_move(size, group->s_brk, group->between);
  71. }
  72. }
  73. void load_betweens()
  74. /* All stack pieces between s_brk and up->s_brk from the current group
  75. * upto the 'highest_group' are loaded onto the stack at the right
  76. * place (i.e. s_brk).
  77. */
  78. {
  79. register struct procgroup *gr=group, *up;
  80. register wordsize size;
  81. while (gr!=highest_group) {
  82. up=gr->up;
  83. if (gr->between!=nil) {
  84. size= (wordsize) up->s_brk - (wordsize) gr->s_brk;
  85. block_move(size, gr->between, gr->s_brk);
  86. }
  87. gr=up;
  88. }
  89. }
  90. void delete_between(group) register struct procgroup *group;
  91. /* Deallocates the stack space between s_brk and up->s_brk. */
  92. {
  93. if (group->between!=nil)
  94. free(group->between);
  95. }
  96. void *malloc();
  97. void *alloc(size) unsigned size;
  98. {
  99. register void *mem;
  100. if ((mem=malloc(size))==nil) {
  101. write(2, "Heap error\n", 14);
  102. abort();
  103. }
  104. return mem;
  105. }