116038816SMartin Matuska /* 216038816SMartin Matuska * CDDL HEADER START 316038816SMartin Matuska * 416038816SMartin Matuska * The contents of this file are subject to the terms of the 516038816SMartin Matuska * Common Development and Distribution License, Version 1.0 only 616038816SMartin Matuska * (the "License"). You may not use this file except in compliance 716038816SMartin Matuska * with the License. 816038816SMartin Matuska * 916038816SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 1116038816SMartin Matuska * See the License for the specific language governing permissions 1216038816SMartin Matuska * and limitations under the License. 1316038816SMartin Matuska * 1416038816SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 1516038816SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1616038816SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 1716038816SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 1816038816SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 1916038816SMartin Matuska * 2016038816SMartin Matuska * CDDL HEADER END 2116038816SMartin Matuska */ 2216038816SMartin Matuska /* 2316038816SMartin Matuska * Copyright (c) 2009 by Sun Microsystems, Inc. All rights reserved. 2416038816SMartin Matuska * Use is subject to license terms. 2516038816SMartin Matuska */ 2616038816SMartin Matuska 2716038816SMartin Matuska #include <atomic.h> 2816038816SMartin Matuska 2916038816SMartin Matuska /* 3016038816SMartin Matuska * These are the void returning variants 3116038816SMartin Matuska */ 3216038816SMartin Matuska #define ATOMIC_INC(name, type) \ 3316038816SMartin Matuska void atomic_inc_##name(volatile type *target) \ 3416038816SMartin Matuska { \ 3516038816SMartin Matuska (void) __atomic_add_fetch(target, 1, __ATOMIC_SEQ_CST); \ 3616038816SMartin Matuska } 3716038816SMartin Matuska 3816038816SMartin Matuska ATOMIC_INC(8, uint8_t) 3916038816SMartin Matuska ATOMIC_INC(16, uint16_t) 4016038816SMartin Matuska ATOMIC_INC(32, uint32_t) 41c03c5b1cSMartin Matuska ATOMIC_INC(64, uint64_t) 42c03c5b1cSMartin Matuska ATOMIC_INC(uchar, uchar_t) 43c03c5b1cSMartin Matuska ATOMIC_INC(ushort, ushort_t) 4416038816SMartin Matuska ATOMIC_INC(uint, uint_t) 4516038816SMartin Matuska ATOMIC_INC(ulong, ulong_t) 4616038816SMartin Matuska 4716038816SMartin Matuska 4816038816SMartin Matuska #define ATOMIC_DEC(name, type) \ 4916038816SMartin Matuska void atomic_dec_##name(volatile type *target) \ 5016038816SMartin Matuska { \ 5116038816SMartin Matuska (void) __atomic_sub_fetch(target, 1, __ATOMIC_SEQ_CST); \ 5216038816SMartin Matuska } 5316038816SMartin Matuska 5416038816SMartin Matuska ATOMIC_DEC(8, uint8_t) 5516038816SMartin Matuska ATOMIC_DEC(16, uint16_t) 5616038816SMartin Matuska ATOMIC_DEC(32, uint32_t) 57c03c5b1cSMartin Matuska ATOMIC_DEC(64, uint64_t) 58c03c5b1cSMartin Matuska ATOMIC_DEC(uchar, uchar_t) 59c03c5b1cSMartin Matuska ATOMIC_DEC(ushort, ushort_t) 6016038816SMartin Matuska ATOMIC_DEC(uint, uint_t) 6116038816SMartin Matuska ATOMIC_DEC(ulong, ulong_t) 6216038816SMartin Matuska 6316038816SMartin Matuska 6416038816SMartin Matuska #define ATOMIC_ADD(name, type1, type2) \ 6516038816SMartin Matuska void atomic_add_##name(volatile type1 *target, type2 bits) \ 6616038816SMartin Matuska { \ 6716038816SMartin Matuska (void) __atomic_add_fetch(target, bits, __ATOMIC_SEQ_CST); \ 6816038816SMartin Matuska } 6916038816SMartin Matuska 7016038816SMartin Matuska void 7116038816SMartin Matuska atomic_add_ptr(volatile void *target, ssize_t bits) 7216038816SMartin Matuska { 7316038816SMartin Matuska (void) __atomic_add_fetch((void **)target, bits, __ATOMIC_SEQ_CST); 7416038816SMartin Matuska } 7516038816SMartin Matuska 76c03c5b1cSMartin Matuska ATOMIC_ADD(8, uint8_t, int8_t) 77c03c5b1cSMartin Matuska ATOMIC_ADD(16, uint16_t, int16_t) 78c03c5b1cSMartin Matuska ATOMIC_ADD(32, uint32_t, int32_t) 79c03c5b1cSMartin Matuska ATOMIC_ADD(64, uint64_t, int64_t) 80c03c5b1cSMartin Matuska ATOMIC_ADD(char, uchar_t, signed char) 81c03c5b1cSMartin Matuska ATOMIC_ADD(short, ushort_t, short) 82c03c5b1cSMartin Matuska ATOMIC_ADD(int, uint_t, int) 83c03c5b1cSMartin Matuska ATOMIC_ADD(long, ulong_t, long) 84c03c5b1cSMartin Matuska 8516038816SMartin Matuska 8616038816SMartin Matuska #define ATOMIC_SUB(name, type1, type2) \ 8716038816SMartin Matuska void atomic_sub_##name(volatile type1 *target, type2 bits) \ 8816038816SMartin Matuska { \ 8916038816SMartin Matuska (void) __atomic_sub_fetch(target, bits, __ATOMIC_SEQ_CST); \ 9016038816SMartin Matuska } 9116038816SMartin Matuska 9216038816SMartin Matuska void 9316038816SMartin Matuska atomic_sub_ptr(volatile void *target, ssize_t bits) 9416038816SMartin Matuska { 9516038816SMartin Matuska (void) __atomic_sub_fetch((void **)target, bits, __ATOMIC_SEQ_CST); 9616038816SMartin Matuska } 9716038816SMartin Matuska 98c03c5b1cSMartin Matuska ATOMIC_SUB(8, uint8_t, int8_t) 99c03c5b1cSMartin Matuska ATOMIC_SUB(16, uint16_t, int16_t) 100c03c5b1cSMartin Matuska ATOMIC_SUB(32, uint32_t, int32_t) 101c03c5b1cSMartin Matuska ATOMIC_SUB(64, uint64_t, int64_t) 102c03c5b1cSMartin Matuska ATOMIC_SUB(char, uchar_t, signed char) 103c03c5b1cSMartin Matuska ATOMIC_SUB(short, ushort_t, short) 104c03c5b1cSMartin Matuska ATOMIC_SUB(int, uint_t, int) 105c03c5b1cSMartin Matuska ATOMIC_SUB(long, ulong_t, long) 106c03c5b1cSMartin Matuska 10716038816SMartin Matuska 10816038816SMartin Matuska #define ATOMIC_OR(name, type) \ 10916038816SMartin Matuska void atomic_or_##name(volatile type *target, type bits) \ 11016038816SMartin Matuska { \ 11116038816SMartin Matuska (void) __atomic_or_fetch(target, bits, __ATOMIC_SEQ_CST); \ 11216038816SMartin Matuska } 11316038816SMartin Matuska 11416038816SMartin Matuska ATOMIC_OR(8, uint8_t) 11516038816SMartin Matuska ATOMIC_OR(16, uint16_t) 11616038816SMartin Matuska ATOMIC_OR(32, uint32_t) 117c03c5b1cSMartin Matuska ATOMIC_OR(64, uint64_t) 118c03c5b1cSMartin Matuska ATOMIC_OR(uchar, uchar_t) 119c03c5b1cSMartin Matuska ATOMIC_OR(ushort, ushort_t) 12016038816SMartin Matuska ATOMIC_OR(uint, uint_t) 12116038816SMartin Matuska ATOMIC_OR(ulong, ulong_t) 12216038816SMartin Matuska 12316038816SMartin Matuska 12416038816SMartin Matuska #define ATOMIC_AND(name, type) \ 12516038816SMartin Matuska void atomic_and_##name(volatile type *target, type bits) \ 12616038816SMartin Matuska { \ 12716038816SMartin Matuska (void) __atomic_and_fetch(target, bits, __ATOMIC_SEQ_CST); \ 12816038816SMartin Matuska } 12916038816SMartin Matuska 13016038816SMartin Matuska ATOMIC_AND(8, uint8_t) 13116038816SMartin Matuska ATOMIC_AND(16, uint16_t) 13216038816SMartin Matuska ATOMIC_AND(32, uint32_t) 133c03c5b1cSMartin Matuska ATOMIC_AND(64, uint64_t) 134c03c5b1cSMartin Matuska ATOMIC_AND(uchar, uchar_t) 135c03c5b1cSMartin Matuska ATOMIC_AND(ushort, ushort_t) 13616038816SMartin Matuska ATOMIC_AND(uint, uint_t) 13716038816SMartin Matuska ATOMIC_AND(ulong, ulong_t) 13816038816SMartin Matuska 13916038816SMartin Matuska 14016038816SMartin Matuska /* 14116038816SMartin Matuska * New value returning variants 14216038816SMartin Matuska */ 14316038816SMartin Matuska 14416038816SMartin Matuska #define ATOMIC_INC_NV(name, type) \ 14516038816SMartin Matuska type atomic_inc_##name##_nv(volatile type *target) \ 14616038816SMartin Matuska { \ 14716038816SMartin Matuska return (__atomic_add_fetch(target, 1, __ATOMIC_SEQ_CST)); \ 14816038816SMartin Matuska } 14916038816SMartin Matuska 15016038816SMartin Matuska ATOMIC_INC_NV(8, uint8_t) 15116038816SMartin Matuska ATOMIC_INC_NV(16, uint16_t) 15216038816SMartin Matuska ATOMIC_INC_NV(32, uint32_t) 153c03c5b1cSMartin Matuska ATOMIC_INC_NV(64, uint64_t) 154c03c5b1cSMartin Matuska ATOMIC_INC_NV(uchar, uchar_t) 155c03c5b1cSMartin Matuska ATOMIC_INC_NV(ushort, ushort_t) 15616038816SMartin Matuska ATOMIC_INC_NV(uint, uint_t) 15716038816SMartin Matuska ATOMIC_INC_NV(ulong, ulong_t) 15816038816SMartin Matuska 15916038816SMartin Matuska 16016038816SMartin Matuska #define ATOMIC_DEC_NV(name, type) \ 16116038816SMartin Matuska type atomic_dec_##name##_nv(volatile type *target) \ 16216038816SMartin Matuska { \ 16316038816SMartin Matuska return (__atomic_sub_fetch(target, 1, __ATOMIC_SEQ_CST)); \ 16416038816SMartin Matuska } 16516038816SMartin Matuska 16616038816SMartin Matuska ATOMIC_DEC_NV(8, uint8_t) 16716038816SMartin Matuska ATOMIC_DEC_NV(16, uint16_t) 16816038816SMartin Matuska ATOMIC_DEC_NV(32, uint32_t) 169c03c5b1cSMartin Matuska ATOMIC_DEC_NV(64, uint64_t) 170c03c5b1cSMartin Matuska ATOMIC_DEC_NV(uchar, uchar_t) 171c03c5b1cSMartin Matuska ATOMIC_DEC_NV(ushort, ushort_t) 17216038816SMartin Matuska ATOMIC_DEC_NV(uint, uint_t) 17316038816SMartin Matuska ATOMIC_DEC_NV(ulong, ulong_t) 17416038816SMartin Matuska 17516038816SMartin Matuska 17616038816SMartin Matuska #define ATOMIC_ADD_NV(name, type1, type2) \ 17716038816SMartin Matuska type1 atomic_add_##name##_nv(volatile type1 *target, type2 bits) \ 17816038816SMartin Matuska { \ 17916038816SMartin Matuska return (__atomic_add_fetch(target, bits, __ATOMIC_SEQ_CST)); \ 18016038816SMartin Matuska } 18116038816SMartin Matuska 18216038816SMartin Matuska void * 18316038816SMartin Matuska atomic_add_ptr_nv(volatile void *target, ssize_t bits) 18416038816SMartin Matuska { 18516038816SMartin Matuska return (__atomic_add_fetch((void **)target, bits, __ATOMIC_SEQ_CST)); 18616038816SMartin Matuska } 18716038816SMartin Matuska 188c03c5b1cSMartin Matuska ATOMIC_ADD_NV(8, uint8_t, int8_t) 189c03c5b1cSMartin Matuska ATOMIC_ADD_NV(16, uint16_t, int16_t) 190c03c5b1cSMartin Matuska ATOMIC_ADD_NV(32, uint32_t, int32_t) 191c03c5b1cSMartin Matuska ATOMIC_ADD_NV(64, uint64_t, int64_t) 192c03c5b1cSMartin Matuska ATOMIC_ADD_NV(char, uchar_t, signed char) 193c03c5b1cSMartin Matuska ATOMIC_ADD_NV(short, ushort_t, short) 194c03c5b1cSMartin Matuska ATOMIC_ADD_NV(int, uint_t, int) 195c03c5b1cSMartin Matuska ATOMIC_ADD_NV(long, ulong_t, long) 196c03c5b1cSMartin Matuska 19716038816SMartin Matuska 19816038816SMartin Matuska #define ATOMIC_SUB_NV(name, type1, type2) \ 19916038816SMartin Matuska type1 atomic_sub_##name##_nv(volatile type1 *target, type2 bits) \ 20016038816SMartin Matuska { \ 20116038816SMartin Matuska return (__atomic_sub_fetch(target, bits, __ATOMIC_SEQ_CST)); \ 20216038816SMartin Matuska } 20316038816SMartin Matuska 204c03c5b1cSMartin Matuska void * 205c03c5b1cSMartin Matuska atomic_sub_ptr_nv(volatile void *target, ssize_t bits) 206c03c5b1cSMartin Matuska { 207c03c5b1cSMartin Matuska return (__atomic_sub_fetch((void **)target, bits, __ATOMIC_SEQ_CST)); 208c03c5b1cSMartin Matuska } 209c03c5b1cSMartin Matuska 21016038816SMartin Matuska ATOMIC_SUB_NV(8, uint8_t, int8_t) 21116038816SMartin Matuska ATOMIC_SUB_NV(char, uchar_t, signed char) 21216038816SMartin Matuska ATOMIC_SUB_NV(16, uint16_t, int16_t) 21316038816SMartin Matuska ATOMIC_SUB_NV(short, ushort_t, short) 21416038816SMartin Matuska ATOMIC_SUB_NV(32, uint32_t, int32_t) 21516038816SMartin Matuska ATOMIC_SUB_NV(int, uint_t, int) 21616038816SMartin Matuska ATOMIC_SUB_NV(long, ulong_t, long) 21716038816SMartin Matuska ATOMIC_SUB_NV(64, uint64_t, int64_t) 21816038816SMartin Matuska 21916038816SMartin Matuska 22016038816SMartin Matuska #define ATOMIC_OR_NV(name, type) \ 22116038816SMartin Matuska type atomic_or_##name##_nv(volatile type *target, type bits) \ 22216038816SMartin Matuska { \ 22316038816SMartin Matuska return (__atomic_or_fetch(target, bits, __ATOMIC_SEQ_CST)); \ 22416038816SMartin Matuska } 22516038816SMartin Matuska 22616038816SMartin Matuska ATOMIC_OR_NV(8, uint8_t) 22716038816SMartin Matuska ATOMIC_OR_NV(16, uint16_t) 22816038816SMartin Matuska ATOMIC_OR_NV(32, uint32_t) 229c03c5b1cSMartin Matuska ATOMIC_OR_NV(64, uint64_t) 230c03c5b1cSMartin Matuska ATOMIC_OR_NV(uchar, uchar_t) 231c03c5b1cSMartin Matuska ATOMIC_OR_NV(ushort, ushort_t) 23216038816SMartin Matuska ATOMIC_OR_NV(uint, uint_t) 23316038816SMartin Matuska ATOMIC_OR_NV(ulong, ulong_t) 23416038816SMartin Matuska 23516038816SMartin Matuska 23616038816SMartin Matuska #define ATOMIC_AND_NV(name, type) \ 23716038816SMartin Matuska type atomic_and_##name##_nv(volatile type *target, type bits) \ 23816038816SMartin Matuska { \ 23916038816SMartin Matuska return (__atomic_and_fetch(target, bits, __ATOMIC_SEQ_CST)); \ 24016038816SMartin Matuska } 24116038816SMartin Matuska 24216038816SMartin Matuska ATOMIC_AND_NV(8, uint8_t) 24316038816SMartin Matuska ATOMIC_AND_NV(16, uint16_t) 24416038816SMartin Matuska ATOMIC_AND_NV(32, uint32_t) 245c03c5b1cSMartin Matuska ATOMIC_AND_NV(64, uint64_t) 246c03c5b1cSMartin Matuska ATOMIC_AND_NV(uchar, uchar_t) 247c03c5b1cSMartin Matuska ATOMIC_AND_NV(ushort, ushort_t) 24816038816SMartin Matuska ATOMIC_AND_NV(uint, uint_t) 24916038816SMartin Matuska ATOMIC_AND_NV(ulong, ulong_t) 25016038816SMartin Matuska 25116038816SMartin Matuska 25216038816SMartin Matuska /* 25316038816SMartin Matuska * If *tgt == exp, set *tgt = des; return old value 25416038816SMartin Matuska * 25516038816SMartin Matuska * This may not look right on the first pass (or the sixteenth), but, 25616038816SMartin Matuska * from https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html: 25716038816SMartin Matuska * > If they are not equal, the operation is a read 25816038816SMartin Matuska * > and the current contents of *ptr are written into *expected. 25916038816SMartin Matuska * And, in the converse case, exp is already *target by definition. 26016038816SMartin Matuska */ 26116038816SMartin Matuska 26216038816SMartin Matuska #define ATOMIC_CAS(name, type) \ 26316038816SMartin Matuska type atomic_cas_##name(volatile type *target, type exp, type des) \ 26416038816SMartin Matuska { \ 26516038816SMartin Matuska __atomic_compare_exchange_n(target, &exp, des, B_FALSE, \ 26616038816SMartin Matuska __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ 26716038816SMartin Matuska return (exp); \ 26816038816SMartin Matuska } 26916038816SMartin Matuska 27016038816SMartin Matuska void * 27116038816SMartin Matuska atomic_cas_ptr(volatile void *target, void *exp, void *des) 27216038816SMartin Matuska { 27316038816SMartin Matuska 27416038816SMartin Matuska __atomic_compare_exchange_n((void **)target, &exp, des, B_FALSE, 27516038816SMartin Matuska __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 27616038816SMartin Matuska return (exp); 27716038816SMartin Matuska } 27816038816SMartin Matuska 279c03c5b1cSMartin Matuska ATOMIC_CAS(8, uint8_t) 280c03c5b1cSMartin Matuska ATOMIC_CAS(16, uint16_t) 281c03c5b1cSMartin Matuska ATOMIC_CAS(32, uint32_t) 282c03c5b1cSMartin Matuska ATOMIC_CAS(64, uint64_t) 283c03c5b1cSMartin Matuska ATOMIC_CAS(uchar, uchar_t) 284c03c5b1cSMartin Matuska ATOMIC_CAS(ushort, ushort_t) 285c03c5b1cSMartin Matuska ATOMIC_CAS(uint, uint_t) 286c03c5b1cSMartin Matuska ATOMIC_CAS(ulong, ulong_t) 287c03c5b1cSMartin Matuska 28816038816SMartin Matuska 28916038816SMartin Matuska /* 29016038816SMartin Matuska * Swap target and return old value 29116038816SMartin Matuska */ 29216038816SMartin Matuska 29316038816SMartin Matuska #define ATOMIC_SWAP(name, type) \ 29416038816SMartin Matuska type atomic_swap_##name(volatile type *target, type bits) \ 29516038816SMartin Matuska { \ 29616038816SMartin Matuska return (__atomic_exchange_n(target, bits, __ATOMIC_SEQ_CST)); \ 29716038816SMartin Matuska } 29816038816SMartin Matuska 29916038816SMartin Matuska ATOMIC_SWAP(8, uint8_t) 30016038816SMartin Matuska ATOMIC_SWAP(16, uint16_t) 30116038816SMartin Matuska ATOMIC_SWAP(32, uint32_t) 302c03c5b1cSMartin Matuska ATOMIC_SWAP(64, uint64_t) 303c03c5b1cSMartin Matuska ATOMIC_SWAP(uchar, uchar_t) 304c03c5b1cSMartin Matuska ATOMIC_SWAP(ushort, ushort_t) 30516038816SMartin Matuska ATOMIC_SWAP(uint, uint_t) 30616038816SMartin Matuska ATOMIC_SWAP(ulong, ulong_t) 30716038816SMartin Matuska 30816038816SMartin Matuska void * 30916038816SMartin Matuska atomic_swap_ptr(volatile void *target, void *bits) 31016038816SMartin Matuska { 31116038816SMartin Matuska return (__atomic_exchange_n((void **)target, bits, __ATOMIC_SEQ_CST)); 31216038816SMartin Matuska } 31316038816SMartin Matuska 31416038816SMartin Matuska #ifndef _LP64 31516038816SMartin Matuska uint64_t 31616038816SMartin Matuska atomic_load_64(volatile uint64_t *target) 31716038816SMartin Matuska { 31816038816SMartin Matuska return (__atomic_load_n(target, __ATOMIC_RELAXED)); 31916038816SMartin Matuska } 32016038816SMartin Matuska 32116038816SMartin Matuska void 32216038816SMartin Matuska atomic_store_64(volatile uint64_t *target, uint64_t bits) 32316038816SMartin Matuska { 32416038816SMartin Matuska return (__atomic_store_n(target, bits, __ATOMIC_RELAXED)); 32516038816SMartin Matuska } 32616038816SMartin Matuska #endif 32716038816SMartin Matuska 32816038816SMartin Matuska int 32916038816SMartin Matuska atomic_set_long_excl(volatile ulong_t *target, uint_t value) 33016038816SMartin Matuska { 33116038816SMartin Matuska ulong_t bit = 1UL << value; 33216038816SMartin Matuska ulong_t old = __atomic_fetch_or(target, bit, __ATOMIC_SEQ_CST); 33316038816SMartin Matuska return ((old & bit) ? -1 : 0); 33416038816SMartin Matuska } 33516038816SMartin Matuska 33616038816SMartin Matuska int 33716038816SMartin Matuska atomic_clear_long_excl(volatile ulong_t *target, uint_t value) 33816038816SMartin Matuska { 33916038816SMartin Matuska ulong_t bit = 1UL << value; 34016038816SMartin Matuska ulong_t old = __atomic_fetch_and(target, ~bit, __ATOMIC_SEQ_CST); 34116038816SMartin Matuska return ((old & bit) ? 0 : -1); 34216038816SMartin Matuska } 34316038816SMartin Matuska 34416038816SMartin Matuska void 34516038816SMartin Matuska membar_enter(void) 34616038816SMartin Matuska { 34716038816SMartin Matuska __atomic_thread_fence(__ATOMIC_SEQ_CST); 34816038816SMartin Matuska } 34916038816SMartin Matuska 35016038816SMartin Matuska void 35116038816SMartin Matuska membar_exit(void) 35216038816SMartin Matuska { 35316038816SMartin Matuska __atomic_thread_fence(__ATOMIC_SEQ_CST); 35416038816SMartin Matuska } 35516038816SMartin Matuska 35616038816SMartin Matuska void 357*c7046f76SMartin Matuska membar_sync(void) 358*c7046f76SMartin Matuska { 359*c7046f76SMartin Matuska __atomic_thread_fence(__ATOMIC_SEQ_CST); 360*c7046f76SMartin Matuska } 361*c7046f76SMartin Matuska 362*c7046f76SMartin Matuska void 36316038816SMartin Matuska membar_producer(void) 36416038816SMartin Matuska { 36516038816SMartin Matuska __atomic_thread_fence(__ATOMIC_RELEASE); 36616038816SMartin Matuska } 36716038816SMartin Matuska 36816038816SMartin Matuska void 36916038816SMartin Matuska membar_consumer(void) 37016038816SMartin Matuska { 37116038816SMartin Matuska __atomic_thread_fence(__ATOMIC_ACQUIRE); 37216038816SMartin Matuska } 373