xref: /aosp_15_r20/external/llvm-libc/src/errno/libc_errno.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Implementation of libc_errno --------------------------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker 
9*71db0c75SAndroid Build Coastguard Worker #include "libc_errno.h"
10*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
11*71db0c75SAndroid Build Coastguard Worker 
12*71db0c75SAndroid Build Coastguard Worker // libc uses a fallback default value, either system or thread local.
13*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_DEFAULT 0
14*71db0c75SAndroid Build Coastguard Worker // libc never stores a value; `errno` macro uses get link-time failure.
15*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_UNDEFINED 1
16*71db0c75SAndroid Build Coastguard Worker // libc maintains per-thread state (requires C++ `thread_local` support).
17*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_THREAD_LOCAL 2
18*71db0c75SAndroid Build Coastguard Worker // libc maintains shared state used by all threads, contrary to standard C
19*71db0c75SAndroid Build Coastguard Worker // semantics unless always single-threaded; nothing prevents data races.
20*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_SHARED 3
21*71db0c75SAndroid Build Coastguard Worker // libc doesn't maintain any internal state, instead the embedder must define
22*71db0c75SAndroid Build Coastguard Worker // `int *__llvm_libc_errno(void);` C function.
23*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_EXTERNAL 4
24*71db0c75SAndroid Build Coastguard Worker // libc uses system `<errno.h>` `errno` macro directly in the overlay mode; in
25*71db0c75SAndroid Build Coastguard Worker // fullbuild mode, effectively the same as `LIBC_ERRNO_MODE_EXTERNAL`.
26*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE_SYSTEM 5
27*71db0c75SAndroid Build Coastguard Worker 
28*71db0c75SAndroid Build Coastguard Worker #if !defined(LIBC_ERRNO_MODE) || LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_DEFAULT
29*71db0c75SAndroid Build Coastguard Worker #undef LIBC_ERRNO_MODE
30*71db0c75SAndroid Build Coastguard Worker #if defined(LIBC_FULL_BUILD) || !defined(LIBC_COPT_PUBLIC_PACKAGING)
31*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_THREAD_LOCAL
32*71db0c75SAndroid Build Coastguard Worker #else
33*71db0c75SAndroid Build Coastguard Worker #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
34*71db0c75SAndroid Build Coastguard Worker #endif
35*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_ERRNO_MODE
36*71db0c75SAndroid Build Coastguard Worker 
37*71db0c75SAndroid Build Coastguard Worker #if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_DEFAULT &&                              \
38*71db0c75SAndroid Build Coastguard Worker     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_UNDEFINED &&                            \
39*71db0c75SAndroid Build Coastguard Worker     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL &&                         \
40*71db0c75SAndroid Build Coastguard Worker     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SHARED &&                               \
41*71db0c75SAndroid Build Coastguard Worker     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL &&                             \
42*71db0c75SAndroid Build Coastguard Worker     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM
43*71db0c75SAndroid Build Coastguard Worker #error LIBC_ERRNO_MODE must be one of the following values: \
44*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_DEFAULT, \
45*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_UNDEFINED, \
46*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_THREAD_LOCAL, \
47*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_SHARED, \
48*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_EXTERNAL, \
49*71db0c75SAndroid Build Coastguard Worker LIBC_ERRNO_MODE_SYSTEM
50*71db0c75SAndroid Build Coastguard Worker #endif
51*71db0c75SAndroid Build Coastguard Worker 
52*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
53*71db0c75SAndroid Build Coastguard Worker 
54*71db0c75SAndroid Build Coastguard Worker #if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_UNDEFINED
55*71db0c75SAndroid Build Coastguard Worker 
operator =(int)56*71db0c75SAndroid Build Coastguard Worker void Errno::operator=(int) {}
operator int()57*71db0c75SAndroid Build Coastguard Worker Errno::operator int() { return 0; }
58*71db0c75SAndroid Build Coastguard Worker 
59*71db0c75SAndroid Build Coastguard Worker #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
60*71db0c75SAndroid Build Coastguard Worker 
61*71db0c75SAndroid Build Coastguard Worker namespace {
62*71db0c75SAndroid Build Coastguard Worker LIBC_THREAD_LOCAL int thread_errno;
63*71db0c75SAndroid Build Coastguard Worker }
64*71db0c75SAndroid Build Coastguard Worker 
65*71db0c75SAndroid Build Coastguard Worker extern "C" int *__llvm_libc_errno() noexcept { return &thread_errno; }
66*71db0c75SAndroid Build Coastguard Worker 
67*71db0c75SAndroid Build Coastguard Worker void Errno::operator=(int a) { thread_errno = a; }
68*71db0c75SAndroid Build Coastguard Worker Errno::operator int() { return thread_errno; }
69*71db0c75SAndroid Build Coastguard Worker 
70*71db0c75SAndroid Build Coastguard Worker #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SHARED
71*71db0c75SAndroid Build Coastguard Worker 
72*71db0c75SAndroid Build Coastguard Worker namespace {
73*71db0c75SAndroid Build Coastguard Worker int shared_errno;
74*71db0c75SAndroid Build Coastguard Worker }
75*71db0c75SAndroid Build Coastguard Worker 
76*71db0c75SAndroid Build Coastguard Worker extern "C" int *__llvm_libc_errno() noexcept { return &shared_errno; }
77*71db0c75SAndroid Build Coastguard Worker 
78*71db0c75SAndroid Build Coastguard Worker void Errno::operator=(int a) { shared_errno = a; }
79*71db0c75SAndroid Build Coastguard Worker Errno::operator int() { return shared_errno; }
80*71db0c75SAndroid Build Coastguard Worker 
81*71db0c75SAndroid Build Coastguard Worker #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
82*71db0c75SAndroid Build Coastguard Worker 
83*71db0c75SAndroid Build Coastguard Worker void Errno::operator=(int a) { *__llvm_libc_errno() = a; }
84*71db0c75SAndroid Build Coastguard Worker Errno::operator int() { return *__llvm_libc_errno(); }
85*71db0c75SAndroid Build Coastguard Worker 
86*71db0c75SAndroid Build Coastguard Worker #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SYSTEM
87*71db0c75SAndroid Build Coastguard Worker 
88*71db0c75SAndroid Build Coastguard Worker void Errno::operator=(int a) { errno = a; }
89*71db0c75SAndroid Build Coastguard Worker Errno::operator int() { return errno; }
90*71db0c75SAndroid Build Coastguard Worker 
91*71db0c75SAndroid Build Coastguard Worker #endif
92*71db0c75SAndroid Build Coastguard Worker 
93*71db0c75SAndroid Build Coastguard Worker // Define the global `libc_errno` instance.
94*71db0c75SAndroid Build Coastguard Worker Errno libc_errno;
95*71db0c75SAndroid Build Coastguard Worker 
96*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
97