Re: [Patch] shm bug introduced with pagecache in 2.3.11

Manfred Spraul (manfreds@colorfullife.com)
Sat, 20 Nov 1999 11:14:54 +0100


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/