[Add jhb and move to -current] On Fri, 15 Mar 2002 10:53:20 -0800, Alfred Perlstein <[EMAIL PROTECTED]> said:
Alfred> * Brian F. Feldman <[EMAIL PROTECTED]> [020315 03:22] wrote: >> Alfred Perlstein <[EMAIL PROTECTED]> wrote: >> > >> > What is the problem? >> >> Damn good question. Are the tracebacks related? If not, what are you >> supposed to be telling me it's deadlocking on? I don't see the system being >> deadlocked. What is it actually supposed to be blocked on? >> >> > Well basically you changed: >> > >> > ! static __inline__ int >> > ! _vm_map_lock_upgrade(vm_map_t map, struct thread *td) { >> > ! int error; >> > ! >> > ! vm_map_printf("locking map LK_EXCLUPGRADE: %p\n", map); >> > ! error = lockmgr(&map->lock, LK_EXCLUPGRADE, NULL, td); >> > ! if (error == 0) >> > ! map->timestamp++; >> > ! return error; >> > } >> > >> > into: >> > >> > ! _vm_map_lock_upgrade(vm_map_t map, const char *file, int line) >> > { >> > ! vm_map_printf("locking map LK_EXCLUPGRADE: %p\n", map); >> > ! if (_sx_try_upgrade(&map->lock, file, line)) { >> > ! map->timestamp++; >> > ! return (0); >> > ! } >> > ! return (EWOULDBLOCK); >> > } >> >> It doesn't need LK_EXCLUPGRADE semantics, only LK_UPGRADE, if it's not >> blocking. It backs out completely and unlocks the shared reference and >> tries for an exclusive lock. Alfred> Sigh, you're making me do all the work here... :( Alfred> lockmgr(&map->lock, LK_EXCLUPGRADE, NULL, td); Alfred> means: Alfred> Turn my shared lock into an exclusive lock, Alfred> if it's shared then wait for all shared locks to drain, Alfred> however if someone else is requesting an exclusive lock, then fail. Alfred> _sx_try_upgrade(&map->lock, file, line) Alfred> means: Alfred> Give me an exclusive lock Alfred> if anyone else has a shared lock then fail immediately. Alfred> What happens in your case is that you get into a busy loop Alfred> because you never yeild the processor. Alfred> This happens in vm_map_lookup() because of this: Alfred> if (fault_type & VM_PROT_WRITE) { Alfred> /* Alfred> * Make a new object, and place it in the object Alfred> * chain. Note that no new references have appeared Alfred> * -- one just moved from the map to the new Alfred> * object. Alfred> */ Alfred> if (vm_map_lock_upgrade(map)) Alfred> goto RetryLookup; Alfred> So, you fail your sx_lock upgrade and cause the cpu to spin. Alfred> You basically need to add logic to the sxlock subsystem to do what Alfred> lockmgr does, actually wait for the others to go away or fail if Alfred> someone else wants an upgrade. Attached patch implements sx_upgrade() which should work as you said above. This compiles fine, but is not tested yet. sx_upgrader records the thread that wants to upgrade. If sx_upgrader is non-NULL, sx_sunlock() wakes up the upgrader rather than other exclusive lock waiters.
sx_upgrade.diff
Description: Binary data
-- Seigo Tanimura <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>