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

Manfred Spraul (manfreds@colorfullife.com)
Sat, 20 Nov 1999 21:31:09 +0100


This is a multi-part message in MIME format.
--------------DEC858512212B394B06D1371
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

"Benjamin C.R. LaHaise" wrote:
>
> On Fri, 19 Nov 1999, Linus Torvalds wrote:
>
> > Is anybody willing to take a stab at creating a read-write semaphore?
>
> Sure. Does the following sound?
>
> void down_read(struct rw_semaphore *sem);
> void down_write(struct rw_semaphore *sem);
> void up_read(struct rw_semaphore *sem);
> void up_write(struct rw_semaphore *sem);
>
> Looking at existing semaphores and rwlocks, it looks like a quick and
> painless beast to create.
>
> -ben
I give it up:
I've attached 2 more ideas, but one of them is a bit slow, and the other
one requires cmpxchg (ie only 486 and above).

--
	Manfred
--------------DEC858512212B394B06D1371
Content-Type: text/plain; charset=us-ascii;
 name="do2.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="do2.c"

/* need_wakeup is required because I must differenciate between * a) release the lock * b) release the lock, and wake-up another thread. * * a normal semaphore is an integer, and if it is below * zero, then a wake-up is required. * the write-lock is just one bit, therefore * I need the explicit "rwm->need_wakeup" variable. */

struct rw_mutex { volatile unsigned int lock; int need_wakeup; wait_queue_head wait; };

void rw_mutex_init(struct rw_mutex* rwm) { rwm->count=0; init_wait_queue_head(&rwm->wait); }

/* i486: 4 asm instructions inline, 1 LOCK */ void acquire_exclusive(struct rw_mutex* rwm) { eax=0 ebx=0x8000 0000 cmpxchg ebx,rwm->lock jnz ok __acquire_failed(); ok: }

/* 2 asm instruction inline, 1 LOCK */ void acquire_shared(struct rw_mutex* rwm) { inc rwm->lock jns ok dec rwm->lock

__acquire_failed() ok: }

void __acquire_failed() { DECLARE_WAITQUEUE(wait,current) add_wait_queue(wait,&rwm->wait); for(;;) { rwm->need_wakeup = 1; set_current_state(); /* rmb() */ if(lock_is_free) break; schedule(); } remove_wait_queue();

} /* 3 asm instructions, 1 LOCK.*/ void release_exclusive(struct rw_mutex* rwm) { lock orl 0x7ffffffff,rwm->lock /* LOCK required for memory ordering */ if(rwm->need_wakeup) __wake_up(); }

/* 3 asm instructions, 1 LOCK.*/ void release_shared(struct rw_mutex* rwm) { lock dec rwm->lock /* LOCK required for memory ordering */ if(rwm->need_wakeup) __wake_up(); }

--------------DEC858512212B394B06D1371 Content-Type: text/plain; charset=us-ascii; name="do.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="do.c"

struct rw_mutex { struct semaphore s1; struct semaphore s1; int count; };

void rw_mutex_init(struct rw_mutex* rwm) { sema_init(&rwm->s1,1); sema_init(&rwm->s2,1); count=-1; }

/* i386: 4 asm instructions inline, 2 LOCK */ void acquire_exclusive(struct rw_mutex* rwm) { down(&rwm->s1); /* this down is only required for fairness */ down(&rwm->s2); }

/* 8 asm instruction inline, 3 LOCK */ void acquire_shared(struct rw_mutex* rwm) { down(&rwm->s1); rwm->count++; if(rwm->count==0) /* zero-flag*/ down(&rwm->s2); up(&rwm->s1); }

/* 4 asm instructions, 2 LOCK.*/ void release_exclusive(struct rw_mutex* rwm) { up(&rwm->s2); up(&rwm->s1); /* this up is only required for fairness */

/* it would possible to merge both up-calls into one * 'lock; orl', but then I need 'rwm->need_wakeup', * and I must replace the 'incl' in down(&sem) * with a (slower) 'bts'. */ }

/* 4 asm instructions, 2 LOCK.*/ void release_shared(struct rw_mutex* rwm) { down(&rwm->s1); /* not required with inline asm */ rwm->count--; if(rwm->count < 0) /* sign-flag */ up(&rwm->s2); up(&rwm->s2); }

--------------DEC858512212B394B06D1371--

- 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/