TWCOS Kernel

Hex Artifact Content
Login

Artifact 2035d6eb1ef8c0e839d91bc9ce0e19922d64d364:


0000: 23 69 6e 63 6c 75 64 65 20 22 74 68 72 65 61 64  #include "thread
0010: 2e 68 22 0a 0a 0a 23 69 66 20 49 4e 54 45 52 46  .h"...#if INTERF
0020: 41 43 45 0a 23 69 6e 63 6c 75 64 65 20 3c 73 74  ACE.#include <st
0030: 64 69 6e 74 2e 68 3e 0a 23 69 6e 63 6c 75 64 65  dint.h>.#include
0040: 20 3c 73 74 64 64 65 66 2e 68 3e 0a 23 69 6e 63   <stddef.h>.#inc
0050: 6c 75 64 65 20 3c 73 74 64 6e 6f 72 65 74 75 72  lude <stdnoretur
0060: 6e 2e 68 3e 0a 0a 74 79 70 65 64 65 66 20 69 6e  n.h>..typedef in
0070: 74 20 74 6c 73 5f 6b 65 79 3b 0a 0a 23 64 65 66  t tls_key;..#def
0080: 69 6e 65 20 54 4c 53 5f 4d 41 58 20 33 32 0a 0a  ine TLS_MAX 32..
0090: 2f 2a 2a 0a 20 2a 20 5c 62 72 69 65 66 20 52 65  /**. * \brief Re
00a0: 70 72 65 73 65 6e 74 61 74 69 6f 6e 20 6f 66 20  presentation of 
00b0: 61 20 6b 65 72 6e 65 6c 20 74 68 72 65 61 64 2e  a kernel thread.
00c0: 0a 20 2a 2f 0a 73 74 72 75 63 74 20 74 68 72 65  . */.struct thre
00d0: 61 64 5f 74 20 7b 0a 09 2f 2a 20 52 75 6e 74 69  ad_t {../* Runti
00e0: 6d 65 20 64 61 74 61 20 2a 2f 0a 0a 09 2f 2a 2a  me data */.../**
00f0: 20 54 68 72 65 61 64 20 6c 6f 63 61 6c 20 73 74   Thread local st
0100: 6f 72 61 67 65 20 70 6f 69 6e 74 65 72 73 20 2a  orage pointers *
0110: 2f 0a 09 76 6f 69 64 20 2a 20 74 6c 73 5b 54 4c  /..void * tls[TL
0120: 53 5f 4d 41 58 5d 3b 0a 09 2f 2a 2a 20 41 72 63  S_MAX];../** Arc
0130: 68 69 74 65 63 74 75 72 65 20 64 65 70 65 6e 64  hitecture depend
0140: 65 6e 74 20 63 6f 6e 74 65 78 74 20 2a 2f 0a 09  ent context */..
0150: 61 72 63 68 5f 63 6f 6e 74 65 78 74 5f 74 20 63  arch_context_t c
0160: 6f 6e 74 65 78 74 3b 0a 09 2f 2a 2a 20 50 72 6f  ontext;../** Pro
0170: 63 65 73 73 20 61 73 73 6f 63 69 61 74 65 64 20  cess associated 
0180: 77 69 74 68 20 74 68 69 73 20 74 68 72 65 61 64  with this thread
0190: 20 2a 2f 0a 09 70 72 6f 63 65 73 73 5f 74 20 2a   */..process_t *
01a0: 20 70 72 6f 63 65 73 73 3b 0a 0a 09 2f 2a 20 54   process;.../* T
01b0: 68 72 65 61 64 20 43 50 55 20 75 73 61 67 65 20  hread CPU usage 
01c0: 2a 2f 0a 09 69 6e 74 20 61 63 63 74 3b 0a 09 73  */..int acct;..s
01d0: 74 72 75 63 74 20 7b 0a 09 09 74 69 6d 65 72 73  truct {...timers
01e0: 70 65 63 5f 74 20 74 73 74 61 72 74 3b 0a 09 09  pec_t tstart;...
01f0: 74 69 6d 65 72 73 70 65 63 5f 74 20 74 6c 65 6e  timerspec_t tlen
0200: 3b 0a 09 7d 20 61 63 63 74 73 5b 36 34 5d 3b 0a  ;..} accts[64];.
0210: 09 74 69 6d 65 72 73 70 65 63 5f 74 20 70 65 72  .timerspec_t per
0220: 69 6f 64 3b 0a 09 74 69 6d 65 72 73 70 65 63 5f  iod;..timerspec_
0230: 74 20 75 73 61 67 65 3b 0a 09 74 69 6d 65 72 73  t usage;..timers
0240: 70 65 63 5f 74 20 70 72 65 65 6d 70 74 3b 0a 0a  pec_t preempt;..
0250: 09 2f 2a 2a 20 43 75 72 72 65 6e 74 20 74 68 72  ./** Current thr
0260: 65 61 64 20 73 74 61 74 65 20 2a 2f 0a 09 74 73  ead state */..ts
0270: 74 61 74 65 20 73 74 61 74 65 3b 0a 09 2f 2a 2a  tate state;../**
0280: 20 54 68 72 65 61 64 20 70 72 69 6f 72 69 74 79   Thread priority
0290: 20 2a 2f 0a 09 74 70 72 69 6f 72 69 74 79 20 70   */..tpriority p
02a0: 72 69 6f 72 69 74 79 3b 0a 09 2f 2a 2a 20 53 65  riority;../** Se
02b0: 74 20 69 66 20 74 68 65 20 74 68 72 65 61 64 20  t if the thread 
02c0: 68 61 73 20 62 65 65 6e 20 69 6e 74 65 72 72 75  has been interru
02d0: 70 74 65 64 20 2a 2f 0a 09 69 6e 74 20 69 6e 74  pted */..int int
02e0: 65 72 72 75 70 74 65 64 3b 0a 09 2f 2a 2a 20 49  errupted;../** I
02f0: 66 20 73 65 74 2c 20 69 6e 64 69 63 61 74 65 73  f set, indicates
0300: 20 77 68 69 63 68 20 69 6e 74 65 72 72 75 70 74   which interrupt
0310: 5f 6d 6f 6e 69 74 6f 72 5f 74 20 77 65 27 72 65  _monitor_t we're
0320: 20 77 61 69 74 69 6e 67 20 66 6f 72 20 2a 2f 0a   waiting for */.
0330: 09 69 6e 74 65 72 72 75 70 74 5f 6d 6f 6e 69 74  .interrupt_monit
0340: 6f 72 5f 74 20 2a 20 77 61 69 74 69 6e 67 66 6f  or_t * waitingfo
0350: 72 3b 0a 09 2f 2a 2a 20 49 66 20 73 65 74 2c 20  r;../** If set, 
0360: 69 6e 64 69 63 61 74 65 73 20 77 68 69 63 68 20  indicates which 
0370: 69 6e 74 65 72 72 75 70 74 5f 6d 6f 6e 69 74 6f  interrupt_monito
0380: 72 5f 74 20 77 65 27 72 65 20 73 6c 65 65 70 69  r_t we're sleepi
0390: 6e 67 20 6f 6e 20 2a 2f 0a 09 69 6e 74 65 72 72  ng on */..interr
03a0: 75 70 74 5f 6d 6f 6e 69 74 6f 72 5f 74 20 2a 20  upt_monitor_t * 
03b0: 73 6c 65 65 70 69 6e 67 6f 6e 3b 0a 0a 09 2f 2a  sleepingon;.../*
03c0: 2a 20 54 68 72 65 61 64 20 6e 61 6d 65 20 2a 2f  * Thread name */
03d0: 0a 09 63 68 61 72 20 2a 20 6e 61 6d 65 3b 0a 0a  ..char * name;..
03e0: 09 2f 2a 2a 20 54 68 72 65 61 64 20 6c 6f 63 6b  ./** Thread lock
03f0: 20 2a 2f 0a 09 6d 6f 6e 69 74 6f 72 5f 74 20 6c   */..monitor_t l
0400: 6f 63 6b 5b 31 5d 3b 0a 0a 09 2f 2a 2a 20 52 65  ock[1];.../** Re
0410: 74 75 72 6e 20 76 61 6c 75 65 20 66 6f 72 20 74  turn value for t
0420: 68 72 65 61 64 5f 6a 6f 69 6e 20 2a 2f 0a 09 76  hread_join */..v
0430: 6f 69 64 20 2a 20 72 65 74 76 61 6c 3b 0a 0a 09  oid * retval;...
0440: 2f 2a 2a 20 54 68 72 65 61 64 20 71 75 65 75 65  /** Thread queue
0450: 20 6e 65 78 74 20 74 68 72 65 61 64 20 2a 2f 0a   next thread */.
0460: 09 74 68 72 65 61 64 5f 74 20 2a 6e 65 78 74 3b  .thread_t *next;
0470: 0a 09 2f 2a 2a 20 54 68 72 65 61 64 20 71 75 65  ../** Thread que
0480: 75 65 20 70 72 65 76 20 74 68 72 65 61 64 20 2a  ue prev thread *
0490: 2f 0a 09 74 68 72 65 61 64 5f 74 20 2a 70 72 65  /..thread_t *pre
04a0: 76 3b 0a 7d 3b 0a 0a 2f 2a 2a 20 54 68 72 65 61  v;.};../** Threa
04b0: 64 20 73 74 61 74 65 20 2a 2f 0a 65 6e 75 6d 20  d state */.enum 
04c0: 74 73 74 61 74 65 20 7b 0a 09 2f 2a 2a 20 54 68  tstate {../** Th
04d0: 72 65 61 64 20 69 73 20 6e 65 77 20 2a 2f 0a 09  read is new */..
04e0: 54 48 52 45 41 44 5f 4e 45 57 2c 0a 09 2f 2a 2a  THREAD_NEW,../**
04f0: 20 54 68 72 65 61 64 20 69 73 20 72 75 6e 6e 61   Thread is runna
0500: 62 6c 65 20 2a 2f 0a 09 54 48 52 45 41 44 5f 52  ble */..THREAD_R
0510: 55 4e 4e 41 42 4c 45 2c 0a 09 2f 2a 2a 20 54 68  UNNABLE,../** Th
0520: 72 65 61 64 20 69 73 20 72 75 6e 6e 69 6e 67 20  read is running 
0530: 2a 2f 0a 09 54 48 52 45 41 44 5f 52 55 4e 4e 49  */..THREAD_RUNNI
0540: 4e 47 2c 0a 09 2f 2a 2a 20 54 68 72 65 61 64 20  NG,../** Thread 
0550: 69 73 20 73 6c 65 65 70 69 6e 67 20 2a 2f 0a 09  is sleeping */..
0560: 54 48 52 45 41 44 5f 53 4c 45 45 50 49 4e 47 2c  THREAD_SLEEPING,
0570: 0a 09 2f 2a 2a 20 54 68 72 65 61 64 20 69 73 20  ../** Thread is 
0580: 74 65 72 6d 69 6e 61 74 65 64 20 2a 2f 0a 09 54  terminated */..T
0590: 48 52 45 41 44 5f 54 45 52 4d 49 4e 41 54 45 44  HREAD_TERMINATED
05a0: 0a 7d 3b 0a 0a 2f 2a 2a 20 54 68 72 65 61 64 20  .};../** Thread 
05b0: 70 72 69 6f 72 69 74 79 20 2a 2f 0a 65 6e 75 6d  priority */.enum
05c0: 20 74 70 72 69 6f 72 69 74 79 20 7b 0a 09 2f 2a   tpriority {../*
05d0: 2a 20 54 68 72 65 61 64 20 69 6e 74 65 72 72 75  * Thread interru
05e0: 70 74 20 70 72 69 6f 72 69 74 79 20 2a 2f 0a 09  pt priority */..
05f0: 54 48 52 45 41 44 5f 49 4e 54 45 52 52 55 50 54  THREAD_INTERRUPT
0600: 20 3d 20 30 2c 0a 09 2f 2a 2a 20 54 68 72 65 61   = 0,../** Threa
0610: 64 20 6e 6f 72 6d 61 6c 20 70 72 69 6f 72 69 74  d normal priorit
0620: 79 20 2a 2f 0a 09 54 48 52 45 41 44 5f 4e 4f 52  y */..THREAD_NOR
0630: 4d 41 4c 2c 0a 09 2f 2a 2a 20 54 68 72 65 61 64  MAL,../** Thread
0640: 20 69 64 6c 65 20 70 72 69 6f 72 69 74 79 20 2a   idle priority *
0650: 2f 0a 09 54 48 52 45 41 44 5f 49 44 4c 45 2c 0a  /..THREAD_IDLE,.
0660: 09 2f 2a 2a 20 54 68 72 65 61 64 20 69 6e 74 65  ./** Thread inte
0670: 72 72 75 70 74 20 70 72 69 6f 72 69 74 79 20 63  rrupt priority c
0680: 6f 75 6e 74 20 2a 2f 0a 09 54 48 52 45 41 44 5f  ount */..THREAD_
0690: 50 52 49 4f 52 49 54 49 45 53 0a 7d 3b 0a 0a 23  PRIORITIES.};..#
06a0: 69 66 6e 64 65 66 20 62 61 72 72 69 65 72 0a 23  ifndef barrier.#
06b0: 64 65 66 69 6e 65 20 62 61 72 72 69 65 72 28 29  define barrier()
06c0: 20 61 73 6d 20 76 6f 6c 61 74 69 6c 65 28 22 22   asm volatile(""
06d0: 3a 20 3a 20 3a 22 6d 65 6d 6f 72 79 22 29 0a 23  : : :"memory").#
06e0: 65 6e 64 69 66 0a 0a 74 79 70 65 64 65 66 20 76  endif..typedef v
06f0: 6f 69 64 20 2a 20 28 2a 74 68 72 65 61 64 5f 66  oid * (*thread_f
0700: 75 6e 63 5f 74 29 28 76 6f 69 64 20 2a 20 61 72  unc_t)(void * ar
0710: 67 29 3b 0a 0a 73 74 72 75 63 74 20 74 68 72 65  g);..struct thre
0720: 61 64 5f 70 6f 6f 6c 5f 74 20 7b 0a 09 71 75 65  ad_pool_t {..que
0730: 75 65 5f 74 20 2a 20 71 75 65 75 65 3b 0a 09 74  ue_t * queue;..t
0740: 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64  hread_t * thread
0750: 3b 0a 7d 3b 0a 0a 23 65 6e 64 69 66 0a 0a 69 6e  ;.};..#endif..in
0760: 74 20 70 72 65 65 6d 70 74 3b 0a 73 74 61 74 69  t preempt;.stati
0770: 63 20 74 6c 73 5f 6b 65 79 20 74 6c 73 5f 6e 65  c tls_key tls_ne
0780: 78 74 20 3d 20 31 3b 0a 0a 2f 2a 2a 20 0a 20 2a  xt = 1;../** . *
0790: 20 47 65 74 20 74 68 65 20 6e 65 78 74 20 54 4c   Get the next TL
07a0: 53 20 6b 65 79 0a 20 2a 20 5c 72 65 74 75 72 6e  S key. * \return
07b0: 20 4e 65 78 74 20 6b 65 79 0a 20 2a 2f 0a 69 6e   Next key. */.in
07c0: 74 20 74 6c 73 5f 67 65 74 5f 6b 65 79 28 29 0a  t tls_get_key().
07d0: 7b 0a 09 72 65 74 75 72 6e 20 61 72 63 68 5f 61  {..return arch_a
07e0: 74 6f 6d 69 63 5f 70 6f 73 74 69 6e 63 28 26 74  tomic_postinc(&t
07f0: 6c 73 5f 6e 65 78 74 29 3b 0a 7d 0a 0a 2f 2a 2a  ls_next);.}../**
0800: 0a 20 2a 20 53 65 74 20 74 68 65 20 74 68 72 65  . * Set the thre
0810: 61 64 20 6c 6f 63 61 6c 20 64 61 74 61 20 67 69  ad local data gi
0820: 76 65 6e 20 62 79 20 74 68 65 20 6b 65 79 2e 0a  ven by the key..
0830: 20 2a 0a 20 2a 20 5c 61 72 67 20 6b 65 79 20 54   *. * \arg key T
0840: 4c 53 20 6b 65 79 20 72 65 74 72 69 65 76 65 64  LS key retrieved
0850: 20 75 73 69 6e 67 20 5c 72 65 66 20 74 6c 73 5f   using \ref tls_
0860: 67 65 74 5f 6b 65 79 0a 20 2a 20 5c 61 72 67 20  get_key. * \arg 
0870: 70 20 50 6f 69 6e 74 65 72 20 76 61 6c 75 65 0a  p Pointer value.
0880: 20 2a 2f 0a 76 6f 69 64 20 74 6c 73 5f 73 65 74   */.void tls_set
0890: 28 69 6e 74 20 6b 65 79 2c 20 76 6f 69 64 20 2a  (int key, void *
08a0: 20 70 29 0a 7b 0a 09 74 68 72 65 61 64 5f 74 20   p).{..thread_t 
08b0: 2a 20 74 68 72 65 61 64 20 3d 20 61 72 63 68 5f  * thread = arch_
08c0: 67 65 74 5f 74 68 72 65 61 64 28 29 3b 0a 0a 09  get_thread();...
08d0: 63 68 65 63 6b 5f 6e 6f 74 5f 6e 75 6c 6c 28 74  check_not_null(t
08e0: 68 72 65 61 64 2c 20 22 55 6e 61 62 6c 65 20 74  hread, "Unable t
08f0: 6f 20 67 65 74 20 74 68 72 65 61 64 22 29 3b 0a  o get thread");.
0900: 09 63 68 65 63 6b 5f 69 6e 74 5f 62 6f 75 6e 64  .check_int_bound
0910: 73 28 6b 65 79 2c 20 31 2c 20 54 4c 53 5f 4d 41  s(key, 1, TLS_MA
0920: 58 2d 31 2c 20 22 54 4c 53 20 6b 65 79 20 6f 75  X-1, "TLS key ou
0930: 74 20 6f 66 20 62 6f 75 6e 64 73 22 29 3b 0a 0a  t of bounds");..
0940: 09 74 68 72 65 61 64 2d 3e 74 6c 73 5b 6b 65 79  .thread->tls[key
0950: 5d 20 3d 20 70 3b 0a 7d 0a 0a 2f 2a 2a 0a 20 2a  ] = p;.}../**. *
0960: 20 47 65 74 20 74 68 65 20 74 68 72 65 61 64 20   Get the thread 
0970: 6c 6f 63 61 6c 20 64 61 74 61 20 67 69 76 65 6e  local data given
0980: 20 62 79 20 74 68 65 20 6b 65 79 2e 0a 20 2a 0a   by the key.. *.
0990: 20 2a 20 5c 61 72 67 20 6b 65 79 20 54 4c 53 20   * \arg key TLS 
09a0: 6b 65 79 20 72 65 74 72 69 65 76 65 64 20 75 73  key retrieved us
09b0: 69 6e 67 20 5c 72 65 66 20 74 6c 73 5f 67 65 74  ing \ref tls_get
09c0: 5f 6b 65 79 0a 20 2a 20 5c 72 65 74 75 72 6e 20  _key. * \return 
09d0: 50 6f 69 6e 74 65 72 20 76 61 6c 75 65 0a 20 2a  Pointer value. *
09e0: 2f 0a 76 6f 69 64 20 2a 20 74 6c 73 5f 67 65 74  /.void * tls_get
09f0: 28 69 6e 74 20 6b 65 79 29 0a 7b 0a 09 74 68 72  (int key).{..thr
0a00: 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64 20 3d  ead_t * thread =
0a10: 20 61 72 63 68 5f 67 65 74 5f 74 68 72 65 61 64   arch_get_thread
0a20: 28 29 3b 0a 0a 09 63 68 65 63 6b 5f 6e 6f 74 5f  ();...check_not_
0a30: 6e 75 6c 6c 28 74 68 72 65 61 64 2c 20 22 55 6e  null(thread, "Un
0a40: 61 62 6c 65 20 74 6f 20 67 65 74 20 74 68 72 65  able to get thre
0a50: 61 64 22 29 3b 0a 09 63 68 65 63 6b 5f 69 6e 74  ad");..check_int
0a60: 5f 62 6f 75 6e 64 73 28 6b 65 79 2c 20 31 2c 20  _bounds(key, 1, 
0a70: 54 4c 53 5f 4d 41 58 2d 31 2c 20 22 54 4c 53 20  TLS_MAX-1, "TLS 
0a80: 6b 65 79 20 6f 75 74 20 6f 66 20 62 6f 75 6e 64  key out of bound
0a90: 73 22 29 3b 0a 0a 09 72 65 74 75 72 6e 20 74 68  s");...return th
0aa0: 72 65 61 64 2d 3e 74 6c 73 5b 6b 65 79 5d 3b 0a  read->tls[key];.
0ab0: 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 20 74  }..static void t
0ac0: 68 72 65 61 64 5f 6d 61 72 6b 28 76 6f 69 64 20  hread_mark(void 
0ad0: 2a 20 70 29 3b 0a 73 74 61 74 69 63 20 76 6f 69  * p);.static voi
0ae0: 64 20 74 68 72 65 61 64 5f 66 69 6e 61 6c 69 7a  d thread_finaliz
0af0: 65 28 76 6f 69 64 20 2a 20 70 29 3b 0a 73 74 61  e(void * p);.sta
0b00: 74 69 63 20 73 6c 61 62 5f 74 79 70 65 5f 74 20  tic slab_type_t 
0b10: 74 68 72 65 61 64 73 5b 31 5d 20 3d 20 7b 53 4c  threads[1] = {SL
0b20: 41 42 5f 54 59 50 45 28 73 69 7a 65 6f 66 28 74  AB_TYPE(sizeof(t
0b30: 68 72 65 61 64 5f 74 29 2c 20 74 68 72 65 61 64  hread_t), thread
0b40: 5f 6d 61 72 6b 2c 20 74 68 72 65 61 64 5f 66 69  _mark, thread_fi
0b50: 6e 61 6c 69 7a 65 29 7d 3b 0a 0a 73 74 61 74 69  nalize)};..stati
0b60: 63 20 73 70 69 6e 5f 74 20 71 75 65 75 65 6c 6f  c spin_t queuelo
0b70: 63 6b 3b 0a 0a 2f 2a 2a 0a 20 2a 20 4c 6f 63 6b  ck;../**. * Lock
0b80: 20 73 63 68 65 64 75 6c 65 72 0a 20 2a 2f 0a 76   scheduler. */.v
0b90: 6f 69 64 20 73 63 68 65 64 75 6c 65 72 5f 6c 6f  oid scheduler_lo
0ba0: 63 6b 28 29 0a 7b 0a 09 73 70 69 6e 5f 6c 6f 63  ck().{..spin_loc
0bb0: 6b 28 26 71 75 65 75 65 6c 6f 63 6b 29 3b 0a 7d  k(&queuelock);.}
0bc0: 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 20 73 63  ..static void sc
0bd0: 68 65 64 75 6c 65 72 5f 75 6e 6c 6f 63 6b 28 29  heduler_unlock()
0be0: 0a 7b 0a 09 73 70 69 6e 5f 75 6e 6c 6f 63 6b 28  .{..spin_unlock(
0bf0: 26 71 75 65 75 65 6c 6f 63 6b 29 3b 0a 7d 0a 0a  &queuelock);.}..
0c00: 2f 2a 2a 0a 20 2a 20 50 75 74 20 74 68 65 20 67  /**. * Put the g
0c10: 69 76 65 6e 20 74 68 72 65 61 64 20 6f 6e 20 74  iven thread on t
0c20: 68 65 20 68 65 61 64 20 6f 66 20 74 68 65 20 67  he head of the g
0c30: 69 76 65 6e 20 71 75 65 75 65 2c 20 69 6e 20 74  iven queue, in t
0c40: 68 65 20 67 69 76 65 6e 20 73 74 61 74 65 2e 0a  he given state..
0c50: 20 2a 20 5c 61 72 67 20 71 75 65 75 65 20 43 75   * \arg queue Cu
0c60: 72 72 65 6e 74 20 71 75 65 75 65 0a 20 2a 20 5c  rrent queue. * \
0c70: 61 72 67 20 74 68 72 65 61 64 20 54 68 72 65 61  arg thread Threa
0c80: 64 20 74 6f 20 71 75 65 75 65 0a 20 2a 20 5c 61  d to queue. * \a
0c90: 72 67 20 73 74 61 74 65 20 54 68 72 65 61 64 20  rg state Thread 
0ca0: 73 74 61 74 65 0a 20 2a 20 5c 72 65 74 75 72 6e  state. * \return
0cb0: 20 4e 65 77 20 71 75 65 75 65 20 68 65 61 64 0a   New queue head.
0cc0: 20 2a 2f 0a 74 68 72 65 61 64 5f 74 20 2a 20 74   */.thread_t * t
0cd0: 68 72 65 61 64 5f 70 72 65 71 75 65 75 65 28 74  hread_prequeue(t
0ce0: 68 72 65 61 64 5f 74 20 2a 20 71 75 65 75 65 2c  hread_t * queue,
0cf0: 20 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65   thread_t * thre
0d00: 61 64 2c 20 74 73 74 61 74 65 20 73 74 61 74 65  ad, tstate state
0d10: 29 0a 7b 0a 09 69 66 20 28 30 20 3d 3d 20 74 68  ).{..if (0 == th
0d20: 72 65 61 64 29 20 7b 0a 09 09 74 68 72 65 61 64  read) {...thread
0d30: 20 3d 20 61 72 63 68 5f 67 65 74 5f 74 68 72 65   = arch_get_thre
0d40: 61 64 28 29 3b 0a 09 7d 0a 09 74 68 72 65 61 64  ad();..}..thread
0d50: 2d 3e 73 74 61 74 65 20 3d 20 73 74 61 74 65 3b  ->state = state;
0d60: 0a 09 4c 49 53 54 5f 50 52 45 50 45 4e 44 28 71  ..LIST_PREPEND(q
0d70: 75 65 75 65 2c 20 74 68 72 65 61 64 29 3b 0a 09  ueue, thread);..
0d80: 72 65 74 75 72 6e 20 71 75 65 75 65 3b 0a 7d 0a  return queue;.}.
0d90: 0a 2f 2a 2a 0a 20 2a 20 50 75 74 20 74 68 65 20  ./**. * Put the 
0da0: 67 69 76 65 6e 20 74 68 72 65 61 64 20 6f 6e 20  given thread on 
0db0: 74 61 69 6c 20 6f 66 20 74 68 65 20 67 69 76 65  tail of the give
0dc0: 6e 20 71 75 65 75 65 2c 20 69 6e 20 74 68 65 20  n queue, in the 
0dd0: 67 69 76 65 6e 20 73 74 61 74 65 2e 0a 20 2a 20  given state.. * 
0de0: 5c 61 72 67 20 71 75 65 75 65 20 43 75 72 72 65  \arg queue Curre
0df0: 6e 74 20 71 75 65 75 65 0a 20 2a 20 5c 61 72 67  nt queue. * \arg
0e00: 20 74 68 72 65 61 64 20 54 68 72 65 61 64 20 74   thread Thread t
0e10: 6f 20 71 75 65 75 65 0a 20 2a 20 5c 61 72 67 20  o queue. * \arg 
0e20: 73 74 61 74 65 20 54 68 72 65 61 64 20 73 74 61  state Thread sta
0e30: 74 65 0a 20 2a 20 5c 72 65 74 75 72 6e 20 4e 65  te. * \return Ne
0e40: 77 20 71 75 65 75 65 20 68 65 61 64 0a 20 2a 2f  w queue head. */
0e50: 0a 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65  .thread_t * thre
0e60: 61 64 5f 71 75 65 75 65 28 74 68 72 65 61 64 5f  ad_queue(thread_
0e70: 74 20 2a 20 71 75 65 75 65 2c 20 74 68 72 65 61  t * queue, threa
0e80: 64 5f 74 20 2a 20 74 68 72 65 61 64 2c 20 74 73  d_t * thread, ts
0e90: 74 61 74 65 20 73 74 61 74 65 29 0a 7b 0a 09 69  tate state).{..i
0ea0: 66 20 28 30 20 3d 3d 20 74 68 72 65 61 64 29 20  f (0 == thread) 
0eb0: 7b 0a 09 09 74 68 72 65 61 64 20 3d 20 61 72 63  {...thread = arc
0ec0: 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29 3b 0a  h_get_thread();.
0ed0: 09 7d 0a 09 74 68 72 65 61 64 2d 3e 73 74 61 74  .}..thread->stat
0ee0: 65 20 3d 20 73 74 61 74 65 3b 0a 09 4c 49 53 54  e = state;..LIST
0ef0: 5f 41 50 50 45 4e 44 28 71 75 65 75 65 2c 20 74  _APPEND(queue, t
0f00: 68 72 65 61 64 29 3b 0a 09 72 65 74 75 72 6e 20  hread);..return 
0f10: 71 75 65 75 65 3b 0a 7d 0a 0a 2f 2a 20 53 69 6d  queue;.}../* Sim
0f20: 70 6c 65 20 52 52 20 73 63 68 65 64 75 6c 65 72  ple RR scheduler
0f30: 20 2a 2f 0a 73 74 61 74 69 63 20 47 43 52 4f 4f   */.static GCROO
0f40: 54 20 74 68 72 65 61 64 5f 74 20 2a 20 71 75 65  T thread_t * que
0f50: 75 65 5b 54 48 52 45 41 44 5f 50 52 49 4f 52 49  ue[THREAD_PRIORI
0f60: 54 49 45 53 5d 3b 0a 0a 2f 2a 2a 0a 20 2a 20 50  TIES];../**. * P
0f70: 72 65 2d 65 6d 70 74 20 74 68 65 20 63 75 72 72  re-empt the curr
0f80: 65 6e 74 20 74 68 72 65 61 64 2c 20 70 75 74 74  ent thread, putt
0f90: 69 6e 67 20 74 68 65 20 74 68 72 65 61 64 20 6f  ing the thread o
0fa0: 6e 74 6f 20 74 68 65 20 68 65 61 64 20 6f 66 20  nto the head of 
0fb0: 74 68 65 20 72 75 6e 20 71 75 65 75 65 0a 20 2a  the run queue. *
0fc0: 20 5c 72 65 74 75 72 6e 20 31 20 69 66 20 74 68   \return 1 if th
0fd0: 65 20 74 68 72 65 61 64 20 77 61 73 20 70 72 65  e thread was pre
0fe0: 2d 65 6d 70 74 65 64 0a 20 2a 2f 0a 69 6e 74 20  -empted. */.int 
0ff0: 74 68 72 65 61 64 5f 70 72 65 65 6d 70 74 28 29  thread_preempt()
1000: 0a 7b 0a 09 74 68 72 65 61 64 5f 74 20 2a 20 74  .{..thread_t * t
1010: 68 69 73 20 3d 20 61 72 63 68 5f 67 65 74 5f 74  his = arch_get_t
1020: 68 72 65 61 64 28 29 3b 0a 09 74 70 72 69 6f 72  hread();..tprior
1030: 69 74 79 20 70 72 69 6f 72 69 74 79 20 3d 20 74  ity priority = t
1040: 68 69 73 2d 3e 70 72 69 6f 72 69 74 79 3b 0a 09  his->priority;..
1050: 73 63 68 65 64 75 6c 65 72 5f 6c 6f 63 6b 28 29  scheduler_lock()
1060: 3b 0a 09 71 75 65 75 65 5b 70 72 69 6f 72 69 74  ;..queue[priorit
1070: 79 5d 20 3d 20 74 68 72 65 61 64 5f 70 72 65 71  y] = thread_preq
1080: 75 65 75 65 28 71 75 65 75 65 5b 70 72 69 6f 72  ueue(queue[prior
1090: 69 74 79 5d 2c 20 74 68 69 73 2c 20 54 48 52 45  ity], this, THRE
10a0: 41 44 5f 52 55 4e 4e 41 42 4c 45 29 3b 0a 09 72  AD_RUNNABLE);..r
10b0: 65 74 75 72 6e 20 74 68 72 65 61 64 5f 73 63 68  eturn thread_sch
10c0: 65 64 75 6c 65 28 29 3b 0a 7d 0a 0a 2f 2a 2a 0a  edule();.}../**.
10d0: 20 2a 20 50 72 65 2d 65 6d 70 74 20 74 68 65 20   * Pre-empt the 
10e0: 63 75 72 72 65 6e 74 20 74 68 72 65 61 64 2c 20  current thread, 
10f0: 70 75 74 74 69 6e 67 20 74 68 65 20 74 68 72 65  putting the thre
1100: 61 64 20 6f 6e 74 6f 20 74 68 65 20 68 65 61 64  ad onto the head
1110: 20 6f 66 20 74 68 65 20 72 75 6e 20 71 75 65 75   of the run queu
1120: 65 0a 20 2a 20 5c 72 65 74 75 72 6e 20 31 20 69  e. * \return 1 i
1130: 66 20 74 68 65 20 74 68 72 65 61 64 20 77 61 73  f the thread was
1140: 20 70 72 65 2d 65 6d 70 74 65 64 0a 20 2a 2f 0a   pre-empted. */.
1150: 69 6e 74 20 74 68 72 65 61 64 5f 79 69 65 6c 64  int thread_yield
1160: 28 29 0a 7b 0a 09 74 68 72 65 61 64 5f 74 20 2a  ().{..thread_t *
1170: 20 74 68 69 73 20 3d 20 61 72 63 68 5f 67 65 74   this = arch_get
1180: 5f 74 68 72 65 61 64 28 29 3b 0a 09 74 70 72 69  _thread();..tpri
1190: 6f 72 69 74 79 20 70 72 69 6f 72 69 74 79 20 3d  ority priority =
11a0: 20 74 68 69 73 2d 3e 70 72 69 6f 72 69 74 79 3b   this->priority;
11b0: 0a 09 73 63 68 65 64 75 6c 65 72 5f 6c 6f 63 6b  ..scheduler_lock
11c0: 28 29 3b 0a 09 71 75 65 75 65 5b 70 72 69 6f 72  ();..queue[prior
11d0: 69 74 79 5d 20 3d 20 74 68 72 65 61 64 5f 71 75  ity] = thread_qu
11e0: 65 75 65 28 71 75 65 75 65 5b 70 72 69 6f 72 69  eue(queue[priori
11f0: 74 79 5d 2c 20 74 68 69 73 2c 20 54 48 52 45 41  ty], this, THREA
1200: 44 5f 52 55 4e 4e 41 42 4c 45 29 3b 0a 09 72 65  D_RUNNABLE);..re
1210: 74 75 72 6e 20 74 68 72 65 61 64 5f 73 63 68 65  turn thread_sche
1220: 64 75 6c 65 28 29 3b 0a 7d 0a 0a 2f 2a 2a 0a 20  dule();.}../**. 
1230: 2a 20 4d 61 72 6b 20 67 69 76 65 6e 20 74 68 72  * Mark given thr
1240: 65 61 64 20 61 73 20 69 6e 74 65 72 72 75 70 74  ead as interrupt
1250: 65 64 0a 20 2a 2f 0a 76 6f 69 64 20 74 68 72 65  ed. */.void thre
1260: 61 64 5f 69 6e 74 65 72 72 75 70 74 28 74 68 72  ad_interrupt(thr
1270: 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64 29 0a  ead_t * thread).
1280: 7b 0a 09 74 68 72 65 61 64 2d 3e 69 6e 74 65 72  {..thread->inter
1290: 72 75 70 74 65 64 20 3d 20 31 3b 0a 7d 0a 0a 2f  rupted = 1;.}../
12a0: 2a 2a 0a 20 2a 20 43 68 65 63 6b 20 69 66 20 74  **. * Check if t
12b0: 68 65 20 67 69 76 65 6e 20 74 68 72 65 61 64 20  he given thread 
12c0: 68 61 73 20 62 65 65 6e 20 69 6e 74 65 72 72 75  has been interru
12d0: 70 74 65 64 0a 20 2a 20 5c 61 72 67 20 74 68 72  pted. * \arg thr
12e0: 65 61 64 20 54 68 72 65 61 64 20 74 6f 20 63 68  ead Thread to ch
12f0: 65 63 6b 20 66 6f 72 20 69 6e 74 65 72 72 75 70  eck for interrup
1300: 74 69 6f 6e 2e 20 49 66 20 30 2c 20 63 68 65 63  tion. If 0, chec
1310: 6b 20 63 75 72 72 65 6e 74 20 74 68 72 65 61 64  k current thread
1320: 0a 20 2a 20 5c 72 65 74 75 72 6e 20 74 72 75 65  . * \return true
1330: 20 28 6e 6f 74 20 30 29 20 69 66 20 69 6e 74 65   (not 0) if inte
1340: 72 72 75 70 74 65 64 0a 20 2a 2f 0a 69 6e 74 20  rrupted. */.int 
1350: 74 68 72 65 61 64 5f 69 73 69 6e 74 65 72 72 75  thread_isinterru
1360: 70 74 65 64 28 74 68 72 65 61 64 5f 74 20 2a 20  pted(thread_t * 
1370: 74 68 72 65 61 64 29 0a 7b 0a 09 69 66 20 28 30  thread).{..if (0
1380: 20 3d 3d 20 74 68 72 65 61 64 29 20 7b 0a 09 09   == thread) {...
1390: 74 68 72 65 61 64 20 3d 20 61 72 63 68 5f 67 65  thread = arch_ge
13a0: 74 5f 74 68 72 65 61 64 28 29 3b 0a 09 7d 0a 0a  t_thread();..}..
13b0: 09 72 65 74 75 72 6e 20 74 68 72 65 61 64 2d 3e  .return thread->
13c0: 69 6e 74 65 72 72 75 70 74 65 64 3b 0a 7d 0a 0a  interrupted;.}..
13d0: 2f 2a 2a 0a 20 2a 20 43 68 65 63 6b 20 69 66 20  /**. * Check if 
13e0: 74 68 65 20 63 75 72 72 65 6e 74 20 74 68 72 65  the current thre
13f0: 61 64 20 68 61 73 20 62 65 65 6e 20 69 6e 74 65  ad has been inte
1400: 72 72 75 70 74 65 64 2c 20 61 6e 64 20 72 65 73  rrupted, and res
1410: 65 74 20 74 68 65 20 69 6e 74 65 72 72 75 70 74  et the interrupt
1420: 20 66 6c 61 67 0a 20 2a 20 5c 72 65 74 75 72 6e   flag. * \return
1430: 20 74 72 75 65 20 28 6e 6f 74 20 30 29 20 69 66   true (not 0) if
1440: 20 69 6e 74 65 72 72 75 70 74 65 64 0a 20 2a 2f   interrupted. */
1450: 0a 69 6e 74 20 74 68 72 65 61 64 5f 69 6e 74 65  .int thread_inte
1460: 72 72 75 70 74 65 64 28 29 0a 7b 0a 09 74 68 72  rrupted().{..thr
1470: 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64 20 3d  ead_t * thread =
1480: 20 61 72 63 68 5f 67 65 74 5f 74 68 72 65 61 64   arch_get_thread
1490: 28 29 3b 0a 0a 09 69 66 20 28 74 68 72 65 61 64  ();...if (thread
14a0: 5f 69 73 69 6e 74 65 72 72 75 70 74 65 64 28 74  _isinterrupted(t
14b0: 68 72 65 61 64 29 29 20 7b 0a 09 09 74 68 72 65  hread)) {...thre
14c0: 61 64 2d 3e 69 6e 74 65 72 72 75 70 74 65 64 20  ad->interrupted 
14d0: 3d 20 30 3b 0a 09 09 72 65 74 75 72 6e 20 31 3b  = 0;...return 1;
14e0: 0a 09 7d 0a 0a 09 72 65 74 75 72 6e 20 30 3b 0a  ..}...return 0;.
14f0: 7d 0a 0a 2f 2a 2a 0a 20 2a 20 52 65 73 75 6d 65  }../**. * Resume
1500: 20 74 68 65 20 67 69 76 65 6e 20 74 68 72 65 61   the given threa
1510: 64 0a 20 2a 20 5c 61 72 67 20 74 68 72 65 61 64  d. * \arg thread
1520: 20 54 68 72 65 61 64 20 74 6f 20 72 65 73 75 6d   Thread to resum
1530: 65 0a 20 2a 2f 0a 76 6f 69 64 20 74 68 72 65 61  e. */.void threa
1540: 64 5f 72 65 73 75 6d 65 28 74 68 72 65 61 64 5f  d_resume(thread_
1550: 74 20 2a 20 74 68 72 65 61 64 29 0a 7b 0a 09 74  t * thread).{..t
1560: 70 72 69 6f 72 69 74 79 20 70 72 69 6f 72 69 74  priority priorit
1570: 79 20 3d 20 74 68 72 65 61 64 2d 3e 70 72 69 6f  y = thread->prio
1580: 72 69 74 79 3b 0a 09 73 63 68 65 64 75 6c 65 72  rity;..scheduler
1590: 5f 6c 6f 63 6b 28 29 3b 0a 09 71 75 65 75 65 5b  _lock();..queue[
15a0: 70 72 69 6f 72 69 74 79 5d 20 3d 20 74 68 72 65  priority] = thre
15b0: 61 64 5f 71 75 65 75 65 28 71 75 65 75 65 5b 70  ad_queue(queue[p
15c0: 72 69 6f 72 69 74 79 5d 2c 20 74 68 72 65 61 64  riority], thread
15d0: 2c 20 54 48 52 45 41 44 5f 52 55 4e 4e 41 42 4c  , THREAD_RUNNABL
15e0: 45 29 3b 0a 09 73 63 68 65 64 75 6c 65 72 5f 75  E);..scheduler_u
15f0: 6e 6c 6f 63 6b 28 29 3b 0a 09 2f 2a 20 43 68 65  nlock();../* Che
1600: 63 6b 20 66 6f 72 20 70 72 65 2d 65 6d 70 74 69  ck for pre-empti
1610: 6f 6e 20 2a 2f 0a 09 69 66 20 28 61 72 63 68 5f  on */..if (arch_
1620: 67 65 74 5f 74 68 72 65 61 64 28 29 2d 3e 70 72  get_thread()->pr
1630: 69 6f 72 69 74 79 20 3e 20 70 72 69 6f 72 69 74  iority > priorit
1640: 79 29 20 7b 0a 09 09 70 72 65 65 6d 70 74 20 3d  y) {...preempt =
1650: 20 31 3b 0a 09 7d 0a 7d 0a 0a 2f 2a 2a 0a 20 2a   1;..}.}../**. *
1660: 20 53 63 68 65 64 75 6c 65 20 74 68 65 20 6e 65   Schedule the ne
1670: 78 74 20 74 68 72 65 61 64 0a 20 2a 20 5c 72 65  xt thread. * \re
1680: 74 75 72 6e 20 31 20 69 66 20 61 20 6e 65 77 20  turn 1 if a new 
1690: 74 68 72 65 61 64 20 77 61 73 20 73 63 68 65 64  thread was sched
16a0: 75 6c 65 64 0a 20 2a 2f 0a 69 6e 74 20 74 68 72  uled. */.int thr
16b0: 65 61 64 5f 73 63 68 65 64 75 6c 65 28 29 0a 7b  ead_schedule().{
16c0: 0a 09 77 68 69 6c 65 28 31 29 20 7b 0a 09 09 69  ..while(1) {...i
16d0: 6e 74 20 69 3b 0a 09 09 66 6f 72 28 69 3d 30 3b  nt i;...for(i=0;
16e0: 20 69 3c 54 48 52 45 41 44 5f 50 52 49 4f 52 49   i<THREAD_PRIORI
16f0: 54 49 45 53 3b 20 69 2b 2b 29 20 7b 0a 09 09 09  TIES; i++) {....
1700: 69 66 20 28 71 75 65 75 65 5b 69 5d 29 20 7b 0a  if (queue[i]) {.
1710: 09 09 09 09 74 68 72 65 61 64 5f 74 20 2a 20 63  ....thread_t * c
1720: 75 72 72 65 6e 74 20 3d 20 61 72 63 68 5f 67 65  urrent = arch_ge
1730: 74 5f 74 68 72 65 61 64 28 29 3b 0a 09 09 09 09  t_thread();.....
1740: 74 68 72 65 61 64 5f 74 20 2a 20 6e 65 78 74 20  thread_t * next 
1750: 3d 20 71 75 65 75 65 5b 69 5d 3b 0a 09 09 09 09  = queue[i];.....
1760: 4c 49 53 54 5f 44 45 4c 45 54 45 28 71 75 65 75  LIST_DELETE(queu
1770: 65 5b 69 5d 2c 20 6e 65 78 74 29 3b 0a 09 09 09  e[i], next);....
1780: 09 73 63 68 65 64 75 6c 65 72 5f 75 6e 6c 6f 63  .scheduler_unloc
1790: 6b 28 29 3b 0a 09 09 09 09 69 66 20 28 61 72 63  k();.....if (arc
17a0: 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29 20 21  h_get_thread() !
17b0: 3d 20 6e 65 78 74 29 20 7b 0a 09 09 09 09 09 2f  = next) {....../
17c0: 2a 20 54 68 72 65 61 64 20 69 73 20 63 68 61 6e  * Thread is chan
17d0: 67 69 6e 67 2c 20 64 6f 20 61 63 63 6f 75 6e 74  ging, do account
17e0: 69 6e 67 20 61 6e 64 20 73 77 69 74 63 68 20 74  ing and switch t
17f0: 6f 20 6e 65 78 74 20 2a 2f 0a 09 09 09 09 09 63  o next */......c
1800: 75 72 72 65 6e 74 2d 3e 61 63 63 74 73 5b 63 75  urrent->accts[cu
1810: 72 72 65 6e 74 2d 3e 61 63 63 74 5d 2e 74 6c 65  rrent->acct].tle
1820: 6e 20 3d 20 74 69 6d 65 72 5f 75 70 74 69 6d 65  n = timer_uptime
1830: 28 31 29 20 2d 20 63 75 72 72 65 6e 74 2d 3e 61  (1) - current->a
1840: 63 63 74 73 5b 63 75 72 72 65 6e 74 2d 3e 61 63  ccts[current->ac
1850: 63 74 5d 2e 74 73 74 61 72 74 3b 0a 09 09 09 09  ct].tstart;.....
1860: 09 63 75 72 72 65 6e 74 2d 3e 61 63 63 74 2b 2b  .current->acct++
1870: 3b 0a 09 09 09 09 09 69 66 20 28 73 69 7a 65 6f  ;......if (sizeo
1880: 66 28 63 75 72 72 65 6e 74 2d 3e 61 63 63 74 73  f(current->accts
1890: 29 2f 73 69 7a 65 6f 66 28 63 75 72 72 65 6e 74  )/sizeof(current
18a0: 2d 3e 61 63 63 74 73 5b 30 5d 29 20 3d 3d 20 63  ->accts[0]) == c
18b0: 75 72 72 65 6e 74 2d 3e 61 63 63 74 29 20 7b 0a  urrent->acct) {.
18c0: 09 09 09 09 09 09 63 75 72 72 65 6e 74 2d 3e 61  ......current->a
18d0: 63 63 74 20 3d 20 30 3b 0a 09 09 09 09 09 7d 0a  cct = 0;......}.
18e0: 09 09 09 09 09 61 72 63 68 5f 74 68 72 65 61 64  .....arch_thread
18f0: 5f 73 77 69 74 63 68 28 6e 65 78 74 29 3b 0a 09  _switch(next);..
1900: 09 09 09 09 63 75 72 72 65 6e 74 2d 3e 61 63 63  ....current->acc
1910: 74 73 5b 63 75 72 72 65 6e 74 2d 3e 61 63 63 74  ts[current->acct
1920: 5d 2e 74 73 74 61 72 74 20 3d 20 74 69 6d 65 72  ].tstart = timer
1930: 5f 75 70 74 69 6d 65 28 31 29 3b 0a 09 09 09 09  _uptime(1);.....
1940: 09 2f 2a 20 42 79 20 64 65 66 61 75 6c 74 2c 20  ./* By default, 
1950: 70 72 65 65 6d 70 74 20 61 66 74 65 72 20 31 30  preempt after 10
1960: 30 6d 73 20 2a 2f 0a 09 09 09 09 09 63 75 72 72  0ms */......curr
1970: 65 6e 74 2d 3e 70 72 65 65 6d 70 74 20 3d 20 63  ent->preempt = c
1980: 75 72 72 65 6e 74 2d 3e 61 63 63 74 73 5b 63 75  urrent->accts[cu
1990: 72 72 65 6e 74 2d 3e 61 63 63 74 5d 2e 74 73 74  rrent->acct].tst
19a0: 61 72 74 20 2b 20 31 30 30 30 30 30 3b 0a 09 09  art + 100000;...
19b0: 09 09 09 72 65 74 75 72 6e 20 31 3b 0a 09 09 09  ...return 1;....
19c0: 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 2f  .} else {....../
19d0: 2a 20 52 65 73 74 6f 72 65 20 74 68 72 65 61 64  * Restore thread
19e0: 20 73 74 61 74 65 20 74 6f 20 72 75 6e 6e 69 6e   state to runnin
19f0: 67 20 2a 2f 0a 09 09 09 09 09 63 75 72 72 65 6e  g */......curren
1a00: 74 2d 3e 73 74 61 74 65 20 3d 20 54 48 52 45 41  t->state = THREA
1a10: 44 5f 52 55 4e 4e 49 4e 47 3b 0a 09 09 09 09 09  D_RUNNING;......
1a20: 72 65 74 75 72 6e 20 30 3b 0a 09 09 09 09 7d 0a  return 0;.....}.
1a30: 09 09 09 7d 0a 09 09 7d 0a 09 09 2f 2f 20 6b 65  ...}...}...// ke
1a40: 72 6e 65 6c 5f 70 72 69 6e 74 6b 28 22 45 6d 70  rnel_printk("Emp
1a50: 74 79 20 72 75 6e 20 71 75 65 75 65 21 5c 6e 22  ty run queue!\n"
1a60: 29 3b 0a 09 09 73 63 68 65 64 75 6c 65 72 5f 75  );...scheduler_u
1a70: 6e 6c 6f 63 6b 28 29 3b 0a 09 09 61 72 63 68 5f  nlock();...arch_
1a80: 69 64 6c 65 28 29 3b 0a 09 09 73 63 68 65 64 75  idle();...schedu
1a90: 6c 65 72 5f 6c 6f 63 6b 28 29 3b 0a 09 7d 0a 7d  ler_lock();..}.}
1aa0: 0a 0a 2f 2a 2a 0a 20 2a 20 47 65 74 20 74 68 65  ../**. * Get the
1ab0: 20 6e 61 6d 65 20 6f 66 20 74 68 65 20 67 69 76   name of the giv
1ac0: 65 6e 20 74 68 72 65 61 64 0a 20 2a 20 5c 61 72  en thread. * \ar
1ad0: 67 20 74 68 72 65 61 64 20 54 68 72 65 61 64 2c  g thread Thread,
1ae0: 20 6f 72 20 63 75 72 72 65 6e 74 20 74 68 72 65   or current thre
1af0: 61 64 20 69 66 20 30 0a 20 2a 20 5c 72 65 74 75  ad if 0. * \retu
1b00: 72 6e 20 54 68 72 65 61 64 20 6e 61 6d 65 2c 20  rn Thread name, 
1b10: 69 66 20 73 65 74 0a 20 2a 2f 0a 63 68 61 72 20  if set. */.char 
1b20: 2a 20 74 68 72 65 61 64 5f 67 65 74 5f 6e 61 6d  * thread_get_nam
1b30: 65 28 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72  e(thread_t * thr
1b40: 65 61 64 29 0a 7b 0a 09 69 66 20 28 30 20 3d 3d  ead).{..if (0 ==
1b50: 20 74 68 72 65 61 64 29 20 7b 0a 09 09 74 68 72   thread) {...thr
1b60: 65 61 64 20 3d 20 61 72 63 68 5f 67 65 74 5f 74  ead = arch_get_t
1b70: 68 72 65 61 64 28 29 3b 0a 09 7d 0a 0a 09 69 66  hread();..}...if
1b80: 20 28 30 20 3d 3d 20 74 68 72 65 61 64 2d 3e 6e   (0 == thread->n
1b90: 61 6d 65 29 20 7b 0a 09 09 74 68 72 65 61 64 2d  ame) {...thread-
1ba0: 3e 6e 61 6d 65 20 3d 20 22 41 6e 6f 6e 79 6d 6f  >name = "Anonymo
1bb0: 75 73 22 3b 0a 09 7d 0a 0a 09 72 65 74 75 72 6e  us";..}...return
1bc0: 20 74 68 72 65 61 64 2d 3e 6e 61 6d 65 3b 0a 7d   thread->name;.}
1bd0: 0a 0a 2f 2a 2a 0a 20 2a 20 53 65 74 20 74 68 65  ../**. * Set the
1be0: 20 6e 61 6d 65 20 6f 66 20 74 68 65 20 67 69 76   name of the giv
1bf0: 65 6e 20 74 68 72 65 61 64 0a 20 2a 20 5c 61 72  en thread. * \ar
1c00: 67 20 74 68 72 65 61 64 20 54 68 72 65 61 64 2c  g thread Thread,
1c10: 20 6f 72 20 63 75 72 72 65 6e 74 20 74 68 72 65   or current thre
1c20: 61 64 20 69 66 20 30 0a 20 2a 20 5c 61 72 67 20  ad if 0. * \arg 
1c30: 6e 61 6d 65 20 4e 65 77 20 74 68 72 65 61 64 20  name New thread 
1c40: 6e 61 6d 65 0a 20 2a 2f 0a 76 6f 69 64 20 74 68  name. */.void th
1c50: 72 65 61 64 5f 73 65 74 5f 6e 61 6d 65 28 74 68  read_set_name(th
1c60: 72 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64 2c  read_t * thread,
1c70: 20 63 68 61 72 20 2a 20 6e 61 6d 65 29 0a 7b 0a   char * name).{.
1c80: 09 69 66 20 28 30 20 3d 3d 20 74 68 72 65 61 64  .if (0 == thread
1c90: 29 20 7b 0a 09 09 74 68 72 65 61 64 20 3d 20 61  ) {...thread = a
1ca0: 72 63 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29  rch_get_thread()
1cb0: 3b 0a 09 7d 0a 0a 09 74 68 72 65 61 64 2d 3e 6e  ;..}...thread->n
1cc0: 61 6d 65 20 3d 20 6e 61 6d 65 3b 0a 7d 0a 0a 73  ame = name;.}..s
1cd0: 74 61 74 69 63 20 73 70 69 6e 5f 74 20 61 6c 6c  tatic spin_t all
1ce0: 74 68 72 65 61 64 73 6c 6f 63 6b 20 3d 20 41 54  threadslock = AT
1cf0: 4f 4d 49 43 5f 46 4c 41 47 5f 49 4e 49 54 3b 0a  OMIC_FLAG_INIT;.
1d00: 73 74 61 74 69 63 20 47 43 52 4f 4f 54 20 6d 61  static GCROOT ma
1d10: 70 5f 74 20 2a 20 61 6c 6c 74 68 72 65 61 64 73  p_t * allthreads
1d20: 20 3d 20 30 3b 0a 73 74 61 74 69 63 20 76 6f 69   = 0;.static voi
1d30: 64 20 74 68 72 65 61 64 5f 74 72 61 63 6b 28 74  d thread_track(t
1d40: 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64  hread_t * thread
1d50: 2c 20 69 6e 74 20 61 64 64 29 0a 7b 0a 09 53 50  , int add).{..SP
1d60: 49 4e 5f 41 55 54 4f 4c 4f 43 4b 28 26 61 6c 6c  IN_AUTOLOCK(&all
1d70: 74 68 72 65 61 64 73 6c 6f 63 6b 29 20 7b 0a 09  threadslock) {..
1d80: 09 69 66 20 28 30 20 3d 3d 20 61 6c 6c 74 68 72  .if (0 == allthr
1d90: 65 61 64 73 29 20 7b 0a 09 09 09 2f 2a 20 41 6c  eads) {..../* Al
1da0: 6c 20 74 68 72 65 61 64 73 20 2a 2f 0a 09 09 09  l threads */....
1db0: 61 6c 6c 74 68 72 65 61 64 73 20 3d 20 74 72 65  allthreads = tre
1dc0: 65 5f 6e 65 77 28 30 2c 20 54 52 45 45 5f 54 52  e_new(0, TREE_TR
1dd0: 45 41 50 29 3b 0a 09 09 7d 0a 09 09 69 66 20 28  EAP);...}...if (
1de0: 61 64 64 29 20 7b 0a 09 09 09 69 66 20 28 6d 61  add) {....if (ma
1df0: 70 5f 70 75 74 70 70 28 61 6c 6c 74 68 72 65 61  p_putpp(allthrea
1e00: 64 73 2c 20 74 68 72 65 61 64 2c 20 74 68 72 65  ds, thread, thre
1e10: 61 64 29 29 20 7b 0a 09 09 09 09 6b 65 72 6e 65  ad)) {.....kerne
1e20: 6c 5f 70 61 6e 69 63 28 22 41 64 64 69 6e 67 20  l_panic("Adding 
1e30: 65 78 69 73 74 69 6e 67 20 74 68 72 65 61 64 21  existing thread!
1e40: 22 29 3b 0a 09 09 09 7d 0a 09 09 7d 20 65 6c 73  ");....}...} els
1e50: 65 20 7b 0a 09 09 09 69 66 20 28 30 20 3d 3d 20  e {....if (0 == 
1e60: 6d 61 70 5f 72 65 6d 6f 76 65 70 70 28 61 6c 6c  map_removepp(all
1e70: 74 68 72 65 61 64 73 2c 20 74 68 72 65 61 64 29  threads, thread)
1e80: 29 20 7b 0a 09 09 09 09 6b 65 72 6e 65 6c 5f 70  ) {.....kernel_p
1e90: 61 6e 69 63 28 22 52 65 6d 6f 76 69 6e 67 20 6e  anic("Removing n
1ea0: 6f 6e 2d 65 78 69 73 74 65 6e 74 20 74 68 72 65  on-existent thre
1eb0: 61 64 21 22 29 3b 0a 09 09 09 7d 0a 09 09 7d 0a  ad!");....}...}.
1ec0: 09 7d 0a 7d 0a 0a 2f 2a 2a 0a 20 2a 20 53 70 61  .}.}../**. * Spa
1ed0: 77 6e 20 61 20 6e 65 77 20 74 68 72 65 61 64 0a  wn a new thread.
1ee0: 20 2a 20 5c 61 72 67 20 66 20 46 75 6e 63 74 69   * \arg f Functi
1ef0: 6f 6e 20 69 6e 74 6f 20 77 68 69 63 68 20 74 68  on into which th
1f00: 65 20 6e 65 77 20 74 68 72 65 61 64 20 77 69 6c  e new thread wil
1f10: 6c 20 72 75 6e 0a 20 2a 20 5c 61 72 67 20 61 72  l run. * \arg ar
1f20: 67 20 41 72 67 75 6d 65 6e 74 20 74 6f 20 6e 65  g Argument to ne
1f30: 77 20 74 68 72 65 61 64 0a 20 2a 20 5c 72 65 74  w thread. * \ret
1f40: 75 72 6e 20 74 68 72 65 61 64 20 70 6f 69 6e 74  urn thread point
1f50: 65 72 20 74 6f 20 74 68 65 20 6e 65 77 20 74 68  er to the new th
1f60: 72 65 61 64 0a 20 2a 2f 0a 74 68 72 65 61 64 5f  read. */.thread_
1f70: 74 20 2a 20 74 68 72 65 61 64 5f 73 70 61 77 6e  t * thread_spawn
1f80: 28 74 68 72 65 61 64 5f 66 75 6e 63 5f 74 20 66  (thread_func_t f
1f90: 2c 20 76 6f 69 64 20 2a 20 61 72 67 29 0a 7b 0a  , void * arg).{.
1fa0: 09 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65  .thread_t * thre
1fb0: 61 64 20 3d 20 74 68 72 65 61 64 5f 66 6f 72 6b  ad = thread_fork
1fc0: 28 29 3b 0a 09 69 66 20 28 74 68 72 65 61 64 29  ();..if (thread)
1fd0: 20 7b 0a 09 09 72 65 74 75 72 6e 20 74 68 72 65   {...return thre
1fe0: 61 64 3b 0a 09 7d 0a 09 2f 2a 20 43 68 69 6c 64  ad;..}../* Child
1ff0: 20 74 68 72 65 61 64 20 2a 2f 0a 09 76 6f 69 64   thread */..void
2000: 20 2a 20 72 65 74 76 61 6c 20 3d 20 66 28 61 72   * retval = f(ar
2010: 67 29 3b 0a 09 74 68 72 65 61 64 5f 65 78 69 74  g);..thread_exit
2020: 28 72 65 74 76 61 6c 29 3b 0a 7d 0a 0a 2f 2a 2a  (retval);.}../**
2030: 0a 20 2a 20 46 6f 72 6b 20 74 68 65 20 63 75 72  . * Fork the cur
2040: 72 65 6e 74 20 74 68 72 65 61 64 2c 20 69 6e 74  rent thread, int
2050: 6f 20 61 20 6e 65 77 20 74 68 72 65 61 64 0a 20  o a new thread. 
2060: 2a 0a 20 2a 20 46 6f 72 6b 20 74 68 65 20 63 75  *. * Fork the cu
2070: 72 72 65 6e 74 20 74 68 72 65 61 64 2c 20 72 65  rrent thread, re
2080: 74 75 72 6e 69 6e 67 20 74 68 65 20 6e 65 77 20  turning the new 
2090: 74 68 72 65 61 64 20 70 6f 69 6e 74 65 72 20 74  thread pointer t
20a0: 6f 20 74 68 65 0a 20 2a 20 63 72 65 61 74 6f 72  o the. * creator
20b0: 20 74 68 72 65 61 64 2c 20 61 6e 64 20 30 20 74   thread, and 0 t
20c0: 6f 20 74 68 65 20 63 72 65 61 74 65 64 20 74 68  o the created th
20d0: 72 65 61 64 2e 0a 20 2a 0a 20 2a 20 54 68 65 20  read.. *. * The 
20e0: 63 72 65 61 74 65 64 20 74 68 72 65 61 64 20 69  created thread i
20f0: 73 20 61 20 63 6f 70 79 20 6f 66 20 74 68 65 20  s a copy of the 
2100: 63 72 65 61 74 6f 72 20 74 68 72 65 61 64 2c 20  creator thread, 
2110: 77 69 74 68 20 74 68 65 20 73 61 6d 65 20 63 61  with the same ca
2120: 6c 6c 20 63 68 61 69 6e 2e 0a 20 2a 0a 20 2a 20  ll chain.. *. * 
2130: 41 75 74 6f 6d 61 74 69 63 20 76 61 72 69 61 62  Automatic variab
2140: 6c 65 73 20 74 68 61 74 20 63 6f 6e 74 61 69 6e  les that contain
2150: 20 70 6f 69 6e 74 65 72 73 20 74 6f 20 6c 6f 63   pointers to loc
2160: 61 74 69 6f 6e 73 20 69 6e 20 74 68 65 20 63 72  ations in the cr
2170: 65 61 74 6f 72 20 73 74 61 63 6b 20 61 72 65 0a  eator stack are.
2180: 20 2a 20 74 72 61 6e 73 66 6f 72 6d 65 64 20 74   * transformed t
2190: 6f 20 70 6f 69 6e 74 20 74 6f 20 74 68 65 20 65  o point to the e
21a0: 71 75 69 76 61 6c 65 6e 74 20 6c 6f 63 61 74 69  quivalent locati
21b0: 6f 6e 73 20 69 6e 20 74 68 65 20 63 72 65 61 74  ons in the creat
21c0: 65 64 20 73 74 61 63 6b 2e 0a 20 2a 20 5c 72 65  ed stack.. * \re
21d0: 74 75 72 6e 20 74 68 72 65 61 64 20 70 6f 69 6e  turn thread poin
21e0: 74 65 72 20 74 6f 20 74 68 65 20 6e 65 77 20 74  ter to the new t
21f0: 68 72 65 61 64 20 69 6e 20 74 68 65 20 63 72 65  hread in the cre
2200: 61 74 6f 72 2c 20 6f 72 20 30 20 69 6e 20 74 68  ator, or 0 in th
2210: 65 20 6e 65 77 20 74 68 72 65 61 64 0a 20 2a 2f  e new thread. */
2220: 0a 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65  .thread_t * thre
2230: 61 64 5f 66 6f 72 6b 28 29 0a 7b 0a 09 74 68 72  ad_fork().{..thr
2240: 65 61 64 5f 74 20 2a 20 74 68 69 73 20 3d 20 61  ead_t * this = a
2250: 72 63 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29  rch_get_thread()
2260: 3b 0a 09 74 68 72 65 61 64 5f 74 20 2a 20 74 68  ;..thread_t * th
2270: 72 65 61 64 20 3d 20 73 6c 61 62 5f 63 61 6c 6c  read = slab_call
2280: 6f 63 28 74 68 72 65 61 64 73 29 3b 0a 0a 09 74  oc(threads);...t
2290: 68 72 65 61 64 2d 3e 70 72 69 6f 72 69 74 79 20  hread->priority 
22a0: 3d 20 74 68 69 73 2d 3e 70 72 69 6f 72 69 74 79  = this->priority
22b0: 3b 0a 09 74 68 72 65 61 64 2d 3e 70 72 6f 63 65  ;..thread->proce
22c0: 73 73 20 3d 20 74 68 69 73 2d 3e 70 72 6f 63 65  ss = this->proce
22d0: 73 73 3b 0a 09 63 68 61 72 20 62 75 66 5b 33 32  ss;..char buf[32
22e0: 5d 3b 0a 09 73 6e 70 72 69 6e 74 66 28 20 62 75  ];..snprintf( bu
22f0: 66 2c 20 73 69 7a 65 6f 66 28 62 75 66 29 2c 20  f, sizeof(buf), 
2300: 22 43 68 69 6c 64 20 6f 66 20 25 70 22 2c 20 74  "Child of %p", t
2310: 68 69 73 29 3b 0a 09 74 68 72 65 61 64 5f 73 65  his);..thread_se
2320: 74 5f 6e 61 6d 65 28 74 68 72 65 61 64 2c 20 73  t_name(thread, s
2330: 74 72 6e 64 75 70 28 62 75 66 2c 20 73 69 7a 65  trndup(buf, size
2340: 6f 66 28 62 75 66 29 29 29 3b 0a 0a 09 69 66 20  of(buf)));...if 
2350: 28 30 20 3d 3d 20 61 72 63 68 5f 74 68 72 65 61  (0 == arch_threa
2360: 64 5f 66 6f 72 6b 28 74 68 72 65 61 64 29 29 20  d_fork(thread)) 
2370: 7b 0a 09 09 72 65 74 75 72 6e 20 30 3b 0a 09 7d  {...return 0;..}
2380: 0a 0a 09 74 68 72 65 61 64 5f 74 72 61 63 6b 28  ...thread_track(
2390: 74 68 72 65 61 64 2c 20 31 29 3b 0a 09 74 68 72  thread, 1);..thr
23a0: 65 61 64 5f 72 65 73 75 6d 65 28 74 68 72 65 61  ead_resume(threa
23b0: 64 29 3b 0a 0a 09 72 65 74 75 72 6e 20 74 68 72  d);...return thr
23c0: 65 61 64 3b 0a 7d 0a 0a 2f 2a 2a 0a 20 2a 20 45  ead;.}../**. * E
23d0: 78 69 74 20 74 68 65 20 63 75 72 72 65 6e 74 20  xit the current 
23e0: 74 68 72 65 61 64 2e 0a 20 2a 0a 20 2a 20 45 78  thread.. *. * Ex
23f0: 69 74 20 74 68 65 20 63 75 72 72 65 6e 74 20 74  it the current t
2400: 68 72 65 61 64 2e 20 54 68 69 73 20 66 75 6e 63  hread. This func
2410: 74 69 6f 6e 20 6e 65 76 65 72 20 72 65 74 75 72  tion never retur
2420: 6e 73 2e 0a 20 2a 20 5c 61 72 67 20 72 65 74 76  ns.. * \arg retv
2430: 61 6c 20 52 65 74 75 72 6e 20 76 61 6c 75 65 20  al Return value 
2440: 72 65 74 75 72 6e 65 64 20 74 6f 20 74 68 65 20  returned to the 
2450: 63 61 6c 6c 65 72 20 6f 66 20 5c 72 65 66 20 74  caller of \ref t
2460: 68 72 65 61 64 5f 6a 6f 69 6e 2e 0a 20 2a 2f 0a  hread_join.. */.
2470: 6e 6f 72 65 74 75 72 6e 20 76 6f 69 64 20 74 68  noreturn void th
2480: 72 65 61 64 5f 65 78 69 74 28 76 6f 69 64 20 2a  read_exit(void *
2490: 20 72 65 74 76 61 6c 29 0a 7b 0a 09 74 68 72 65   retval).{..thre
24a0: 61 64 5f 74 20 2a 20 74 68 69 73 20 3d 20 61 72  ad_t * this = ar
24b0: 63 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29 3b  ch_get_thread();
24c0: 0a 0a 09 74 68 69 73 2d 3e 72 65 74 76 61 6c 20  ...this->retval 
24d0: 3d 20 72 65 74 76 61 6c 3b 0a 09 74 68 69 73 2d  = retval;..this-
24e0: 3e 73 74 61 74 65 20 3d 20 54 48 52 45 41 44 5f  >state = THREAD_
24f0: 54 45 52 4d 49 4e 41 54 45 44 3b 0a 0a 09 2f 2a  TERMINATED;.../*
2500: 20 53 69 67 6e 69 66 79 20 74 6f 20 61 6e 79 20   Signify to any 
2510: 74 68 72 65 61 64 73 20 77 61 69 74 69 6e 67 20  threads waiting 
2520: 6f 6e 20 74 68 69 73 20 74 68 72 65 61 64 20 2a  on this thread *
2530: 2f 0a 09 4d 4f 4e 49 54 4f 52 5f 41 55 54 4f 4c  /..MONITOR_AUTOL
2540: 4f 43 4b 28 74 68 69 73 2d 3e 6c 6f 63 6b 29 20  OCK(this->lock) 
2550: 7b 0a 09 09 6d 6f 6e 69 74 6f 72 5f 62 72 6f 61  {...monitor_broa
2560: 64 63 61 73 74 28 74 68 69 73 2d 3e 6c 6f 63 6b  dcast(this->lock
2570: 29 3b 0a 09 7d 0a 0a 09 2f 2a 20 52 65 6d 6f 76  );..}.../* Remov
2580: 65 20 74 68 69 73 20 74 68 72 65 61 64 20 66 72  e this thread fr
2590: 6f 6d 20 74 68 65 20 73 65 74 20 6f 66 20 70 72  om the set of pr
25a0: 6f 63 65 73 73 20 74 68 72 65 61 64 73 20 2a 2f  ocess threads */
25b0: 0a 09 69 66 20 28 74 68 69 73 2d 3e 70 72 6f 63  ..if (this->proc
25c0: 65 73 73 29 20 7b 0a 09 09 4d 4f 4e 49 54 4f 52  ess) {...MONITOR
25d0: 5f 41 55 54 4f 4c 4f 43 4b 28 26 74 68 69 73 2d  _AUTOLOCK(&this-
25e0: 3e 70 72 6f 63 65 73 73 2d 3e 6c 6f 63 6b 29 20  >process->lock) 
25f0: 7b 0a 09 09 09 6d 61 70 5f 72 65 6d 6f 76 65 70  {....map_removep
2600: 70 28 74 68 69 73 2d 3e 70 72 6f 63 65 73 73 2d  p(this->process-
2610: 3e 74 68 72 65 61 64 73 2c 20 74 68 69 73 29 3b  >threads, this);
2620: 0a 09 09 7d 0a 09 7d 0a 0a 09 74 68 69 73 2d 3e  ...}..}...this->
2630: 70 72 6f 63 65 73 73 20 3d 20 30 3b 0a 0a 09 2f  process = 0;.../
2640: 2a 20 52 65 6d 6f 76 65 20 74 68 69 73 20 74 68  * Remove this th
2650: 72 65 61 64 20 66 72 6f 6d 20 74 68 65 20 73 65  read from the se
2660: 74 20 6f 66 20 61 6c 6c 20 74 68 72 65 61 64 73  t of all threads
2670: 20 2a 2f 0a 09 74 68 72 65 61 64 5f 74 72 61 63   */..thread_trac
2680: 6b 28 74 68 69 73 2c 20 30 29 3b 0a 0a 09 2f 2a  k(this, 0);.../*
2690: 20 53 63 68 65 64 75 6c 65 20 74 68 65 20 6e 65   Schedule the ne
26a0: 78 74 20 74 68 72 65 61 64 20 2a 2f 0a 09 73 63  xt thread */..sc
26b0: 68 65 64 75 6c 65 72 5f 6c 6f 63 6b 28 29 3b 0a  heduler_lock();.
26c0: 09 74 68 72 65 61 64 5f 73 63 68 65 64 75 6c 65  .thread_schedule
26d0: 28 29 3b 0a 09 6b 65 72 6e 65 6c 5f 70 61 6e 69  ();..kernel_pani
26e0: 63 28 22 74 68 72 65 61 64 5f 65 78 69 74 3a 20  c("thread_exit: 
26f0: 53 68 6f 75 6c 64 20 6e 65 76 65 72 20 67 65 74  Should never get
2700: 20 68 65 72 65 5c 6e 22 29 3b 0a 7d 0a 0a 2f 2a   here\n");.}../*
2710: 2a 0a 20 2a 20 47 65 74 20 72 65 74 75 72 6e 20  *. * Get return 
2720: 63 6f 64 65 20 66 72 6f 6d 20 67 69 76 65 6e 20  code from given 
2730: 74 68 72 65 61 64 2e 0a 20 2a 0a 20 2a 20 47 65  thread.. *. * Ge
2740: 74 20 72 65 74 75 72 6e 20 63 6f 64 65 20 66 72  t return code fr
2750: 6f 6d 20 67 69 76 65 6e 20 74 68 72 65 61 64 2e  om given thread.
2760: 20 49 66 20 74 68 65 20 74 68 72 65 61 64 20 68   If the thread h
2770: 61 73 20 6e 6f 74 20 79 65 74 20 65 78 69 74 65  as not yet exite
2780: 64 2c 0a 20 2a 20 74 68 65 20 63 75 72 72 65 6e  d,. * the curren
2790: 74 20 74 68 72 65 61 64 20 77 69 6c 6c 20 73 6c  t thread will sl
27a0: 65 65 70 20 77 61 69 74 69 6e 67 20 66 6f 72 20  eep waiting for 
27b0: 74 68 65 20 74 68 72 65 61 64 20 74 6f 20 65 78  the thread to ex
27c0: 69 74 2e 0a 20 2a 0a 20 2a 20 5c 61 72 67 20 74  it.. *. * \arg t
27d0: 68 72 65 61 64 20 54 68 72 65 61 64 20 74 6f 20  hread Thread to 
27e0: 67 65 74 20 72 65 74 75 72 6e 20 63 6f 64 65 20  get return code 
27f0: 66 72 6f 6d 2e 0a 20 2a 20 5c 72 65 74 75 72 6e  from.. * \return
2800: 20 52 65 74 75 72 6e 20 63 6f 64 65 20 61 73 20   Return code as 
2810: 70 61 73 73 65 64 20 74 6f 20 5c 72 65 66 20 74  passed to \ref t
2820: 68 72 65 61 64 5f 65 78 69 74 0a 20 2a 2f 0a 76  hread_exit. */.v
2830: 6f 69 64 20 2a 20 74 68 72 65 61 64 5f 6a 6f 69  oid * thread_joi
2840: 6e 28 74 68 72 65 61 64 5f 74 20 2a 20 74 68 72  n(thread_t * thr
2850: 65 61 64 29 0a 7b 0a 09 4d 4f 4e 49 54 4f 52 5f  ead).{..MONITOR_
2860: 41 55 54 4f 4c 4f 43 4b 28 74 68 72 65 61 64 2d  AUTOLOCK(thread-
2870: 3e 6c 6f 63 6b 29 20 7b 0a 09 09 77 68 69 6c 65  >lock) {...while
2880: 28 74 68 72 65 61 64 2d 3e 73 74 61 74 65 20 21  (thread->state !
2890: 3d 20 54 48 52 45 41 44 5f 54 45 52 4d 49 4e 41  = THREAD_TERMINA
28a0: 54 45 44 29 20 7b 0a 09 09 09 6d 6f 6e 69 74 6f  TED) {....monito
28b0: 72 5f 77 61 69 74 28 74 68 72 65 61 64 2d 3e 6c  r_wait(thread->l
28c0: 6f 63 6b 29 3b 0a 09 09 7d 0a 09 7d 0a 09 72 65  ock);...}..}..re
28d0: 74 75 72 6e 20 74 68 72 65 61 64 2d 3e 72 65 74  turn thread->ret
28e0: 76 61 6c 3b 0a 7d 0a 0a 2f 2a 2a 0a 20 2a 20 53  val;.}../**. * S
28f0: 65 74 20 74 68 65 20 70 72 69 6f 72 69 74 79 20  et the priority 
2900: 6f 66 20 74 68 65 20 67 69 76 65 6e 20 74 68 72  of the given thr
2910: 65 61 64 2e 0a 20 2a 20 5c 61 72 67 20 74 68 72  ead.. * \arg thr
2920: 65 61 64 20 54 68 72 65 61 64 20 74 6f 20 73 65  ead Thread to se
2930: 74 20 70 72 69 6f 72 69 74 79 20 6f 66 2c 20 6f  t priority of, o
2940: 72 20 63 75 72 72 65 6e 74 20 74 68 72 65 61 64  r current thread
2950: 20 69 66 20 30 2e 0a 20 2a 20 5c 61 72 67 20 70   if 0.. * \arg p
2960: 72 69 6f 72 69 74 79 20 4e 65 77 20 74 68 72 65  riority New thre
2970: 61 64 20 70 72 69 6f 72 69 74 79 2e 0a 20 2a 2f  ad priority.. */
2980: 0a 76 6f 69 64 20 74 68 72 65 61 64 5f 73 65 74  .void thread_set
2990: 5f 70 72 69 6f 72 69 74 79 28 74 68 72 65 61 64  _priority(thread
29a0: 5f 74 20 2a 20 74 68 72 65 61 64 2c 20 74 70 72  _t * thread, tpr
29b0: 69 6f 72 69 74 79 20 70 72 69 6f 72 69 74 79 29  iority priority)
29c0: 0a 7b 0a 09 63 68 65 63 6b 5f 69 6e 74 5f 62 6f  .{..check_int_bo
29d0: 75 6e 64 73 28 70 72 69 6f 72 69 74 79 2c 20 54  unds(priority, T
29e0: 48 52 45 41 44 5f 49 4e 54 45 52 52 55 50 54 2c  HREAD_INTERRUPT,
29f0: 20 54 48 52 45 41 44 5f 49 44 4c 45 2c 20 22 54   THREAD_IDLE, "T
2a00: 68 72 65 61 64 20 70 72 69 6f 72 69 74 79 20 6f  hread priority o
2a10: 75 74 20 6f 66 20 62 6f 75 6e 64 73 22 29 3b 0a  ut of bounds");.
2a20: 09 69 66 20 28 30 20 3d 3d 20 74 68 72 65 61 64  .if (0 == thread
2a30: 29 20 7b 0a 09 09 74 68 72 65 61 64 20 3d 20 61  ) {...thread = a
2a40: 72 63 68 5f 67 65 74 5f 74 68 72 65 61 64 28 29  rch_get_thread()
2a50: 3b 0a 09 7d 0a 09 74 68 72 65 61 64 2d 3e 70 72  ;..}..thread->pr
2a60: 69 6f 72 69 74 79 20 3d 20 70 72 69 6f 72 69 74  iority = priorit
2a70: 79 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 47 43 52  y;.}..static GCR
2a80: 4f 4f 54 20 76 6f 69 64 20 2a 2a 20 72 6f 6f 74  OOT void ** root
2a90: 73 3b 0a 0a 23 64 65 66 69 6e 65 20 47 43 50 52  s;..#define GCPR
2aa0: 4f 46 49 4c 45 20 31 0a 0a 23 69 66 20 47 43 50  OFILE 1..#if GCP
2ab0: 52 4f 46 49 4c 45 0a 73 74 61 74 69 63 20 74 69  ROFILE.static ti
2ac0: 6d 65 72 73 70 65 63 5f 74 20 67 63 74 69 6d 65  merspec_t gctime
2ad0: 20 3d 20 30 3b 0a 23 65 6e 64 69 66 0a 0a 2f 2a   = 0;.#endif../*
2ae0: 2a 0a 20 2a 20 52 75 6e 20 67 61 72 62 61 67 65  *. * Run garbage
2af0: 20 63 6f 6c 6c 65 63 74 69 6f 6e 2e 0a 20 2a 2f   collection.. */
2b00: 0a 76 6f 69 64 20 74 68 72 65 61 64 5f 67 63 28  .void thread_gc(
2b10: 29 0a 7b 0a 09 2f 2f 20 74 68 72 65 61 64 5f 63  ).{..// thread_c
2b20: 6c 65 61 6e 6c 6f 63 6b 73 28 29 3b 0a 23 69 66  leanlocks();.#if
2b30: 20 47 43 50 52 4f 46 49 4c 45 0a 09 74 69 6d 65   GCPROFILE..time
2b40: 72 73 70 65 63 5f 74 20 73 74 61 72 74 20 3d 20  rspec_t start = 
2b50: 74 69 6d 65 72 5f 75 70 74 69 6d 65 28 31 29 3b  timer_uptime(1);
2b60: 0a 23 65 6e 64 69 66 0a 09 73 6c 61 62 5f 67 63  .#endif..slab_gc
2b70: 5f 62 65 67 69 6e 28 29 3b 0a 09 73 6c 61 62 5f  _begin();..slab_
2b80: 67 63 28 29 3b 0a 09 73 6c 61 62 5f 67 63 5f 65  gc();..slab_gc_e
2b90: 6e 64 28 29 3b 0a 23 69 66 20 47 43 50 52 4f 46  nd();.#if GCPROF
2ba0: 49 4c 45 0a 09 73 74 61 74 69 63 20 74 69 6d 65  ILE..static time
2bb0: 72 73 70 65 63 5f 74 20 67 63 74 69 6d 65 20 3d  rspec_t gctime =
2bc0: 20 30 3b 0a 09 67 63 74 69 6d 65 20 2b 3d 20 28   0;..gctime += (
2bd0: 74 69 6d 65 72 5f 75 70 74 69 6d 65 28 31 29 20  timer_uptime(1) 
2be0: 2d 20 73 74 61 72 74 29 3b 0a 09 6b 65 72 6e 65  - start);..kerne
2bf0: 6c 5f 70 72 69 6e 74 6b 28 22 47 43 20 74 69 6d  l_printk("GC tim
2c00: 65 20 25 64 20 28 25 64 25 25 29 5c 6e 22 2c 20  e %d (%d%%)\n", 
2c10: 28 69 6e 74 29 67 63 74 69 6d 65 2c 20 28 69 6e  (int)gctime, (in
2c20: 74 29 28 31 30 30 30 20 2a 20 67 63 74 69 6d 65  t)(1000 * gctime
2c30: 20 2f 20 73 74 61 72 74 29 29 3b 0a 23 65 6e 64   / start));.#end
2c40: 69 66 0a 7d 0a 0a 2f 2a 2a 0a 20 2a 20 41 64 64  if.}../**. * Add
2c50: 20 61 20 6e 65 77 20 67 61 72 62 61 67 65 20 63   a new garbage c
2c60: 6f 6c 6c 65 63 74 69 6f 6e 20 72 6f 6f 74 2e 0a  ollection root..
2c70: 20 2a 20 5c 61 72 67 20 70 20 50 6f 69 6e 74 65   * \arg p Pointe
2c80: 72 20 74 6f 20 74 68 65 20 6e 65 77 20 72 6f 6f  r to the new roo
2c90: 74 2e 0a 20 2a 2f 0a 76 6f 69 64 20 74 68 72 65  t.. */.void thre
2ca0: 61 64 5f 67 63 5f 72 6f 6f 74 28 76 6f 69 64 20  ad_gc_root(void 
2cb0: 2a 20 70 29 0a 7b 0a 09 73 74 61 74 69 63 20 69  * p).{..static i
2cc0: 6e 74 20 72 6f 6f 74 63 6f 75 6e 74 20 3d 20 30  nt rootcount = 0
2cd0: 3b 0a 0a 09 72 6f 6f 74 73 20 3d 20 72 65 61 6c  ;...roots = real
2ce0: 6c 6f 63 28 72 6f 6f 74 73 2c 20 73 69 7a 65 6f  loc(roots, sizeo
2cf0: 66 28 2a 72 6f 6f 74 73 29 2a 28 72 6f 6f 74 63  f(*roots)*(rootc
2d00: 6f 75 6e 74 2b 31 29 29 3b 0a 09 72 6f 6f 74 73  ount+1));..roots
2d10: 5b 72 6f 6f 74 63 6f 75 6e 74 2b 2b 5d 20 3d 20  [rootcount++] = 
2d20: 70 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69  p;.}..static voi
2d30: 64 20 74 68 72 65 61 64 5f 6d 61 72 6b 28 76 6f  d thread_mark(vo
2d40: 69 64 20 2a 20 70 29 0a 7b 0a 09 74 68 72 65 61  id * p).{..threa
2d50: 64 5f 74 20 2a 20 74 68 72 65 61 64 20 3d 20 28  d_t * thread = (
2d60: 74 68 72 65 61 64 5f 74 20 2a 29 70 3b 0a 0a 09  thread_t *)p;...
2d70: 73 6c 61 62 5f 67 63 5f 6d 61 72 6b 28 74 68 72  slab_gc_mark(thr
2d80: 65 61 64 2d 3e 6e 61 6d 65 29 3b 0a 09 69 66 20  ead->name);..if 
2d90: 28 74 68 72 65 61 64 2d 3e 73 74 61 74 65 20 21  (thread->state !
2da0: 3d 20 54 48 52 45 41 44 5f 54 45 52 4d 49 4e 41  = THREAD_TERMINA
2db0: 54 45 44 29 20 7b 0a 09 09 2f 2a 20 4d 61 72 6b  TED) {.../* Mark
2dc0: 20 6c 69 76 65 20 73 74 61 74 65 20 6f 6e 6c 79   live state only
2dd0: 20 2a 2f 0a 09 09 61 72 63 68 5f 74 68 72 65 61   */...arch_threa
2de0: 64 5f 6d 61 72 6b 28 74 68 72 65 61 64 29 3b 0a  d_mark(thread);.
2df0: 09 09 73 6c 61 62 5f 67 63 5f 6d 61 72 6b 5f 62  ..slab_gc_mark_b
2e00: 6c 6f 63 6b 28 74 68 72 65 61 64 2d 3e 74 6c 73  lock(thread->tls
2e10: 2c 20 73 69 7a 65 6f 66 28 74 68 72 65 61 64 2d  , sizeof(thread-
2e20: 3e 74 6c 73 29 29 3b 0a 09 09 73 6c 61 62 5f 67  >tls));...slab_g
2e30: 63 5f 6d 61 72 6b 28 74 68 72 65 61 64 2d 3e 70  c_mark(thread->p
2e40: 72 6f 63 65 73 73 29 3b 0a 09 7d 20 65 6c 73 65  rocess);..} else
2e50: 20 7b 0a 09 09 2f 2a 20 4d 61 72 6b 20 64 65 61   {.../* Mark dea
2e60: 64 20 73 74 61 74 65 20 6f 6e 6c 79 20 2a 2f 0a  d state only */.
2e70: 09 09 73 6c 61 62 5f 67 63 5f 6d 61 72 6b 28 74  ..slab_gc_mark(t
2e80: 68 72 65 61 64 2d 3e 72 65 74 76 61 6c 29 3b 0a  hread->retval);.
2e90: 09 7d 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69  .}.}..static voi
2ea0: 64 20 74 68 72 65 61 64 5f 66 69 6e 61 6c 69 7a  d thread_finaliz
2eb0: 65 28 76 6f 69 64 20 2a 20 70 29 0a 7b 0a 09 74  e(void * p).{..t
2ec0: 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64  hread_t * thread
2ed0: 20 3d 20 28 74 68 72 65 61 64 5f 74 20 2a 29 70   = (thread_t *)p
2ee0: 3b 0a 0a 09 61 72 65 6e 61 5f 74 68 72 65 61 64  ;...arena_thread
2ef0: 5f 66 72 65 65 28 29 3b 0a 09 61 72 63 68 5f 74  _free();..arch_t
2f00: 68 72 65 61 64 5f 66 69 6e 61 6c 69 7a 65 28 74  hread_finalize(t
2f10: 68 72 65 61 64 29 3b 0a 7d 0a 0a 2f 2a 2a 0a 20  hread);.}../**. 
2f20: 2a 20 47 65 6e 65 72 61 74 65 20 61 20 66 75 6e  * Generate a fun
2f30: 63 74 69 6f 6e 20 63 61 6c 6c 20 73 74 61 63 6b  ction call stack
2f40: 20 62 61 63 6b 74 72 61 63 65 0a 20 2a 20 5c 61   backtrace. * \a
2f50: 72 67 20 62 75 66 66 65 72 20 50 6f 69 6e 74 65  rg buffer Pointe
2f60: 72 20 74 6f 20 61 72 72 61 79 20 6f 66 20 70 6f  r to array of po
2f70: 69 6e 74 65 72 73 2e 0a 20 2a 20 5c 61 72 67 20  inters.. * \arg 
2f80: 6c 65 76 65 6c 73 20 4e 75 6d 62 65 72 20 6f 66  levels Number of
2f90: 20 70 6f 69 6e 74 65 72 73 20 69 6e 20 74 68 65   pointers in the
2fa0: 20 5c 72 65 66 20 62 75 66 66 65 72 20 61 72 72   \ref buffer arr
2fb0: 61 79 2e 0a 20 2a 20 5c 72 65 74 75 72 6e 20 62  ay.. * \return b
2fc0: 75 66 66 65 72 0a 20 2a 2f 0a 76 6f 69 64 20 2a  uffer. */.void *
2fd0: 2a 20 74 68 72 65 61 64 5f 62 61 63 6b 74 72 61  * thread_backtra
2fe0: 63 65 28 76 6f 69 64 20 2a 2a 20 62 75 66 66 65  ce(void ** buffe
2ff0: 72 2c 20 69 6e 74 20 6c 65 76 65 6c 73 29 0a 7b  r, int levels).{
3000: 0a 09 72 65 74 75 72 6e 20 61 72 63 68 5f 74 68  ..return arch_th
3010: 72 65 61 64 5f 62 61 63 6b 74 72 61 63 65 28 62  read_backtrace(b
3020: 75 66 66 65 72 2c 20 6c 65 76 65 6c 73 29 3b 0a  uffer, levels);.
3030: 7d 0a 0a 76 6f 69 64 20 74 68 72 65 61 64 5f 69  }..void thread_i
3040: 6e 69 74 28 29 0a 7b 0a 09 49 4e 49 54 5f 4f 4e  nit().{..INIT_ON
3050: 43 45 28 29 3b 0a 0a 09 2f 2a 20 43 72 61 66 74  CE();.../* Craft
3060: 20 61 20 6e 65 77 20 62 6f 6f 74 73 74 72 61 70   a new bootstrap
3070: 20 74 68 72 65 61 64 20 74 6f 20 72 65 70 6c 61   thread to repla
3080: 63 65 20 74 68 65 20 73 74 61 74 69 63 20 64 65  ce the static de
3090: 66 69 6e 65 64 20 74 68 72 65 61 64 20 2a 2f 0a  fined thread */.
30a0: 09 61 72 63 68 5f 74 68 72 65 61 64 5f 69 6e 69  .arch_thread_ini
30b0: 74 28 73 6c 61 62 5f 63 61 6c 6c 6f 63 28 74 68  t(slab_calloc(th
30c0: 72 65 61 64 73 29 29 3b 0a 09 74 68 72 65 61 64  reads));..thread
30d0: 5f 74 72 61 63 6b 28 61 72 63 68 5f 67 65 74 5f  _track(arch_get_
30e0: 74 68 72 65 61 64 28 29 2c 20 31 29 3b 0a 7d 0a  thread(), 1);.}.
30f0: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 74 68 72  .static void thr
3100: 65 61 64 5f 74 65 73 74 32 28 29 3b 0a 73 74 61  ead_test2();.sta
3110: 74 69 63 20 76 6f 69 64 20 74 68 72 65 61 64 5f  tic void thread_
3120: 74 65 73 74 31 28 72 77 6c 6f 63 6b 5f 74 20 2a  test1(rwlock_t *
3130: 20 72 77 29 0a 7b 0a 09 76 6f 69 64 20 2a 2a 20   rw).{..void ** 
3140: 62 74 20 3d 20 74 68 72 65 61 64 5f 62 61 63 6b  bt = thread_back
3150: 74 72 61 63 65 28 4e 55 4c 4c 2c 20 31 35 29 3b  trace(NULL, 15);
3160: 0a 09 6b 65 72 6e 65 6c 5f 70 72 69 6e 74 6b 28  ..kernel_printk(
3170: 22 74 68 72 65 61 64 5f 74 65 73 74 31 5c 6e 22  "thread_test1\n"
3180: 29 3b 0a 09 77 68 69 6c 65 28 2a 62 74 29 20 7b  );..while(*bt) {
3190: 0a 09 09 6b 65 72 6e 65 6c 5f 70 72 69 6e 74 6b  ...kernel_printk
31a0: 28 22 5c 74 25 70 5c 6e 22 2c 20 2a 62 74 2b 2b  ("\t%p\n", *bt++
31b0: 29 3b 0a 09 7d 0a 0a 09 72 77 6c 6f 63 6b 5f 65  );..}...rwlock_e
31c0: 73 63 61 6c 61 74 65 28 72 77 29 3b 0a 09 72 77  scalate(rw);..rw
31d0: 6c 6f 63 6b 5f 72 65 61 64 28 72 77 29 3b 0a 09  lock_read(rw);..
31e0: 72 77 6c 6f 63 6b 5f 75 6e 6c 6f 63 6b 28 72 77  rwlock_unlock(rw
31f0: 29 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69  );.}..static voi
3200: 64 20 74 68 72 65 61 64 5f 74 65 73 74 32 28 72  d thread_test2(r
3210: 77 6c 6f 63 6b 5f 74 20 2a 20 72 77 29 0a 7b 0a  wlock_t * rw).{.
3220: 09 76 6f 69 64 20 2a 2a 20 62 74 20 3d 20 74 68  .void ** bt = th
3230: 72 65 61 64 5f 62 61 63 6b 74 72 61 63 65 28 4e  read_backtrace(N
3240: 55 4c 4c 2c 20 31 35 29 3b 0a 09 6b 65 72 6e 65  ULL, 15);..kerne
3250: 6c 5f 70 72 69 6e 74 6b 28 22 74 68 72 65 61 64  l_printk("thread
3260: 5f 74 65 73 74 32 5c 6e 22 29 3b 0a 09 77 68 69  _test2\n");..whi
3270: 6c 65 28 2a 62 74 29 20 7b 0a 09 09 6b 65 72 6e  le(*bt) {...kern
3280: 65 6c 5f 70 72 69 6e 74 6b 28 22 5c 74 25 70 5c  el_printk("\t%p\
3290: 6e 22 2c 20 2a 62 74 2b 2b 29 3b 0a 09 7d 0a 09  n", *bt++);..}..
32a0: 72 77 6c 6f 63 6b 5f 75 6e 6c 6f 63 6b 28 72 77  rwlock_unlock(rw
32b0: 29 3b 0a 09 72 77 6c 6f 63 6b 5f 77 72 69 74 65  );..rwlock_write
32c0: 28 72 77 29 3b 0a 09 72 77 6c 6f 63 6b 5f 75 6e  (rw);..rwlock_un
32d0: 6c 6f 63 6b 28 72 77 29 3b 0a 7d 0a 0a 73 74 61  lock(rw);.}..sta
32e0: 74 69 63 20 76 6f 69 64 20 74 68 72 65 61 64 5f  tic void thread_
32f0: 75 70 64 61 74 65 5f 61 63 63 74 28 63 6f 6e 73  update_acct(cons
3300: 74 20 76 6f 69 64 20 2a 20 63 6f 6e 73 74 20 70  t void * const p
3310: 2c 20 76 6f 69 64 20 2a 20 6b 65 79 2c 20 76 6f  , void * key, vo
3320: 69 64 20 2a 20 64 61 74 61 29 0a 7b 0a 09 63 6f  id * data).{..co
3330: 6e 73 74 20 74 69 6d 65 72 73 70 65 63 5f 74 20  nst timerspec_t 
3340: 2a 70 75 70 74 69 6d 65 20 3d 20 70 3b 0a 09 74  *puptime = p;..t
3350: 68 72 65 61 64 5f 74 20 2a 20 74 68 72 65 61 64  hread_t * thread
3360: 20 3d 20 6b 65 79 3b 0a 09 69 66 20 28 74 68 72   = key;..if (thr
3370: 65 61 64 20 3d 3d 20 61 72 63 68 5f 67 65 74 5f  ead == arch_get_
3380: 74 68 72 65 61 64 28 29 29 20 7b 0a 09 09 74 68  thread()) {...th
3390: 72 65 61 64 2d 3e 61 63 63 74 73 5b 74 68 72 65  read->accts[thre
33a0: 61 64 2d 3e 61 63 63 74 5d 2e 74 6c 65 6e 20 3d  ad->acct].tlen =
33b0: 20 28 2a 70 75 70 74 69 6d 65 29 20 2d 20 74 68   (*puptime) - th
33c0: 72 65 61 64 2d 3e 61 63 63 74 73 5b 74 68 72 65  read->accts[thre
33d0: 61 64 2d 3e 61 63 63 74 5d 2e 74 73 74 61 72 74  ad->acct].tstart
33e0: 3b 0a 09 09 74 68 72 65 61 64 2d 3e 61 63 63 74  ;...thread->acct
33f0: 2b 2b 3b 0a 09 09 69 66 20 28 73 69 7a 65 6f 66  ++;...if (sizeof
3400: 28 74 68 72 65 61 64 2d 3e 61 63 63 74 73 29 2f  (thread->accts)/
3410: 73 69 7a 65 6f 66 28 74 68 72 65 61 64 2d 3e 61  sizeof(thread->a
3420: 63 63 74 73 5b 30 5d 29 20 3d 3d 20 74 68 72 65  ccts[0]) == thre
3430: 61 64 2d 3e 61 63 63 74 29 20 7b 0a 09 09 09 74  ad->acct) {....t
3440: 68 72 65 61 64 2d 3e 61 63 63 74 20 3d 20 30 3b  hread->acct = 0;
3450: 0a 09 09 7d 0a 09 7d 0a 09 74 69 6d 65 72 73 70  ...}..}..timersp
3460: 65 63 5f 74 20 73 75 6d 20 3d 20 30 3b 0a 09 74  ec_t sum = 0;..t
3470: 69 6d 65 72 73 70 65 63 5f 74 20 66 72 6f 6d 20  imerspec_t from 
3480: 3d 20 28 2a 70 75 70 74 69 6d 65 29 20 2d 20 31  = (*puptime) - 1
3490: 30 30 30 30 30 30 3b 0a 09 66 6f 72 28 69 6e 74  000000;..for(int
34a0: 20 69 3d 30 3b 20 69 3c 63 6f 75 6e 74 6f 66 28   i=0; i<countof(
34b0: 74 68 72 65 61 64 2d 3e 61 63 63 74 73 29 3b 20  thread->accts); 
34c0: 69 2b 2b 29 20 7b 0a 09 09 74 69 6d 65 72 73 70  i++) {...timersp
34d0: 65 63 5f 74 20 61 63 63 74 73 74 61 72 74 20 3d  ec_t acctstart =
34e0: 20 74 68 72 65 61 64 2d 3e 61 63 63 74 73 5b 69   thread->accts[i
34f0: 5d 2e 74 73 74 61 72 74 3b 0a 09 09 74 69 6d 65  ].tstart;...time
3500: 72 73 70 65 63 5f 74 20 61 63 63 74 65 6e 64 20  rspec_t acctend 
3510: 3d 20 61 63 63 74 73 74 61 72 74 20 2b 20 74 68  = acctstart + th
3520: 72 65 61 64 2d 3e 61 63 63 74 73 5b 69 5d 2e 74  read->accts[i].t
3530: 6c 65 6e 3b 0a 09 09 69 66 20 28 61 63 63 74 73  len;...if (accts
3540: 74 61 72 74 20 3e 20 66 72 6f 6d 29 20 7b 0a 09  tart > from) {..
3550: 09 09 73 75 6d 20 2b 3d 20 28 61 63 63 74 65 6e  ..sum += (accten
3560: 64 20 2d 20 61 63 63 74 73 74 61 72 74 29 3b 0a  d - acctstart);.
3570: 09 09 7d 20 65 6c 73 65 20 69 66 20 28 61 63 63  ..} else if (acc
3580: 74 65 6e 64 20 3e 20 66 72 6f 6d 29 20 7b 0a 09  tend > from) {..
3590: 09 09 73 75 6d 20 2b 3d 20 28 61 63 63 74 65 6e  ..sum += (accten
35a0: 64 20 2d 20 66 72 6f 6d 29 3b 0a 09 09 7d 0a 09  d - from);...}..
35b0: 7d 0a 09 74 68 72 65 61 64 2d 3e 75 73 61 67 65  }..thread->usage
35c0: 20 3d 20 73 75 6d 3b 0a 0a 09 69 6e 74 20 70 65   = sum;...int pe
35d0: 72 63 65 6e 74 20 3d 20 31 30 30 20 2a 20 74 68  rcent = 100 * th
35e0: 72 65 61 64 2d 3e 75 73 61 67 65 20 2f 20 31 30  read->usage / 10
35f0: 30 30 30 30 30 3b 0a 09 6b 65 72 6e 65 6c 5f 70  00000;..kernel_p
3600: 72 69 6e 74 6b 28 22 25 73 3a 20 25 64 5c 6e 22  rintk("%s: %d\n"
3610: 2c 20 74 68 72 65 61 64 2d 3e 6e 61 6d 65 20 3f  , thread->name ?
3620: 20 74 68 72 65 61 64 2d 3e 6e 61 6d 65 20 3a 20   thread->name : 
3630: 22 55 6e 6b 6e 6f 77 6e 22 2c 20 70 65 72 63 65  "Unknown", perce
3640: 6e 74 29 3b 0a 7d 0a 0a 74 79 70 65 64 65 66 20  nt);.}..typedef 
3650: 73 74 72 75 63 74 20 74 68 72 65 61 64 5f 70 6f  struct thread_po
3660: 6f 6c 5f 72 65 71 75 65 73 74 5f 74 20 74 68 72  ol_request_t thr
3670: 65 61 64 5f 70 6f 6f 6c 5f 72 65 71 75 65 73 74  ead_pool_request
3680: 5f 74 3b 0a 73 74 72 75 63 74 20 74 68 72 65 61  _t;.struct threa
3690: 64 5f 70 6f 6f 6c 5f 72 65 71 75 65 73 74 5f 74  d_pool_request_t
36a0: 20 7b 0a 09 76 6f 69 64 20 28 2a 66 75 6e 63 74   {..void (*funct
36b0: 69 6f 6e 29 28 76 6f 69 64 20 2a 20 61 72 67 29  ion)(void * arg)
36c0: 3b 0a 09 76 6f 69 64 20 2a 20 61 72 67 3b 0a 7d  ;..void * arg;.}
36d0: 3b 0a 0a 76 6f 69 64 20 2a 20 74 68 72 65 61 64  ;..void * thread
36e0: 5f 70 6f 6f 6c 5f 70 72 6f 63 65 73 73 6f 72 28  _pool_processor(
36f0: 76 6f 69 64 20 2a 20 70 29 0a 7b 0a 09 74 68 72  void * p).{..thr
3700: 65 61 64 5f 70 6f 6f 6c 5f 74 20 2a 20 70 6f 6f  ead_pool_t * poo
3710: 6c 20 3d 20 70 3b 0a 09 77 68 69 6c 65 28 31 29  l = p;..while(1)
3720: 20 7b 0a 09 09 74 68 72 65 61 64 5f 70 6f 6f 6c   {...thread_pool
3730: 5f 72 65 71 75 65 73 74 5f 74 20 2a 20 72 65 71  _request_t * req
3740: 75 65 73 74 20 3d 20 71 75 65 75 65 5f 67 65 74  uest = queue_get
3750: 70 28 70 6f 6f 6c 2d 3e 71 75 65 75 65 29 3b 0a  p(pool->queue);.
3760: 09 09 4b 54 52 59 20 7b 0a 09 09 09 72 65 71 75  ..KTRY {....requ
3770: 65 73 74 2d 3e 66 75 6e 63 74 69 6f 6e 28 72 65  est->function(re
3780: 71 75 65 73 74 2d 3e 61 72 67 29 3b 0a 09 09 7d  quest->arg);...}
3790: 20 4b 43 41 54 43 48 28 54 68 72 6f 77 61 62 6c   KCATCH(Throwabl
37a0: 65 29 20 7b 0a 09 09 09 65 78 63 65 70 74 69 6f  e) {....exceptio
37b0: 6e 5f 6c 6f 67 28 29 3b 0a 09 09 7d 0a 09 7d 0a  n_log();...}..}.
37c0: 7d 0a 0a 74 68 72 65 61 64 5f 70 6f 6f 6c 5f 74  }..thread_pool_t
37d0: 20 2a 20 74 68 72 65 61 64 5f 70 6f 6f 6c 5f 63   * thread_pool_c
37e0: 72 65 61 74 65 28 29 0a 7b 0a 09 74 68 72 65 61  reate().{..threa
37f0: 64 5f 70 6f 6f 6c 5f 74 20 2a 20 70 6f 6f 6c 20  d_pool_t * pool 
3800: 3d 20 63 61 6c 6c 6f 63 28 31 2c 20 73 69 7a 65  = calloc(1, size
3810: 6f 66 28 2a 70 6f 6f 6c 29 29 3b 0a 09 70 6f 6f  of(*pool));..poo
3820: 6c 2d 3e 71 75 65 75 65 20 3d 20 71 75 65 75 65  l->queue = queue
3830: 5f 6e 65 77 28 31 36 29 3b 0a 09 70 6f 6f 6c 2d  _new(16);..pool-
3840: 3e 74 68 72 65 61 64 20 3d 20 74 68 72 65 61 64  >thread = thread
3850: 5f 73 70 61 77 6e 28 74 68 72 65 61 64 5f 70 6f  _spawn(thread_po
3860: 6f 6c 5f 70 72 6f 63 65 73 73 6f 72 2c 20 70 6f  ol_processor, po
3870: 6f 6c 29 3b 0a 0a 09 72 65 74 75 72 6e 20 70 6f  ol);...return po
3880: 6f 6c 3b 0a 7d 0a 0a 76 6f 69 64 20 74 68 72 65  ol;.}..void thre
3890: 61 64 5f 70 6f 6f 6c 5f 73 75 62 6d 69 74 28 74  ad_pool_submit(t
38a0: 68 72 65 61 64 5f 70 6f 6f 6c 5f 74 20 2a 20 70  hread_pool_t * p
38b0: 6f 6f 6c 2c 20 76 6f 69 64 20 28 2a 66 75 6e 63  ool, void (*func
38c0: 74 69 6f 6e 29 28 76 6f 69 64 20 2a 20 61 72 67  tion)(void * arg
38d0: 29 2c 20 76 6f 69 64 20 2a 20 61 72 67 29 0a 7b  ), void * arg).{
38e0: 0a 09 73 74 61 74 69 63 20 47 43 52 4f 4f 54 20  ..static GCROOT 
38f0: 74 68 72 65 61 64 5f 70 6f 6f 6c 5f 74 20 2a 20  thread_pool_t * 
3900: 64 65 66 61 75 6c 74 70 6f 6f 6c 3b 0a 0a 09 69  defaultpool;...i
3910: 66 20 28 30 20 3d 3d 20 70 6f 6f 6c 29 20 7b 0a  f (0 == pool) {.
3920: 09 09 69 66 20 28 64 65 66 61 75 6c 74 70 6f 6f  ..if (defaultpoo
3930: 6c 20 3d 3d 20 30 29 20 7b 0a 09 09 09 64 65 66  l == 0) {....def
3940: 61 75 6c 74 70 6f 6f 6c 20 3d 20 74 68 72 65 61  aultpool = threa
3950: 64 5f 70 6f 6f 6c 5f 63 72 65 61 74 65 28 29 3b  d_pool_create();
3960: 0a 09 09 7d 0a 09 09 70 6f 6f 6c 20 3d 20 64 65  ...}...pool = de
3970: 66 61 75 6c 74 70 6f 6f 6c 3b 0a 09 7d 0a 0a 09  faultpool;..}...
3980: 74 68 72 65 61 64 5f 70 6f 6f 6c 5f 72 65 71 75  thread_pool_requ
3990: 65 73 74 5f 74 20 72 65 71 75 65 73 74 20 3d 20  est_t request = 
39a0: 7b 2e 66 75 6e 63 74 69 6f 6e 20 3d 20 66 75 6e  {.function = fun
39b0: 63 74 69 6f 6e 2c 20 2e 61 72 67 20 3d 20 61 72  ction, .arg = ar
39c0: 67 7d 3b 0a 0a 09 71 75 65 75 65 5f 70 75 74 70  g};...queue_putp
39d0: 28 70 6f 6f 6c 2d 3e 71 75 65 75 65 2c 20 6d 63  (pool->queue, mc
39e0: 6c 6f 6e 65 28 26 72 65 71 75 65 73 74 29 29 3b  lone(&request));
39f0: 0a 7d 0a 0a 76 6f 69 64 20 74 68 72 65 61 64 5f  .}..void thread_
3a00: 75 70 64 61 74 65 5f 61 63 63 74 73 28 29 0a 7b  update_accts().{
3a10: 0a 09 53 50 49 4e 5f 41 55 54 4f 4c 4f 43 4b 28  ..SPIN_AUTOLOCK(
3a20: 26 61 6c 6c 74 68 72 65 61 64 73 6c 6f 63 6b 29  &allthreadslock)
3a30: 20 7b 0a 09 09 74 69 6d 65 72 73 70 65 63 5f 74   {...timerspec_t
3a40: 20 75 70 74 69 6d 65 20 3d 20 74 69 6d 65 72 5f   uptime = timer_
3a50: 75 70 74 69 6d 65 28 31 29 3b 0a 09 09 69 66 20  uptime(1);...if 
3a60: 28 61 6c 6c 74 68 72 65 61 64 73 29 20 7b 0a 09  (allthreads) {..
3a70: 09 09 6d 61 70 5f 77 61 6c 6b 70 70 28 61 6c 6c  ..map_walkpp(all
3a80: 74 68 72 65 61 64 73 2c 20 74 68 72 65 61 64 5f  threads, thread_
3a90: 75 70 64 61 74 65 5f 61 63 63 74 2c 20 26 75 70  update_acct, &up
3aa0: 74 69 6d 65 29 3b 0a 09 09 7d 0a 09 7d 0a 7d 0a  time);...}..}.}.
3ab0: 0a 76 6f 69 64 20 74 68 72 65 61 64 5f 74 65 73  .void thread_tes
3ac0: 74 28 29 0a 7b 0a 09 74 68 72 65 61 64 5f 74 20  t().{..thread_t 
3ad0: 2a 20 74 68 72 65 61 64 31 3b 0a 0a 09 74 68 72  * thread1;...thr
3ae0: 65 61 64 31 20 3d 20 74 68 72 65 61 64 5f 66 6f  ead1 = thread_fo
3af0: 72 6b 28 29 3b 0a 09 69 66 20 28 74 68 72 65 61  rk();..if (threa
3b00: 64 31 29 20 7b 0a 09 09 74 68 72 65 61 64 5f 6a  d1) {...thread_j
3b10: 6f 69 6e 28 74 68 72 65 61 64 31 29 3b 0a 09 09  oin(thread1);...
3b20: 74 68 72 65 61 64 31 20 3d 20 30 3b 0a 09 7d 20  thread1 = 0;..} 
3b30: 65 6c 73 65 20 7b 0a 09 09 73 74 61 74 69 63 20  else {...static 
3b40: 72 77 6c 6f 63 6b 5f 74 20 72 77 5b 31 5d 20 3d  rwlock_t rw[1] =
3b50: 20 7b 30 7d 3b 0a 09 09 74 68 72 65 61 64 5f 74   {0};...thread_t
3b60: 20 2a 20 74 68 72 65 61 64 32 20 3d 20 74 68 72   * thread2 = thr
3b70: 65 61 64 5f 66 6f 72 6b 28 29 3b 0a 09 09 72 77  ead_fork();...rw
3b80: 6c 6f 63 6b 5f 72 65 61 64 28 72 77 29 3b 0a 09  lock_read(rw);..
3b90: 09 69 66 20 28 74 68 72 65 61 64 32 29 20 7b 0a  .if (thread2) {.
3ba0: 09 09 09 74 68 72 65 61 64 5f 74 65 73 74 31 28  ...thread_test1(
3bb0: 72 77 29 3b 0a 09 09 09 74 68 72 65 61 64 5f 6a  rw);....thread_j
3bc0: 6f 69 6e 28 74 68 72 65 61 64 32 29 3b 0a 09 09  oin(thread2);...
3bd0: 09 74 68 72 65 61 64 32 20 3d 20 30 3b 0a 09 09  .thread2 = 0;...
3be0: 09 74 68 72 65 61 64 5f 65 78 69 74 28 30 29 3b  .thread_exit(0);
3bf0: 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 74  ...} else {....t
3c00: 68 72 65 61 64 5f 74 65 73 74 32 28 72 77 29 3b  hread_test2(rw);
3c10: 0a 09 09 09 74 68 72 65 61 64 5f 65 78 69 74 28  ....thread_exit(
3c20: 30 29 3b 0a 09 09 7d 0a 09 7d 0a 7d 0a           0);...}..}.}.