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 18#include "apr.h" 19#include "apr_atomic.h" 20 21#include <stdlib.h> 22 23apr_status_t apr_atomic_init(apr_pool_t *p) 24{ 25 return APR_SUCCESS; 26} 27 28apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) 29{ 30 apr_uint32_t old, new_val; 31 32 old = *mem; /* old is automatically updated on cs failure */ 33 do { 34 new_val = old + val; 35 } while (__cs(&old, (cs_t *)mem, new_val)); 36 return old; 37} 38 39void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) 40{ 41 apr_uint32_t old, new_val; 42 43 old = *mem; /* old is automatically updated on cs failure */ 44 do { 45 new_val = old - val; 46 } while (__cs(&old, (cs_t *)mem, new_val)); 47} 48 49apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem) 50{ 51 return apr_atomic_add32(mem, 1); 52} 53 54int apr_atomic_dec32(volatile apr_uint32_t *mem) 55{ 56 apr_uint32_t old, new_val; 57 58 old = *mem; /* old is automatically updated on cs failure */ 59 do { 60 new_val = old - 1; 61 } while (__cs(&old, (cs_t *)mem, new_val)); 62 63 return new_val != 0; 64} 65 66apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem) 67{ 68 return *mem; 69} 70 71void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) 72{ 73 *mem = val; 74} 75 76apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t swap, 77 apr_uint32_t cmp) 78{ 79 apr_uint32_t old = cmp; 80 81 __cs(&old, (cs_t *)mem, swap); 82 return old; /* old is automatically updated from mem on cs failure */ 83} 84 85#if APR_SIZEOF_VOIDP == 4 86void *apr_atomic_casptr(volatile void **mem_ptr, 87 void *swap_ptr, 88 const void *cmp_ptr) 89{ 90 __cs1(&cmp_ptr, /* automatically updated from mem on __cs1 failure */ 91 mem_ptr, /* set from swap when __cs1 succeeds */ 92 &swap_ptr); 93 return (void *)cmp_ptr; 94} 95#elif APR_SIZEOF_VOIDP == 8 96void *apr_atomic_casptr(volatile void **mem_ptr, 97 void *swap_ptr, 98 const void *cmp_ptr) 99{ 100 __csg(&cmp_ptr, /* automatically updated from mem on __csg failure */ 101 mem_ptr, /* set from swap when __csg succeeds */ 102 &swap_ptr); 103 return (void *)cmp_ptr; 104} 105#else 106#error APR_SIZEOF_VOIDP value not supported 107#endif /* APR_SIZEOF_VOIDP */ 108 109apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) 110{ 111 apr_uint32_t old, new_val; 112 113 old = *mem; /* old is automatically updated on cs failure */ 114 do { 115 new_val = val; 116 } while (__cs(&old, (cs_t *)mem, new_val)); 117 118 return old; 119} 120 121APR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem_ptr, void *new_ptr) 122{ 123 void *old_ptr; 124 125 old_ptr = *(void **)mem_ptr; /* old is automatically updated on cs failure */ 126#if APR_SIZEOF_VOIDP == 4 127 do { 128 } while (__cs1(&old_ptr, mem_ptr, &new_ptr)); 129#elif APR_SIZEOF_VOIDP == 8 130 do { 131 } while (__csg(&old_ptr, mem_ptr, &new_ptr)); 132#else 133#error APR_SIZEOF_VOIDP value not supported 134#endif /* APR_SIZEOF_VOIDP */ 135 136 return old_ptr; 137} 138