common.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /* SPDX-License-Identifier: MPL-1.1 OR GPL-2.0-or-later */
  2. /*
  3. * The contents of this file are subject to the Mozilla Public
  4. * License Version 1.1 (the "License"); you may not use this file
  5. * except in compliance with the License. You may obtain a copy of
  6. * the License at http://www.mozilla.org/MPL/
  7. *
  8. * Software distributed under the License is distributed on an "AS
  9. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10. * implied. See the License for the specific language governing
  11. * rights and limitations under the License.
  12. *
  13. * The Original Code is the Netscape Portable Runtime library.
  14. *
  15. * The Initial Developer of the Original Code is Netscape
  16. * Communications Corporation. Portions created by Netscape are
  17. * Copyright (C) 1994-2000 Netscape Communications Corporation. All
  18. * Rights Reserved.
  19. *
  20. * Contributor(s): Silicon Graphics, Inc.
  21. *
  22. * Portions created by SGI are Copyright (C) 2000-2001 Silicon
  23. * Graphics, Inc. All Rights Reserved.
  24. *
  25. * Alternatively, the contents of this file may be used under the
  26. * terms of the GNU General Public License Version 2 or later (the
  27. * "GPL"), in which case the provisions of the GPL are applicable
  28. * instead of those above. If you wish to allow use of your
  29. * version of this file only under the terms of the GPL and not to
  30. * allow others to use your version of this file under the MPL,
  31. * indicate your decision by deleting the provisions above and
  32. * replace them with the notice and other provisions required by
  33. * the GPL. If you do not delete the provisions above, a recipient
  34. * may use your version of this file under either the MPL or the
  35. * GPL.
  36. */
  37. /*
  38. * This file is derived directly from Netscape Communications Corporation,
  39. * and consists of extensive modifications made during the year(s) 1999-2000.
  40. */
  41. #ifndef __ST_COMMON_H__
  42. #define __ST_COMMON_H__
  43. #include <stddef.h>
  44. #include <unistd.h>
  45. #include <sys/types.h>
  46. #include <sys/time.h>
  47. #include <setjmp.h>
  48. /* Enable assertions only if DEBUG is defined */
  49. #ifndef DEBUG
  50. #define NDEBUG
  51. #endif
  52. #include <assert.h>
  53. #define ST_ASSERT(expr) assert(expr)
  54. #define ST_BEGIN_MACRO {
  55. #define ST_END_MACRO }
  56. #ifdef DEBUG
  57. #define ST_HIDDEN /*nothing*/
  58. #else
  59. #define ST_HIDDEN static
  60. #endif
  61. #include "public.h"
  62. #include "md.h"
  63. /* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
  64. #ifndef MD_VALGRIND
  65. #ifndef NVALGRIND
  66. #define NVALGRIND
  67. #endif
  68. #else
  69. #undef NVALGRIND
  70. #endif
  71. /*****************************************
  72. * Circular linked list definitions
  73. */
  74. typedef struct _st_clist {
  75. struct _st_clist *next;
  76. struct _st_clist *prev;
  77. } _st_clist_t;
  78. /* Insert element "_e" into the list, before "_l" */
  79. #define ST_INSERT_BEFORE(_e,_l) \
  80. ST_BEGIN_MACRO \
  81. (_e)->next = (_l); \
  82. (_e)->prev = (_l)->prev; \
  83. (_l)->prev->next = (_e); \
  84. (_l)->prev = (_e); \
  85. ST_END_MACRO
  86. /* Insert element "_e" into the list, after "_l" */
  87. #define ST_INSERT_AFTER(_e,_l) \
  88. ST_BEGIN_MACRO \
  89. (_e)->next = (_l)->next; \
  90. (_e)->prev = (_l); \
  91. (_l)->next->prev = (_e); \
  92. (_l)->next = (_e); \
  93. ST_END_MACRO
  94. /* Return the element following element "_e" */
  95. #define ST_NEXT_LINK(_e) ((_e)->next)
  96. /* Append an element "_e" to the end of the list "_l" */
  97. #define ST_APPEND_LINK(_e,_l) ST_INSERT_BEFORE(_e,_l)
  98. /* Insert an element "_e" at the head of the list "_l" */
  99. #define ST_INSERT_LINK(_e,_l) ST_INSERT_AFTER(_e,_l)
  100. /* Return the head/tail of the list */
  101. #define ST_LIST_HEAD(_l) (_l)->next
  102. #define ST_LIST_TAIL(_l) (_l)->prev
  103. /* Remove the element "_e" from it's circular list */
  104. #define ST_REMOVE_LINK(_e) \
  105. ST_BEGIN_MACRO \
  106. (_e)->prev->next = (_e)->next; \
  107. (_e)->next->prev = (_e)->prev; \
  108. ST_END_MACRO
  109. /* Return non-zero if the given circular list "_l" is empty, */
  110. /* zero if the circular list is not empty */
  111. #define ST_CLIST_IS_EMPTY(_l) \
  112. ((_l)->next == (_l))
  113. /* Initialize a circular list */
  114. #define ST_INIT_CLIST(_l) \
  115. ST_BEGIN_MACRO \
  116. (_l)->next = (_l); \
  117. (_l)->prev = (_l); \
  118. ST_END_MACRO
  119. #define ST_INIT_STATIC_CLIST(_l) \
  120. {(_l), (_l)}
  121. /*****************************************
  122. * Basic types definitions
  123. */
  124. typedef void (*_st_destructor_t)(void *);
  125. typedef struct _st_stack {
  126. _st_clist_t links;
  127. char *vaddr; /* Base of stack's allocated memory */
  128. int vaddr_size; /* Size of stack's allocated memory */
  129. int stk_size; /* Size of usable portion of the stack */
  130. char *stk_bottom; /* Lowest address of stack's usable portion */
  131. char *stk_top; /* Highest address of stack's usable portion */
  132. void *sp; /* Stack pointer from C's point of view */
  133. /* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
  134. #ifndef NVALGRIND
  135. /* id returned by VALGRIND_STACK_REGISTER */
  136. /* http://valgrind.org/docs/manual/manual-core-adv.html */
  137. unsigned long valgrind_stack_id;
  138. #endif
  139. } _st_stack_t;
  140. typedef struct _st_cond {
  141. _st_clist_t wait_q; /* Condition variable wait queue */
  142. } _st_cond_t;
  143. typedef struct _st_thread _st_thread_t;
  144. struct _st_thread {
  145. int state; /* Thread's state */
  146. int flags; /* Thread's flags */
  147. void *(*start)(void *arg); /* The start function of the thread */
  148. void *arg; /* Argument of the start function */
  149. void *retval; /* Return value of the start function */
  150. _st_stack_t *stack; /* Info about thread's stack */
  151. _st_clist_t links; /* For putting on run/sleep/zombie queue */
  152. _st_clist_t wait_links; /* For putting on mutex/condvar wait queue */
  153. #ifdef DEBUG
  154. _st_clist_t tlink; /* For putting on thread queue */
  155. #endif
  156. st_utime_t due; /* Wakeup time when thread is sleeping */
  157. _st_thread_t *left; /* For putting in timeout heap */
  158. _st_thread_t *right; /* -- see docs/timeout_heap.txt for details */
  159. int heap_index;
  160. void **private_data; /* Per thread private data */
  161. _st_cond_t *term; /* Termination condition variable for join */
  162. _st_jmp_buf_t context; /* Thread's context */
  163. };
  164. typedef struct _st_mutex {
  165. _st_thread_t *owner; /* Current mutex owner */
  166. _st_clist_t wait_q; /* Mutex wait queue */
  167. } _st_mutex_t;
  168. typedef struct _st_pollq {
  169. _st_clist_t links; /* For putting on io queue */
  170. _st_thread_t *thread; /* Polling thread */
  171. struct pollfd *pds; /* Array of poll descriptors */
  172. int npds; /* Length of the array */
  173. int on_ioq; /* Is it on ioq? */
  174. } _st_pollq_t;
  175. typedef struct _st_eventsys_ops {
  176. const char *name; /* Name of this event system */
  177. int val; /* Type of this event system */
  178. int (*init)(void); /* Initialization */
  179. void (*dispatch)(void); /* Dispatch function */
  180. int (*pollset_add)(struct pollfd *, int); /* Add descriptor set */
  181. void (*pollset_del)(struct pollfd *, int); /* Delete descriptor set */
  182. int (*fd_new)(int); /* New descriptor allocated */
  183. int (*fd_close)(int); /* Descriptor closed */
  184. int (*fd_getlimit)(void); /* Descriptor hard limit */
  185. void (*destroy)(void); /* Destroy the event object */
  186. } _st_eventsys_t;
  187. typedef struct _st_vp {
  188. _st_thread_t *idle_thread; /* Idle thread for this vp */
  189. st_utime_t last_clock; /* The last time we went into vp_check_clock() */
  190. _st_clist_t run_q; /* run queue for this vp */
  191. _st_clist_t io_q; /* io queue for this vp */
  192. _st_clist_t zombie_q; /* zombie queue for this vp */
  193. #ifdef DEBUG
  194. _st_clist_t thread_q; /* all threads of this vp */
  195. #endif
  196. int pagesize;
  197. _st_thread_t *sleep_q; /* sleep queue for this vp */
  198. int sleepq_size; /* number of threads on sleep queue */
  199. #ifdef ST_SWITCH_CB
  200. st_switch_cb_t switch_out_cb; /* called when a thread is switched out */
  201. st_switch_cb_t switch_in_cb; /* called when a thread is switched in */
  202. #endif
  203. } _st_vp_t;
  204. typedef struct _st_netfd {
  205. int osfd; /* Underlying OS file descriptor */
  206. int inuse; /* In-use flag */
  207. void *private_data; /* Per descriptor private data */
  208. _st_destructor_t destructor; /* Private data destructor function */
  209. void *aux_data; /* Auxiliary data for internal use */
  210. struct _st_netfd *next; /* For putting on the free list */
  211. } _st_netfd_t;
  212. /*****************************************
  213. * Current vp, thread, and event system
  214. */
  215. extern __thread _st_vp_t _st_this_vp;
  216. extern __thread _st_thread_t *_st_this_thread;
  217. extern __thread _st_eventsys_t *_st_eventsys;
  218. #define _ST_CURRENT_THREAD() (_st_this_thread)
  219. #define _ST_SET_CURRENT_THREAD(_thread) (_st_this_thread = (_thread))
  220. #define _ST_LAST_CLOCK (_st_this_vp.last_clock)
  221. #define _ST_RUNQ (_st_this_vp.run_q)
  222. #define _ST_IOQ (_st_this_vp.io_q)
  223. #define _ST_ZOMBIEQ (_st_this_vp.zombie_q)
  224. #ifdef DEBUG
  225. #define _ST_THREADQ (_st_this_vp.thread_q)
  226. #endif
  227. #define _ST_PAGE_SIZE (_st_this_vp.pagesize)
  228. #define _ST_SLEEPQ (_st_this_vp.sleep_q)
  229. #define _ST_SLEEPQ_SIZE (_st_this_vp.sleepq_size)
  230. #define _ST_VP_IDLE() (*_st_eventsys->dispatch)()
  231. /*****************************************
  232. * vp queues operations
  233. */
  234. #define _ST_ADD_IOQ(_pq) ST_APPEND_LINK(&_pq.links, &_ST_IOQ)
  235. #define _ST_DEL_IOQ(_pq) ST_REMOVE_LINK(&_pq.links)
  236. #define _ST_ADD_RUNQ(_thr) ST_APPEND_LINK(&(_thr)->links, &_ST_RUNQ)
  237. #define _ST_INSERT_RUNQ(_thr) ST_INSERT_LINK(&(_thr)->links, &_ST_RUNQ)
  238. #define _ST_DEL_RUNQ(_thr) ST_REMOVE_LINK(&(_thr)->links)
  239. #define _ST_ADD_SLEEPQ(_thr, _timeout) _st_add_sleep_q(_thr, _timeout)
  240. #define _ST_DEL_SLEEPQ(_thr) _st_del_sleep_q(_thr)
  241. #define _ST_ADD_ZOMBIEQ(_thr) ST_APPEND_LINK(&(_thr)->links, &_ST_ZOMBIEQ)
  242. #define _ST_DEL_ZOMBIEQ(_thr) ST_REMOVE_LINK(&(_thr)->links)
  243. #ifdef DEBUG
  244. #define _ST_ADD_THREADQ(_thr) ST_APPEND_LINK(&(_thr)->tlink, &_ST_THREADQ)
  245. #define _ST_DEL_THREADQ(_thr) ST_REMOVE_LINK(&(_thr)->tlink)
  246. #endif
  247. /*****************************************
  248. * Thread states and flags
  249. */
  250. #define _ST_ST_RUNNING 0
  251. #define _ST_ST_RUNNABLE 1
  252. #define _ST_ST_IO_WAIT 2
  253. #define _ST_ST_LOCK_WAIT 3
  254. #define _ST_ST_COND_WAIT 4
  255. #define _ST_ST_SLEEPING 5
  256. #define _ST_ST_ZOMBIE 6
  257. #define _ST_ST_SUSPENDED 7
  258. #define _ST_FL_PRIMORDIAL 0x01
  259. #define _ST_FL_IDLE_THREAD 0x02
  260. #define _ST_FL_ON_SLEEPQ 0x04
  261. #define _ST_FL_INTERRUPT 0x08
  262. #define _ST_FL_TIMEDOUT 0x10
  263. /*****************************************
  264. * Pointer conversion
  265. */
  266. #ifndef offsetof
  267. #define offsetof(type, identifier) ((size_t)&(((type *)0)->identifier))
  268. #endif
  269. #define _ST_THREAD_PTR(_qp) \
  270. ((_st_thread_t *)((char *)(_qp) - offsetof(_st_thread_t, links)))
  271. #define _ST_THREAD_WAITQ_PTR(_qp) \
  272. ((_st_thread_t *)((char *)(_qp) - offsetof(_st_thread_t, wait_links)))
  273. #define _ST_THREAD_STACK_PTR(_qp) \
  274. ((_st_stack_t *)((char*)(_qp) - offsetof(_st_stack_t, links)))
  275. #define _ST_POLLQUEUE_PTR(_qp) \
  276. ((_st_pollq_t *)((char *)(_qp) - offsetof(_st_pollq_t, links)))
  277. #ifdef DEBUG
  278. #define _ST_THREAD_THREADQ_PTR(_qp) \
  279. ((_st_thread_t *)((char *)(_qp) - offsetof(_st_thread_t, tlink)))
  280. #endif
  281. /*****************************************
  282. * Constants
  283. */
  284. #ifndef ST_UTIME_NO_TIMEOUT
  285. #define ST_UTIME_NO_TIMEOUT ((st_utime_t) -1LL)
  286. #endif
  287. #define ST_DEFAULT_STACK_SIZE (128*1024) /* Includes register stack size */
  288. #ifndef ST_KEYS_MAX
  289. #define ST_KEYS_MAX 16
  290. #endif
  291. #ifndef ST_MIN_POLLFDS_SIZE
  292. #define ST_MIN_POLLFDS_SIZE 64
  293. #endif
  294. /*****************************************
  295. * Threads context switching
  296. */
  297. #ifdef DEBUG
  298. void _st_iterate_threads(void);
  299. #define ST_DEBUG_ITERATE_THREADS() _st_iterate_threads()
  300. #else
  301. #define ST_DEBUG_ITERATE_THREADS()
  302. #endif
  303. #ifdef ST_SWITCH_CB
  304. #define ST_SWITCH_OUT_CB(_thread) \
  305. if (_st_this_vp.switch_out_cb != NULL && \
  306. _thread != _st_this_vp.idle_thread && \
  307. _thread->state != _ST_ST_ZOMBIE) { \
  308. _st_this_vp.switch_out_cb(); \
  309. }
  310. #define ST_SWITCH_IN_CB(_thread) \
  311. if (_st_this_vp.switch_in_cb != NULL && \
  312. _thread != _st_this_vp.idle_thread && \
  313. _thread->state != _ST_ST_ZOMBIE) { \
  314. _st_this_vp.switch_in_cb(); \
  315. }
  316. #else
  317. #define ST_SWITCH_OUT_CB(_thread)
  318. #define ST_SWITCH_IN_CB(_thread)
  319. #endif
  320. /*
  321. * Switch away from the current thread context by saving its state and
  322. * calling the thread scheduler
  323. */
  324. #define _ST_SWITCH_CONTEXT(_thread) \
  325. ST_BEGIN_MACRO \
  326. ST_SWITCH_OUT_CB(_thread); \
  327. if (!MD_SETJMP((_thread)->context)) { \
  328. _st_vp_schedule(); \
  329. } \
  330. ST_DEBUG_ITERATE_THREADS(); \
  331. ST_SWITCH_IN_CB(_thread); \
  332. ST_END_MACRO
  333. /*
  334. * Restore a thread context that was saved by _ST_SWITCH_CONTEXT or
  335. * initialized by _ST_INIT_CONTEXT
  336. */
  337. #define _ST_RESTORE_CONTEXT(_thread) \
  338. ST_BEGIN_MACRO \
  339. _ST_SET_CURRENT_THREAD(_thread); \
  340. MD_LONGJMP((_thread)->context, 1); \
  341. ST_END_MACRO
  342. /*
  343. * Initialize the thread context preparing it to execute _main
  344. */
  345. #ifdef MD_INIT_CONTEXT
  346. #define _ST_INIT_CONTEXT MD_INIT_CONTEXT
  347. #else
  348. #error Unknown OS
  349. #endif
  350. /*
  351. * Number of bytes reserved under the stack "bottom"
  352. */
  353. #define _ST_STACK_PAD_SIZE MD_STACK_PAD_SIZE
  354. /*****************************************
  355. * Forward declarations
  356. */
  357. void _st_vp_schedule(void);
  358. void _st_vp_check_clock(void);
  359. void *_st_idle_thread_start(void *arg);
  360. void _st_thread_main(void);
  361. void _st_thread_cleanup(_st_thread_t *thread);
  362. void _st_add_sleep_q(_st_thread_t *thread, st_utime_t timeout);
  363. void _st_del_sleep_q(_st_thread_t *thread);
  364. _st_stack_t *_st_stack_new(int stack_size);
  365. void _st_stack_free(_st_stack_t *ts);
  366. int _st_io_init(void);
  367. st_utime_t st_utime(void);
  368. _st_cond_t *st_cond_new(void);
  369. int st_cond_destroy(_st_cond_t *cvar);
  370. int st_cond_timedwait(_st_cond_t *cvar, st_utime_t timeout);
  371. int st_cond_signal(_st_cond_t *cvar);
  372. ssize_t st_read(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout);
  373. ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte, st_utime_t timeout);
  374. int st_poll(struct pollfd *pds, int npds, st_utime_t timeout);
  375. _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size);
  376. #endif /* !__ST_COMMON_H__ */