vm_pageout.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
  4. * Copyright (c) 1993,1994 The University of Utah and
  5. * the Computer Systems Laboratory (CSL).
  6. * All rights reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
  15. * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
  16. * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
  17. * THIS SOFTWARE.
  18. *
  19. * Carnegie Mellon requests users of this software to return to
  20. *
  21. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  22. * School of Computer Science
  23. * Carnegie Mellon University
  24. * Pittsburgh PA 15213-3890
  25. *
  26. * any improvements or extensions that they make and grant Carnegie Mellon
  27. * the rights to redistribute these changes.
  28. */
  29. /*
  30. * File: vm/vm_pageout.c
  31. * Author: Avadis Tevanian, Jr., Michael Wayne Young
  32. * Date: 1985
  33. *
  34. * The proverbial page-out daemon.
  35. */
  36. #include <device/net_io.h>
  37. #include <mach/mach_types.h>
  38. #include <mach/memory_object.h>
  39. #include <vm/memory_object_default.user.h>
  40. #include <vm/memory_object_user.user.h>
  41. #include <mach/vm_param.h>
  42. #include <mach/vm_statistics.h>
  43. #include <kern/counters.h>
  44. #include <kern/debug.h>
  45. #include <kern/slab.h>
  46. #include <kern/task.h>
  47. #include <kern/thread.h>
  48. #include <kern/printf.h>
  49. #include <vm/memory_object.h>
  50. #include <vm/pmap.h>
  51. #include <vm/vm_map.h>
  52. #include <vm/vm_object.h>
  53. #include <vm/vm_page.h>
  54. #include <vm/vm_pageout.h>
  55. #include <machine/locore.h>
  56. #define DEBUG 0
  57. /*
  58. * Maximum delay, in milliseconds, between two pageout scans.
  59. */
  60. #define VM_PAGEOUT_TIMEOUT 50
  61. /*
  62. * Event placeholder for pageout requests, synchronized with
  63. * the free page queue lock.
  64. */
  65. static int vm_pageout_requested;
  66. /*
  67. * Event placeholder for pageout throttling, synchronized with
  68. * the free page queue lock.
  69. */
  70. static int vm_pageout_continue;
  71. /*
  72. * Routine: vm_pageout_setup
  73. * Purpose:
  74. * Set up a page for pageout.
  75. *
  76. * Move or copy the page to a new object, as part
  77. * of which it will be sent to its memory manager
  78. * in a memory_object_data_return or memory_object_initialize
  79. * message.
  80. *
  81. * The "paging_offset" argument specifies the offset
  82. * of the page within its external memory object.
  83. *
  84. * The "new_object" and "new_offset" arguments
  85. * indicate where the page should be moved.
  86. *
  87. * The "flush" argument specifies whether the page
  88. * should be flushed from its object. If not, a
  89. * copy of the page is moved to the new object.
  90. *
  91. * In/Out conditions:
  92. * The page in question must not be on any pageout queues,
  93. * and must be busy. The object to which it belongs
  94. * must be unlocked, and the caller must hold a paging
  95. * reference to it. The new_object must not be locked.
  96. *
  97. * If the page is flushed from its original object,
  98. * this routine returns a pointer to a place-holder page,
  99. * inserted at the same offset, to block out-of-order
  100. * requests for the page. The place-holder page must
  101. * be freed after the data_return or initialize message
  102. * has been sent. If the page is copied,
  103. * the holding page is VM_PAGE_NULL.
  104. *
  105. * The original page is put on a paging queue and marked
  106. * not busy on exit.
  107. */
  108. vm_page_t
  109. vm_pageout_setup(
  110. vm_page_t m,
  111. vm_offset_t paging_offset,
  112. vm_object_t new_object,
  113. vm_offset_t new_offset,
  114. boolean_t flush)
  115. {
  116. vm_object_t old_object = m->object;
  117. vm_page_t holding_page = 0; /*'=0'to quiet gcc warnings*/
  118. vm_page_t new_m;
  119. assert(m->busy && !m->absent && !m->fictitious);
  120. /*
  121. * If we are not flushing the page, allocate a
  122. * page in the object.
  123. */
  124. if (!flush) {
  125. for (;;) {
  126. vm_object_lock(new_object);
  127. new_m = vm_page_alloc(new_object, new_offset);
  128. vm_object_unlock(new_object);
  129. if (new_m != VM_PAGE_NULL) {
  130. break;
  131. }
  132. VM_PAGE_WAIT(NULL);
  133. }
  134. }
  135. if (flush) {
  136. /*
  137. * Create a place-holder page where the old one was,
  138. * to prevent anyone from attempting to page in this
  139. * page while we`re unlocked.
  140. */
  141. while ((holding_page = vm_page_grab_fictitious())
  142. == VM_PAGE_NULL)
  143. vm_page_more_fictitious();
  144. vm_object_lock(old_object);
  145. vm_page_lock_queues();
  146. vm_page_remove(m);
  147. vm_page_unlock_queues();
  148. PAGE_WAKEUP_DONE(m);
  149. vm_page_lock_queues();
  150. vm_page_insert(holding_page, old_object, m->offset);
  151. vm_page_unlock_queues();
  152. /*
  153. * Record that this page has been written out
  154. */
  155. #if MACH_PAGEMAP
  156. vm_external_state_set(old_object->existence_info,
  157. paging_offset,
  158. VM_EXTERNAL_STATE_EXISTS);
  159. #endif /* MACH_PAGEMAP */
  160. vm_object_unlock(old_object);
  161. vm_object_lock(new_object);
  162. /*
  163. * Move this page into the new object
  164. */
  165. vm_page_lock_queues();
  166. vm_page_insert(m, new_object, new_offset);
  167. vm_page_unlock_queues();
  168. m->dirty = TRUE;
  169. m->precious = FALSE;
  170. m->page_lock = VM_PROT_NONE;
  171. m->unlock_request = VM_PROT_NONE;
  172. }
  173. else {
  174. /*
  175. * Copy the data into the new page,
  176. * and mark the new page as clean.
  177. */
  178. vm_page_copy(m, new_m);
  179. vm_object_lock(old_object);
  180. m->dirty = FALSE;
  181. pmap_clear_modify(m->phys_addr);
  182. /*
  183. * Deactivate old page.
  184. */
  185. vm_page_lock_queues();
  186. vm_page_deactivate(m);
  187. vm_page_unlock_queues();
  188. PAGE_WAKEUP_DONE(m);
  189. /*
  190. * Record that this page has been written out
  191. */
  192. #if MACH_PAGEMAP
  193. vm_external_state_set(old_object->existence_info,
  194. paging_offset,
  195. VM_EXTERNAL_STATE_EXISTS);
  196. #endif /* MACH_PAGEMAP */
  197. vm_object_unlock(old_object);
  198. vm_object_lock(new_object);
  199. /*
  200. * Use the new page below.
  201. */
  202. m = new_m;
  203. m->dirty = TRUE;
  204. assert(!m->precious);
  205. PAGE_WAKEUP_DONE(m);
  206. }
  207. /*
  208. * Make the old page eligible for replacement again; if a
  209. * user-supplied memory manager fails to release the page,
  210. * it will be paged out again to the default memory manager.
  211. *
  212. * Note that pages written to the default memory manager
  213. * must be wired down -- in return, it guarantees to free
  214. * this page, rather than reusing it.
  215. */
  216. vm_page_lock_queues();
  217. vm_stat.pageouts++;
  218. if (m->laundry) {
  219. /*
  220. * The caller is telling us that it is going to
  221. * immediately double page this page to the default
  222. * pager.
  223. */
  224. assert(!old_object->internal);
  225. m->laundry = FALSE;
  226. } else if (old_object->internal ||
  227. memory_manager_default_port(old_object->pager)) {
  228. m->laundry = TRUE;
  229. vm_page_laundry_count++;
  230. vm_page_wire(m);
  231. } else {
  232. m->external_laundry = TRUE;
  233. /*
  234. * If vm_page_external_laundry_count is negative,
  235. * the pageout daemon isn't expecting to be
  236. * notified.
  237. */
  238. if (vm_page_external_laundry_count >= 0) {
  239. vm_page_external_laundry_count++;
  240. }
  241. vm_page_activate(m);
  242. }
  243. vm_page_unlock_queues();
  244. /*
  245. * Since IPC operations may block, we drop locks now.
  246. * [The placeholder page is busy, and we still have
  247. * paging_in_progress incremented.]
  248. */
  249. vm_object_unlock(new_object);
  250. /*
  251. * Return the placeholder page to simplify cleanup.
  252. */
  253. return (flush ? holding_page : VM_PAGE_NULL);
  254. }
  255. /*
  256. * Routine: vm_pageout_page
  257. * Purpose:
  258. * Causes the specified page to be written back to
  259. * the appropriate memory object.
  260. *
  261. * The "initial" argument specifies whether this
  262. * data is an initialization only, and should use
  263. * memory_object_data_initialize instead of
  264. * memory_object_data_return.
  265. *
  266. * The "flush" argument specifies whether the page
  267. * should be flushed from the object. If not, a
  268. * copy of the data is sent to the memory object.
  269. *
  270. * In/out conditions:
  271. * The page in question must not be on any pageout queues.
  272. * The object to which it belongs must be locked.
  273. * Implementation:
  274. * Move this page to a completely new object, if flushing;
  275. * copy to a new page in a new object, if not.
  276. */
  277. void
  278. vm_pageout_page(
  279. vm_page_t m,
  280. boolean_t initial,
  281. boolean_t flush)
  282. {
  283. vm_map_copy_t copy;
  284. vm_object_t old_object;
  285. vm_object_t new_object;
  286. vm_page_t holding_page;
  287. vm_offset_t paging_offset;
  288. kern_return_t rc;
  289. boolean_t precious_clean;
  290. assert(m->busy);
  291. /*
  292. * Cleaning but not flushing a clean precious page is a
  293. * no-op. Remember whether page is clean and precious now
  294. * because vm_pageout_setup will mark it dirty and not precious.
  295. *
  296. * XXX Check if precious_clean && !flush can really happen.
  297. */
  298. precious_clean = (!m->dirty) && m->precious;
  299. if (precious_clean && !flush) {
  300. PAGE_WAKEUP_DONE(m);
  301. return;
  302. }
  303. /*
  304. * Verify that we really want to clean this page.
  305. */
  306. if (m->absent || m->error || (!m->dirty && !m->precious)) {
  307. VM_PAGE_FREE(m);
  308. return;
  309. }
  310. /*
  311. * Create a paging reference to let us play with the object.
  312. */
  313. old_object = m->object;
  314. paging_offset = m->offset + old_object->paging_offset;
  315. vm_object_paging_begin(old_object);
  316. vm_object_unlock(old_object);
  317. /*
  318. * Allocate a new object into which we can put the page.
  319. */
  320. new_object = vm_object_allocate(PAGE_SIZE);
  321. new_object->used_for_pageout = TRUE;
  322. /*
  323. * Move the page into the new object.
  324. */
  325. holding_page = vm_pageout_setup(m,
  326. paging_offset,
  327. new_object,
  328. 0, /* new offset */
  329. flush); /* flush */
  330. rc = vm_map_copyin_object(new_object, 0, PAGE_SIZE, &copy);
  331. assert(rc == KERN_SUCCESS);
  332. if (initial) {
  333. rc = memory_object_data_initialize(
  334. old_object->pager,
  335. old_object->pager_request,
  336. paging_offset, (pointer_t) copy, PAGE_SIZE);
  337. }
  338. else {
  339. rc = memory_object_data_return(
  340. old_object->pager,
  341. old_object->pager_request,
  342. paging_offset, (pointer_t) copy, PAGE_SIZE,
  343. !precious_clean, !flush);
  344. }
  345. if (rc != KERN_SUCCESS)
  346. vm_map_copy_discard(copy);
  347. /*
  348. * Clean up.
  349. */
  350. vm_object_lock(old_object);
  351. if (holding_page != VM_PAGE_NULL)
  352. VM_PAGE_FREE(holding_page);
  353. vm_object_paging_end(old_object);
  354. }
  355. /*
  356. * vm_pageout_scan does the dirty work for the pageout daemon.
  357. *
  358. * Return TRUE if the pageout daemon is done for now, FALSE otherwise,
  359. * in which case should_wait indicates whether the pageout daemon
  360. * should wait to allow pagers to keep up.
  361. *
  362. * It returns with vm_page_queue_free_lock held.
  363. */
  364. boolean_t vm_pageout_scan(boolean_t *should_wait)
  365. {
  366. boolean_t done;
  367. /*
  368. * Try balancing pages among segments first, since this
  369. * may be enough to resume unprivileged allocations.
  370. */
  371. /* This function returns with vm_page_queue_free_lock held */
  372. done = vm_page_balance();
  373. if (done) {
  374. return TRUE;
  375. }
  376. simple_unlock(&vm_page_queue_free_lock);
  377. /*
  378. * Balancing is not enough. Shrink caches and scan pages
  379. * for eviction.
  380. */
  381. stack_collect();
  382. net_kmsg_collect();
  383. consider_task_collect();
  384. if (0) /* XXX: pcb_collect doesn't do anything yet, so it is
  385. pointless to call consider_thread_collect. */
  386. consider_thread_collect();
  387. /*
  388. * slab_collect should be last, because the other operations
  389. * might return memory to caches.
  390. */
  391. slab_collect();
  392. vm_page_refill_inactive();
  393. /* This function returns with vm_page_queue_free_lock held */
  394. return vm_page_evict(should_wait);
  395. }
  396. void vm_pageout(void)
  397. {
  398. boolean_t done, should_wait;
  399. current_thread()->vm_privilege = 1;
  400. stack_privilege(current_thread());
  401. thread_set_own_priority(0);
  402. for (;;) {
  403. done = vm_pageout_scan(&should_wait);
  404. /* we hold vm_page_queue_free_lock now */
  405. if (done) {
  406. thread_sleep(&vm_pageout_requested,
  407. simple_lock_addr(vm_page_queue_free_lock),
  408. FALSE);
  409. } else if (should_wait) {
  410. assert_wait(&vm_pageout_continue, FALSE);
  411. thread_set_timeout(VM_PAGEOUT_TIMEOUT * hz / 1000);
  412. simple_unlock(&vm_page_queue_free_lock);
  413. thread_block(NULL);
  414. #if DEBUG
  415. if (current_thread()->wait_result != THREAD_AWAKENED) {
  416. printf("vm_pageout: timeout,"
  417. " vm_page_laundry_count:%d"
  418. " vm_page_external_laundry_count:%d\n",
  419. vm_page_laundry_count,
  420. vm_page_external_laundry_count);
  421. }
  422. #endif
  423. } else {
  424. simple_unlock(&vm_page_queue_free_lock);
  425. }
  426. }
  427. }
  428. /*
  429. * Start pageout
  430. *
  431. * The free page queue lock must be held before calling this function.
  432. */
  433. void vm_pageout_start(void)
  434. {
  435. if (!current_thread())
  436. return;
  437. thread_wakeup_one(&vm_pageout_requested);
  438. }
  439. /*
  440. * Resume pageout
  441. *
  442. * The free page queue lock must be held before calling this function.
  443. */
  444. void vm_pageout_resume(void)
  445. {
  446. thread_wakeup_one(&vm_pageout_continue);
  447. }