[SelectOpt] Support ADD and SUB with zext operands. (#115489)
[llvm-project.git] / libcxx / src / call_once.cpp
bloba398eaecfd009d440b4ef8b9c35140f69c747ead
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include <__mutex/once_flag.h>
10 #include <__utility/exception_guard.h>
12 #if _LIBCPP_HAS_THREADS
13 # include <__thread/support.h>
14 #endif
16 #include "include/atomic_support.h"
18 _LIBCPP_BEGIN_NAMESPACE_STD
20 // If dispatch_once_f ever handles C++ exceptions, and if one can get to it
21 // without illegal macros (unexpected macros not beginning with _UpperCase or
22 // __lowercase), and if it stops spinning waiting threads, then call_once should
23 // call into dispatch_once_f instead of here. Relevant radar this code needs to
24 // keep in sync with: 7741191.
26 #if _LIBCPP_HAS_THREADS
27 static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
28 static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
29 #endif
31 void __call_once(volatile once_flag::_State_type& flag, void* arg, void (*func)(void*)) {
32 #if !_LIBCPP_HAS_THREADS
34 if (flag == once_flag::_Unset) {
35 auto guard = std::__make_exception_guard([&flag] { flag = once_flag::_Unset; });
36 flag = once_flag::_Pending;
37 func(arg);
38 flag = once_flag::_Complete;
39 guard.__complete();
42 #else // !_LIBCPP_HAS_THREADS
44 __libcpp_mutex_lock(&mut);
45 while (flag == once_flag::_Pending)
46 __libcpp_condvar_wait(&cv, &mut);
47 if (flag == once_flag::_Unset) {
48 auto guard = std::__make_exception_guard([&flag] {
49 __libcpp_mutex_lock(&mut);
50 __libcpp_relaxed_store(&flag, once_flag::_Unset);
51 __libcpp_mutex_unlock(&mut);
52 __libcpp_condvar_broadcast(&cv);
53 });
55 __libcpp_relaxed_store(&flag, once_flag::_Pending);
56 __libcpp_mutex_unlock(&mut);
57 func(arg);
58 __libcpp_mutex_lock(&mut);
59 __libcpp_atomic_store(&flag, once_flag::_Complete, _AO_Release);
60 __libcpp_mutex_unlock(&mut);
61 __libcpp_condvar_broadcast(&cv);
62 guard.__complete();
63 } else {
64 __libcpp_mutex_unlock(&mut);
67 #endif // !_LIBCPP_HAS_THREADS
70 _LIBCPP_END_NAMESPACE_STD