Home | History | Annotate | Download | only in tests
      1 
      2 #include <pthread.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 
      6 /* Simple test program, no race.  Parent and child both modify x and
      7    use the hardware bus lock. */
      8 
      9 #undef PLAT_x86_darwin
     10 #undef PLAT_amd64_darwin
     11 #undef PLAT_x86_linux
     12 #undef PLAT_amd64_linux
     13 #undef PLAT_ppc32_linux
     14 #undef PLAT_ppc64_linux
     15 #undef PLAT_arm_linux
     16 #undef PLAT_arm64_linux
     17 #undef PLAT_s390x_linux
     18 #undef PLAT_mips32_linux
     19 #undef PLAT_tilegx_linux
     20 #undef PLAT_x86_solaris
     21 #undef PLAT_amd64_solaris
     22 
     23 #if defined(__APPLE__) && defined(__i386__)
     24 #  define PLAT_x86_darwin 1
     25 #elif defined(__APPLE__) && defined(__x86_64__)
     26 #  define PLAT_amd64_darwin 1
     27 #elif defined(__linux__) && defined(__i386__)
     28 #  define PLAT_x86_linux 1
     29 #elif defined(__linux__) && defined(__x86_64__)
     30 #  define PLAT_amd64_linux 1
     31 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
     32 #  define PLAT_ppc32_linux 1
     33 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
     34 #  define PLAT_ppc64_linux 1
     35 #elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
     36 #  define PLAT_arm_linux 1
     37 #elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
     38 #  define PLAT_arm64_linux 1
     39 #elif defined(__linux__) && defined(__s390x__)
     40 #  define PLAT_s390x_linux 1
     41 #elif defined(__linux__) && defined(__mips__)
     42 #  define PLAT_mips32_linux 1
     43 #elif defined(__linux__) && defined(__tilegx__)
     44 #  define PLAT_tilegx_linux 1
     45 #elif defined(__sun__) && defined(__i386__)
     46 #  define PLAT_x86_solaris 1
     47 #elif defined(__sun__) && defined(__x86_64__)
     48 #  define PLAT_amd64_solaris 1
     49 #endif
     50 
     51 #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \
     52     || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \
     53     || defined(PLAT_amd64_solaris) || defined(PLAT_x86_solaris)
     54 #  define INC(_lval,_lqual) \
     55       __asm__ __volatile__ ( \
     56       "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" )
     57 #elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux)
     58 #  define INC(_lval,_lqual)               \
     59    __asm__ __volatile__(                  \
     60       "1:\n"                              \
     61       "        lwarx 15,0,%0\n"           \
     62       "        addi 15,15,1\n"            \
     63       "        stwcx. 15,0,%0\n"          \
     64       "        bne- 1b\n"                 \
     65       : /*out*/ : /*in*/ "b"(&(_lval))    \
     66       : /*trash*/ "r15", "cr0", "memory"  \
     67    )
     68 #elif defined(PLAT_arm_linux)
     69 #  define INC(_lval,_lqual) \
     70   __asm__ __volatile__( \
     71       "1:\n"                                 \
     72       "        ldrex r8, [%0, #0]\n"         \
     73       "        add   r8, r8, #1\n"           \
     74       "        strex r9, r8, [%0, #0]\n"     \
     75       "        cmp   r9, #0\n"               \
     76       "        bne   1b\n"                   \
     77       : /*out*/ : /*in*/ "r"(&(_lval))       \
     78       : /*trash*/ "r8", "r9", "cc", "memory" \
     79   );
     80 #elif defined(PLAT_arm64_linux)
     81 #  define INC(_lval,_lqual) \
     82   __asm__ __volatile__( \
     83       "1:\n"                                 \
     84       "        ldxr  w8, [%0, #0]\n"         \
     85       "        add   w8, w8, #1\n"           \
     86       "        stxr  w9, w8, [%0, #0]\n"     \
     87       "        cmp   w9, #0\n"               \
     88       "        bne   1b\n"                   \
     89       : /*out*/ : /*in*/ "r"(&(_lval))       \
     90       : /*trash*/ "x8", "x9", "cc", "memory" \
     91   );
     92 #elif defined(PLAT_s390x_linux)
     93 #  define INC(_lval,_lqual) \
     94    __asm__ __volatile__( \
     95       "1: l     0,%0\n"                            \
     96       "   lr    1,0\n"                             \
     97       "   ahi   1,1\n"                             \
     98       "   cs    0,1,%0\n"                          \
     99       "   jl    1b\n"                              \
    100       : "+m" (_lval) :: "cc", "1","2" \
    101    )
    102 #elif defined(PLAT_mips32_linux)
    103 #  define INC(_lval,_lqual)                         \
    104      __asm__ __volatile__ (                         \
    105       "1:\n"                                        \
    106       "        move $8, %0\n"                       \
    107       "        ll $9, 0($8)\n"                      \
    108       "        addiu $9, $9, 1\n"                   \
    109       "        sc $9, 0($8)\n"                      \
    110       "        li $10, 1\n"                         \
    111       "        bne $9, $10, 1b\n"                   \
    112       "        nop\n"                               \
    113       : /*out*/ : /*in*/ "r"(&(_lval))              \
    114       : /*trash*/ "$8", "$9", "$10", "cc", "memory" \
    115    )
    116 #elif defined(PLAT_tilegx_linux)
    117 #  define INC(_lval,_lqual)                        \
    118    if (sizeof(_lval) == 4)                         \
    119       __insn_fetchadd(&(_lval), 1);                \
    120    else if(sizeof(_lval) == 8)                     \
    121       __insn_fetchadd(&(_lval), 1)
    122 #else
    123 #  error "Fix Me for this platform"
    124 #endif
    125 
    126 
    127 int x = 0;
    128 
    129 void* child_fn ( void* arg )
    130 {
    131    INC(x, "childfn");
    132    return NULL;
    133 }
    134 
    135 int main ( void )
    136 {
    137    pthread_t child;
    138 
    139    if (pthread_create(&child, NULL, child_fn, NULL)) {
    140       perror("pthread_create");
    141       exit(1);
    142    }
    143 
    144    INC(x, "main");
    145 
    146    if (pthread_join(child, NULL)) {
    147       perror("pthread join");
    148       exit(1);
    149    }
    150 
    151    printf("x = %d\n", x);
    152    return 0;
    153 }
    154