rendez.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. Rgrp _threadrgrp;
  6. static int isdirty;
  7. static void*
  8. finish(Thread *t, void *val)
  9. {
  10. void *ret;
  11. ret = t->rendval;
  12. t->rendval = val;
  13. while(t->state == Running)
  14. sleep(0);
  15. lock(&t->proc->lock);
  16. if(t->state == Rendezvous){ /* not always true: might be Dead */
  17. t->state = Ready;
  18. _threadready(t);
  19. }
  20. unlock(&t->proc->lock);
  21. return ret;
  22. }
  23. void*
  24. _threadrendezvous(void *tag, void *val)
  25. {
  26. void *ret;
  27. Thread *t, **l;
  28. lock(&_threadrgrp.lock);
  29. l = &_threadrgrp.hash[((uintptr)tag)%nelem(_threadrgrp.hash)];
  30. for(t=*l; t; l=&t->rendhash, t=*l){
  31. if(t->rendtag==tag){
  32. _threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id);
  33. *l = t->rendhash;
  34. ret = finish(t, val);
  35. unlock(&_threadrgrp.lock);
  36. return ret;
  37. }
  38. }
  39. /* Going to sleep here. */
  40. t = _threadgetproc()->thread;
  41. t->rendbreak = 0;
  42. t->inrendez = 1;
  43. t->rendtag = tag;
  44. t->rendval = val;
  45. t->rendhash = *l;
  46. *l = t;
  47. t->nextstate = Rendezvous;
  48. _threaddebug(DBGREND, "Rendezvous for tag %p", t->rendtag);
  49. unlock(&_threadrgrp.lock);
  50. _sched();
  51. t->inrendez = 0;
  52. _threaddebug(DBGREND, "Woke after rendezvous; val is %p", t->rendval);
  53. return t->rendval;
  54. }
  55. /*
  56. * This is called while holding _threadpq.lock and p->lock,
  57. * so we can't lock _threadrgrp.lock. Instead our caller has
  58. * to call _threadbreakrendez after dropping those locks.
  59. */
  60. void
  61. _threadflagrendez(Thread *t)
  62. {
  63. t->rendbreak = 1;
  64. isdirty = 1;
  65. }
  66. void
  67. _threadbreakrendez(void)
  68. {
  69. int i;
  70. Thread *t, **l;
  71. if(isdirty == 0)
  72. return;
  73. lock(&_threadrgrp.lock);
  74. if(isdirty == 0){
  75. unlock(&_threadrgrp.lock);
  76. return;
  77. }
  78. isdirty = 0;
  79. for(i=0; i<nelem(_threadrgrp.hash); i++){
  80. l = &_threadrgrp.hash[i];
  81. for(t=*l; t; t=*l){
  82. if(t->rendbreak){
  83. *l = t->rendhash;
  84. finish(t, (void*)~0);
  85. }else
  86. l=&t->rendhash;
  87. }
  88. }
  89. unlock(&_threadrgrp.lock);
  90. }