Re: sparc implementation

From: Vincentius Robby (vincentius_at_umich_dot_edu)
Date: Wed Sep 03 2008 - 10:38:53 PDT

  • Next message: Paul H. Hargrove: "Re: sparc implementation"
    Hello Paul,
    
    Apologies, regarding the directory I forgot to add the CR_ARCH32  
    option because I was working on a 64-bit sparc machine for testing this.
    While my question regarding the fetch and add still stands, I am  
    playing around with the syscall handlers now. Currently the errors I  
    am encountering are:
             then mv -f ".deps/libcr_la-cr_syscall.Tpo"  
    ".deps/libcr_la-cr_syscall.Plo"; else rm -f  
    ".deps/libcr_la-cr_syscall.Tpo"; exit 1; fi
      gcc -DHAVE_CONFIG_H -I. -I../../libcr -I.. -D_GNU_SOURCE  
    -D_REENTRANT -I../include -I../../include -I../../libcr/arch/sparc/  
    -Wall -Wno-unused-function -fno-stack-protector -g -O2 -MT  
    libcr_la-cr_syscall.lo -MD -MP -MF .deps/libcr_la-cr_syscall.Tpo -c  
    ../../libcr/cr_syscall.c  -fPIC -DPIC -o .libs/libcr_la-cr_syscall.o
    ../../libcr/cr_syscall.c:169: error: expected ')' before 'int'
    ../../libcr/cr_syscall.c:170: error: expected ')' before 'const'
    ../../libcr/cr_syscall.c:171: error: expected ')' before 'int'
    ../../libcr/cr_syscall.c: In function '__cri_sched_yield':
    ../../libcr/cr_syscall.c:172: warning: initialization makes integer  
    from pointer without a cast
    ../../libcr/cr_syscall.c:172: error: expected string literal before 'string'
    ../../libcr/cr_syscall.c:172: warning: statement with no effect
    ../../libcr/cr_syscall.c: At top level:
    ../../libcr/cr_syscall.c:173: error: expected ')' before 'const'
    ../../libcr/cr_syscall.c:174: error: expected ')' before 'int'
    ../../libcr/cr_syscall.c:176: error: expected ')' before 'int'
    ../../libcr/cr_syscall.c:183: error: expected ')' before 'int'
    ../../libcr/cr_syscall.c:189: error: expected ')' before 'int'
    make[2]: *** [libcr_la-cr_syscall.lo] Error 1
    make[2]: Leaving directory `/opt/blcr-0.7.3_vincent/builddir/libcr'
    
    and this is what the beginning of libcr/arch/sparc/cr_arch.h looks like:
    #define cri_syscall_cleanup(res,errno_p) \
         __asm__ volatile ("" ::: "memory", "cc", "cx", "dx");\
         if ((unsigned long)res >= (unsigned long)(-4096)) { \
             if (errno_p != NULL) { *errno_p = -res; }       \
             res = -1;                                       \
         }
    
    #define cri_syscall0(type,name,nr)                                      \
    type name(int *errno_p)                                                 \
    {                                                                       \
             register long __o0 __asm__ ("o0");                              \
             register long __g1 __asm__ ("g1") = name;                       \
             __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
                               "0" (__g1) :                                  \
                               __SYSCALL_CLOBBERS);                          \
             __o0;                                                           \
             cri_syscall_cleanup(__g1, errno_p);                             \
    }
    
    #define cri_syscall1(type,name,nr,arg1)                                 \
    type name(type1 arg1,int *errno_p)                                      \
    {                                                                       \
             register long __o0 __asm__ ("o0") = (long)(arg1);               \
             register long __g1 __asm__ ("g1") = name;                       \
             __asm __volatile (string : "=r" (__g1), "=r" (__o0) :           \
                               "0" (__g1), "1" (__o0) :                      \
                               __SYSCALL_CLOBBERS);                          \
             __o0;                                                           \
             cri_syscall_cleanup(__g1, errno_p);                             \
    }
    
    One question I have is where it is written __asm __volatile (string :,  
    is the string to be replaced by 'type'? Originally the inline_syscall  
    has arguments (string,name) so I assumed I had to change the 'string'  
    to 'type' in the __asm __volatile arguments but after these errors I  
    changed it back, but either way it was not a solution to the errors.  
    Is this what you mentioned for the inclusion syscall_cleanup routine  
    as well?
    
    Thank you.
    
    -- 
    Vincentius Robby
    
    
    Quoting "Paul H. Hargrove" <PHHargrove_at_lbl_dot_gov>:
    
    > My best guess is that the -I options are not quite right to include  
    > the libcr/arch/sparc directory.  Take a look at the full command  
    > line that make executes for a file in libcr.  For example, on a i686  
    > I see:
    >
    > /bin/sh ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.  
    > -I.. -I../../libcr -D_GNU_SOURCE -D_REENTRANT -I../include  
    > -I../../include -I../../libcr/arch/i386/   -Wall  
    > -Wno-unused-function -fno-stack-protector  -g -O2 -MT  
    > libcr_la-cr_async.lo -MD -MP -MF .deps/libcr_la-cr_async.Tpo -c -o  
    > libcr_la-cr_async.lo `test -f 'cr_async.c' || echo  
    > '../../libcr/'`cr_async.c
    >
    > Notice the -I../../libcr/arch/i386/ part.  My best guess is that  
    > your says -I../../libcr/arch/sparc64/, rather than  
    > -I../../libcr/arch/sparc/ as you are expecting (note the ../.. is  
    > based on where my build dir is located in relation to my source dir,  
    > your -I's may differ).  If this is the case, then you should  
    > consider sparc and sparc64 dirs with the same relation as the  
    > existing ppc and ppc64 dirs (64 includes the 32bit code).
    >
    > As for the inc and dec-and-test, you can implement them using the following:
    >
    > CR_INLINE unsigned int
    > __cri_atomic_add_fetch(cri_atomic_t *p, unsigned int op)
    > {
    >    unsigned long oldval, newval;
    >    do {
    >        oldval = cri_atomic_read(p);
    >        newval = oldval + op;
    >    } while (!cri_cmp_swap(p, oldval, newval));
    >    return newval;
    > }
    >
    > CR_INLINE void
    > cri_atomic_inc(cri_atomic_t *p)
    > {
    >    (void)__cri_atomic_add_fetch(p, 1);
    > }
    >
    > CR_INLINE int
    > cri_atomic_dec_and_test(cri_atomic_t *p)
    > {
    >    return (__cri_atomic_add_fetch(p, -1) == 0);
    > }
    >
    >
    > These should be considered the "reference" implementations and would  
    > appear in a porting guide if I had written one.
    >
    > However, I think the following would be the (nearly) "optimal"  
    > __cri_atomic_add_fetch() for UltraSPARC and newer:
    >
    > CR_INLINE unsigned int
    > __cri_atomic_add_fetch(cri_atomic_t *p, unsigned int op)
    > {
    >    register unsigned int oldval, newval;
    >    __asm__ __volatile__ (
    >        "ld       [%4],%0    \n\t" /* oldval = *addr; */
    >        "0:                  \t"
    >        "add      %0,%3,%1   \n\t" /* newval = oldval + op; */
    >        "cas      [%4],%0,%1 \n\t" /* if (*addr == oldval)  
    > SWAP(*addr,newval); else newval = *addr; */
    >        "cmp      %0, %1     \n\t" /* check if newval == oldval (swap  
    > succeeded) */
    >        "bne,a,pn %%icc, 0b  \n\t" /* otherwise, retry (,pn ==  
    > predict not taken; ,a == annul) */
    >        "  mov    %1, %0     "     /* oldval = newval; (branch delay  
    > slot, annulled if not taken) */
    >        : "=&r"(oldval), "=&r"(newval), "=m"(*p)
    >        : "rn"(op), "r"(p), "m"(*p) );
    >    return newval;
    > }
    >
    >
    > If I got that right (based on a different SPARC atomics project I  
    > worked on), the generated asm for atomic inc and dec-and-test will  
    > use immediate +1 and -1 arguments to the add instruction.
    >
    > I'll need to think about whether you need any memory barriers to  
    > make this 100% correct on the SPARC architecture.  Have you  
    > considered that for the cri_cmp_swap()?
    >
    > The syscall code is found in glibc.  For instance in  
    > glibc-2.6/sysdeps/unix/sysv/linux/sparc/sysdep.h, where you'll want  
    > to use guts of the inline_syscall0() through inline_syscall5()  
    > macros, combined with the errno handling as seen in  
    > blcr/libcr/arch/i386/cr_arch.h:cri_syscall_cleanup().
    >
    > Just to be 100% proper about this code I've included here:
    > Signed-off-by: Paul H. Hargrove <PHHargrove_at_lbl_dot_gov>
    >
    > -Paul
    >
    > Vincentius Robby wrote:
    >> Thank you Paul,
    >>
    >> Now even after I put the cr_arch.h and cr_atomic.h under  
    >> libcr/arch/sparc, the following errors appear:
    >> In file included from ../../libcr/cr_async.c:37:
    >> ../../libcr/cr_private.h:63:23: error: cr_atomic.h: No such file or  
    >> directory
    >> In file included from ../../libcr/cr_private.h:65,
    >>                 from ../../libcr/cr_async.c:37:
    >> [some more errors]
    >> ../../libcr/cr_private.h:66:21: error: cr_arch.h: No such file or directory
    >>
    >> Do I have to change something else for blcr to realize the files' existence?
    >> Also, would you be able to point me to some other resources for the  
    >> assembly codes? For cr_atomic.h, I understood how to implement  
    >> compare_and_swap but I am not able to infer the atomic increment  
    >> and decrement and test from the glibc source codes as well as the  
    >> source for other architectures. For the syscall functions, would  
    >> you know of where can I look into? Should the glibc have these?
    >>
    >> Thank you very much for the help, I've been slowly looking into  
    >> these for a while, but my inexperience hinders me from advancing as  
    >> quick.
    >>
    >
    >
    > -- 
    > Paul H. Hargrove                          PHHargrove_at_lbl_dot_gov
    > Future Technologies Group                 HPC Research Department     
    >                Tel: +1-510-495-2352
    > Lawrence Berkeley National Laboratory     Fax: +1-510-486-6900
    >
    >
    >
    >
    

  • Next message: Paul H. Hargrove: "Re: sparc implementation"