From: "H . J . Lu" <hjl@lucon.org> Subject: Re: [libc-alpha] Re: PATCH: Fix ll/sc for mips Date: Thu, 31 Jan 2002 23:00:50 -0800 > On Fri, Feb 01, 2002 at 01:59:03PM +0900, Hiroyuki Machida wrote: > > > > From: Kaz Kylheku <kaz@ashi.footprints.net> > > Subject: Re: [libc-alpha] Re: PATCH: Fix ll/sc for mips > > Date: Thu, 31 Jan 2002 20:02:25 -0800 (PST) > > > > > On Fri, 1 Feb 2002, Hiroyuki Machida wrote: > > > > Please note that "sc" may fail even if nobody write the > > > > variable. (See P.211 "8.4.2 Load-Linked/Sotre-Conditional" of "See > > > > MIPS RUN" for more detail.) > > > > So, after your patch applied, compare_and_swap() may fail, even if > > > > *p is equal to oldval. > > > > > > I can't think of anything that will break because of this, as long > > > as the compare_and_swap eventually succeeds on some subsequent trial. > > > If the atomic operation has to abort for some reason other than *p being > > > unequal to oldval, that should be cool. > > > > I mean that this patch breaks the spec of compare_and_swap(). > > In most case, this patch may works as Kaz said. If this patch have > > no side-effect to any application, it's ok to apply the patch. But > > we can't know how to use compare_and_swap() in all aplications in a > > whole world. So we have to follow the spec. > > > > Please note that the old compare_and_swap is broken. If you use > compare_and_swap to check if *p == oldval, my patch doesn't help > you. But if you use it to swap old/new, my patch works fine. But I > don't think you can use it check if *p == oldval since *p can change > at any time. It is the same as simply using "*p == oldval". I don't > see my patch should break any sane applications. > > > H.J. > I know the orinal compare_and_swap() is bad, and I believe the spec of compare_and_swap() as below; compare_and_swap(p, oldval, newval) { retval = 0; begin_atomic if (*p==oldval) { *p = newval; retval = 1; } end_atomic return retval; } So, compare_and_swap() should be ... __compare_and_swap (a0 long int oldval, long int newval) a0: *p a1: oldval a2: newval v0: return value .set noreorder retry: ll v0, (a0) bne v0, a1 move v0, zero move v0, a2 sc v0, (a0) beqz v0, retry nop j ra But, with your patch ... .set noreorder ll t0, (a0) bne t0, a1 move v0, zero move v0, a sc v0, (a0) j ra In this way, compare_and_swap() was changed as compare_and_swap(p, oldval, newval) { retval = 0; begin_atomic if (*p==oldval) { if "sc" was failed goto out; *p = newval; retval = 1; } out: end_atomic return retval; } --- Hiroyuki Machida Sony Corp.