Commit Graph

13 Commits

Author SHA1 Message Date
Tim J. Robbins
f05a427aa6 Return EINVAL if the contested bit is not set on the umtx passed to
_umtx_unlock() instead of firing a KASSERT.
2003-09-07 11:14:52 +00:00
Peter Wemm
80611144e4 Initialize 'blocked' to NULL. I think this was a real problem, but I
am not sure about that.  The lack of -Werror and the inline noise hid
this for a while.
2003-07-23 20:29:13 +00:00
Mike Makonnen
6022ec6737 Turn a KASSERT back into an EINVAL return value. So, next time someone
comes across it, it will turn into a core dump in userland instead of
a kernel panic. I had also inverted the sense of the test, so

Double pointy hat to:	mtm
2003-07-19 11:32:48 +00:00
Mike Makonnen
5c6edbec80 Remove a lock held across casuptr() that snuck in last commit. 2003-07-18 21:26:45 +00:00
Mike Makonnen
7df7f5c5ab Move the decision on whether to unset the contested
bit or not from lock to unlock time.

Suggested by:	jhb
2003-07-18 17:58:37 +00:00
Mike Makonnen
994599d782 Fix umtx locking, for libthr, in the kernel.
1. There was a race condition between a thread unlocking
   a umtx and the thread contesting it. If the unlocking
   thread won the race it may try to wakeup a thread that
   was not yet in msleep(). The contesting thread would then
   go to sleep to await a wakeup that would never come. It's
   not possible to close the race by using a lock because
   calls to casuptr() may have to fault a page in from swap.
   Instead, the race was closed by introducing a flag that
   the unlocking thread will set when waking up a thread.
   The contesting thread will check for this flag before
   going to sleep. For now the flag is kept in td_flags,
   but it may be better to use some other member or create
   a new one because of the possible performance/contention
   issues of having to own sched_lock. Thanks to jhb for
   pointing me in the right direction on this one.

2. Once a umtx was contested all future locks and unlocks
   were happening in the kernel, regardless of whether it
   was contested or not. To prevent this from happening,
   when a thread locks a umtx it checks the queue for that
   umtx and unsets the contested bit if there are no other
   threads waiting on it. Again, this is slightly more
   complicated than it needs to be because we can't hold
   a lock across casuptr(). So, the thread has to check
   the queue again after unseting the bit, and reset the
   contested bit if it finds that another thread has put
   itself on the queue in the mean time.

3. Remove the if... block for unlocking an uncontested
   umtx, and replace it with a KASSERT. The _only_ time
   a thread should be unlocking a umtx in the kernel is
   if it is contested.
2003-07-17 11:06:40 +00:00
Mike Makonnen
e55c35c433 I was so happy I found the semi-colon from hell that I didn't
notice another typo in the same line. This typo makes libthr unuseable,
but it's effects where counter-balanced by the extra semicolon, which
made libthr remarkably useable for the past several months.
2003-07-04 23:28:42 +00:00
Mike Makonnen
1069e3a6f4 It's unfair how one extraneous semi-colon can cause so much grief. 2003-07-04 11:18:07 +00:00
David E. O'Brien
677b542ea2 Use __FBSDID(). 2003-06-11 00:56:59 +00:00
Jeff Roberson
980c75b4d8 - Remove the blocked pointer from the umtx structure.
- Use a hash of umtx queues to queue blocked threads.  We hash on pid and the
   virtual address of the umtx structure.  This eliminates cases where we
   previously held a lock across a casuptr call.

Reviwed by:	jhb (quickly)
2003-06-03 05:24:46 +00:00
Jeff Roberson
0003d1b74e - Create a new lock, umtx_lock, for use instead of the proc lock for
protecting the umtx queues.  We can't use the proc lock because we need
   to hold the lock across calls to casuptr, which can fault.

Approved by:	re
2003-05-25 18:18:32 +00:00
Jake Burkholder
cef57e7624 - Make casuptr return the old value of the location we're trying to update,
and change the umtx code to expect this.

Reviewed by:	jeff
2003-04-02 08:02:27 +00:00
Jeff Roberson
69404b5090 - Add an api for doing smp safe locks in userland.
- umtx_lock() is defined as an inline in umtx.h.  It tries to do an
   uncontested acquire of a lock which falls back to the _umtx_lock()
   system-call if that fails.
 - umtx_unlock() is also an inline which falls back to _umtx_unlock() if the
   uncontested unlock fails.
 - Locks are keyed off of the thr_id_t of the currently running thread which
   is currently just the pointer to the 'struct thread' in kernel.
 - _umtx_lock() uses the proc pointer to synchronize access to blocked thread
   queues which are stored in the first blocked thread.
2003-04-01 01:10:42 +00:00