I'd like to abstract the use of PG_WANTED to start unifying & cleaning
the various cases where a code path is waiting for a busy page. Here's
the first step.
ok?
Index: uvm/uvm_amap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
retrieving revision 1.90
diff -u -p -r1.90 uvm_amap.c
--- uvm/uvm_amap.c 30 Aug 2021 16:59:17 -0000 1.90
+++ uvm/uvm_amap.c 28 Jun 2022 11:53:08 -0000
@@ -781,9 +781,7 @@ ReStart:
* it and then restart.
*/
if (pg->pg_flags & PG_BUSY) {
- atomic_setbits_int(&pg->pg_flags, PG_WANTED);
- rwsleep_nsec(pg, amap->am_lock, PVM | PNORELOCK,
- "cownow", INFSLP);
+ uvm_pagewait(pg, amap->am_lock, "cownow");
goto ReStart;
}
Index: uvm/uvm_aobj.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_aobj.c,v
retrieving revision 1.103
diff -u -p -r1.103 uvm_aobj.c
--- uvm/uvm_aobj.c 29 Dec 2021 20:22:06 -0000 1.103
+++ uvm/uvm_aobj.c 28 Jun 2022 11:53:08 -0000
@@ -835,9 +835,8 @@ uao_detach(struct uvm_object *uobj)
while ((pg = RBT_ROOT(uvm_objtree, &uobj->memt)) != NULL) {
pmap_page_protect(pg, PROT_NONE);
if (pg->pg_flags & PG_BUSY) {
- atomic_setbits_int(&pg->pg_flags, PG_WANTED);
- rwsleep_nsec(pg, uobj->vmobjlock, PVM, "uao_det",
- INFSLP);
+ uvm_pagewait(pg, uobj->vmobjlock, "uao_det");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
continue;
}
uao_dropswap(&aobj->u_obj, pg->offset >> PAGE_SHIFT);
@@ -909,9 +908,8 @@ uao_flush(struct uvm_object *uobj, voff_
/* Make sure page is unbusy, else wait for it. */
if (pg->pg_flags & PG_BUSY) {
- atomic_setbits_int(&pg->pg_flags, PG_WANTED);
- rwsleep_nsec(pg, uobj->vmobjlock, PVM, "uaoflsh",
- INFSLP);
+ uvm_pagewait(pg, uobj->vmobjlock, "uaoflsh");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
curoff -= PAGE_SIZE;
continue;
}
@@ -1147,9 +1145,8 @@ uao_get(struct uvm_object *uobj, voff_t
/* page is there, see if we need to wait on it */
if ((ptmp->pg_flags & PG_BUSY) != 0) {
- atomic_setbits_int(&ptmp->pg_flags, PG_WANTED);
- rwsleep_nsec(ptmp, uobj->vmobjlock, PVM,
- "uao_get", INFSLP);
+ uvm_pagewait(ptmp, uobj->vmobjlock, "uao_get");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
continue; /* goto top of pps while loop */
}
Index: uvm/uvm_km.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.c,v
retrieving revision 1.150
diff -u -p -r1.150 uvm_km.c
--- uvm/uvm_km.c 7 Jun 2022 12:07:45 -0000 1.150
+++ uvm/uvm_km.c 28 Jun 2022 11:53:08 -0000
@@ -255,9 +255,8 @@ uvm_km_pgremove(struct uvm_object *uobj,
for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) {
pp = uvm_pagelookup(uobj, curoff);
if (pp && pp->pg_flags & PG_BUSY) {
- atomic_setbits_int(&pp->pg_flags, PG_WANTED);
- rwsleep_nsec(pp, uobj->vmobjlock, PVM, "km_pgrm",
- INFSLP);
+ uvm_pagewait(pp, uobj->vmobjlock, "km_pgrm");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
curoff -= PAGE_SIZE; /* loop back to us */
continue;
}
Index: uvm/uvm_page.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_page.c,v
retrieving revision 1.166
diff -u -p -r1.166 uvm_page.c
--- uvm/uvm_page.c 12 May 2022 12:48:36 -0000 1.166
+++ uvm/uvm_page.c 28 Jun 2022 11:57:42 -0000
@@ -1087,6 +1087,23 @@ uvm_page_unbusy(struct vm_page **pgs, in
}
}
+/*
+ * uvm_pagewait: wait for a busy page
+ *
+ * => page must be known PG_BUSY
+ * => object must be locked
+ * => object will be unlocked on return
+ */
+void
+uvm_pagewait(struct vm_page *pg, struct rwlock *lock, const char *wmesg)
+{
+ KASSERT(rw_lock_held(lock));
+ KASSERT((pg->pg_flags & PG_BUSY) != 0);
+
+ atomic_setbits_int(&pg->pg_flags, PG_WANTED);
+ rwsleep_nsec(pg, lock, PVM | PNORELOCK, wmesg, INFSLP);
+}
+
#if defined(UVM_PAGE_TRKOWN)
/*
* uvm_page_own: set or release page ownership
Index: uvm/uvm_page.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_page.h,v
retrieving revision 1.68
diff -u -p -r1.68 uvm_page.h
--- uvm/uvm_page.h 12 May 2022 12:48:36 -0000 1.68
+++ uvm/uvm_page.h 28 Jun 2022 11:53:08 -0000
@@ -233,7 +233,7 @@ void uvm_pagefree(struct vm_page *);
void uvm_page_unbusy(struct vm_page **, int);
struct vm_page *uvm_pagelookup(struct uvm_object *, voff_t);
void uvm_pageunwire(struct vm_page *);
-void uvm_pagewait(struct vm_page *, int);
+void uvm_pagewait(struct vm_page *, struct rwlock *, const char *);
void uvm_pagewake(struct vm_page *);
void uvm_pagewire(struct vm_page *);
void uvm_pagezero(struct vm_page *);
Index: uvm/uvm_vnode.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_vnode.c,v
retrieving revision 1.124
diff -u -p -r1.124 uvm_vnode.c
--- uvm/uvm_vnode.c 3 May 2022 21:20:35 -0000 1.124
+++ uvm/uvm_vnode.c 28 Jun 2022 11:53:08 -0000
@@ -684,11 +684,10 @@ uvn_flush(struct uvm_object *uobj, voff_
}
} else if (flags & PGO_FREE) {
if (pp->pg_flags & PG_BUSY) {
- atomic_setbits_int(&pp->pg_flags,
- PG_WANTED);
uvm_unlock_pageq();
- rwsleep_nsec(pp, uobj->vmobjlock, PVM,
- "uvn_flsh", INFSLP);
+ uvm_pagewait(pp, uobj->vmobjlock,
+ "uvn_flsh");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
uvm_lock_pageq();
curoff -= PAGE_SIZE;
continue;
@@ -1054,9 +1053,8 @@ uvn_get(struct uvm_object *uobj, voff_t
/* page is there, see if we need to wait on it */
if ((ptmp->pg_flags & PG_BUSY) != 0) {
- atomic_setbits_int(&ptmp->pg_flags, PG_WANTED);
- rwsleep_nsec(ptmp, uobj->vmobjlock, PVM,
- "uvn_get", INFSLP);
+ uvm_pagewait(ptmp, uobj->vmobjlock, "uvn_get");
+ rw_enter(uobj->vmobjlock, RW_WRITE);
continue; /* goto top of pps while loop */
}