Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Re: pdaemon, interrupts and ci_idepth
To:
Mark Kettenis <mark.kettenis@xs4all.nl>
Cc:
tech@openbsd.org
Date:
Sat, 2 Nov 2024 09:51:03 +0100

Download raw body.

Thread
On 22/10/24(Tue) 21:01, Mark Kettenis wrote:
> > Date: Sat, 19 Oct 2024 15:23:32 +0200
> > From: Martin Pieuchot <mpi@grenadille.net>
> > 
> > When a system is OOM and has only its reserved pages available, it is
> > not helpful to let interrupt handlers steal such memory from the page
> > daemon.  
> > 
> > I've seen iwm(4)'s interrupt handler allocate memory reserved for the
> > pagedaemon because checking against `curproc' is not good enough.  So
> > the diff below use the MD `ci_idepth' variable to prevent such scenario.
> > If this is acceptable, I'd be happy to rename `ci_intrdepth' used by
> > some architectures to `ci_idepth'.
> > 
> > Ok?
> 
> Yes, this makes sense.  But this does require some MD work first.
> 
> Also I wonder if it makes sense to abstract the
> 
>   (curproc == uvm.pagedaemon_proc && curcpu()->ci_idepth == 0)
> 
> and
> 
>   (curproc == syncerproc && curcpu()->ci_idepth == 0)
> 
> conditions into inline functions, such that that first multi-line
> condition becomes a bit easier to understand...

Here's where I am now.  sparc64 and landisk still lack `ci_idepth'.

The last chunk is for correctness and might find unexpected bugs.

Index: uvm/uvm_pmemrange.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pmemrange.c,v
diff -u -p -r1.68 uvm_pmemrange.c
--- uvm/uvm_pmemrange.c	2 Oct 2024 10:17:28 -0000	1.68
+++ uvm/uvm_pmemrange.c	2 Nov 2024 08:48:05 -0000
@@ -81,6 +81,20 @@ int	uvm_pmr_pg_to_memtype(struct vm_page
 void	uvm_pmr_print(void);
 #endif
 
+static inline int
+in_pagedaemon(int allowsyncer)
+{
+#if !defined(__sparc64__) && !defined(__landisk__)
+	if (curcpu()->ci_idepth > 0)
+		return 0;
+#endif
+	if (curproc == uvm.pagedaemon_proc)
+		return 1;
+	if (allowsyncer && (curproc == syncerproc))
+		return 1;
+	return 0;
+}
+
 /*
  * Memory types. The page flags are used to derive what the current memory
  * type of a page is.
@@ -967,7 +981,7 @@ again:
 	}
 
 	if ((uvmexp.free <= (uvmexp.reserve_pagedaemon + count)) &&
-	    (curproc != uvm.pagedaemon_proc) && (curproc != syncerproc)) {
+	    !in_pagedaemon(1)) {
 		uvm_unlock_fpageq();
 		if (flags & UVM_PLA_WAITOK) {
 			uvm_wait("uvm_pmr_getpages");
@@ -2094,6 +2108,10 @@ uvm_wait_pla(paddr_t low, paddr_t high, 
 {
 	struct uvm_pmalloc pma;
 	const char *wmsg = "pmrwait";
+
+#if !defined(__sparc64__) && !defined(__landisk__)
+	KASSERT(curcpu()->ci_idepth == 0);
+#endif
 
 	if (curproc == uvm.pagedaemon_proc) {
 		/*