1 //===-- Implementation of libc_errno --------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "libc_errno.h"
10 #include "src/__support/macros/config.h"
12 // libc uses a fallback default value, either system or thread local.
13 #define LIBC_ERRNO_MODE_DEFAULT 0
14 // libc never stores a value; `errno` macro uses get link-time failure.
15 #define LIBC_ERRNO_MODE_UNDEFINED 1
16 // libc maintains per-thread state (requires C++ `thread_local` support).
17 #define LIBC_ERRNO_MODE_THREAD_LOCAL 2
18 // libc maintains shared state used by all threads, contrary to standard C
19 // semantics unless always single-threaded; nothing prevents data races.
20 #define LIBC_ERRNO_MODE_SHARED 3
21 // libc doesn't maintain any internal state, instead the embedder must define
22 // `int *__llvm_libc_errno(void);` C function.
23 #define LIBC_ERRNO_MODE_EXTERNAL 4
24 // libc uses system `<errno.h>` `errno` macro directly in the overlay mode; in
25 // fullbuild mode, effectively the same as `LIBC_ERRNO_MODE_EXTERNAL`.
26 #define LIBC_ERRNO_MODE_SYSTEM 5
28 #if !defined(LIBC_ERRNO_MODE) || LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_DEFAULT
29 #undef LIBC_ERRNO_MODE
30 #if defined(LIBC_FULL_BUILD) || !defined(LIBC_COPT_PUBLIC_PACKAGING)
31 #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_THREAD_LOCAL
33 #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
35 #endif // LIBC_ERRNO_MODE
37 #if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_DEFAULT && \
38 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_UNDEFINED && \
39 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL && \
40 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SHARED && \
41 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL && \
42 LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM
43 #error LIBC_ERRNO_MODE must be one of the following values: \
44 LIBC_ERRNO_MODE_DEFAULT, \
45 LIBC_ERRNO_MODE_UNDEFINED, \
46 LIBC_ERRNO_MODE_THREAD_LOCAL, \
47 LIBC_ERRNO_MODE_SHARED, \
48 LIBC_ERRNO_MODE_EXTERNAL, \
49 LIBC_ERRNO_MODE_SYSTEM
52 namespace LIBC_NAMESPACE_DECL
{
54 #if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_UNDEFINED
56 void Errno::operator=(int) {}
57 Errno::operator int() { return 0; }
59 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
62 LIBC_THREAD_LOCAL
int thread_errno
;
65 extern "C" int *__llvm_libc_errno() noexcept
{ return &thread_errno
; }
67 void Errno::operator=(int a
) { thread_errno
= a
; }
68 Errno::operator int() { return thread_errno
; }
70 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SHARED
76 extern "C" int *__llvm_libc_errno() noexcept
{ return &shared_errno
; }
78 void Errno::operator=(int a
) { shared_errno
= a
; }
79 Errno::operator int() { return shared_errno
; }
81 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
83 void Errno::operator=(int a
) { *__llvm_libc_errno() = a
; }
84 Errno::operator int() { return *__llvm_libc_errno(); }
86 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SYSTEM
88 void Errno::operator=(int a
) { errno
= a
; }
89 Errno::operator int() { return errno
; }
93 // Define the global `libc_errno` instance.
96 } // namespace LIBC_NAMESPACE_DECL