ia32.c revision 256281
1145479Smp/* Licensed to the Apache Software Foundation (ASF) under one or more 259243Sobrien * contributor license agreements. See the NOTICE file distributed with 359243Sobrien * this work for additional information regarding copyright ownership. 459243Sobrien * The ASF licenses this file to You under the Apache License, Version 2.0 559243Sobrien * (the "License"); you may not use this file except in compliance with 659243Sobrien * the License. You may obtain a copy of the License at 759243Sobrien * 859243Sobrien * http://www.apache.org/licenses/LICENSE-2.0 959243Sobrien * 1059243Sobrien * Unless required by applicable law or agreed to in writing, software 1159243Sobrien * distributed under the License is distributed on an "AS IS" BASIS, 1259243Sobrien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1359243Sobrien * See the License for the specific language governing permissions and 1459243Sobrien * limitations under the License. 1559243Sobrien */ 1659243Sobrien 1759243Sobrien#include "apr_arch_atomic.h" 1859243Sobrien 1959243Sobrien#ifdef USE_ATOMICS_IA32 2059243Sobrien 2159243SobrienAPR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p) 2259243Sobrien{ 2359243Sobrien return APR_SUCCESS; 2459243Sobrien} 25100616Smp 2659243SobrienAPR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) 2759243Sobrien{ 2859243Sobrien return *mem; 2959243Sobrien} 3059243Sobrien 3159243SobrienAPR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) 3259243Sobrien{ 3359243Sobrien *mem = val; 3459243Sobrien} 3559243Sobrien 3659243SobrienAPR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) 3759243Sobrien{ 3859243Sobrien asm volatile ("lock; xaddl %0,%1" 3959243Sobrien : "=r" (val), "=m" (*mem) 4059243Sobrien : "0" (val), "m" (*mem) 4159243Sobrien : "memory", "cc"); 4259243Sobrien return val; 43145479Smp} 4459243Sobrien 4559243SobrienAPR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) 4659243Sobrien{ 4759243Sobrien asm volatile ("lock; subl %1, %0" 4859243Sobrien : /* no output */ 4959243Sobrien : "m" (*(mem)), "r" (val) 5069408Sache : "memory", "cc"); 5159243Sobrien} 5259243Sobrien 5359243SobrienAPR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) 5459243Sobrien{ 5569408Sache return apr_atomic_add32(mem, 1); 5659243Sobrien} 5759243Sobrien 5859243SobrienAPR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) 5959243Sobrien{ 6059243Sobrien unsigned char prev; 6159243Sobrien 6259243Sobrien asm volatile ("lock; decl %0; setnz %1" 6359243Sobrien : "=m" (*mem), "=qm" (prev) 6459243Sobrien : "m" (*mem) 6559243Sobrien : "memory"); 6659243Sobrien 6759243Sobrien return prev; 6859243Sobrien} 6959243Sobrien 7059243SobrienAPR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, 7159243Sobrien apr_uint32_t cmp) 7259243Sobrien{ 7359243Sobrien apr_uint32_t prev; 7459243Sobrien 7559243Sobrien asm volatile ("lock; cmpxchgl %1, %2" 7659243Sobrien : "=a" (prev) 7759243Sobrien : "r" (with), "m" (*(mem)), "0"(cmp) 7859243Sobrien : "memory", "cc"); 7959243Sobrien return prev; 8059243Sobrien} 8159243Sobrien 8259243SobrienAPR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) 8359243Sobrien{ 8459243Sobrien apr_uint32_t prev = val; 8559243Sobrien 8659243Sobrien asm volatile ("xchgl %0, %1" 8759243Sobrien : "=r" (prev), "+m" (*mem) 8859243Sobrien : "0" (prev)); 8959243Sobrien return prev; 9059243Sobrien} 9159243Sobrien 9259243SobrienAPR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) 9359243Sobrien{ 9459243Sobrien void *prev; 9559243Sobrien#if APR_SIZEOF_VOIDP == 4 9659243Sobrien asm volatile ("lock; cmpxchgl %2, %1" 9759243Sobrien : "=a" (prev), "=m" (*mem) 9859243Sobrien : "r" (with), "m" (*mem), "0" (cmp)); 9959243Sobrien#elif APR_SIZEOF_VOIDP == 8 10059243Sobrien asm volatile ("lock; cmpxchgq %q2, %1" 10159243Sobrien : "=a" (prev), "=m" (*mem) 10259243Sobrien : "r" ((unsigned long)with), "m" (*mem), 10359243Sobrien "0" ((unsigned long)cmp)); 10459243Sobrien#else 10559243Sobrien#error APR_SIZEOF_VOIDP value not supported 10659243Sobrien#endif 10759243Sobrien return prev; 10859243Sobrien} 10959243Sobrien 11059243SobrienAPR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem, void *with) 11159243Sobrien{ 11259243Sobrien void *prev; 11359243Sobrien#if APR_SIZEOF_VOIDP == 4 11459243Sobrien asm volatile ("xchgl %2, %1" 11559243Sobrien : "=a" (prev), "+m" (*mem) 11659243Sobrien : "0" (with)); 11759243Sobrien#elif APR_SIZEOF_VOIDP == 8 11859243Sobrien asm volatile ("xchgq %q2, %1" 11959243Sobrien : "=a" (prev), "+m" (*mem) 12059243Sobrien : "0" (with)); 12159243Sobrien#else 12259243Sobrien#error APR_SIZEOF_VOIDP value not supported 12359243Sobrien#endif 12459243Sobrien return prev; 12559243Sobrien} 12659243Sobrien 12759243Sobrien#endif /* USE_ATOMICS_IA32 */ 12859243Sobrien