uvm_object.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* $OpenBSD: uvm_object.c,v 1.12 2014/12/17 19:42:15 tedu Exp $ */
  2. /*
  3. * Copyright (c) 2006 The NetBSD Foundation, Inc.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to The NetBSD Foundation
  7. * by Mindaugas Rasiukevicius.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  20. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  21. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  22. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /*
  31. * uvm_object.c: operate with memory objects
  32. *
  33. */
  34. #include <sys/param.h>
  35. #include <sys/mman.h>
  36. #include <sys/atomic.h>
  37. #include <uvm/uvm.h>
  38. /* We will fetch this page count per step */
  39. #define FETCH_PAGECOUNT 16
  40. /*
  41. * uvm_objinit: initialise a uvm object.
  42. */
  43. void
  44. uvm_objinit(struct uvm_object *uobj, struct uvm_pagerops *pgops, int refs)
  45. {
  46. uobj->pgops = pgops;
  47. RB_INIT(&uobj->memt);
  48. uobj->uo_npages = 0;
  49. uobj->uo_refs = refs;
  50. }
  51. #ifndef SMALL_KERNEL
  52. /*
  53. * uvm_objwire: wire the pages of entire uobj
  54. *
  55. * => caller must pass page-aligned start and end values
  56. * => if the caller passes in a pageq pointer, we'll return a list of
  57. * wired pages.
  58. */
  59. int
  60. uvm_objwire(struct uvm_object *uobj, voff_t start, voff_t end,
  61. struct pglist *pageq)
  62. {
  63. int i, npages, left, error;
  64. struct vm_page *pgs[FETCH_PAGECOUNT];
  65. voff_t offset = start;
  66. left = (end - start) >> PAGE_SHIFT;
  67. while (left) {
  68. npages = MIN(FETCH_PAGECOUNT, left);
  69. /* Get the pages */
  70. memset(pgs, 0, sizeof(pgs));
  71. error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0,
  72. PROT_READ | PROT_WRITE, MADV_SEQUENTIAL,
  73. PGO_ALLPAGES | PGO_SYNCIO);
  74. if (error)
  75. goto error;
  76. for (i = 0; i < npages; i++) {
  77. KASSERT(pgs[i] != NULL);
  78. KASSERT(!(pgs[i]->pg_flags & PG_RELEASED));
  79. #if 0
  80. /*
  81. * Loan break
  82. */
  83. if (pgs[i]->loan_count) {
  84. while (pgs[i]->loan_count) {
  85. pg = uvm_loanbreak(pgs[i]);
  86. if (!pg) {
  87. uvm_wait("uobjwirepg");
  88. continue;
  89. }
  90. }
  91. pgs[i] = pg;
  92. }
  93. #endif
  94. if (pgs[i]->pg_flags & PQ_AOBJ) {
  95. atomic_clearbits_int(&pgs[i]->pg_flags,
  96. PG_CLEAN);
  97. uao_dropswap(uobj, i);
  98. }
  99. }
  100. /* Wire the pages */
  101. uvm_lock_pageq();
  102. for (i = 0; i < npages; i++) {
  103. uvm_pagewire(pgs[i]);
  104. if (pageq != NULL)
  105. TAILQ_INSERT_TAIL(pageq, pgs[i], pageq);
  106. }
  107. uvm_unlock_pageq();
  108. /* Unbusy the pages */
  109. uvm_page_unbusy(pgs, npages);
  110. left -= npages;
  111. offset += (voff_t)npages << PAGE_SHIFT;
  112. }
  113. return 0;
  114. error:
  115. /* Unwire the pages which have been wired */
  116. uvm_objunwire(uobj, start, offset);
  117. return error;
  118. }
  119. /*
  120. * uobj_unwirepages: unwire the pages of entire uobj
  121. *
  122. * => caller must pass page-aligned start and end values
  123. */
  124. void
  125. uvm_objunwire(struct uvm_object *uobj, voff_t start, voff_t end)
  126. {
  127. struct vm_page *pg;
  128. off_t offset;
  129. uvm_lock_pageq();
  130. for (offset = start; offset < end; offset += PAGE_SIZE) {
  131. pg = uvm_pagelookup(uobj, offset);
  132. KASSERT(pg != NULL);
  133. KASSERT(!(pg->pg_flags & PG_RELEASED));
  134. uvm_pageunwire(pg);
  135. }
  136. uvm_unlock_pageq();
  137. }
  138. #endif /* !SMALL_KERNEL */