posix.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Posix generic OS implementation for drawterm.
  3. */
  4. #define _XOPEN_SOURCE 500
  5. #include <pthread.h>
  6. #include <time.h>
  7. #include <sys/time.h>
  8. #include <sys/select.h>
  9. #include <signal.h>
  10. #include <pwd.h>
  11. #include <errno.h>
  12. #include "u.h"
  13. #include "lib.h"
  14. #include "dat.h"
  15. #include "fns.h"
  16. typedef struct Oproc Oproc;
  17. struct Oproc
  18. {
  19. int nsleep;
  20. int nwakeup;
  21. pthread_mutex_t mutex;
  22. pthread_cond_t cond;
  23. };
  24. static pthread_key_t prdakey;
  25. Proc*
  26. _getproc(void)
  27. {
  28. void *v;
  29. if((v = pthread_getspecific(prdakey)) == nil)
  30. panic("cannot getspecific");
  31. return v;
  32. }
  33. void
  34. _setproc(Proc *p)
  35. {
  36. if(pthread_setspecific(prdakey, p) != 0)
  37. panic("cannot setspecific");
  38. }
  39. void
  40. osinit(void)
  41. {
  42. if(pthread_key_create(&prdakey, 0))
  43. panic("cannot pthread_key_create");
  44. }
  45. #undef pipe
  46. void
  47. osnewproc(Proc *p)
  48. {
  49. Oproc *op;
  50. pthread_mutexattr_t attr;
  51. op = (Oproc*)p->oproc;
  52. pthread_mutexattr_init(&attr);
  53. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  54. pthread_mutex_init(&op->mutex, &attr);
  55. pthread_mutexattr_destroy(&attr);
  56. pthread_cond_init(&op->cond, 0);
  57. }
  58. void
  59. osmsleep(int ms)
  60. {
  61. struct timeval tv;
  62. tv.tv_sec = ms / 1000;
  63. tv.tv_usec = (ms % 1000) * 1000; /* micro */
  64. if(select(0, NULL, NULL, NULL, &tv) < 0)
  65. panic("select");
  66. }
  67. void
  68. osyield(void)
  69. {
  70. sched_yield();
  71. }
  72. void
  73. oserrstr(void)
  74. {
  75. char *p;
  76. if((p = strerror(errno)) != nil)
  77. strecpy(up->errstr, up->errstr+ERRMAX, p);
  78. else
  79. snprint(up->errstr, ERRMAX, "unix error %d", errno);
  80. }
  81. void
  82. oserror(void)
  83. {
  84. oserrstr();
  85. nexterror();
  86. }
  87. static void* tramp(void*);
  88. void
  89. osproc(Proc *p)
  90. {
  91. pthread_t pid;
  92. if(pthread_create(&pid, nil, tramp, p)){
  93. oserrstr();
  94. panic("osproc: %r");
  95. }
  96. sched_yield();
  97. }
  98. static void*
  99. tramp(void *vp)
  100. {
  101. Proc *p;
  102. p = vp;
  103. if(pthread_setspecific(prdakey, p))
  104. panic("cannot setspecific");
  105. (*p->fn)(p->arg);
  106. /* BUG: leaks Proc */
  107. pthread_setspecific(prdakey, 0);
  108. pthread_exit(0);
  109. return 0;
  110. }
  111. void
  112. procsleep(void)
  113. {
  114. Proc *p;
  115. Oproc *op;
  116. p = up;
  117. op = (Oproc*)p->oproc;
  118. pthread_mutex_lock(&op->mutex);
  119. op->nsleep++;
  120. while(op->nsleep > op->nwakeup)
  121. pthread_cond_wait(&op->cond, &op->mutex);
  122. pthread_mutex_unlock(&op->mutex);
  123. }
  124. void
  125. procwakeup(Proc *p)
  126. {
  127. Oproc *op;
  128. op = (Oproc*)p->oproc;
  129. pthread_mutex_lock(&op->mutex);
  130. op->nwakeup++;
  131. if(op->nwakeup == op->nsleep)
  132. pthread_cond_signal(&op->cond);
  133. pthread_mutex_unlock(&op->mutex);
  134. }
  135. int randfd;
  136. #undef open
  137. void
  138. randominit(void)
  139. {
  140. #ifdef USE_RANDOM
  141. srandom(getpid()+fastticks(nil)+ticks());
  142. #else
  143. if((randfd = open("/dev/urandom", OREAD)) < 0)
  144. if((randfd = open("/dev/random", OREAD)) < 0)
  145. panic("open /dev/random: %r");
  146. #endif
  147. }
  148. #undef read
  149. ulong
  150. randomread(void *v, ulong n)
  151. {
  152. #ifdef USE_RANDOM
  153. int i;
  154. for(i=0; i<n; i++)
  155. ((uchar*)v)[i] = random();
  156. return n;
  157. #else
  158. int m;
  159. if((m = read(randfd, v, n)) != n)
  160. panic("short read from /dev/random: %d but %d", n, m);
  161. return m;
  162. #endif
  163. }
  164. #undef time
  165. long
  166. seconds(void)
  167. {
  168. return time(0);
  169. }
  170. ulong
  171. ticks(void)
  172. {
  173. static long sec0 = 0, usec0;
  174. struct timeval t;
  175. if(gettimeofday(&t, nil) < 0)
  176. return 0;
  177. if(sec0 == 0){
  178. sec0 = t.tv_sec;
  179. usec0 = t.tv_usec;
  180. }
  181. return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
  182. }
  183. long
  184. showfilewrite(char *a, int n)
  185. {
  186. error("not implemented");
  187. return -1;
  188. }