pondering pi futexes

From: Dmitry Chagin <dchagin_at_freebsd.org>
Date: Sun, 27 Jun 2021 19:39:35 UTC
Hi,
some time ago I have changed Linuxulator futexes from sx lock to mtx.
sx was used as it allows copyin/copyout with sx lock held.
to use mtx I have changed the code like:
1. lock mtx;
2. disable_pagefaults;
3. copyin()
4. enable_pagefaults;
5. if error
   - unlock mtx;
   copyin();
   if error == 0 goto 1.

it works (needto replace copyin() by fueword32()), but pondering pi futexes
imlementation, I see that it is not possible to drop the futex lock on a return
from msleep() path. 

below a simplified FUTEX_LOCK_PI operation, where on enter to the kernel current thread:

0. acquire futex lock (which is mtx)
1. cmpset(0 -> current thread TID), return (0) on success;
2. fetch() from futex *uaddr (for TID of owner):
   - check EDEADLK case (the futex word at *uaddr is already locked by the caller);
   - check that is no waiters on *uaddr exists which is waiting via FUTEX_WAIT or
     FUTEX_WAIT_BITSET, return (EINVAL) if so;
   - cmpset(TID -> (FUTEX_WAITERS|TID));
      - on error, the futex owner changed in user-space, repeat from 1.
3. Here we have: the owner, one waiter (current thread) and 0 or more waiters
   sleeping on a waiting_proc. FUTEX_WAITERS bit is set, so any new waiters go to
   the kernel and owner should unlock futex via the FUTEX_UNLOCK_PI op;
4. Try to find the thread which is associated with the owner’s TID:
   - on error, something bad happened, owner died? Clean owner state link?
     return (ESRCH). Or if no other waiters? Check this...
   - on success:
      - save owner state link to the struct futex (save priority);
      - check the owner's priority, bump it if needed;
      - put the current thread to the waiters list in descending priority order;
      - change priority of all waiters if needed;
      - msleep on a futex waiting_proc; come back with futex lock held;
         - restore own priority? If last waiter?; [ponders..]
         - on timeout return (ETIMEDOUT);
         - the current thread is the new owner:
bah!!    - store() the owner TID to *uaddr; [check what should I do on error..]
         - release futex lock;
         - return (0).

is it possible to hold *uaddr page to prevent page faults?