create.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <thread.h>
  12. #include "threadimpl.h"
  13. Pqueue _threadpq;
  14. static int
  15. nextID(void)
  16. {
  17. static Lock l;
  18. static int id;
  19. int i;
  20. lock(&l);
  21. i = ++id;
  22. unlock(&l);
  23. return i;
  24. }
  25. /*
  26. * Create and initialize a new Thread structure attached to a given proc.
  27. */
  28. static int
  29. newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
  30. char *name, int grp)
  31. {
  32. int id;
  33. Thread *t;
  34. if(stacksize < 32)
  35. sysfatal("bad stacksize %d", stacksize);
  36. t = _threadmalloc(sizeof(Thread), 1);
  37. t->stksize = stacksize;
  38. t->stk = _threadmalloc(stacksize, 0);
  39. memset(t->stk, 0xFE, stacksize);
  40. _threadinitstack(t, f, arg);
  41. t->grp = grp;
  42. if(name)
  43. t->cmdname = strdup(name);
  44. t->id = nextID();
  45. id = t->id;
  46. t->next = (Thread*)~0;
  47. t->proc = p;
  48. _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->pid, t->id, name);
  49. lock(&p->lock);
  50. p->nthreads++;
  51. if(p->threads.head == nil)
  52. p->threads.head = t;
  53. else
  54. *p->threads.tail = t;
  55. p->threads.tail = &t->nextt;
  56. t->nextt = nil;
  57. t->state = Ready;
  58. _threadready(t);
  59. unlock(&p->lock);
  60. return id;
  61. }
  62. /*
  63. * Create a new thread and schedule it to run.
  64. * The thread grp is inherited from the currently running thread.
  65. */
  66. int
  67. threadcreate(void (*f)(void *arg), void *arg, uint stacksize)
  68. {
  69. return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());
  70. }
  71. /*
  72. * Create and initialize a new Proc structure with a single Thread
  73. * running inside it. Add the Proc to the global process list.
  74. */
  75. Proc*
  76. _newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name,
  77. int grp, int rforkflag)
  78. {
  79. Proc *p;
  80. p = _threadmalloc(sizeof *p, 1);
  81. p->pid = -1;
  82. p->rforkflag = rforkflag;
  83. newthread(p, f, arg, stacksize, name, grp);
  84. lock(&_threadpq.lock);
  85. if(_threadpq.head == nil)
  86. _threadpq.head = p;
  87. else
  88. *_threadpq.tail = p;
  89. _threadpq.tail = &p->next;
  90. unlock(&_threadpq.lock);
  91. return p;
  92. }
  93. int
  94. procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag)
  95. {
  96. Proc *p;
  97. int id;
  98. p = _threadgetproc();
  99. assert(p->newproc == nil);
  100. p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag);
  101. id = p->newproc->threads.head->id;
  102. _sched();
  103. return id;
  104. }
  105. int
  106. proccreate(void (*f)(void*), void *arg, uint stacksize)
  107. {
  108. return procrfork(f, arg, stacksize, 0);
  109. }
  110. void
  111. _freeproc(Proc *p)
  112. {
  113. Thread *t, *nextt;
  114. for(t = p->threads.head; t; t = nextt){
  115. if(t->cmdname)
  116. free(t->cmdname);
  117. assert(t->stk != nil);
  118. free(t->stk);
  119. nextt = t->nextt;
  120. free(t);
  121. }
  122. free(p);
  123. }
  124. void
  125. _freethread(Thread *t)
  126. {
  127. Proc *p;
  128. Thread **l;
  129. p = t->proc;
  130. lock(&p->lock);
  131. for(l=&p->threads.head; *l; l=&(*l)->nextt){
  132. if(*l == t){
  133. *l = t->nextt;
  134. if(*l == nil)
  135. p->threads.tail = l;
  136. break;
  137. }
  138. }
  139. unlock(&p->lock);
  140. if (t->cmdname)
  141. free(t->cmdname);
  142. assert(t->stk != nil);
  143. free(t->stk);
  144. free(t);
  145. }