[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]>
