ngx_gcc_atomic_ppc.h revision e18a033b
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8/*
9 * The ppc assembler treats ";" as comment, so we have to use "\n".
10 * The minus in "bne-" is a hint for the branch prediction unit that
11 * this branch is unlikely to be taken.
12 * The "1b" means the nearest backward label "1" and the "1f" means
13 * the nearest forward label "1".
14 *
15 * The "b" means that the base registers can be used only, i.e.
16 * any register except r0.  The r0 register always has a zero value and
17 * could not be used in "addi  r0, r0, 1".
18 * The "=&b" means that no input registers can be used.
19 *
20 * "sync"    read and write barriers
21 * "isync"   read barrier, is faster than "sync"
22 * "eieio"   write barrier, is faster than "sync"
23 * "lwsync"  write barrier, is faster than "eieio" on ppc64
24 */
25
26#if (NGX_PTR_SIZE == 8)
27
28static ngx_inline ngx_atomic_uint_t
29ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
30    ngx_atomic_uint_t set)
31{
32    ngx_atomic_uint_t  res, temp;
33
34    __asm__ volatile (
35
36    "    li      %0, 0       \n" /* preset "0" to "res"                      */
37    "    lwsync              \n" /* write barrier                            */
38    "1:                      \n"
39    "    ldarx   %1, 0, %2   \n" /* load from [lock] into "temp"             */
40                                 /*   and store reservation                  */
41    "    cmpd    %1, %3      \n" /* compare "temp" and "old"                 */
42    "    bne-    2f          \n" /* not equal                                */
43    "    stdcx.  %4, 0, %2   \n" /* store "set" into [lock] if reservation   */
44                                 /*   is not cleared                         */
45    "    bne-    1b          \n" /* the reservation was cleared              */
46    "    isync               \n" /* read barrier                             */
47    "    li      %0, 1       \n" /* set "1" to "res"                         */
48    "2:                      \n"
49
50    : "=&b" (res), "=&b" (temp)
51    : "b" (lock), "b" (old), "b" (set)
52    : "cc", "memory");
53
54    return res;
55}
56
57
58static ngx_inline ngx_atomic_int_t
59ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
60{
61    ngx_atomic_uint_t  res, temp;
62
63    __asm__ volatile (
64
65    "    lwsync              \n" /* write barrier                            */
66    "1:  ldarx   %0, 0, %2   \n" /* load from [value] into "res"             */
67                                 /*   and store reservation                  */
68    "    add     %1, %0, %3  \n" /* "res" + "add" store in "temp"            */
69    "    stdcx.  %1, 0, %2   \n" /* store "temp" into [value] if reservation */
70                                 /*   is not cleared                         */
71    "    bne-    1b          \n" /* try again if reservation was cleared     */
72    "    isync               \n" /* read barrier                             */
73
74    : "=&b" (res), "=&b" (temp)
75    : "b" (value), "b" (add)
76    : "cc", "memory");
77
78    return res;
79}
80
81
82#if (NGX_SMP)
83#define ngx_memory_barrier()                                                  \
84    __asm__ volatile ("isync  \n  lwsync  \n" ::: "memory")
85#else
86#define ngx_memory_barrier()   __asm__ volatile ("" ::: "memory")
87#endif
88
89#else
90
91static ngx_inline ngx_atomic_uint_t
92ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
93    ngx_atomic_uint_t set)
94{
95    ngx_atomic_uint_t  res, temp;
96
97    __asm__ volatile (
98
99    "    li      %0, 0       \n" /* preset "0" to "res"                      */
100    "    eieio               \n" /* write barrier                            */
101    "1:                      \n"
102    "    lwarx   %1, 0, %2   \n" /* load from [lock] into "temp"             */
103                                 /*   and store reservation                  */
104    "    cmpw    %1, %3      \n" /* compare "temp" and "old"                 */
105    "    bne-    2f          \n" /* not equal                                */
106    "    stwcx.  %4, 0, %2   \n" /* store "set" into [lock] if reservation   */
107                                 /*   is not cleared                         */
108    "    bne-    1b          \n" /* the reservation was cleared              */
109    "    isync               \n" /* read barrier                             */
110    "    li      %0, 1       \n" /* set "1" to "res"                         */
111    "2:                      \n"
112
113    : "=&b" (res), "=&b" (temp)
114    : "b" (lock), "b" (old), "b" (set)
115    : "cc", "memory");
116
117    return res;
118}
119
120
121static ngx_inline ngx_atomic_int_t
122ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
123{
124    ngx_atomic_uint_t  res, temp;
125
126    __asm__ volatile (
127
128    "    eieio               \n" /* write barrier                            */
129    "1:  lwarx   %0, 0, %2   \n" /* load from [value] into "res"             */
130                                 /*   and store reservation                  */
131    "    add     %1, %0, %3  \n" /* "res" + "add" store in "temp"            */
132    "    stwcx.  %1, 0, %2   \n" /* store "temp" into [value] if reservation */
133                                 /*   is not cleared                         */
134    "    bne-    1b          \n" /* try again if reservation was cleared     */
135    "    isync               \n" /* read barrier                             */
136
137    : "=&b" (res), "=&b" (temp)
138    : "b" (value), "b" (add)
139    : "cc", "memory");
140
141    return res;
142}
143
144
145#if (NGX_SMP)
146#define ngx_memory_barrier()                                                  \
147    __asm__ volatile ("isync  \n  eieio  \n" ::: "memory")
148#else
149#define ngx_memory_barrier()   __asm__ volatile ("" ::: "memory")
150#endif
151
152#endif
153
154
155#define ngx_cpu_pause()
156