create.c 2.8 KB

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