thread_swap.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. *
  28. * File: kern/thread_swap.c
  29. * Author: Avadis Tevanian, Jr.
  30. * Date: 1987
  31. *
  32. * Mach thread swapper:
  33. * Find idle threads to swap, freeing up kernel stack resources
  34. * at the expense of allowing them to execute.
  35. *
  36. * Swap in threads that need to be run. This is done here
  37. * by the swapper thread since it cannot be done (in general)
  38. * when the kernel tries to place a thread on a run queue.
  39. *
  40. * Note: The act of swapping a thread in Mach does not mean that
  41. * its memory gets forcibly swapped to secondary storage. The memory
  42. * for the task corresponding to a swapped thread is paged out
  43. * through the normal paging mechanism.
  44. *
  45. */
  46. #include <ipc/ipc_kmsg.h>
  47. #include <kern/counters.h>
  48. #include <kern/debug.h>
  49. #include <kern/thread.h>
  50. #include <kern/lock.h>
  51. #include <vm/vm_map.h>
  52. #include <vm/vm_kern.h>
  53. #include <mach/vm_param.h>
  54. #include <kern/sched_prim.h>
  55. #include <kern/processor.h>
  56. #include <kern/thread_swap.h>
  57. #include <machine/machspl.h> /* for splsched */
  58. queue_head_t swapin_queue;
  59. decl_simple_lock_data(, swapper_lock_data)
  60. #define swapper_lock() simple_lock(&swapper_lock_data)
  61. #define swapper_unlock() simple_unlock(&swapper_lock_data)
  62. /*
  63. * swapper_init: [exported]
  64. *
  65. * Initialize the swapper module.
  66. */
  67. void swapper_init(void)
  68. {
  69. queue_init(&swapin_queue);
  70. simple_lock_init(&swapper_lock_data);
  71. }
  72. /*
  73. * thread_swapin: [exported]
  74. *
  75. * Place the specified thread in the list of threads to swapin. It
  76. * is assumed that the thread is locked, therefore we are at splsched.
  77. *
  78. * We don't bother with stack_alloc_try to optimize swapin;
  79. * our callers have already tried that route.
  80. */
  81. void thread_swapin(thread_t thread)
  82. {
  83. switch (thread->state & TH_SWAP_STATE) {
  84. case TH_SWAPPED:
  85. /*
  86. * Swapped out - queue for swapin thread.
  87. */
  88. thread->state = (thread->state & ~TH_SWAP_STATE)
  89. | TH_SW_COMING_IN;
  90. swapper_lock();
  91. enqueue_tail(&swapin_queue, &(thread->links));
  92. swapper_unlock();
  93. thread_wakeup((event_t) &swapin_queue);
  94. break;
  95. case TH_SW_COMING_IN:
  96. /*
  97. * Already queued for swapin thread, or being
  98. * swapped in.
  99. */
  100. break;
  101. default:
  102. /*
  103. * Already swapped in.
  104. */
  105. panic("thread_swapin");
  106. }
  107. }
  108. /*
  109. * thread_doswapin:
  110. *
  111. * Swapin the specified thread, if it should be runnable, then put
  112. * it on a run queue. No locks should be held on entry, as it is
  113. * likely that this routine will sleep (waiting for stack allocation).
  114. */
  115. kern_return_t thread_doswapin(thread_t thread)
  116. {
  117. kern_return_t kr;
  118. spl_t s;
  119. /*
  120. * Allocate the kernel stack.
  121. */
  122. kr = stack_alloc(thread, thread_continue);
  123. if (kr != KERN_SUCCESS)
  124. return kr;
  125. /*
  126. * Place on run queue.
  127. */
  128. s = splsched();
  129. thread_lock(thread);
  130. thread->state &= ~(TH_SWAPPED | TH_SW_COMING_IN);
  131. if (thread->state & TH_RUN)
  132. thread_setrun(thread, TRUE);
  133. thread_unlock(thread);
  134. (void) splx(s);
  135. return KERN_SUCCESS;
  136. }
  137. /*
  138. * swapin_thread: [exported]
  139. *
  140. * This procedure executes as a kernel thread. Threads that need to
  141. * be swapped in are swapped in by this thread.
  142. */
  143. void __attribute__((noreturn)) swapin_thread_continue(void)
  144. {
  145. for (;;) {
  146. thread_t thread;
  147. spl_t s;
  148. s = splsched();
  149. swapper_lock();
  150. while ((thread = (thread_t) dequeue_head(&swapin_queue))
  151. != THREAD_NULL) {
  152. kern_return_t kr;
  153. swapper_unlock();
  154. (void) splx(s);
  155. kr = thread_doswapin(thread); /* may block */
  156. s = splsched();
  157. swapper_lock();
  158. if (kr != KERN_SUCCESS) {
  159. enqueue_head(&swapin_queue,
  160. (queue_entry_t) thread);
  161. break;
  162. }
  163. }
  164. assert_wait((event_t) &swapin_queue, FALSE);
  165. swapper_unlock();
  166. (void) splx(s);
  167. counter(c_swapin_thread_block++);
  168. thread_block(swapin_thread_continue);
  169. }
  170. }
  171. void swapin_thread(void)
  172. {
  173. stack_privilege(current_thread());
  174. swapin_thread_continue();
  175. /*NOTREACHED*/
  176. }