133675390SSiva Chandra Reddy //===-- Linux implementation of the callonce function ---------------------===// 233675390SSiva Chandra Reddy // 333675390SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 433675390SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 533675390SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 633675390SSiva Chandra Reddy // 733675390SSiva Chandra Reddy //===----------------------------------------------------------------------===// 833675390SSiva Chandra Reddy 933675390SSiva Chandra Reddy #include "src/__support/threads/callonce.h" 10*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 116d61d837SSchrodinger ZHU Yifan #include "src/__support/threads/linux/callonce.h" 12ab3a9e72SSchrodinger ZHU Yifan #include "src/__support/threads/linux/futex_utils.h" 1333675390SSiva Chandra Reddy 14*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 156d61d837SSchrodinger ZHU Yifan namespace callonce_impl { 166d61d837SSchrodinger ZHU Yifan int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *func) { 17ab3a9e72SSchrodinger ZHU Yifan auto *futex_word = reinterpret_cast<Futex *>(flag); 1833675390SSiva Chandra Reddy 1933675390SSiva Chandra Reddy FutexWordType not_called = NOT_CALLED; 2033675390SSiva Chandra Reddy 2133675390SSiva Chandra Reddy // The call_once call can return only after the called function |func| 2233675390SSiva Chandra Reddy // returns. So, we use futexes to synchronize calls with the same flag value. 2333675390SSiva Chandra Reddy if (futex_word->compare_exchange_strong(not_called, START)) { 2433675390SSiva Chandra Reddy func(); 2533675390SSiva Chandra Reddy auto status = futex_word->exchange(FINISH); 26ab3a9e72SSchrodinger ZHU Yifan if (status == WAITING) 27ab3a9e72SSchrodinger ZHU Yifan futex_word->notify_all(); 2833675390SSiva Chandra Reddy return 0; 2933675390SSiva Chandra Reddy } 3033675390SSiva Chandra Reddy 3133675390SSiva Chandra Reddy FutexWordType status = START; 3233675390SSiva Chandra Reddy if (futex_word->compare_exchange_strong(status, WAITING) || 3333675390SSiva Chandra Reddy status == WAITING) { 34ab3a9e72SSchrodinger ZHU Yifan futex_word->wait(WAITING); 3533675390SSiva Chandra Reddy } 3633675390SSiva Chandra Reddy 3733675390SSiva Chandra Reddy return 0; 3833675390SSiva Chandra Reddy } 396d61d837SSchrodinger ZHU Yifan } // namespace callonce_impl 40*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 41