[parisc-linux] Re:[parisc-linux-cvs] linux-2.6 kyle

Joel Soete soete.joel at scarlet.be
Tue Aug 22 08:37:29 MDT 2006


> On Sun August 20 2006 21:47, Grant Grundler wrote:
> > On Thu, Aug 17, 2006 at 10:02:51AM +0200, Joel Soete wrote:
> > > One more question (according to assembly stuff)
> > > what happen when the two cpu excute at the same time the same:
> > > 
> > >  ldcw,co 0(%r3),%r28
> > 
> > Simply answer: One of the CPUs loses bus arbitration and will stall
> > until it can get access to the "central bus" (e.g. runway or Mckinley).
> > The CPUs no longer execute insn "at the same time" after that.
> > 
Sorry for late answer but I was sadly spining in this nightmare ;-)

I would like to thank all of you for kind advises: they help me to understand
some stuff a bit more:
  1/ "central bus" manage arbitration in such situation,
  2/ a 'cache line' is the smallest memory cache block which can be transfered
     between ram and cache?
  3/ from cpu view this cache line can be of 16, 32, 64 bytes
     (may be 128 for newer) in length but that's the memory controler
     of the "central bus" which give the actual value?
 
> > BTW, I like the URL Michael Zick posted in reply.
> >
> 
> If you meant my draft paper, there is a *.pdf version also:
> http://www.morethan.org/parisc/pa-spinlocks.pdf
> 
> That draft is all of the published information I could find,
> If anything else ever slips out of the hp tech. vaults...
> 

well it seems that I also missed an important detail: the 2 smp I am trying
are pa8000 (d380) and pa8600 (n4k), i.e. all pa2.0 family which afaik are all
weakly ordered?

Could be the pb which can solve Mike's proposal?

In my small head, it became as a very first draft:
for the "Anderson Acquire":
static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock)
{
        unsigned long ret;
        volatile unsigned int *aligned_lock;
        mb();
        aligned_lock = __ldcw_align(lock);
        asm volatile ("\n"
                "ldw,sl         0(%1), %0       \n"
        "1:     /* repeat */                    \n\t"
                "cmpib,=,n      0, %0, 1b       \n\t"
                "ldw,sl         0(%1), %0       \n\t"
                /* Three instructions critical to a no-race lock */
        "2:     /* may_be */                    \n\t"
                /* No outstanding transactions */
                "sync                           \n\t"
                "ldcw,co        0(%1), %0       \n\t"
                /*
                   Set state Private-Dirty if not yet set.
                        Enables memory write-back if line is copied.
                   Set the sl condition.
                        Forces write-to-memory if line is displaced.
                 */
                "stbys,e,sl     %%r0, 0(%1)     \n\t"
                /* Now test if it is really ours */
                "cmpib,=,n      0, %0, repeat   \n\t"
                "ldw,sl         0(%1), %0       \n\t"
        "3:     /* got_it */                    \n\t"
                : "=r"(ret)
                : "r"(aligned_lock)
        );
        return ret;
        mb();
}

and for the Anderson release:
static __inline__ void __spin_unlock(raw_spinlock_t *x)
{
        volatile unsigned int *aligned_lock;
        mb();
        aligned_lock = __ldcw_align(x);
        __asm__ __volatile__ ("\n"
                "ldi            1, %%r28        \n\t"
                "stw,sl         %%ret0, 0(%0)   \n\t"
                "sync                           \n\t"
                : /* no output */
                : "r"(aligned_lock)
                : "r28"
        );
        mb();
}

which I expect to use like e.g. (the basic idea being from powerpc
implementation):

static inline void __raw_spin_lock(raw_spinlock_t *x)
{
        mb();
        while (1) {
                if (likely(__spin_trylock(x) !=0))
                        break;
                __raw_spin_unlock_wait(x);
        }
        mb();
}

All comments, advise are obvioulsy welcome.


That said I also noticed this:
static  __inline__ void __raw_write_lock(raw_rwlock_t *rw)
{
retry:
        __raw_spin_lock(&rw->lock);

        if(rw->counter != 0) {
                /* this basically never happens */
                __raw_spin_unlock(&rw->lock);

                while (rw->counter != 0)
                        cpu_relax();

                goto retry;
        }

        /* got it.  now leave without unlocking */
        rw->counter = -1; /* remember we are locked */
}

afaik no pb here: at the end of if() we loop on retry and "leave without
unlocking" as comment said.

Let trust it for now and check the other stuff:
static  __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
{
        __raw_spin_lock(&rw->lock);
        if (rw->counter != 0) {
                /* this basically never happens */
                __raw_spin_unlock(&rw->lock);

                return 0;
        }

        /* got it.  now leave without unlocking */
        rw->counter = -1; /* remember we are locked */
        return 1;
}

otoh here the spinlock status (locked or unlocked) is not always the same, is
it right?

Thanks again,
    Joel

PS: I would also read back this intersting doc
<http://h21007.www2.hp.com/dspp/files/unprotected/itanium/spinlocks.pdf> still
available on Sunday but not anymore on Monday. Is there some other place where
a copy could stand?

----------
Club Scarlet : Tout le monde gagne! Si vous devenez aujourd'hui Scarlet One grace a un client existant de Scarlet, vous recevez tous les deux un cadeau d'une valeur de 50 euros! Surfez vite sur http://www.clubscarlet.be




More information about the parisc-linux mailing list