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 return APR_SUCCESS; 30} 31 32APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) 33{ 34 return *mem; 35} 36 37APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) 38{ 39 *mem = val; 40} 41 42APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) 43{ 44 apr_uint32_t prev, temp; 45 46 asm volatile ("1:\n" /* lost reservation */ 47 " lwarx %0,0,%3\n" /* load and reserve */ 48 " add %1,%0,%4\n" /* add val and prev */ 49 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 50 " stwcx. %1,0,%3\n" /* store new value */ 51 " bne- 1b\n" /* loop if lost */ 52 : "=&r" (prev), "=&r" (temp), "=m" (*mem) 53 : "b" (mem), "r" (val) 54 : "cc", "memory"); 55 56 return prev; 57} 58 59APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) 60{ 61 apr_uint32_t temp; 62 63 asm volatile ("1:\n" /* lost reservation */ 64 " lwarx %0,0,%2\n" /* load and reserve */ 65 " subf %0,%3,%0\n" /* subtract val */ 66 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 67 " stwcx. %0,0,%2\n" /* store new value */ 68 " bne- 1b\n" /* loop if lost */ 69 : "=&r" (temp), "=m" (*mem) 70 : "b" (mem), "r" (val) 71 : "cc", "memory"); 72} 73 74APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) 75{ 76 apr_uint32_t prev; 77 78 asm volatile ("1:\n" /* lost reservation */ 79 " lwarx %0,0,%2\n" /* load and reserve */ 80 " addi %0,%0,1\n" /* add immediate */ 81 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 82 " stwcx. %0,0,%2\n" /* store new value */ 83 " bne- 1b\n" /* loop if lost */ 84 " subi %0,%0,1\n" /* return old value */ 85 : "=&b" (prev), "=m" (*mem) 86 : "b" (mem), "m" (*mem) 87 : "cc", "memory"); 88 89 return prev; 90} 91 92APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) 93{ 94 apr_uint32_t prev; 95 96 asm volatile ("1:\n" /* lost reservation */ 97 " lwarx %0,0,%2\n" /* load and reserve */ 98 " subi %0,%0,1\n" /* subtract immediate */ 99 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 100 " stwcx. %0,0,%2\n" /* store new value */ 101 " bne- 1b\n" /* loop if lost */ 102 : "=&b" (prev), "=m" (*mem) 103 : "b" (mem), "m" (*mem) 104 : "cc", "memory"); 105 106 return prev; 107} 108 109APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, 110 apr_uint32_t cmp) 111{ 112 apr_uint32_t prev; 113 114 asm volatile ("1:\n" /* lost reservation */ 115 " lwarx %0,0,%1\n" /* load and reserve */ 116 " cmpw %0,%3\n" /* compare operands */ 117 " bne- exit_%=\n" /* skip if not equal */ 118 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 119 " stwcx. %2,0,%1\n" /* store new value */ 120 " bne- 1b\n" /* loop if lost */ 121 "exit_%=:\n" /* not equal */ 122 : "=&r" (prev) 123 : "b" (mem), "r" (with), "r" (cmp) 124 : "cc", "memory"); 125 126 return prev; 127} 128 129APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) 130{ 131 apr_uint32_t prev; 132 133 asm volatile ("1:\n" /* lost reservation */ 134 " lwarx %0,0,%1\n" /* load and reserve */ 135 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 136 " stwcx. %2,0,%1\n" /* store new value */ 137 " bne- 1b" /* loop if lost */ 138 : "=&r" (prev) 139 : "b" (mem), "r" (val) 140 : "cc", "memory"); 141 142 return prev; 143} 144 145APR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) 146{ 147 void *prev; 148#if APR_SIZEOF_VOIDP == 4 149 asm volatile ("1:\n" /* lost reservation */ 150 " lwarx %0,0,%1\n" /* load and reserve */ 151 " cmpw %0,%3\n" /* compare operands */ 152 " bne- 2f\n" /* skip if not equal */ 153 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 154 " stwcx. %2,0,%1\n" /* store new value */ 155 " bne- 1b\n" /* loop if lost */ 156 "2:\n" /* not equal */ 157 : "=&r" (prev) 158 : "b" (mem), "r" (with), "r" (cmp) 159 : "cc", "memory"); 160#elif APR_SIZEOF_VOIDP == 8 161 asm volatile ("1:\n" /* lost reservation */ 162 " ldarx %0,0,%1\n" /* load and reserve */ 163 " cmpd %0,%3\n" /* compare operands */ 164 " bne- 2f\n" /* skip if not equal */ 165 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 166 " stdcx. %2,0,%1\n" /* store new value */ 167 " bne- 1b\n" /* loop if lost */ 168 "2:\n" /* not equal */ 169 : "=&r" (prev) 170 : "b" (mem), "r" (with), "r" (cmp) 171 : "cc", "memory"); 172#else 173#error APR_SIZEOF_VOIDP value not supported 174#endif 175 return prev; 176} 177 178APR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem, void *with) 179{ 180 void *prev; 181#if APR_SIZEOF_VOIDP == 4 182 asm volatile ("1:\n" /* lost reservation */ 183 " lwarx %0,0,%1\n" /* load and reserve */ 184 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 185 " stwcx. %2,0,%1\n" /* store new value */ 186 " bne- 1b\n" /* loop if lost */ 187 " isync\n" /* memory barrier */ 188 : "=&r" (prev) 189 : "b" (mem), "r" (with) 190 : "cc", "memory"); 191#elif APR_SIZEOF_VOIDP == 8 192 asm volatile ("1:\n" /* lost reservation */ 193 " ldarx %0,0,%1\n" /* load and reserve */ 194 PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ 195 " stdcx. %2,0,%1\n" /* store new value */ 196 " bne- 1b\n" /* loop if lost */ 197 " isync\n" /* memory barrier */ 198 : "=&r" (prev) 199 : "b" (mem), "r" (with) 200 : "cc", "memory"); 201#else 202#error APR_SIZEOF_VOIDP value not supported 203#endif 204 return prev; 205} 206 207#endif /* USE_ATOMICS_PPC */ 208