Marek Waszkiewicz
Marek Waszkiewicz

Reputation: 325

kernel read_lock followed by write_lock gives soft lock up

In order to optimize clearing items from hash table, I have used read_lock followed by write_lock :

DEFINE_RWLOCK(ht_rwlock);

void Clear(void (*deleter)(const void*))
{
    int i;
    struct hash_table* temp_node;

    read_lock(&ht_rwlock);
    hash_for_each(spu_hash_table, i, temp_node, next)
    {
        write_lock(&ht_rwlock);
        hash_del(&temp_node->next);
        write_unlock(&ht_rwlock);

        deleter((const void*)temp_node);
    }
    read_unlock(&ht_rwlock);
}

However this gives me an error: kernel:BUG: soft lockup - CPU#0 stuck for 22s! [rmmod:6724]

Non optimized version with write_lock/write_unlock only works OK:

void Clear(void (*deleter)(const void*))
{
    int i;
    struct hash_table* temp_node;

    write_lock(&ht_rwlock);
    hash_for_each(spu_hash_table, i, temp_node, next)
    {
        hash_del(&temp_node->next);
        deleter((const void*)temp_node);
    }
    write_unlock(&ht_rwlock);
}

My question is do I really have to use write lock to iterate over hash table ?

Upvotes: 1

Views: 436

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 65870

My question is do I really have to use write lock to iterate over hash table?

Yes. RWlock in the kernel doesn't support transition from read lock to write lock.

Reason is simple: having two processes, each of them under read section and wanted to advance it to write one, leads to deadlock.

But your case is pure modification one (you delete all elements from the list), so using read_lock with transforming it to write lock wouldn't gain performance in any case. Use write_lock, as in your 2nd code.


If you care about perfomance, consider using RCU locks - it allows reader and writer to operate concurrently, so rwlock becomes not needed at all, simple lock for synchronize writers is sufficient. But appliance of RCU is depended from context.

Upvotes: 1

Related Questions