diff --git a/include/__config b/include/__config index ae907cfe..9540a114 100644 --- a/include/__config +++ b/include/__config @@ -114,8 +114,9 @@ typedef __char32_t char32_t; #define _LIBCPP_HAS_NO_ATTRIBUTES #endif -#if !(__has_feature(cxx_deleted_functions)) #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + +#if !(__has_feature(cxx_deleted_functions)) #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #endif // !(__has_feature(cxx_deleted_functions)) diff --git a/include/atomic b/include/atomic index 97089776..be912d3a 100644 --- a/include/atomic +++ b/include/atomic @@ -2411,6 +2411,7 @@ void atomic_signal_fence(memory_order); */ #include <__config> +#include <initializer_list> #pragma GCC system_header @@ -2430,6 +2431,71 @@ kill_dependency(_Tp __y) return __y; } +// flag type and operations + +struct __atomic_flag_init {}; + +typedef struct atomic_flag +{ + bool __flg_; + + bool test_and_set(memory_order __o = memory_order_seq_cst) volatile + { + switch (__o) + { + case memory_order_relaxed: + case memory_order_consume: + case memory_order_acquire: + return __sync_lock_test_and_set(&__flg_, true); + case memory_order_release: + case memory_order_acq_rel: + case memory_order_seq_cst: + bool __r = __sync_lock_test_and_set(&__flg_, true); + __sync_synchronize(); + return __r; + } + } + + bool test_and_set(memory_order __o = memory_order_seq_cst) + {return const_cast<volatile atomic_flag*>(this)->test_and_set(__o);} + void clear(memory_order = memory_order_seq_cst) volatile; + void clear(memory_order = memory_order_seq_cst); + +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + atomic_flag() = default; +#else + atomic_flag() {}; +#endif + +#if 0 + +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; +#else +private: + atomic_flag(const atomic_flag&); + atomic_flag& operator=(const atomic_flag&); + atomic_flag& operator=(const atomic_flag&) volatile; +public: +#endif +#else + atomic_flag(__atomic_flag_init) : __flg_(false) {} // temporary +#endif +} atomic_flag; + +bool atomic_flag_test_and_set(volatile atomic_flag*); +bool atomic_flag_test_and_set(atomic_flag*); +bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order); +bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order); +void atomic_flag_clear(volatile atomic_flag*); +void atomic_flag_clear(atomic_flag*); +void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order); +void atomic_flag_clear_explicit(atomic_flag*, memory_order); + +#define ATOMIC_FLAG_INIT _STD::__atomic_flag_init() + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ATOMIC diff --git a/test/atomics/atomics.flag/test_and_set.pass.cpp b/test/atomics/atomics.flag/test_and_set.pass.cpp new file mode 100644 index 00000000..9247d7ba --- /dev/null +++ b/test/atomics/atomics.flag/test_and_set.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <atomic> + +// struct atomic_flag + +// bool test_and_set(memory_order = memory_order_seq_cst); +// bool test_and_set(memory_order = memory_order_seq_cst) volatile; + +#include <atomic> +#include <cassert> + +int main() +{ + std::atomic_flag f = ATOMIC_FLAG_INIT; + assert(f.test_and_set() == 0); + assert(f.test_and_set() == 1); +} diff --git a/test/atomics/atomics.flag/test_and_set.pass.s b/test/atomics/atomics.flag/test_and_set.pass.s new file mode 100644 index 00000000..94d389da --- /dev/null +++ b/test/atomics/atomics.flag/test_and_set.pass.s @@ -0,0 +1,275 @@ + .section __TEXT,__text,regular,pure_instructions + .globl _main + .align 4, 0x90 +_main: ## @main +Leh_func_begin0: +## BB#0: + pushl %ebp +Ltmp0: + movl %esp, %ebp +Ltmp1: + pushl %edi + pushl %esi + subl $48, %esp +Ltmp2: + calll L0$pb +L0$pb: + popl %eax + leal -16(%ebp), %ecx + movl $5, %edx + movl $0, -12(%ebp) + movl %ecx, -20(%ebp) ## 4-byte Spill + movb $0, (%ecx) + movl -20(%ebp), %ecx ## 4-byte Reload + movl %ecx, (%esp) + movl $5, 4(%esp) + movl %eax, -24(%ebp) ## 4-byte Spill + movl %edx, -28(%ebp) ## 4-byte Spill + calll __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE + andb $1, %al + andb $1, %al + movzbl %al, %ecx + cmpl $0, %ecx + sete %al + xorb $1, %al + testb %al, %al + jne LBB0_1 + jmp LBB0_2 +LBB0_1: + movl -24(%ebp), %eax ## 4-byte Reload + leal L___func__.main-L0$pb(%eax), %ecx + leal L_.str-L0$pb(%eax), %edx + movl $23, %esi + leal L_.str1-L0$pb(%eax), %edi + movl %ecx, (%esp) + movl %edx, 4(%esp) + movl $23, 8(%esp) + movl %edi, 12(%esp) + movl %esi, -32(%ebp) ## 4-byte Spill + calll ___assert_rtn +LBB0_2: +## BB#3: + leal -16(%ebp), %eax + movl %esp, %ecx + movl %eax, (%ecx) + movl $5, 4(%ecx) + calll __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE + andb $1, %al + movzbl %al, %ecx + cmpl $1, %ecx + sete %al + xorb $1, %al + testb %al, %al + jne LBB0_4 + jmp LBB0_5 +LBB0_4: + movl -24(%ebp), %eax ## 4-byte Reload + leal L___func__.main-L0$pb(%eax), %ecx + leal L_.str-L0$pb(%eax), %edx + movl $24, %esi + leal L_.str2-L0$pb(%eax), %edi + movl %ecx, (%esp) + movl %edx, 4(%esp) + movl $24, 8(%esp) + movl %edi, 12(%esp) + movl %esi, -36(%ebp) ## 4-byte Spill + calll ___assert_rtn +LBB0_5: +## BB#6: + movl -12(%ebp), %eax + addl $48, %esp + popl %esi + popl %edi + popl %ebp + ret +Leh_func_end0: + + .section __TEXT,__textcoal_nt,coalesced,pure_instructions + .globl __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE + .weak_definition __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE + .align 4, 0x90 +__ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE: ## @_ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE +Leh_func_begin1: +## BB#0: + pushl %ebp +Ltmp3: + movl %esp, %ebp +Ltmp4: + pushl %ebx + subl $20, %esp +Ltmp5: + movl 12(%ebp), %eax + movl 8(%ebp), %ecx + movl %ecx, -8(%ebp) + movl %eax, -12(%ebp) + movl -8(%ebp), %ecx + movl %esp, %edx + movl %eax, 4(%edx) + movl %ecx, (%edx) + calll __ZNVSt3__111atomic_flag12test_and_setENS_12memory_orderE + movb %al, -13(%ebp) ## 1-byte Spill + movzbl %al, %eax + movb -13(%ebp), %bl ## 1-byte Reload + movb %bl, -14(%ebp) ## 1-byte Spill + addl $20, %esp + popl %ebx + popl %ebp + ret +Leh_func_end1: + + .globl __ZNVSt3__111atomic_flag12test_and_setENS_12memory_orderE + .weak_definition __ZNVSt3__111atomic_flag12test_and_setENS_12memory_orderE + .align 4, 0x90 +__ZNVSt3__111atomic_flag12test_and_setENS_12memory_orderE: ## @_ZNVSt3__111atomic_flag12test_and_setENS_12memory_orderE +## BB#0: + pushl %ebp + movl %esp, %ebp + subl $32, %esp + movl 12(%ebp), %eax + movl 8(%ebp), %ecx + movl %ecx, -8(%ebp) + movl %eax, -12(%ebp) + movl -8(%ebp), %ecx + leal -3(%eax), %edx + cmpl $3, %edx + movl %ecx, -20(%ebp) ## 4-byte Spill + movl %eax, -24(%ebp) ## 4-byte Spill + jb LBB2_2 +## BB#4: + movl -24(%ebp), %eax ## 4-byte Reload + cmpl $2, %eax + ja LBB2_3 +## BB#1: + movb $-1, %al + movl -20(%ebp), %ecx ## 4-byte Reload + xchgb %al, (%ecx) + andb $1, %al + movb %al, -1(%ebp) + jmp LBB2_3 +LBB2_2: + movb $-1, %al + movl -20(%ebp), %ecx ## 4-byte Reload + xchgb %al, (%ecx) + andb $1, %al + movb %al, -13(%ebp) + #MEMBARRIER + movb -13(%ebp), %al + andb $1, %al + movb %al, -1(%ebp) +LBB2_3: + movzbl -1(%ebp), %eax + movl %eax, -28(%ebp) ## 4-byte Spill + movb %al, %cl + movl -28(%ebp), %eax ## 4-byte Reload + movb %cl, -29(%ebp) ## 1-byte Spill + addl $32, %esp + popl %ebp + ret + + .section __TEXT,__cstring,cstring_literals +L___func__.main: ## @__func__.main + .asciz "main" + + .align 4 ## @.str +L_.str: + .asciz "test_and_set.pass.cpp" + + .align 4 ## @.str1 +L_.str1: + .asciz "f.test_and_set() == 0" + + .align 4 ## @.str2 +L_.str2: + .asciz "f.test_and_set() == 1" + + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame0: +Lsection_eh_frame0: +Leh_frame_common0: +Lset0 = Leh_frame_common_end0-Leh_frame_common_begin0 ## Length of Common Information Entry + .long Lset0 +Leh_frame_common_begin0: + .long 0 ## CIE Identifier Tag + .byte 1 ## DW_CIE_VERSION + .asciz "zR" ## CIE Augmentation + .byte 1 ## CIE Code Alignment Factor + .byte 124 ## CIE Data Alignment Factor + .byte 8 ## CIE Return Address Column + .byte 1 ## Augmentation Size + .byte 16 ## FDE Encoding = pcrel + .byte 12 ## DW_CFA_def_cfa + .byte 5 ## Register + .byte 4 ## Offset + .byte 136 ## DW_CFA_offset + Reg (8) + .byte 1 ## Offset + .align 2 +Leh_frame_common_end0: + .globl _main.eh +_main.eh: +Lset1 = Leh_frame_end0-Leh_frame_begin0 ## Length of Frame Information Entry + .long Lset1 +Leh_frame_begin0: +Lset2 = Leh_frame_begin0-Leh_frame_common0 ## FDE CIE offset + .long Lset2 +Ltmp6: ## FDE initial location + .long Leh_func_begin0-Ltmp6 +Lset3 = Leh_func_end0-Leh_func_begin0 ## FDE address range + .long Lset3 + .byte 0 ## Augmentation size + .byte 4 ## DW_CFA_advance_loc4 +Lset4 = Ltmp0-Leh_func_begin0 + .long Lset4 + .byte 14 ## DW_CFA_def_cfa_offset + .byte 8 ## Offset + .byte 132 ## DW_CFA_offset + Reg (4) + .byte 2 ## Offset + .byte 4 ## DW_CFA_advance_loc4 +Lset5 = Ltmp1-Ltmp0 + .long Lset5 + .byte 13 ## DW_CFA_def_cfa_register + .byte 4 ## Register + .byte 4 ## DW_CFA_advance_loc4 +Lset6 = Ltmp2-Ltmp1 + .long Lset6 + .byte 134 ## DW_CFA_offset + Reg (6) + .byte 4 ## Offset + .byte 135 ## DW_CFA_offset + Reg (7) + .byte 3 ## Offset + .align 2 +Leh_frame_end0: + + .globl __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE.eh + .weak_definition __ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE.eh +__ZNSt3__111atomic_flag12test_and_setENS_12memory_orderE.eh: +Lset7 = Leh_frame_end1-Leh_frame_begin1 ## Length of Frame Information Entry + .long Lset7 +Leh_frame_begin1: +Lset8 = Leh_frame_begin1-Leh_frame_common0 ## FDE CIE offset + .long Lset8 +Ltmp7: ## FDE initial location + .long Leh_func_begin1-Ltmp7 +Lset9 = Leh_func_end1-Leh_func_begin1 ## FDE address range + .long Lset9 + .byte 0 ## Augmentation size + .byte 4 ## DW_CFA_advance_loc4 +Lset10 = Ltmp3-Leh_func_begin1 + .long Lset10 + .byte 14 ## DW_CFA_def_cfa_offset + .byte 8 ## Offset + .byte 132 ## DW_CFA_offset + Reg (4) + .byte 2 ## Offset + .byte 4 ## DW_CFA_advance_loc4 +Lset11 = Ltmp4-Ltmp3 + .long Lset11 + .byte 13 ## DW_CFA_def_cfa_register + .byte 4 ## Register + .byte 4 ## DW_CFA_advance_loc4 +Lset12 = Ltmp5-Ltmp4 + .long Lset12 + .byte 131 ## DW_CFA_offset + Reg (3) + .byte 3 ## Offset + .align 2 +Leh_frame_end1: + + +.subsections_via_symbols diff --git a/test/atomics/atomics.types/nothing_to_do.pass.cpp b/test/atomics/atomics.types/nothing_to_do.pass.cpp new file mode 100644 index 00000000..256c0e2a --- /dev/null +++ b/test/atomics/atomics.types/nothing_to_do.pass.cpp @@ -0,0 +1,13 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int main() +{ +}