I never figured out how to upgrade a reader to a writer:
what if 2 threads acquire the lock 'read', and and both decide to
promote to "write"?
Could you send me the patch?
I have attached below a pseudo-code version of a rw-mutex, what do you
think?
acquire_{shared,exclusive} should be possible with 2 asm instructions
inline
release_exclusive with 3 asm instructions inline
-- Manfred >>>>>>>>>>>>>>struct rw_mutex { rwlock_t rwl; wait_queue_head_t wait; int wake_me_up; };
/* TODO: add asm, add TASK_EXCLUSIVE for acquire_exclusive, * check if a waiting writer should stop new readers. * optimize release_shared */
void rw_mutex_init(struct rw_mutex* rwm) { init_wait_queue_head(&rwm->wait); rwm->wake_me_up = 0; rwm->rwl = RW_LOCK_UNLOCKED; }
/* 2 asm instructions inline */ void acquire_exclusive(struct rw_mutex* rwm) { if(!write_lock_trylock(&rwm->rwl)) { DECLARE_WAIT_QUEUE(wait,current); add_wait_queue(wait,&rwm->wait); for(;;) { current->state = TASK_UNINTERRUPTIBLE; rwm->wake_me_up = 1; if(write_lock_trylock(&rwm->rwl)) { break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(wait,&rwm->wait); } }
/* 2 asm instruction inline */ void acquire_shared(struct rw_mutex* rwm) { if(!read_lock_trylock(&rwm->rwl)) { DECLARE_WAIT_QUEUE(wait,current); add_wait_queue(wait,&rwm->wait); for(;;) { current->state = TASK_UNINTERRUPTIBLE; rwm->wake_me_up = 1; if(read_lock_trylock(&rwm->rwl)) { break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(wait,&rwm->wait); } }
/* 3 asm instructions */ void release_exclusive(struct rw_mutex* rwm) { read_unlock(&rwm->rwl); if(rwm->wake_me_up) { rwm->wake_me_up = 0; wake_up(&rwm->wait); } } void release_shared(struct rw_mutex* rwm) { read_unlock(&rwm->rwl); if(rwm->wake_me_up) { /* FIXME: is this a race? */ if(rwm->rwl != 0) return; rwm->wake_me_up = 0; wake_up(&rwm->wait); } } >>>>>>>>>>>>>>>>>
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/