note.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. int _threadnopasser;
  6. #define NFN 33
  7. #define ERRLEN 48
  8. typedef struct Note Note;
  9. struct Note
  10. {
  11. Lock inuse;
  12. Proc *proc; /* recipient */
  13. char s[ERRMAX]; /* arg2 */
  14. };
  15. static Note notes[128];
  16. static Note *enotes = notes+nelem(notes);
  17. static int (*onnote[NFN])(void*, char*);
  18. static int onnotepid[NFN];
  19. static Lock onnotelock;
  20. int
  21. threadnotify(int (*f)(void*, char*), int in)
  22. {
  23. int i, topid;
  24. int (*from)(void*, char*), (*to)(void*, char*);
  25. if(in){
  26. from = nil;
  27. to = f;
  28. topid = _threadgetproc()->pid;
  29. }else{
  30. from = f;
  31. to = nil;
  32. topid = 0;
  33. }
  34. lock(&onnotelock);
  35. for(i=0; i<NFN; i++)
  36. if(onnote[i]==from){
  37. onnote[i] = to;
  38. onnotepid[i] = topid;
  39. break;
  40. }
  41. unlock(&onnotelock);
  42. return i<NFN;
  43. }
  44. static void
  45. delayednotes(Proc *p, void *v)
  46. {
  47. int i;
  48. Note *n;
  49. int (*fn)(void*, char*);
  50. if(!p->pending)
  51. return;
  52. p->pending = 0;
  53. for(n=notes; n<enotes; n++){
  54. if(n->proc == p){
  55. for(i=0; i<NFN; i++){
  56. if(onnotepid[i]!=p->pid || (fn = onnote[i])==nil)
  57. continue;
  58. if((*fn)(v, n->s))
  59. break;
  60. }
  61. if(i==NFN){
  62. _threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p);
  63. if(v != nil)
  64. noted(NDFLT);
  65. else if(strncmp(n->s, "sys:", 4)==0)
  66. abort();
  67. threadexitsall(n->s);
  68. }
  69. n->proc = nil;
  70. unlock(&n->inuse);
  71. }
  72. }
  73. }
  74. void
  75. _threadnote(void *v, char *s)
  76. {
  77. Proc *p;
  78. Note *n;
  79. _threaddebug(DBGNOTE, "Got note %s", s);
  80. if(strncmp(s, "sys:", 4) == 0)
  81. noted(NDFLT);
  82. if(_threadexitsallstatus){
  83. _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
  84. _exits(_threadexitsallstatus);
  85. }
  86. if(strcmp(s, "threadint")==0)
  87. noted(NCONT);
  88. p = _threadgetproc();
  89. if(p == nil)
  90. noted(NDFLT);
  91. for(n=notes; n<enotes; n++)
  92. if(canlock(&n->inuse))
  93. break;
  94. if(n==enotes)
  95. sysfatal("libthread: too many delayed notes");
  96. utfecpy(n->s, n->s+ERRMAX, s);
  97. n->proc = p;
  98. p->pending = 1;
  99. if(!p->splhi)
  100. delayednotes(p, v);
  101. noted(NCONT);
  102. }
  103. int
  104. _procsplhi(void)
  105. {
  106. int s;
  107. Proc *p;
  108. p = _threadgetproc();
  109. s = p->splhi;
  110. p->splhi = 1;
  111. return s;
  112. }
  113. void
  114. _procsplx(int s)
  115. {
  116. Proc *p;
  117. p = _threadgetproc();
  118. p->splhi = s;
  119. if(s)
  120. return;
  121. if(p->pending)
  122. delayednotes(p, nil);
  123. }