Messages in this thread | | | Date | Sat, 20 Nov 1999 11:14:54 +0100 | From | Manfred Spraul <> | Subject | Re: [Patch] shm bug introduced with pagecache in 2.3.11 |
| |
Alexander Viro wrote: > > IIRC, there was an implementation and analysis in Vahalia. Streamlining it > shouldn't be too hard (I have something like that in AFFS patches, but > there I didn't need {up,down}_write and did need upgrade/downgrade. IOW, > writrs always started as readers).
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/
| |