1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_arch_atomic.h" 18 19#ifdef USE_ATOMICS_PPC 20 21#ifdef PPC405_ERRATA 22# define PPC405_ERR77_SYNC " sync\n" 23#else 24# define PPC405_ERR77_SYNC 25#endif 26 27APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p) 28{ 29#if defined (NEED_ATOMICS_GENERIC64) 30 return apr__atomic_generic64_init(p); 31#else 32 return APR_SUCCESS; 33#endif 34} 35 36APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) 37{ 38 return *mem; 39} 40 41APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) 42{ 43 *mem = val; 44} 45 46APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) 47{ 48 apr_uint32_t prev, temp; 49 50 asm volatile ("1:\n" /* lost reservation */ 51 " lwarx %0,0,%3\n" /* load and reserve */ 52 " add %1,%0,%4\n" /* add val and prev */ 53 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 54 " stwcx. %1,0,%3\n" /* store new value */ 55 " bne- 1b\n" /* loop if lost */ 56 : "=&r" (prev), "=&r" (temp), "=m" (*mem) 57 : "b" (mem), "r" (val) 58 : "cc", "memory"); 59 60 return prev; 61} 62 63APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) 64{ 65 apr_uint32_t temp; 66 67 asm volatile ("1:\n" /* lost reservation */ 68 " lwarx %0,0,%2\n" /* load and reserve */ 69 " subf %0,%3,%0\n" /* subtract val */ 70 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 71 " stwcx. %0,0,%2\n" /* store new value */ 72 " bne- 1b\n" /* loop if lost */ 73 : "=&r" (temp), "=m" (*mem) 74 : "b" (mem), "r" (val) 75 : "cc", "memory"); 76} 77 78APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) 79{ 80 apr_uint32_t prev; 81 82 asm volatile ("1:\n" /* lost reservation */ 83 " lwarx %0,0,%2\n" /* load and reserve */ 84 " addi %0,%0,1\n" /* add immediate */ 85 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 86 " stwcx. %0,0,%2\n" /* store new value */ 87 " bne- 1b\n" /* loop if lost */ 88 " subi %0,%0,1\n" /* return old value */ 89 : "=&b" (prev), "=m" (*mem) 90 : "b" (mem), "m" (*mem) 91 : "cc", "memory"); 92 93 return prev; 94} 95 96APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) 97{ 98 apr_uint32_t prev; 99 100 asm volatile ("1:\n" /* lost reservation */ 101 " lwarx %0,0,%2\n" /* load and reserve */ 102 " subi %0,%0,1\n" /* subtract immediate */ 103 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 104 " stwcx. %0,0,%2\n" /* store new value */ 105 " bne- 1b\n" /* loop if lost */ 106 : "=&b" (prev), "=m" (*mem) 107 : "b" (mem), "m" (*mem) 108 : "cc", "memory"); 109 110 return prev; 111} 112 113APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, 114 apr_uint32_t cmp) 115{ 116 apr_uint32_t prev; 117 118 asm volatile ("1:\n" /* lost reservation */ 119 " lwarx %0,0,%1\n" /* load and reserve */ 120 " cmpw %0,%3\n" /* compare operands */ 121 " bne- exit_%=\n" /* skip if not equal */ 122 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 123 " stwcx. %2,0,%1\n" /* store new value */ 124 " bne- 1b\n" /* loop if lost */ 125 "exit_%=:\n" /* not equal */ 126 : "=&r" (prev) 127 : "b" (mem), "r" (with), "r" (cmp) 128 : "cc", "memory"); 129 130 return prev; 131} 132 133APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) 134{ 135 apr_uint32_t prev; 136 137 asm volatile ("1:\n" /* lost reservation */ 138 " lwarx %0,0,%1\n" /* load and reserve */ 139 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 140 " stwcx. %2,0,%1\n" /* store new value */ 141 " bne- 1b" /* loop if lost */ 142 : "=&r" (prev) 143 : "b" (mem), "r" (val) 144 : "cc", "memory"); 145 146 return prev; 147} 148 149APR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) 150{ 151 void *prev; 152#if APR_SIZEOF_VOIDP == 4 153 asm volatile ("1:\n" /* lost reservation */ 154 " lwarx %0,0,%1\n" /* load and reserve */ 155 " cmpw %0,%3\n" /* compare operands */ 156 " bne- 2f\n" /* skip if not equal */ 157 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 158 " stwcx. %2,0,%1\n" /* store new value */ 159 " bne- 1b\n" /* loop if lost */ 160 "2:\n" /* not equal */ 161 : "=&r" (prev) 162 : "b" (mem), "r" (with), "r" (cmp) 163 : "cc", "memory"); 164#elif APR_SIZEOF_VOIDP == 8 165 asm volatile ("1:\n" /* lost reservation */ 166 " ldarx %0,0,%1\n" /* load and reserve */ 167 " cmpd %0,%3\n" /* compare operands */ 168 " bne- 2f\n" /* skip if not equal */ 169 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 170 " stdcx. %2,0,%1\n" /* store new value */ 171 " bne- 1b\n" /* loop if lost */ 172 "2:\n" /* not equal */ 173 : "=&r" (prev) 174 : "b" (mem), "r" (with), "r" (cmp) 175 : "cc", "memory"); 176#else 177#error APR_SIZEOF_VOIDP value not supported 178#endif 179 return prev; 180} 181 182APR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem, void *with) 183{ 184 void *prev; 185#if APR_SIZEOF_VOIDP == 4 186 asm volatile ("1:\n" /* lost reservation */ 187 " lwarx %0,0,%1\n" /* load and reserve */ 188 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 189 " stwcx. %2,0,%1\n" /* store new value */ 190 " bne- 1b\n" /* loop if lost */ 191 " isync\n" /* memory barrier */ 192 : "=&r" (prev) 193 : "b" (mem), "r" (with) 194 : "cc", "memory"); 195#elif APR_SIZEOF_VOIDP == 8 196 asm volatile ("1:\n" /* lost reservation */ 197 " ldarx %0,0,%1\n" /* load and reserve */ 198 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 199 " stdcx. %2,0,%1\n" /* store new value */ 200 " bne- 1b\n" /* loop if lost */ 201 " isync\n" /* memory barrier */ 202 : "=&r" (prev) 203 : "b" (mem), "r" (with) 204 : "cc", "memory"); 205#else 206#error APR_SIZEOF_VOIDP value not supported 207#endif 208 return prev; 209} 210 211#endif /* USE_ATOMICS_PPC */ 212