diff options
Diffstat (limited to 'lib')
63 files changed, 2702 insertions, 2 deletions
diff --git a/lib/Build.mk b/lib/Build.mk index 77d380c..2d5a095 100644 --- a/lib/Build.mk +++ b/lib/Build.mk @@ -1,4 +1,18 @@ -targets += lib/runtime lib/string lib/libfdt lib/core +targets += lib/ktl/headers lib/libc/headers lib/ktl lib/runtime lib/string \ + lib/libfdt lib/core + +target.lib/ktl/headers.kind := header-library +target.lib/ktl/headers.public-includes := lib/ktl/include +target.lib/ktl/headers.public-after-includes := lib/ktl/include-after + +target.lib/libc/headers.kind := header-library +target.lib/libc/headers.public-includes := lib/libc/include +target.lib/libc/headers.public-after-includes := lib/libc/include-after +target.lib/libc/headers.deps := lib/ktl/headers + +target.lib/ktl.kind := source-set +target.lib/ktl.sources := lib/ktl/popcount.cc lib/ktl/stub-new.cc +target.lib/ktl.deps := lib/ktl/headers lib/libc/headers target.lib/runtime.kind := source-set target.lib/runtime.sources := \ @@ -32,4 +46,4 @@ target.lib/libfdt.private-includes := scripts/dtc/libfdt target.lib/libfdt.cflags := -Wno-parentheses -Wno-sign-compare target.lib/core.kind := header-library -target.lib/core.deps := lib/runtime lib/string lib/libfdt +target.lib/core.deps := lib/ktl lib/libc/headers lib/runtime lib/string lib/libfdt diff --git a/lib/ktl/LICENSE b/lib/ktl/LICENSE new file mode 100644 index 0000000..8580f02 --- /dev/null +++ b/lib/ktl/LICENSE @@ -0,0 +1,21 @@ +Copyright 2016 The Fuchsia Authors +Copyright (c) 2008-2015 Travis Geiselbrecht + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/ktl/README.lume b/lib/ktl/README.lume new file mode 100644 index 0000000..7e7c8a4 --- /dev/null +++ b/lib/ktl/README.lume @@ -0,0 +1,8 @@ +KTL configuration overlay imported from Zircon + +Source: zircon/kernel/lib/ktl +Fuchsia revision: f8d670ab4bbb71bfb4d569893ba12fbb8a83bacd + +The complete KTL header overlay and its two implementation files, popcount.cc +and stub-new.cc, are imported. The KTL target is built together with the +Zircon kernel libc header layer and the version-matched libc++ snapshot. diff --git a/lib/ktl/README.md b/lib/ktl/README.md new file mode 100644 index 0000000..667c678 --- /dev/null +++ b/lib/ktl/README.md @@ -0,0 +1,36 @@ +# Kernel Template Library + +The Kernel Template Library is a curated subset of the C++ standard library API +using the `ktl` namespace rather than the `std` namespace. When a specific +interface is deemed useful, safe, and appropriate for use in the kernel, it can +be added here. No `std` APIs are ever used directly in the kernel, only `ktl`. + +The API is a strict subset of the standard C++ library API aside from the +namespace. The header file names are mostly directly mapped as well: + + <foo> -> <ktl/foo.h> + +There can be exceptions. For example, <memory> is a very broad collection of +APIs and the ktl subset is more focused. So instead of <ktl/memory.h> there +are specific headers for the standard APIs from <memory> that are included, such +as <ktl/unique_ptr.h> for `ktl::unique_ptr` (`std::unique_ptr` in <memory>). + +The implementation here simply leverages the libc++ implementation and defines +`using` aliases in the `ktl` namespace. It's expected that ktl will only ever +provide "header only" APIs. + +## ktl enforcement + +The [`<ktl/enforce.h>`](include/ktl/enforce.h) header file should be used in +most `.cc` files (but not `.h`) files meant only for the kernel environment. +That is, in `.cc` files that use the `<ktl/*.h>` headers or use kernel-only +headers that use them. + +This file must appear last in the `#include` list and `clang-format` will +arrange that automatically. + +After this `#include` any use of the `std` identifier in C++ code will cause a +compile-time error. When such errors are encountered, the kernel code should +be checked for use of C++ standard library headers (with no `.h` in the name, +like `<memory>, etc.) that should be replaced with `<ktl/*.h>` headers and for +`std::` names that should be replaced with `ktl::` names. diff --git a/lib/ktl/include-after/errno.h b/lib/ktl/include-after/errno.h new file mode 100644 index 0000000..52edc9c --- /dev/null +++ b/lib/ktl/include-after/errno.h @@ -0,0 +1,13 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_ERRNO_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_ERRNO_H_ + +// The kernel doesn't want this file but some libc++ headers we need +// wind up including it. + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_ERRNO_H_ diff --git a/lib/ktl/include-after/wchar.h b/lib/ktl/include-after/wchar.h new file mode 100644 index 0000000..41d11ae --- /dev/null +++ b/lib/ktl/include-after/wchar.h @@ -0,0 +1,30 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_AFTER_WCHAR_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_AFTER_WCHAR_H_ + +#include <stddef.h> + +// The kernel doesn't want this file but some libc++ headers we need wind up +// including it and they need these declarations. +// +// **NOTE** This file is include-after because libc++ headers get it via +// #include_next so as to get the "system" <wchar.h> rather than libc++'s +// own wrapper. + +typedef struct { +} mbstate_t; + +typedef unsigned int wint_t; +#define WEOF (~wint_t{0}) + +// <string_view> refers to these in code that's never actually used in ktl. +wchar_t* wmemcpy(wchar_t* __restrict, const wchar_t* __restrict, size_t); +wchar_t* wmemmove(wchar_t*, const wchar_t*, size_t); +wchar_t* wmemset(wchar_t*, wchar_t, size_t); + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_AFTER_WCHAR_H_ diff --git a/lib/ktl/include/__chrono/system_clock.h b/lib/ktl/include/__chrono/system_clock.h new file mode 100644 index 0000000..5d39243 --- /dev/null +++ b/lib/ktl/include/__chrono/system_clock.h @@ -0,0 +1,15 @@ +// Copyright 2023 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE___CHRONO_SYSTEM_CLOCK_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE___CHRONO_SYSTEM_CLOCK_H_ + +// libc++'s <atomic> includes this file via various internal headers. +// The declarations it provides aren't needed for the kernel and rely +// on other things stubbed out by the kernel. So this placeholder file +// just prevents compiling the libc++ code that doesn't work. + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE___CHRONO_SYSTEM_CLOCK_H_ diff --git a/lib/ktl/include/__config b/lib/ktl/include/__config new file mode 100644 index 0000000..e04573e --- /dev/null +++ b/lib/ktl/include/__config @@ -0,0 +1,53 @@ +// Copyright 2022 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_ + +// The libc++ internal header <__config> unconditionally responds to some +// predefines set in the EFI environment. So this header wraps it and then +// undoes the damage that our __config_site header can't prevent. + +#include_next <__config> + +#undef _LIBCPP_WIN32API +#undef _LIBCPP_MSVCRT_LIKE +#undef _LIBCPP_MSVCRT +#undef _LIBCPP_HAS_OPEN_WITH_WCHAR + +// This prevents libc++ from doing fallback to spin locks and the like for +// cases where is_always_lock_free is not true. In the kernel, we don't want +// any behind-the-scenes help like that, we want to get link errors from +// libcalls if atomics can't be lowered to real hardware instructions. +#undef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS + +// These are used by <__configuration/availability.h> to decide when headers +// should expect things to be defined in the library. For the kernel, there is +// no library and so everything must be defined in headers. +#undef _LIBCPP_INTRODUCED_IN_LLVM_21 +#define _LIBCPP_INTRODUCED_IN_LLVM_21 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_20 +#define _LIBCPP_INTRODUCED_IN_LLVM_20 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_19 +#define _LIBCPP_INTRODUCED_IN_LLVM_19 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_18 +#define _LIBCPP_INTRODUCED_IN_LLVM_18 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_16 +#define _LIBCPP_INTRODUCED_IN_LLVM_16 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_15 +#define _LIBCPP_INTRODUCED_IN_LLVM_15 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_14 +#define _LIBCPP_INTRODUCED_IN_LLVM_14 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_12 +#define _LIBCPP_INTRODUCED_IN_LLVM_12 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_11 +#define _LIBCPP_INTRODUCED_IN_LLVM_11 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_9 +#define _LIBCPP_INTRODUCED_IN_LLVM_9 0 +#undef _LIBCPP_INTRODUCED_IN_LLVM_4 +#define _LIBCPP_INTRODUCED_IN_LLVM_4 0 + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_ diff --git a/lib/ktl/include/__config_site b/lib/ktl/include/__config_site new file mode 100644 index 0000000..4d2236b --- /dev/null +++ b/lib/ktl/include/__config_site @@ -0,0 +1,81 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_SITE_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_SITE_ + +// The libc++ internal header <__config> does #include <__config_site> to get +// definitions that vary by operating system, machine, or configuration. The +// toolchain's libc++ installation provides include/$triple/.../__config_site +// files for each $cpu-fuchsia appropriate for normal userland. But the ktl +// abuse of libc++ is different from public userland libc++, so provide special +// kernel-appropriate definitions here. This file will be in the include path +// ahead of any toolchain-supplied header. Also, some special bare-metal build +// environments such as phys32 or efi that reuse ktl and kernel libc code may +// use settings that cause the compiler to change the $triple it injects into +// the include path to one for which no runtimes are built and so there is no +// __config_site file to be found at all. + +// These two are what <__config_site> for Fuchsia userland defines. +#define _LIBCPP_ABI_VERSION 2 +#define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS 1 + +// This has to be defined to some `__*` string but what doesn't really matter. +#define _LIBCPP_ABI_NAMESPACE __ktl + +// When compiling in the UEFI environment, the predefines look like Windows +// but there is no Windows runtime environment to use. +#define _LIBCPP_NO_VCRUNTIME 1 + +// This tells the headers not to use `extern template` declarations that +// expect specific instantiations/specializations to come from the libc++ +// library rather than the headers. In the kernel, only the headers are +// ever going to be available. +#define _LIBCPP_DISABLE_EXTERN_TEMPLATE 1 + +// This tells <atomic> not to use threading APIs. +#define _LIBCPP_HAS_NO_PLATFORM_WAIT 1 + +// This tells <atomic> et al to use <__external_threading> instead +// of expecting either POSIX or C11 threading APIs. +#define _LIBCPP_HAS_THREAD_API_EXTERNAL 1 +#define _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL 1 + +// <__config> requires that these be set if _LIBCPP_HAS_THREAD_API_EXTERNAL is. +#define _LIBCPP_HAS_THREADS 1 +#define _LIBCPP_HAS_MONOTONIC_CLOCK 1 + +// This tells <new> not to use `aligned_alloc` from <stdlib.h>. +#define _LIBCPP_HAS_NO_C11_ALIGNED_ALLOC 1 + +// This tells various headers to be strict about what includes what. +#define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES 1 + +// This tells libc++ not to expect full locale APIs in some places. +#define _LIBCPP_HAS_NO_LOCALIZATION 1 + +// This is unfortunately required even though the kernel does not use wide +// characters. +#define _LIBCPP_HAS_WIDE_CHARACTERS 1 + +// This tells pstl headers to use serial algorithms and not try to +// do any multithreading. +#define _LIBCPP_PSTL_CPU_BACKEND_SERIAL 1 + +// This will probably never be used in code that ktl actually uses. +// But define it for completeness. +#define _LIBCPP_INSTRUMENTED_WITH_ASAN __has_feature(address_sanitizer) + +// TODO(https://fxbug.dev/42082322): make the hardening mode selectable through build +// configurations. +// This sets the default to tell libc++ to not enable assertions to prevent +// undefined behavior, but may be overridden if _LIBCPP_HARDENING_MODE is +// defined elsewhere. +#define _LIBCPP_HARDENING_MODE_DEFAULT _LIBCPP_HARDENING_MODE_NONE + +#define _LIBCPP_ASSERTION_SEMANTIC_DEFAULT _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIG_SITE_ diff --git a/lib/ktl/include/__configuration/platform.h b/lib/ktl/include/__configuration/platform.h new file mode 100644 index 0000000..b15e1e0 --- /dev/null +++ b/lib/ktl/include/__configuration/platform.h @@ -0,0 +1,23 @@ +// Copyright 2025 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIGURATION_PLATFORM_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIGURATION_PLATFORM_H_ + +// Other libc++ headers use <__configuration/platform.h> but libc++'s +// <__configuration/platform.h> does not yet recognize the `__PE_COFF__` +// predefine. Until we support this new predefine upstream, +// we must define _LIBCPP_OBJECT_FORMAT_COFF for UEFI targets here. +// TODO(https://fxbug.dev/435771251) -- Support `__PE_COFF__` predefine +// upstream. + +#if defined(__PE_COFF__) +#define _LIBCPP_OBJECT_FORMAT_COFF 2 // Tell libc++ this is PE-COFF. +#endif // __PE_COFF__ + +#include_next <__configuration/platform.h> + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE___CONFIGURATION_PLATFORM_H_ diff --git a/lib/ktl/include/__external_threading b/lib/ktl/include/__external_threading new file mode 100644 index 0000000..9cec903 --- /dev/null +++ b/lib/ktl/include/__external_threading @@ -0,0 +1,35 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE___EXTERNAL_THREADING +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE___EXTERNAL_THREADING + +// libc++'s <atomic> includes this file via <__threading_support>. It needs +// these types and functions declared, but only for use in interfaces that +// aren't supported in the kernel, so stub declarations are all they need. + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __libcpp_timespec_t { + long int tv_sec, tv_nsec; +}; + +using __libcpp_thread_id = int; + +bool __libcpp_thread_id_equal(__libcpp_thread_id, __libcpp_thread_id); +bool __libcpp_thread_id_less(__libcpp_thread_id, __libcpp_thread_id); +__libcpp_thread_id __libcpp_thread_get_current_id(); + +void __libcpp_thread_sleep_for(chrono::nanoseconds); +void __libcpp_thread_yield(); + +// This macro is used unconditionally in <__threading_support> but defined +// there only conditionally on when <__external_threading> is not used. +#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY + +_LIBCPP_END_NAMESPACE_STD + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE___EXTERNAL_THREADING diff --git a/lib/ktl/include/climits b/lib/ktl/include/climits new file mode 100644 index 0000000..86e537d --- /dev/null +++ b/lib/ktl/include/climits @@ -0,0 +1,15 @@ +// Copyright 2022 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +// Other libc++ headers use <climits> but libc++'s <climits> complains if it +// thinks <limits.h> is not its own wrapper, which we do not need. We always +// get the kernel's <limits.h> before the libc++ with the way the include paths +// are set up, which is necessary because of other headers where preempting +// libc++'s header is unavoidable for the kernel environment. + +#include <limits.h> diff --git a/lib/ktl/include/cmath b/lib/ktl/include/cmath new file mode 100644 index 0000000..13b8e6b --- /dev/null +++ b/lib/ktl/include/cmath @@ -0,0 +1,53 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_CMATH_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_CMATH_ + +// The kernel doesn't want this file but some libc++ headers we need +// wind up including it. They don't actually most of the math +// declarations except under #if conditions that aren't true. + +#include <__config> +#include <type_traits> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// These are used in templates that won't ever be instantiated in kernel code. + +template <typename T> +constexpr bool isinf(T&& x) { + static_assert(!is_same_v<T, T>, "must not be instantiated in kernel code"); + return false; +} + +template <typename T> +constexpr bool isnan(T&& x) { + static_assert(!is_same_v<T, T>, "must not be instantiated in kernel code"); + return false; +} + +template <typename T> +constexpr bool signbit(T&& x) { + static_assert(!is_same_v<T, T>, "must not be instantiated in kernel code"); + return false; +} + +template <typename T> +constexpr T frexp(T&& x, int* exponent) { + static_assert(!is_same_v<T, T>, "must not be instantiated in kernel code"); + return x; +} + +template <typename T> +constexpr auto ceil(T&& x) { + static_assert(!is_same_v<T, T>, "must not be instantiated in kernel code"); + return x; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_CMATH_ diff --git a/lib/ktl/include/cstdint b/lib/ktl/include/cstdint new file mode 100644 index 0000000..0ab922c --- /dev/null +++ b/lib/ktl/include/cstdint @@ -0,0 +1,18 @@ +// Copyright 2022 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +// Other libc++ headers use <cstdint> but libc++'s <cstdint> complains if it +// thinks <stdint.h> is not its own wrapper, so we define _LIBCPP_STDINT_H. We +// always get the real <stdint.h> before the libc++ with the way the include +// paths are set up, which is necessary because of other headers where +// preempting libc++'s header is unavoidable for the kernel environment. + +#include <stdint.h> + +#define _LIBCPP_STDINT_H +#include_next <cstdint> diff --git a/lib/ktl/include/cstdio b/lib/ktl/include/cstdio new file mode 100644 index 0000000..349e736 --- /dev/null +++ b/lib/ktl/include/cstdio @@ -0,0 +1,21 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_CSTDIO_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_CSTDIO_ + +// The kernel doesn't want this file but some libc++ headers we need +// wind up including it and they need these declarations. +// +// Note this specifically avoids <stdio.h> because libc++ doesn't need that +// but <string_view> indirectly reaches <cstdio> and the kernel's <stdio.h> +// uses <ktl/string_view.h> so there would be a circularity. + +#include <wchar.h> + +#define EOF (-1) + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_CSTDIO_ diff --git a/lib/ktl/include/cstdlib b/lib/ktl/include/cstdlib new file mode 100644 index 0000000..25ad762 --- /dev/null +++ b/lib/ktl/include/cstdlib @@ -0,0 +1,30 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +// This is used by libc++'s <new> just for std::abort, ::posix_memalign, and +// ::free. + +#include <stdlib.h> + +#include <__config> + +#define _LIBCPP_UNREACHABLE() __builtin_unreachable() + +// This is used by the __libcpp_aligned_alloc inline. Since it always fails +// that inline will trivially always return nullptr. +inline int posix_memalign(void** ptr, size_t align, size_t size) { return 1; } + +// This is used by the __libcpp_aligned_free inline, which won't really ever be +// called. The kernel does have a real free declared elsewhere. +void free(void* ptr); + +_LIBCPP_BEGIN_NAMESPACE_STD + +using ::abort; + +_LIBCPP_END_NAMESPACE_STD diff --git a/lib/ktl/include/cwchar b/lib/ktl/include/cwchar new file mode 100644 index 0000000..4f24c73 --- /dev/null +++ b/lib/ktl/include/cwchar @@ -0,0 +1,62 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_CWCHAR +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_CWCHAR + +// The kernel doesn't want this file but some libc++ headers we need +// wind up including it and they need these declarations. + +#include <wchar.h> + +#include <__config> + +_LIBCPP_BEGIN_NAMESPACE_STD + +using ::wmemcpy; +using ::wmemmove; +using ::wmemset; + +// These are called by libc++ header code. The first two should never actually +// be called by anything that really gets instantiated in kernel code since +// wchar_t is never used. However, __constexpr_wmemchr is used by places like +// std::find not just for wchar_t per se but for any trivial type of the same +// size, e.g. uint32_t. So its code must be correct. The other two are filled +// out just in case of an unexpected use. + +constexpr size_t __constexpr_wcslen(const wchar_t* str) { + size_t len = 0; + while (*str++ != L'\0') { + ++len; + } + return len; +} + +constexpr int __constexpr_wmemcmp(const wchar_t* lhs, const wchar_t* rhs, size_t count) { + while (count-- > 0) { + if (*lhs != *rhs) { + return static_cast<int>(*lhs - *rhs); + } + ++lhs; + ++rhs; + } + return 0; +} + +template <class Tp, class Up> +constexpr Tp* __constexpr_wmemchr(Tp* str, Up wc, size_t count) { + while (count-- > 0) { + if (*str == wc) { + return str; + } + ++str; + } + return nullptr; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_CWCHAR diff --git a/lib/ktl/include/ktl/algorithm.h b/lib/ktl/include/ktl/algorithm.h new file mode 100644 index 0000000..7b7baed --- /dev/null +++ b/lib/ktl/include/ktl/algorithm.h @@ -0,0 +1,116 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ALGORITHM_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ALGORITHM_H_ + +#include <algorithm> + +namespace ktl { + +// "Non-modifying sequence operations" +using std::adjacent_find; +using std::all_of; +using std::any_of; +using std::count; +using std::count_if; +using std::find; +using std::find_end; +using std::find_first_of; +using std::find_if; +using std::find_if_not; +using std::for_each; +using std::for_each_n; +using std::none_of; +using std::search; +using std::search_n; + +namespace ranges { +using std::ranges::adjacent_find; +using std::ranges::all_of; +using std::ranges::any_of; +using std::ranges::count; +using std::ranges::count_if; +using std::ranges::find; +using std::ranges::find_end; +using std::ranges::find_first_of; +using std::ranges::find_if; +using std::ranges::find_if_not; +using std::ranges::for_each; +using std::ranges::for_each_n; +using std::ranges::none_of; +using std::ranges::search; +using std::ranges::search_n; +} // namespace ranges + +// "Modifying sequence operations" (subset) +using std::copy; +using std::copy_if; +using std::fill; +using std::fill_n; +using std::reverse; +using std::shuffle; +using std::transform; + +namespace ranges { +using std::ranges::copy; +using std::ranges::copy_if; +using std::ranges::fill; +using std::ranges::fill_n; +using std::ranges::reverse; +using std::ranges::shuffle; +using std::ranges::transform; +} // namespace ranges + +// "Sorting operations" (subset) +using std::is_sorted; +using std::is_sorted_until; +using std::sort; +using std::stable_sort; + +namespace ranges { +using std::ranges::is_sorted; +using std::ranges::is_sorted_until; +using std::ranges::sort; +using std::ranges::stable_sort; +} // namespace ranges + +// "Binary search operations (on sorted ranges)" +using std::binary_search; +using std::equal_range; +using std::lower_bound; +using std::upper_bound; + +namespace ranges { +using std::ranges::binary_search; +using std::ranges::equal_range; +using std::ranges::lower_bound; +using std::ranges::upper_bound; +} // namespace ranges + +// "Minimum/maximum operations" +using std::clamp; +using std::equal; +using std::max; +using std::max_element; +using std::min; +using std::min_element; +using std::minmax; +using std::minmax_element; + +namespace ranges { +using std::ranges::clamp; +using std::ranges::max; +using std::ranges::max_element; +using std::ranges::min; +using std::ranges::min_element; +using std::ranges::minmax; +using std::ranges::minmax_element; +} // namespace ranges + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ALGORITHM_H_ diff --git a/lib/ktl/include/ktl/array.h b/lib/ktl/include/ktl/array.h new file mode 100644 index 0000000..90d445a --- /dev/null +++ b/lib/ktl/include/ktl/array.h @@ -0,0 +1,19 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ARRAY_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ARRAY_H_ + +#include <array> + +namespace ktl { + +using std::array; +using std::to_array; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ARRAY_H_ diff --git a/lib/ktl/include/ktl/atomic.h b/lib/ktl/include/ktl/atomic.h new file mode 100644 index 0000000..017db6b --- /dev/null +++ b/lib/ktl/include/ktl/atomic.h @@ -0,0 +1,40 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ATOMIC_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ATOMIC_H_ + +#include <atomic> + +// On arm64 and x86-64, lock-free 128-bit (16-byte) atomics are available. +// But riscv64 does not support them. +#ifdef __riscv +#define HAVE_ATOMIC_128 0 +#else +#define HAVE_ATOMIC_128 1 +#endif + +namespace ktl { + +using std::atomic; +using std::atomic_init; +using std::atomic_ref; + +using std::memory_order; + +using std::memory_order_acq_rel; +using std::memory_order_acquire; +using std::memory_order_consume; +using std::memory_order_relaxed; +using std::memory_order_release; +using std::memory_order_seq_cst; + +using std::atomic_signal_fence; +using std::atomic_thread_fence; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ATOMIC_H_ diff --git a/lib/ktl/include/ktl/bit.h b/lib/ktl/include/ktl/bit.h new file mode 100644 index 0000000..c3ccb7e --- /dev/null +++ b/lib/ktl/include/ktl/bit.h @@ -0,0 +1,30 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BIT_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BIT_H_ + +#include <bit> + +namespace ktl { + +using std::bit_cast; +using std::bit_ceil; +using std::bit_floor; +using std::bit_width; +using std::countl_one; +using std::countl_zero; +using std::countr_one; +using std::countr_zero; +using std::endian; +using std::has_single_bit; +using std::popcount; +using std::rotl; +using std::rotr; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BIT_H_ diff --git a/lib/ktl/include/ktl/byte.h b/lib/ktl/include/ktl/byte.h new file mode 100644 index 0000000..26b1294 --- /dev/null +++ b/lib/ktl/include/ktl/byte.h @@ -0,0 +1,18 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BYTE_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BYTE_H_ + +#include <cstddef> + +namespace ktl { + +using std::byte; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_BYTE_H_ diff --git a/lib/ktl/include/ktl/concepts.h b/lib/ktl/include/ktl/concepts.h new file mode 100644 index 0000000..93b3f62 --- /dev/null +++ b/lib/ktl/include/ktl/concepts.h @@ -0,0 +1,46 @@ +// Copyright 2025 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_CONCEPTS_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_CONCEPTS_H_ + +#include <concepts> + +namespace ktl { + +using std::assignable_from; +using std::common_reference_with; +using std::common_with; +using std::constructible_from; +using std::copy_constructible; +using std::copyable; +using std::default_initializable; +using std::derived_from; +using std::destructible; +using std::equality_comparable; +using std::equality_comparable_with; +using std::equivalence_relation; +using std::integral; +using std::invocable; +using std::movable; +using std::move_constructible; +using std::predicate; +using std::regular; +using std::regular_invocable; +using std::relation; +using std::same_as; +using std::semiregular; +using std::signed_integral; +using std::strict_weak_order; +using std::swappable; +using std::swappable_with; +using std::totally_ordered; +using std::totally_ordered_with; +using std::unsigned_integral; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_CONCEPTS_H_ diff --git a/lib/ktl/include/ktl/declval.h b/lib/ktl/include/ktl/declval.h new file mode 100644 index 0000000..925fe9c --- /dev/null +++ b/lib/ktl/include/ktl/declval.h @@ -0,0 +1,18 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_DECLVAL_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_DECLVAL_H_ + +#include <utility> + +namespace ktl { + +using std::declval; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_DECLVAL_H_ diff --git a/lib/ktl/include/ktl/enforce.h b/lib/ktl/include/ktl/enforce.h new file mode 100644 index 0000000..9c948d2 --- /dev/null +++ b/lib/ktl/include/ktl/enforce.h @@ -0,0 +1,37 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ENFORCE_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ENFORCE_H_ + +// `#include <ktl/enforce.h>` should appear last in the include list of any +// kernel .cc file that uses `ktl` headers. Since many other kernel headers +// use ktl headers and this must appear after *all* uses of any ktl headers, +// whether direct or indirect, it's a good idea to just make sure that +// `#include <ktl/enforce.h>` in each .cc file of kernel-only code (i.e. code +// that might ever use ktl directly). +// +// The //.clang-format file has a rule to ensure this file is placed last and +// separate from the other #include lines, so just adding the `#include` line +// to each source file should make sure its placement stays correct. + +// This directive tells the preprocessor that the identifier `std` cannot +// appear in any context (except the expansion of a macro already defined +// before now). This ensures that any stray use of std::name in kernel code +// can get caught at compile time so people remember to use ktl::name instead +// and ensure that what they're using is in the approved ktl subset of std. +// +// It also affects harmless use of `std` as a local variable name or whatever, +// but we can live without kernel code being able to use that one name. +#pragma GCC poison std + +// Also poison the stdcompat namespaces, as the same rules for ktl wrappers +// apply to those as std proper. +#pragma GCC poison cpp17 +#pragma GCC poison cpp20 +#pragma GCC poison cpp23 + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ENFORCE_H_ diff --git a/lib/ktl/include/ktl/forward.h b/lib/ktl/include/ktl/forward.h new file mode 100644 index 0000000..62874e6 --- /dev/null +++ b/lib/ktl/include/ktl/forward.h @@ -0,0 +1,18 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_INCLUDE_KTL_FORWARD_H_ +#define ZIRCON_KERNEL_INCLUDE_KTL_FORWARD_H_ + +#include <utility> + +namespace ktl { + +using std::forward; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_INCLUDE_KTL_FORWARD_H_ diff --git a/lib/ktl/include/ktl/functional.h b/lib/ktl/include/ktl/functional.h new file mode 100644 index 0000000..026f4cf --- /dev/null +++ b/lib/ktl/include/ktl/functional.h @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_FUNCTIONAL_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_FUNCTIONAL_H_ + +#include <functional> + +namespace ktl { + +using std::bind_front; +using std::invoke; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_FUNCTIONAL_H_ diff --git a/lib/ktl/include/ktl/initializer_list.h b/lib/ktl/include/ktl/initializer_list.h new file mode 100644 index 0000000..3a69abb --- /dev/null +++ b/lib/ktl/include/ktl/initializer_list.h @@ -0,0 +1,18 @@ +// Copyright 2021 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INITIALIZER_LIST_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INITIALIZER_LIST_H_ + +#include <initializer_list> + +namespace ktl { + +using std::initializer_list; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INITIALIZER_LIST_H_ diff --git a/lib/ktl/include/ktl/inplace_vector.h b/lib/ktl/include/ktl/inplace_vector.h new file mode 100644 index 0000000..4eaf92b --- /dev/null +++ b/lib/ktl/include/ktl/inplace_vector.h @@ -0,0 +1,18 @@ +// Copyright 2025 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INPLACE_VECTOR_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INPLACE_VECTOR_H_ + +#include <lib/stdcompat/inplace_vector.h> + +namespace ktl { + +using cpp26::inplace_vector; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_INPLACE_VECTOR_H_ diff --git a/lib/ktl/include/ktl/iterator.h b/lib/ktl/include/ktl/iterator.h new file mode 100644 index 0000000..58d92be --- /dev/null +++ b/lib/ktl/include/ktl/iterator.h @@ -0,0 +1,38 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ITERATOR_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ITERATOR_H_ + +#include <iterator> + +namespace ktl { + +// This includes only the "iterator operations" and "range access" subsets +// of the <iterator> API. These are useful for treating all sorts of +// container types, raw arrays, pointers, and {...} literal lists uniformly. +// It leaves out iterator_traits and the "iterator adaptors" subset, which +// have not yet seemed desirable to employ in kernel code. + +using std::advance; +using std::begin; +using std::cbegin; +using std::cend; +using std::crbegin; +using std::crend; +using std::data; +using std::distance; +using std::empty; +using std::end; +using std::next; +using std::prev; +using std::rbegin; +using std::rend; +using std::size; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_ITERATOR_H_ diff --git a/lib/ktl/include/ktl/limits.h b/lib/ktl/include/ktl/limits.h new file mode 100644 index 0000000..8f6adf4 --- /dev/null +++ b/lib/ktl/include/ktl/limits.h @@ -0,0 +1,18 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_INCLUDE_KTL_LIMITS_H_ +#define ZIRCON_KERNEL_INCLUDE_KTL_LIMITS_H_ + +#include <limits> + +namespace ktl { + +using std::numeric_limits; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_INCLUDE_KTL_LIMITS_H_ diff --git a/lib/ktl/include/ktl/memory.h b/lib/ktl/include/ktl/memory.h new file mode 100644 index 0000000..caf8d47 --- /dev/null +++ b/lib/ktl/include/ktl/memory.h @@ -0,0 +1,41 @@ +// Copyright 2024 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_MEMORY_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_MEMORY_H_ + +#include <memory> + +namespace ktl { + +using std::addressof; +using std::to_address; + +using std::align; +using std::assume_aligned; + +using std::default_delete; + +using std::pointer_traits; + +using std::construct_at; +using std::destroy; +using std::destroy_at; +using std::destroy_n; +using std::uninitialized_copy; +using std::uninitialized_copy_n; +using std::uninitialized_default_construct; +using std::uninitialized_default_construct_n; +using std::uninitialized_fill; +using std::uninitialized_fill_n; +using std::uninitialized_move; +using std::uninitialized_move_n; +using std::uninitialized_value_construct; +using std::uninitialized_value_construct_n; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_MEMORY_H_ diff --git a/lib/ktl/include/ktl/new.h b/lib/ktl/include/ktl/new.h new file mode 100644 index 0000000..12def96 --- /dev/null +++ b/lib/ktl/include/ktl/new.h @@ -0,0 +1,25 @@ +// Copyright 2026 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NEW_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NEW_H_ + +#include <new> + +namespace ktl { + +using std::align_val_t; + +using std::destroying_delete; +using std::destroying_delete_t; +using std::nothrow; +using std::nothrow_t; + +using std::launder; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NEW_H_ diff --git a/lib/ktl/include/ktl/numeric.h b/lib/ktl/include/ktl/numeric.h new file mode 100644 index 0000000..18cad1f --- /dev/null +++ b/lib/ktl/include/ktl/numeric.h @@ -0,0 +1,20 @@ +// Copyright 2023 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NUMERIC_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NUMERIC_H_ + +#include <numeric> + +namespace ktl { + +// "Numeric operations" +using std::accumulate; +using std::reduce; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_NUMERIC_H_ diff --git a/lib/ktl/include/ktl/optional.h b/lib/ktl/include/ktl/optional.h new file mode 100644 index 0000000..e08451d --- /dev/null +++ b/lib/ktl/include/ktl/optional.h @@ -0,0 +1,23 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_OPTIONAL_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_OPTIONAL_H_ + +#include <optional> + +namespace ktl { + +using std::in_place; +using std::in_place_t; +using std::make_optional; +using std::nullopt; +using std::nullopt_t; +using std::optional; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_OPTIONAL_H_ diff --git a/lib/ktl/include/ktl/ranges.h b/lib/ktl/include/ktl/ranges.h new file mode 100644 index 0000000..8e3ee09 --- /dev/null +++ b/lib/ktl/include/ktl/ranges.h @@ -0,0 +1,25 @@ +// Copyright 2025 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_RANGES_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_RANGES_H_ + +#include <ranges> + +namespace ktl { + +// This can't be a namespace alias like `views` because <ktl/algorithm.h> also +// adds things to ktl::ranges and redundant namespace aliases aren't allowed. +namespace ranges { +using namespace std::ranges; +} // namespace ranges + +// Only this header defines this namespace, so a simple namespace alias works. +namespace views = std::views; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_RANGES_H_ diff --git a/lib/ktl/include/ktl/ref.h b/lib/ktl/include/ktl/ref.h new file mode 100644 index 0000000..fdaddc4 --- /dev/null +++ b/lib/ktl/include/ktl/ref.h @@ -0,0 +1,19 @@ +// Copyright 2023 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_REF_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_REF_H_ + +#include <functional> + +namespace ktl { + +using std::cref; +using std::ref; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_REF_H_ diff --git a/lib/ktl/include/ktl/source_location.h b/lib/ktl/include/ktl/source_location.h new file mode 100644 index 0000000..121668d --- /dev/null +++ b/lib/ktl/include/ktl/source_location.h @@ -0,0 +1,18 @@ +// Copyright 2025 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SOURCE_LOCATION_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SOURCE_LOCATION_H_ + +#include <source_location> + +namespace ktl { + +using std::source_location; + +} + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SOURCE_LOCATION_H_ diff --git a/lib/ktl/include/ktl/span.h b/lib/ktl/include/ktl/span.h new file mode 100644 index 0000000..deb1df3 --- /dev/null +++ b/lib/ktl/include/ktl/span.h @@ -0,0 +1,26 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SPAN_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SPAN_H_ + +#include <span> + +namespace ktl { + +using std::span; + +using std::as_bytes; +using std::as_writable_bytes; + +using std::dynamic_extent; + +using std::data; +using std::size; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_SPAN_H_ diff --git a/lib/ktl/include/ktl/string_view.h b/lib/ktl/include/ktl/string_view.h new file mode 100644 index 0000000..9ba949f --- /dev/null +++ b/lib/ktl/include/ktl/string_view.h @@ -0,0 +1,22 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_STRING_VIEW_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_STRING_VIEW_H_ + +#include <string_view> + +namespace ktl { + +using std::basic_string_view; +using std::string_view; + +} // namespace ktl + +// Just including <ktl/string_view.h> enables "foo"sv literals. +using namespace std::literals::string_view_literals; + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_STRING_VIEW_H_ diff --git a/lib/ktl/include/ktl/tuple.h b/lib/ktl/include/ktl/tuple.h new file mode 100644 index 0000000..b00c7e0 --- /dev/null +++ b/lib/ktl/include/ktl/tuple.h @@ -0,0 +1,30 @@ +// Copyright 2024 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TUPLE_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TUPLE_H_ + +#include <tuple> + +namespace ktl { + +using std::apply; +using std::forward_as_tuple; +using std::get; +using std::ignore; +using std::make_from_tuple; +using std::make_tuple; +using std::tie; +using std::tuple; +using std::tuple_cat; +using std::tuple_element; +using std::tuple_element_t; +using std::tuple_size; +using std::tuple_size_v; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TUPLE_H_ diff --git a/lib/ktl/include/ktl/type_traits.h b/lib/ktl/include/ktl/type_traits.h new file mode 100644 index 0000000..fc0a2f0 --- /dev/null +++ b/lib/ktl/include/ktl/type_traits.h @@ -0,0 +1,165 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TYPE_TRAITS_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TYPE_TRAITS_H_ + +#include <type_traits> + +namespace ktl { + +using std::add_const; +using std::add_const_t; + +using std::is_array; +using std::is_array_v; +using std::is_bounded_array; +using std::is_bounded_array_v; +using std::is_unbounded_array; +using std::is_unbounded_array_v; + +using std::false_type; +using std::true_type; + +using std::conjunction; +using std::conjunction_v; + +using std::disjunction; +using std::disjunction_v; + +using std::conditional; +using std::conditional_t; + +using std::decay; +using std::decay_t; + +using std::void_t; + +using std::enable_if; +using std::enable_if_t; + +using std::has_unique_object_representations; +using std::has_unique_object_representations_v; + +using std::is_base_of; +using std::is_base_of_v; + +using std::is_const; +using std::is_const_v; + +using std::is_constructible; +using std::is_constructible_v; + +using std::is_copy_constructible; +using std::is_copy_constructible_v; + +using std::is_copy_assignable; +using std::is_copy_assignable_v; + +using std::is_default_constructible; +using std::is_default_constructible_v; + +using std::is_class; +using std::is_class_v; + +using std::is_enum; +using std::is_enum_v; + +using std::is_floating_point; +using std::is_floating_point_v; + +using std::is_function; +using std::is_function_v; + +using std::is_integral; +using std::is_integral_v; + +using std::invoke_result_t; +using std::is_invocable; +using std::is_invocable_r; +using std::is_invocable_r_v; +using std::is_invocable_v; + +using std::is_lvalue_reference; +using std::is_lvalue_reference_v; + +using std::is_move_constructible; +using std::is_move_constructible_v; + +using std::is_move_assignable; +using std::is_move_assignable_v; + +using std::is_pod; +using std::is_pod_v; + +using std::is_same; +using std::is_same_v; + +using std::is_signed; +using std::is_signed_v; + +using std::is_standard_layout; +using std::is_standard_layout_v; + +using std::is_empty; +using std::is_empty_v; + +using std::is_trivial; +using std::is_trivial_v; + +using std::is_trivially_copy_assignable; +using std::is_trivially_copy_assignable_v; + +using std::is_trivially_copy_constructible; +using std::is_trivially_copy_constructible_v; + +using std::is_trivially_constructible; +using std::is_trivially_constructible_v; + +using std::is_trivially_destructible; +using std::is_trivially_destructible_v; + +using std::is_trivially_move_assignable; +using std::is_trivially_move_assignable_v; + +using std::is_trivially_move_constructible; +using std::is_trivially_move_constructible_v; + +using std::is_member_object_pointer; +using std::is_member_object_pointer_v; + +using std::is_unsigned; +using std::is_unsigned_v; + +using std::is_void; +using std::is_void_v; + +using std::make_signed; +using std::make_signed_t; +using std::make_unsigned; +using std::make_unsigned_t; + +using std::remove_all_extents; +using std::remove_all_extents_t; + +using std::remove_const; +using std::remove_const_t; + +using std::remove_extent; +using std::remove_extent_t; + +using std::remove_pointer; +using std::remove_pointer_t; + +using std::remove_reference; +using std::remove_reference_t; + +using std::underlying_type; +using std::underlying_type_t; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_TYPE_TRAITS_H_ diff --git a/lib/ktl/include/ktl/unique_ptr.h b/lib/ktl/include/ktl/unique_ptr.h new file mode 100644 index 0000000..e2d2f39 --- /dev/null +++ b/lib/ktl/include/ktl/unique_ptr.h @@ -0,0 +1,37 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_INCLUDE_KTL_UNIQUE_PTR_H_ +#define ZIRCON_KERNEL_INCLUDE_KTL_UNIQUE_PTR_H_ + +#include <memory> +#include <new> + +#include <fbl/alloc_checker.h> +#include <ktl/type_traits.h> + +namespace ktl { + +using std::align_val_t; +using std::unique_ptr; + +template <typename T, typename... Args> +ktl::enable_if_t<!ktl::is_array_v<T>, unique_ptr<T>> make_unique(fbl::AllocChecker* ac, + Args&&... args) { + return unique_ptr<T>(new (ac) T(std::forward<Args>(args)...)); +} + +// For an unbounded array of given size, each element is value-initialized. +// This is different from plain `new (ac) T[n]`, which performs default-initialization. +template <typename T, typename... Args> +ktl::enable_if_t<ktl::is_unbounded_array_v<T>, unique_ptr<T>> make_unique(fbl::AllocChecker* ac, + size_t n) { + return unique_ptr<T>(new (ac) ktl::remove_extent_t<T>[n]()); +} + +} // namespace ktl + +#endif // ZIRCON_KERNEL_INCLUDE_KTL_UNIQUE_PTR_H_ diff --git a/lib/ktl/include/ktl/utility.h b/lib/ktl/include/ktl/utility.h new file mode 100644 index 0000000..1e699e2 --- /dev/null +++ b/lib/ktl/include/ktl/utility.h @@ -0,0 +1,41 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_UTILITY_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_UTILITY_H_ + +#include <utility> + +namespace ktl { + +using std::declval; +using std::exchange; +using std::forward; +using std::move; +using std::swap; + +using std::in_place; +using std::in_place_index; +using std::in_place_index_t; +using std::in_place_t; + +using std::index_sequence; +using std::index_sequence_for; +using std::integer_sequence; +using std::make_index_sequence; +using std::make_integer_sequence; + +using std::get; +using std::make_pair; +using std::pair; +using std::piecewise_construct; +using std::piecewise_construct_t; + +using std::ignore; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_UTILITY_H_ diff --git a/lib/ktl/include/ktl/variant.h b/lib/ktl/include/ktl/variant.h new file mode 100644 index 0000000..68ef362 --- /dev/null +++ b/lib/ktl/include/ktl/variant.h @@ -0,0 +1,31 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_VARIANT_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_VARIANT_H_ + +#include <utility> +#include <variant> + +namespace ktl { + +using std::get; +using std::get_if; +using std::holds_alternative; +using std::in_place_type; +using std::in_place_type_t; +using std::monostate; +using std::variant; +using std::variant_alternative; +using std::variant_alternative_t; +using std::variant_npos; +using std::variant_size; +using std::variant_size_v; +using std::visit; + +} // namespace ktl + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_KTL_VARIANT_H_ diff --git a/lib/ktl/include/limits b/lib/ktl/include/limits new file mode 100644 index 0000000..d8ea37d --- /dev/null +++ b/lib/ktl/include/limits @@ -0,0 +1,110 @@ +// Copyright 2018 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +// TODO(https://fxbug.dev/42106615): The libc++ <limits> defines specializations for +// floating-point types, which in GCC is incompatible with the command-line +// switches used for the kernel. So this header fakes out the other libc++ +// headers with a std::numeric_limits that is close enough. + +#include <limits.h> + +namespace std { + +template <class T> +class numeric_limits {}; + +#define SPECIALIZE_INT(type, sign, modulo, digits_, min_, max_) \ + template <> \ + class numeric_limits<type> { \ + public: \ + static constexpr bool is_specialized = true; \ + static constexpr bool is_signed = (sign); \ + static constexpr bool is_integer = true; \ + static constexpr bool is_exact = true; \ + static constexpr bool has_infinity = false; \ + static constexpr bool has_quiet_NaN = false; \ + static constexpr bool has_signaling_NaN = false; \ + static constexpr bool has_denorm = false; \ + static constexpr bool has_denorm_loss = false; \ + static constexpr bool round_style = false; \ + static constexpr bool is_iec559 = false; \ + static constexpr bool is_bounded = true; \ + static constexpr bool is_modulo = (modulo); \ + static constexpr int digits = (digits_); \ + static constexpr int digits10 = (digits_) * 3 / 10; \ + static constexpr int max_digits10 = 0; \ + static constexpr int radix = 2; \ + static constexpr int min_exponent = 0; \ + static constexpr int min_exponent10 = 0; \ + static constexpr int max_exponent = 0; \ + static constexpr int max_exponent10 = 0; \ + static constexpr bool traps = false; \ + static constexpr bool tinyness_before = false; \ + static constexpr type min() { \ + return (min_); \ + } \ + static constexpr type lowest() { \ + return (min_); \ + } \ + static constexpr type max() { \ + return (max_); \ + } \ + static constexpr type epsilon() { \ + return 0; \ + } \ + static constexpr type round_error() { \ + return 0; \ + } \ + static constexpr type infinity() { \ + return 0; \ + } \ + static constexpr type quiet_NaN() { \ + return 0; \ + } \ + static constexpr type signaling_NaN() { \ + return 0; \ + } \ + static constexpr type denorm_min() { \ + return 0; \ + } \ + } + +#define SPECIALIZE_SIGNED(type, min, max) \ + SPECIALIZE_INT(type, true, false, CHAR_BIT * sizeof(type) - 1, min, max) + +#define SPECIALIZE_UNSIGNED(type, min, max) \ + SPECIALIZE_INT(type, false, true, CHAR_BIT * sizeof(type), min, max) + +SPECIALIZE_INT(bool, false, true, 1, false, true); +#if CHAR_MIN == 0 +SPECIALIZE_UNSIGNED(char, CHAR_MIN, CHAR_MAX); +#else +SPECIALIZE_SIGNED(char, CHAR_MIN, CHAR_MAX); +#endif +SPECIALIZE_SIGNED(signed char, SCHAR_MIN, SCHAR_MAX); +SPECIALIZE_UNSIGNED(unsigned char, 0, UCHAR_MAX); + +SPECIALIZE_SIGNED(short, SHRT_MIN, SHRT_MAX); +SPECIALIZE_UNSIGNED(unsigned short, 0, USHRT_MAX); +SPECIALIZE_SIGNED(int, INT_MIN, INT_MAX); +SPECIALIZE_UNSIGNED(unsigned int, 0, UINT_MAX); +SPECIALIZE_SIGNED(long, LONG_MIN, LONG_MAX); +SPECIALIZE_UNSIGNED(unsigned long, 0, ULONG_MAX); +SPECIALIZE_SIGNED(long long, (-__LONG_LONG_MAX__ - 1LL), __LONG_LONG_MAX__); +SPECIALIZE_UNSIGNED(unsigned long long, 0, (__LONG_LONG_MAX__ * 2ULL + 1ULL)); + +#ifdef __SIZEOF_INT128__ +SPECIALIZE_SIGNED(__int128_t, (__int128_t{1} << 127), (~__uint128_t{0} ^ (__int128_t{1} << 127))); +SPECIALIZE_UNSIGNED(__uint128_t, 0, (~__uint128_t{0})); +#endif + +#undef SPECIALIZE_SIGNED +#undef SPECIALIZE_UNSIGNED +#undef SPECIALIZE_INT + +} // namespace std diff --git a/lib/ktl/include/time.h b/lib/ktl/include/time.h new file mode 100644 index 0000000..138801f --- /dev/null +++ b/lib/ktl/include/time.h @@ -0,0 +1,39 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_TIME_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_TIME_H_ + +#include <stddef.h> + +// <zircon/time.h> uses these when __has_include(<time.h>). +typedef long int time_t; +struct timespec { + time_t tv_sec; + long int tv_nsec; +}; + +// The kernel doesn't want this file but some libc++ headers we need +// wind up including it and they need these declarations. + +#ifdef __cplusplus + +using clock_t = long int; +struct tm {}; +char* asctime(tm*) noexcept; +clock_t clock() noexcept; +char* ctime(const time_t*) noexcept; +double difftime(time_t, time_t) noexcept; +tm* gmtime(const time_t*) noexcept; +tm* localtime(const time_t*) noexcept; +time_t mktime(tm*) noexcept; +size_t strftime(char*, size_t, const char*, const tm*) noexcept; +time_t time(time_t*) noexcept; +int timespec_get(timespec* ts, int) noexcept; + +#endif // __cplusplus + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_TIME_H_ diff --git a/lib/ktl/include/version b/lib/ktl/include/version new file mode 100644 index 0000000..ba04749 --- /dev/null +++ b/lib/ktl/include/version @@ -0,0 +1,14 @@ +// Copyright 2024 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +#include_next <version> + +// We want to be able to implement specialization for std::formatter in common libraries for kernel +// and userspace. By undefing it here, we allow those libraries to avoid exposing that code to the +// kernel where it's not supported. +#undef __cpp_lib_format diff --git a/lib/ktl/include/wchar.h b/lib/ktl/include/wchar.h new file mode 100644 index 0000000..b3f2ccb --- /dev/null +++ b/lib/ktl/include/wchar.h @@ -0,0 +1,23 @@ +// Copyright 2023 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_KTL_INCLUDE_WCHAR_H_ +#define ZIRCON_KERNEL_LIB_KTL_INCLUDE_WCHAR_H_ + +// This file is included by <cstdio> and the like that are used from other +// libc++ headers that are wrapped by ktl. This file exists to preempt those +// inclusions so that libc++'s <wchar.h> wrapper header won't be used, since +// it's not compatible with the kernel environment. However, other libc++ +// headers also use `#include_next <wchar.h>` to get to "the system libc" +// version of the header. To satisfy those, include-after/wchar.h provides the +// actual declarations needed from the standard C <wchar.h> API. So this +// header just defers to that one, but must exist separately in this directory +// so that it preempt's libc++'s wrapper. This can't itself use #include_next +// because that would reach libc++'s wrapper before the include-after file. + +#include "../include-after/wchar.h" + +#endif // ZIRCON_KERNEL_LIB_KTL_INCLUDE_WCHAR_H_ diff --git a/lib/ktl/popcount.cc b/lib/ktl/popcount.cc new file mode 100644 index 0000000..07b7888 --- /dev/null +++ b/lib/ktl/popcount.cc @@ -0,0 +1,135 @@ +// Copyright 2019 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#include <stdint.h> + +// When the compiler doesn't inline __builtin_popcount{,l}, it calls these. +extern "C" int __popcountsi2(uint32_t val); +extern "C" int __popcountdi2(uint64_t val); +// If the compiler doesn't inline __builtin_popcount % 2 it calls this. +extern "C" int __paritydi2(uint64_t val); + +extern "C" int __popcountsi2(uint32_t val) { + // Implement a log2(bits) popcount, with a few tricks to save some + // instructions. + // + // The general idea here is to simply add up the bits in the word in + // parallel, storing intermediate results in different bit positions in + // the word as we go, and eventually arriving at a sum which is the + // popcount of the word. + // + // For example, consider an 8 bit integer written as + // + // b7 b6 b5 b4 b3 b2 b1 b0 + // + // Each of the bits in the word represent a partial sum that, when added + // together, produce our result. We can compute... + // + // ( + // b7 b6 b5 b4 b3 b2 b1 b0 & + // 0 1 0 1 0 1 0 1 = + // 0 b6 0 b4 0 b2 0 b0 + // ) + ( + // b7 b6 b5 b4 b3 b2 b1 b0 >> 1 = + // 0 b7 b6 b5 b4 b3 b2 b1 & + // 0 1 0 1 0 1 0 1 = + // 0 b7 0 b5 0 b3 0 b1 + // ) = + // b7+b6 b5+b4 b3+b2 b1+b0 + // + // And now we have 4 partial sums, each of which takes two bits of + // storage instead of one. Repeating this process with appropriate + // masks and shifts will eventually give us the answer we are looking + // for. After the next step, we will have partial sums which require 3 + // bits of storage, but aligned to 4 bit boundaries; so... + // + // 0 (b7+b6+b5+b4) 0 (b3+b2+b1+b0) + // + // After the last step, we will get the final sum stored in 4 bits, with + // guaranteed 0s for the upper bits. + // aligned to ... + // + // 0 0 0 0 (b7+b6+b5+b4+b3+b2+b1+b0) + // + // While this is the general idea, it turns out that we only need to + // follow this exact process during step #2. For each of the other + // steps (there will be 5 for a 32 bit integer) we can shave a few + // cycles by taking advantage of some of the particular properties of + // each step. See the comments below. + constexpr uint32_t mask1 = 0x55555555; + constexpr uint32_t mask2 = 0x33333333; + constexpr uint32_t mask3 = 0x0F0F0F0F; + constexpr uint32_t mult1 = 0x01010101; + + // Step 1: + // While we could compute (val & mask) + ((val >> 1) & mask), we can + // actually save one of the mask operations by subtracting instead of + // adding. Consider the following truth table... + // + // In | >>1 | & | - | + // X00 | XX0 | X00 | X00 | + // X01 | XX0 | X00 | X01 | + // X10 | XX1 | X01 | X01 | + // X11 | XX1 | X01 | X10 | + // + val = val - ((val >> 1) & mask1); + + // Step 2: + // This is simply the operation described in the overview, adding a + // bunch of 2 bit partials to produce a 3 bit result, but which is + // aligned on 4 bit boundaries (where the MSB of each 4 bit nibble is + // guaranteed to be 0) + val = (val & mask2) + ((val >> 2) & mask2); + + // Step 3: + // Again, we can save a mask operation here. This time, it is because + // the we know that all bit positions ((i * 4) + 3) are guaranteed to be + // zero. We can simply shift by 4 and add the partial sums. Any + // overflow will go into the ((i * 4) + 3) position and not interfere + // with any of the other partial sums. + val = (val + (val >> 4)) & mask3; + + // Step 4 + 5: + // Finally, we can combine steps 4 and 5 using a multiply. We have 4 + // remaining partial sums, each of which is contained in 4 bits and + // aligned to 8 bit boundaries (with 4 bits of zero in-between each + // sum). Now, we have enough space that if we could perform all 4 sums + // at once, we know that the result would fit in (at most) 6 bits, which + // easily fits in our 8 bits of space. + // + // At its heart, multiplying is the equivalent of repeated shifting, and + // conditional adding. IOW - if I multiply by 0101b, it is basically + // the same as saying "shift X left by 0, then add that to shift X left + // by 2" (because bits 0 and bits 2 are the only bits set). + // + // So, we have, 0x0A0B0C0D, and want to compute (A+B+C+D). Multiplying + // our register by 0x01010101 basically does this for us. We are + // summing our register shifted left by 0 (A), 8 (B), 16 (C) and 24 (D), + // which puts A+B+C+D into the upper 8 bits of the register. The lower + // 24 bits are junk, but we know (because of the 0s which separate A-D) + // that this junk is not going to overflow into our result. All we need + // to do is right shift by 24, and we are done. + return (val * mult1) >> 24; +} + +extern "C" int __popcountdi2(uint64_t val) { + // See notes above for how this works. The 64 bit version of this is + // identical to the 32 bit version, the only difference is that during + // the final stage, we use the multiply trick to combine steps 4, 5, and + // 6 to sum all 8 4-bit partial sums at once, fitting the result into a + // 7 bit value. + constexpr uint64_t mask1 = 0x5555555555555555; + constexpr uint64_t mask2 = 0x3333333333333333; + constexpr uint64_t mask3 = 0x0F0F0F0F0F0F0F0F; + constexpr uint64_t mult1 = 0x0101010101010101; + + val = val - ((val >> 1) & mask1); + val = (val & mask2) + ((val >> 2) & mask2); + val = (val + (val >> 4)) & mask3; + return static_cast<int>((val * mult1) >> 56); +} + +extern "C" int __paritydi2(uint64_t val) { return __popcountdi2(val) % 2; } diff --git a/lib/ktl/stub-new.cc b/lib/ktl/stub-new.cc new file mode 100644 index 0000000..919d941 --- /dev/null +++ b/lib/ktl/stub-new.cc @@ -0,0 +1,25 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#include <new> + +// std::stable_sort (used as ktl::stable_sort) uses std::get_temporary_buffer, +// which uses operator new to request a temporary buffer but then works fine +// if it can't get one. There is no "default" memory allocation in the +// kernel, so just provide a stub operator new that always fails so +// std::stable_sort falls back to its no-allocation algorithm. + +namespace std { + +const nothrow_t nothrow; + +} // namespace std + +void* operator new(std::size_t, const std::nothrow_t&) noexcept { return nullptr; } + +void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept { + return nullptr; +} diff --git a/lib/libc/LICENSE b/lib/libc/LICENSE new file mode 100644 index 0000000..8580f02 --- /dev/null +++ b/lib/libc/LICENSE @@ -0,0 +1,21 @@ +Copyright 2016 The Fuchsia Authors +Copyright (c) 2008-2015 Travis Geiselbrecht + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/libc/README.lume b/lib/libc/README.lume new file mode 100644 index 0000000..8d50752 --- /dev/null +++ b/lib/libc/README.lume @@ -0,0 +1,10 @@ +Zircon kernel libc header layer + +Source: zircon/kernel/lib/libc/include and include-after +Fuchsia revision: f8d670ab4bbb71bfb4d569893ba12fbb8a83bacd + +This first import contains the complete public header layer. The libc +implementation sources are intentionally not imported yet because abort, +panic, heap, console output, and C++ ABI providers belong to later foundation +batches. Existing LumeOS C implementations continue to provide the symbols +used by the current kernel. diff --git a/lib/libc/include-after/ctype.h b/lib/libc/include-after/ctype.h new file mode 100644 index 0000000..ff2fcfe --- /dev/null +++ b/lib/libc/include-after/ctype.h @@ -0,0 +1,33 @@ +// Copyright 2016 The Fuchsia Authors +// Copyright (c) 2008 Travis Geiselbrecht +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_CTYPE_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_CTYPE_H_ + +#include <zircon/compiler.h> + +__BEGIN_CDECLS + +int isalnum(int c); +int isalpha(int c); +int isblank(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); + +int tolower(int c); +int toupper(int c); + +__END_CDECLS + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_CTYPE_H_ diff --git a/lib/libc/include-after/limits.h b/lib/libc/include-after/limits.h new file mode 100644 index 0000000..f946def --- /dev/null +++ b/lib/libc/include-after/limits.h @@ -0,0 +1,7 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +// Empty file for toolchain's #include_next <limits.h> to find. diff --git a/lib/libc/include/assert.h b/lib/libc/include/assert.h new file mode 100644 index 0000000..8b6252e --- /dev/null +++ b/lib/libc/include/assert.h @@ -0,0 +1,20 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#pragma once + +#include <zircon/assert.h> + +#ifdef NDEBUG +#define assert(expr) ((void)0) +#else +#define assert(expr) ZX_ASSERT(expr) +#endif + +// make sure static_assert() is defined, even in C +#if !defined(__cplusplus) && !defined(static_assert) +#define static_assert(e, msg) _Static_assert(e, msg) +#endif diff --git a/lib/libc/include/inttypes.h b/lib/libc/include/inttypes.h new file mode 100644 index 0000000..b19e0f5 --- /dev/null +++ b/lib/libc/include/inttypes.h @@ -0,0 +1,117 @@ +// Copyright 2016 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_ + +// This (or the compiler) defines all the __<type>_FMT<letter>__ macros. +#include <stdint.h> + +#define PRId8 __INT8_FMTd__ +#define PRId16 __INT16_FMTd__ +#define PRId32 __INT32_FMTd__ +#define PRId64 __INT64_FMTd__ + +#define PRIdLEAST8 __INT_LEAST8_FMTd__ +#define PRIdLEAST16 __INT_LEAST16_FMTd__ +#define PRIdLEAST32 __INT_LEAST32_FMTd__ +#define PRIdLEAST64 __INT_LEAST64_FMTd__ + +#define PRIdFAST8 __INT_FAST8_FMTd__ +#define PRIdFAST16 __INT_FAST16_FMTd__ +#define PRIdFAST32 __INT_FAST32_FMTd__ +#define PRIdFAST64 __INT_FAST64_FMTd__ + +#define PRIi8 __INT8_FMTi__ +#define PRIi16 __INT16_FMTi__ +#define PRIi32 __INT32_FMTi__ +#define PRIi64 __INT64_FMTi__ + +#define PRIiLEAST8 __INT_LEAST8_FMTi__ +#define PRIiLEAST16 __INT_LEAST16_FMTi__ +#define PRIiLEAST32 __INT_LEAST32_FMTi__ +#define PRIiLEAST64 __INT_LEAST64_FMTi__ + +#define PRIiFAST8 __INT_FAST8_FMTi__ +#define PRIiFAST16 __INT_FAST16_FMTi__ +#define PRIiFAST32 __INT_FAST32_FMTi__ +#define PRIiFAST64 __INT_FAST64_FMTi__ + +#define PRIo8 __UINT8_FMTo__ +#define PRIo16 __UINT16_FMTo__ +#define PRIo32 __UINT32_FMTo__ +#define PRIo64 __UINT64_FMTo__ + +#define PRIoLEAST8 __UINT_LEAST8_FMTo__ +#define PRIoLEAST16 __UINT_LEAST16_FMTo__ +#define PRIoLEAST32 __UINT_LEAST32_FMTo__ +#define PRIoLEAST64 __UINT_LEAST64_FMTo__ + +#define PRIoFAST8 __UINT_FAST8_FMTo__ +#define PRIoFAST16 __UINT_FAST16_FMTo__ +#define PRIoFAST32 __UINT_FAST32_FMTo__ +#define PRIoFAST64 __UINT_FAST64_FMTo__ + +#define PRIu8 __UINT8_FMTu__ +#define PRIu16 __UINT16_FMTu__ +#define PRIu32 __UINT32_FMTu__ +#define PRIu64 __UINT64_FMTu__ + +#define PRIuLEAST8 __UINT_LEAST8_FMTu__ +#define PRIuLEAST16 __UINT_LEAST16_FMTu__ +#define PRIuLEAST32 __UINT_LEAST32_FMTu__ +#define PRIuLEAST64 __UINT_LEAST64_FMTu__ + +#define PRIuFAST8 __UINT_FAST8_FMTu__ +#define PRIuFAST16 __UINT_FAST16_FMTu__ +#define PRIuFAST32 __UINT_FAST32_FMTu__ +#define PRIuFAST64 __UINT_FAST64_FMTu__ + +#define PRIx8 __UINT8_FMTx__ +#define PRIx16 __UINT16_FMTx__ +#define PRIx32 __UINT32_FMTx__ +#define PRIx64 __UINT64_FMTx__ + +#define PRIxLEAST8 __UINT_LEAST8_FMTx__ +#define PRIxLEAST16 __UINT_LEAST16_FMTx__ +#define PRIxLEAST32 __UINT_LEAST32_FMTx__ +#define PRIxLEAST64 __UINT_LEAST64_FMTx__ + +#define PRIxFAST8 __UINT_FAST8_FMTx__ +#define PRIxFAST16 __UINT_FAST16_FMTx__ +#define PRIxFAST32 __UINT_FAST32_FMTx__ +#define PRIxFAST64 __UINT_FAST64_FMTx__ + +#define PRIX8 __UINT8_FMTX__ +#define PRIX16 __UINT16_FMTX__ +#define PRIX32 __UINT32_FMTX__ +#define PRIX64 __UINT64_FMTX__ + +#define PRIXLEAST8 __UINT_LEAST8_FMTX__ +#define PRIXLEAST16 __UINT_LEAST16_FMTX__ +#define PRIXLEAST32 __UINT_LEAST32_FMTX__ +#define PRIXLEAST64 __UINT_LEAST64_FMTX__ + +#define PRIXFAST8 __UINT_FAST8_FMTX__ +#define PRIXFAST16 __UINT_FAST16_FMTX__ +#define PRIXFAST32 __UINT_FAST32_FMTX__ +#define PRIXFAST64 __UINT_FAST64_FMTX__ + +#define PRIdMAX __INTMAX_FMTd__ +#define PRIiMAX __INTMAX_FMTi__ +#define PRIoMAX __UINTMAX_FMTo__ +#define PRIuMAX __UINTMAX_FMTu__ +#define PRIxMAX __UINTMAX_FMTx__ +#define PRIXMAX __UINTMAX_FMTX__ + +#define PRIdPTR __INTPTR_FMTd__ +#define PRIiPTR __INTPTR_FMTi__ +#define PRIoPTR __UINTPTR_FMTo__ +#define PRIuPTR __UINTPTR_FMTu__ +#define PRIxPTR __UINTPTR_FMTx__ +#define PRIXPTR __UINTPTR_FMTX__ + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_INTTYPES_H_ diff --git a/lib/libc/include/multi-file.h b/lib/libc/include/multi-file.h new file mode 100644 index 0000000..a04a031 --- /dev/null +++ b/lib/libc/include/multi-file.h @@ -0,0 +1,50 @@ +// Copyright 2022 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_ + +#include <stdio.h> + +#include <ktl/array.h> +#include <ktl/forward.h> +#include <ktl/string_view.h> +#include <ktl/type_traits.h> + +// MultiFile broadcasts Write calls across multiple FILE* pointers. Each +// pointer is ignored if it's null. MultiFile::Write always returns success, +// ignoring any failures or short writes from the underlying FILE objects. +template <size_t N> +class MultiFile : public FILE { + public: + using FileArray = ktl::array<FILE*, N>; + + constexpr MultiFile() : FILE{this} {} + + constexpr explicit MultiFile(const FileArray& files) : FILE{this}, files_(files) {} + + constexpr MultiFile(const MultiFile& other) : MultiFile(other.files_) {} + + FileArray& files() { return files_; } + const FileArray& files() const { return files_; } + + int Write(ktl::string_view str) { + for (FILE* file : files_) { + if (file) { + file->Write(str); + } + } + return static_cast<int>(str.size()); + } + + private: + FileArray files_ = {}; +}; + +template <size_t N> +MultiFile(const ktl::array<FILE*, N>&) -> MultiFile<N>; + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_MULTI_FILE_H_ diff --git a/lib/libc/include/stdint.h b/lib/libc/include/stdint.h new file mode 100644 index 0000000..3cbdfeb --- /dev/null +++ b/lib/libc/include/stdint.h @@ -0,0 +1,278 @@ +// Copyright 2016 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_ + +// The compiler predefines macros __<type>_TYPE__, __<type>_MAX__, +// and __<type>_C for the various types. All we have to do here is +// define the public names based on those macros. + +// Clang predefines macros __<type>_FMT<letter>__ for each type, +// with <letter> being i and for signed types, and o, u, x, and X +// for unsigned types. That lets <inttypes.h> do its work without +// any special knowledge of what the underlying types are. +// Unfortunately, GCC does not define these macros. To keep all +// knowledge of the compiler's choices isolated to this file, define +// them here for GCC so that <inttypes.h> can use them unconditionally. +#ifndef __INTMAX_FMTd__ + +#define __INT8_FMT_MODIFIER__ "hh" +#define __INT16_FMT_MODIFIER__ "h" +#ifdef _LP64 +#define __INT32_FMT_MODIFIER__ "" +#else +#define __INT32_FMT_MODIFIER__ "l" +#endif + +#define __INT_LEAST8_FMT_MODIFIER__ __INT8_FMT_MODIFIER__ +#define __INT_LEAST16_FMT_MODIFIER__ __INT16_FMT_MODIFIER__ +#define __INT_LEAST32_FMT_MODIFIER__ __INT32_FMT_MODIFIER__ +#define __INT_LEAST64_FMT_MODIFIER__ __INT64_FMT_MODIFIER__ + +// The *-elf and arm-eabi GCC targets use 'int' for the fast{8,16,32} +// types. On LP64 systems, 'long' is used for the fast64 type, and +// 'long long' on non-LP64 systems. +#define __INT_FAST8_FMT_MODIFIER__ "" +#define __INT_FAST16_FMT_MODIFIER__ "" +#define __INT_FAST32_FMT_MODIFIER__ "" +#if _LP64 +#define __INT_FAST64_FMT_MODIFIER__ "l" +#else +#define __INT_FAST64_FMT_MODIFIER__ "ll" +#endif + +// On machines where 'long' types are 64 bits, the compiler defines +// __INT64_TYPE__ et al using 'long', not 'long long', though both are +// 64-bit types. +#ifdef _LP64 +#define __INT64_FMT_MODIFIER__ "l" +#define __INTPTR_FMT_MODIFIER__ "l" +#else +#define __INT64_FMT_MODIFIER__ "ll" +#define __INTPTR_FMT_MODIFIER__ "" +#endif + +#define __INTMAX_FMT_MODIFIER__ __INT64_FMT_MODIFIER__ + +#define __INTMAX_FMTd__ __INTMAX_FMT_MODIFIER__ "d" +#define __INTMAX_FMTi__ __INTMAX_FMT_MODIFIER__ "i" +#define __UINTMAX_FMTo__ __INTMAX_FMT_MODIFIER__ "o" +#define __UINTMAX_FMTu__ __INTMAX_FMT_MODIFIER__ "u" +#define __UINTMAX_FMTx__ __INTMAX_FMT_MODIFIER__ "x" +#define __UINTMAX_FMTX__ __INTMAX_FMT_MODIFIER__ "X" +#define __INTPTR_FMTd__ __INTPTR_FMT_MODIFIER__ "d" +#define __INTPTR_FMTi__ __INTPTR_FMT_MODIFIER__ "i" +#define __UINTPTR_FMTo__ __INTPTR_FMT_MODIFIER__ "o" +#define __UINTPTR_FMTu__ __INTPTR_FMT_MODIFIER__ "u" +#define __UINTPTR_FMTx__ __INTPTR_FMT_MODIFIER__ "x" +#define __UINTPTR_FMTX__ __INTPTR_FMT_MODIFIER__ "X" +#define __INT8_FMTd__ __INT8_FMT_MODIFIER__ "d" +#define __INT8_FMTi__ __INT8_FMT_MODIFIER__ "i" +#define __INT16_FMTd__ __INT16_FMT_MODIFIER__ "d" +#define __INT16_FMTi__ __INT16_FMT_MODIFIER__ "i" +#define __INT32_FMTd__ __INT32_FMT_MODIFIER__ "d" +#define __INT32_FMTi__ __INT32_FMT_MODIFIER__ "i" +#define __INT64_FMTd__ __INT64_FMT_MODIFIER__ "d" +#define __INT64_FMTi__ __INT64_FMT_MODIFIER__ "i" +#define __UINT8_FMTo__ __INT8_FMT_MODIFIER__ "o" +#define __UINT8_FMTu__ __INT8_FMT_MODIFIER__ "u" +#define __UINT8_FMTx__ __INT8_FMT_MODIFIER__ "x" +#define __UINT8_FMTX__ __INT8_FMT_MODIFIER__ "X" +#define __UINT16_FMTo__ __INT16_FMT_MODIFIER__ "o" +#define __UINT16_FMTu__ __INT16_FMT_MODIFIER__ "u" +#define __UINT16_FMTx__ __INT16_FMT_MODIFIER__ "x" +#define __UINT16_FMTX__ __INT16_FMT_MODIFIER__ "X" +#define __UINT32_FMTo__ __INT32_FMT_MODIFIER__ "o" +#define __UINT32_FMTu__ __INT32_FMT_MODIFIER__ "u" +#define __UINT32_FMTx__ __INT32_FMT_MODIFIER__ "x" +#define __UINT32_FMTX__ __INT32_FMT_MODIFIER__ "X" +#define __UINT64_FMTo__ __INT64_FMT_MODIFIER__ "o" +#define __UINT64_FMTu__ __INT64_FMT_MODIFIER__ "u" +#define __UINT64_FMTx__ __INT64_FMT_MODIFIER__ "x" +#define __UINT64_FMTX__ __INT64_FMT_MODIFIER__ "X" +#define __INT_LEAST8_FMTd__ __INT_LEAST8_FMT_MODIFIER__ "d" +#define __INT_LEAST8_FMTi__ __INT_LEAST8_FMT_MODIFIER__ "i" +#define __UINT_LEAST8_FMTo__ __INT_LEAST8_FMT_MODIFIER__ "o" +#define __UINT_LEAST8_FMTu__ __INT_LEAST8_FMT_MODIFIER__ "u" +#define __UINT_LEAST8_FMTx__ __INT_LEAST8_FMT_MODIFIER__ "x" +#define __UINT_LEAST8_FMTX__ __INT_LEAST8_FMT_MODIFIER__ "X" +#define __INT_LEAST16_FMTd__ __INT_LEAST16_FMT_MODIFIER__ "d" +#define __INT_LEAST16_FMTi__ __INT_LEAST16_FMT_MODIFIER__ "i" +#define __UINT_LEAST16_FMTo__ __INT_LEAST16_FMT_MODIFIER__ "o" +#define __UINT_LEAST16_FMTu__ __INT_LEAST16_FMT_MODIFIER__ "u" +#define __UINT_LEAST16_FMTx__ __INT_LEAST16_FMT_MODIFIER__ "x" +#define __UINT_LEAST16_FMTX__ __INT_LEAST16_FMT_MODIFIER__ "X" +#define __INT_LEAST32_FMTd__ __INT_LEAST32_FMT_MODIFIER__ "d" +#define __INT_LEAST32_FMTi__ __INT_LEAST32_FMT_MODIFIER__ "i" +#define __UINT_LEAST32_FMTo__ __INT_LEAST32_FMT_MODIFIER__ "o" +#define __UINT_LEAST32_FMTu__ __INT_LEAST32_FMT_MODIFIER__ "u" +#define __UINT_LEAST32_FMTx__ __INT_LEAST32_FMT_MODIFIER__ "x" +#define __UINT_LEAST32_FMTX__ __INT_LEAST32_FMT_MODIFIER__ "X" +#define __INT_LEAST64_FMTd__ __INT_LEAST64_FMT_MODIFIER__ "d" +#define __INT_LEAST64_FMTi__ __INT_LEAST64_FMT_MODIFIER__ "i" +#define __UINT_LEAST64_FMTo__ __INT_LEAST64_FMT_MODIFIER__ "o" +#define __UINT_LEAST64_FMTu__ __INT_LEAST64_FMT_MODIFIER__ "u" +#define __UINT_LEAST64_FMTx__ __INT_LEAST64_FMT_MODIFIER__ "x" +#define __UINT_LEAST64_FMTX__ __INT_LEAST64_FMT_MODIFIER__ "X" +#define __INT_FAST8_FMTd__ __INT_FAST8_FMT_MODIFIER__ "d" +#define __INT_FAST8_FMTi__ __INT_FAST8_FMT_MODIFIER__ "i" +#define __UINT_FAST8_FMTo__ __INT_FAST8_FMT_MODIFIER__ "o" +#define __UINT_FAST8_FMTu__ __INT_FAST8_FMT_MODIFIER__ "u" +#define __UINT_FAST8_FMTx__ __INT_FAST8_FMT_MODIFIER__ "x" +#define __UINT_FAST8_FMTX__ __INT_FAST8_FMT_MODIFIER__ "X" +#define __INT_FAST16_FMTd__ __INT_FAST16_FMT_MODIFIER__ "d" +#define __INT_FAST16_FMTi__ __INT_FAST16_FMT_MODIFIER__ "i" +#define __UINT_FAST16_FMTo__ __INT_FAST16_FMT_MODIFIER__ "o" +#define __UINT_FAST16_FMTu__ __INT_FAST16_FMT_MODIFIER__ "u" +#define __UINT_FAST16_FMTx__ __INT_FAST16_FMT_MODIFIER__ "x" +#define __UINT_FAST16_FMTX__ __INT_FAST16_FMT_MODIFIER__ "X" +#define __INT_FAST32_FMTd__ __INT_FAST32_FMT_MODIFIER__ "d" +#define __INT_FAST32_FMTi__ __INT_FAST32_FMT_MODIFIER__ "i" +#define __UINT_FAST32_FMTo__ __INT_FAST32_FMT_MODIFIER__ "o" +#define __UINT_FAST32_FMTu__ __INT_FAST32_FMT_MODIFIER__ "u" +#define __UINT_FAST32_FMTx__ __INT_FAST32_FMT_MODIFIER__ "x" +#define __UINT_FAST32_FMTX__ __INT_FAST32_FMT_MODIFIER__ "X" +#define __INT_FAST64_FMTd__ __INT_FAST64_FMT_MODIFIER__ "d" +#define __INT_FAST64_FMTi__ __INT_FAST64_FMT_MODIFIER__ "i" +#define __UINT_FAST64_FMTo__ __INT_FAST64_FMT_MODIFIER__ "o" +#define __UINT_FAST64_FMTu__ __INT_FAST64_FMT_MODIFIER__ "u" +#define __UINT_FAST64_FMTx__ __INT_FAST64_FMT_MODIFIER__ "x" +#define __UINT_FAST64_FMTX__ __INT_FAST64_FMT_MODIFIER__ "X" + +#endif + +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; + +#define UINT8_MAX __UINT8_MAX__ +#define UINT16_MAX __UINT16_MAX__ +#define UINT32_MAX __UINT32_MAX__ +#define UINT64_MAX __UINT64_MAX__ + +#define INT8_MAX __INT8_MAX__ +#define INT16_MAX __INT16_MAX__ +#define INT32_MAX __INT32_MAX__ +#define INT64_MAX __INT64_MAX__ + +#define INT8_MIN (-INT8_MAX - 1) +#define INT16_MIN (-INT16_MAX - 1) +#define INT32_MIN (-INT32_MAX - 1) +#define INT64_MIN (-INT64_MAX - 1) + +typedef __UINT_LEAST8_TYPE__ uint_least8_t; +typedef __UINT_LEAST16_TYPE__ uint_least16_t; +typedef __UINT_LEAST32_TYPE__ uint_least32_t; +typedef __UINT_LEAST64_TYPE__ uint_least64_t; +typedef __INT_LEAST8_TYPE__ int_least8_t; +typedef __INT_LEAST16_TYPE__ int_least16_t; +typedef __INT_LEAST32_TYPE__ int_least32_t; +typedef __INT_LEAST64_TYPE__ int_least64_t; + +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ + +#define INT_LEAST8_MAX __INT_LEAST8_MAX__ +#define INT_LEAST16_MAX __INT_LEAST16_MAX__ +#define INT_LEAST32_MAX __INT_LEAST32_MAX__ +#define INT_LEAST64_MAX __INT_LEAST64_MAX__ + +#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1) +#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1) +#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1) +#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1) + +typedef __UINT_FAST8_TYPE__ uint_fast8_t; +typedef __UINT_FAST16_TYPE__ uint_fast16_t; +typedef __UINT_FAST32_TYPE__ uint_fast32_t; +typedef __UINT_FAST64_TYPE__ uint_fast64_t; +typedef __INT_FAST8_TYPE__ int_fast8_t; +typedef __INT_FAST16_TYPE__ int_fast16_t; +typedef __INT_FAST32_TYPE__ int_fast32_t; +typedef __INT_FAST64_TYPE__ int_fast64_t; + +#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#define UINT_FAST64_MAX __UINT_FAST64_MAX__ + +#define INT_FAST8_MAX __INT_FAST8_MAX__ +#define INT_FAST16_MAX __INT_FAST16_MAX__ +#define INT_FAST32_MAX __INT_FAST32_MAX__ +#define INT_FAST64_MAX __INT_FAST64_MAX__ + +#define INT_FAST8_MIN (-INT_FAST8_MAX - 1) +#define INT_FAST16_MIN (-INT_FAST16_MAX - 1) +#define INT_FAST32_MIN (-INT_FAST32_MAX - 1) +#define INT_FAST64_MIN (-INT_FAST64_MAX - 1) + +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; + +#define INTPTR_MAX __INTPTR_MAX__ +#define INTPTR_MIN (-INTPTR_MAX - 1) +#define UINTPTR_MAX __UINTPTR_MAX__ + +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MIN (-INTMAX_MAX - 1) +#define UINTMAX_MAX __UINTMAX_MAX__ + +#define SIZE_MAX __SIZE_MAX__ + +// GCC defines __<type>INT<size>_C macros which append the correct suffix +// to an (un)signed integer literal, with <size> being one of 8, 16, 32, 64 +// and MAX, and type being U for unsigned types. The standard stdint.h macros +// with the same names without the leading __ could be implemented in terms of +// these macros. +// +// Clang predefines macros __<type>INT<size>_C_SUFFIX__ which expand to the +// suffix itself. We define the standard stdint.h macros in terms of the GCC +// variants and for Clang we define their equivalents. +#ifndef __INTMAX_C + +#define __int_c_join(a, b) a##b +#define __int_c(v, suffix) __int_c_join(v, suffix) + +#define __INT8_C(c) __int_c(c, __INT8_C_SUFFIX__) +#define __INT16_C(c) __int_c(c, __INT16_C_SUFFIX__) +#define __INT32_C(c) __int_c(c, __INT32_C_SUFFIX__) +#define __INT64_C(c) __int_c(c, __INT64_C_SUFFIX__) + +#define __UINT8_C(c) __int_c(c, __UINT8_C_SUFFIX__) +#define __UINT16_C(c) __int_c(c, __UINT16_C_SUFFIX__) +#define __UINT32_C(c) __int_c(c, __UINT32_C_SUFFIX__) +#define __UINT64_C(c) __int_c(c, __UINT64_C_SUFFIX__) + +#define __INTMAX_C(c) __int_c(c, __INTMAX_C_SUFFIX__) +#define __UINTMAX_C(c) __int_c(c, __UINTMAX_C_SUFFIX__) + +#endif + +#define INT8_C(c) __INT8_C(c) +#define INT16_C(c) __INT16_C(c) +#define INT32_C(c) __INT32_C(c) +#define INT64_C(c) __INT64_C(c) + +#define UINT8_C(c) __UINT8_C(c) +#define UINT16_C(c) __UINT16_C(c) +#define UINT32_C(c) __UINT32_C(c) +#define UINT64_C(c) __UINT64_C(c) + +#define INTMAX_C(c) __INTMAX_C(c) +#define UINTMAX_C(c) __UINTMAX_C(c) + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDINT_H_ diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h new file mode 100644 index 0000000..ae5a84b --- /dev/null +++ b/lib/libc/include/stdio.h @@ -0,0 +1,102 @@ +// Copyright 2020 The Fuchsia Authors +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_ + +#include <stdarg.h> +#include <stddef.h> +#include <zircon/compiler.h> + +// All anybody really wants from stdio is printf. + +#ifdef __cplusplus +#include <ktl/string_view.h> + +class FILE { + public: + // This is basically equivalent to having a virtual Write function with + // subclasses providing their own data members in lieu of ptr. But it's + // simpler and avoids a vtable that might need address fixup at load time + // (and the double indirection for a single-entry vtable--at the cost of + // double indirection for the ptr data in a callback that uses it). + + using Callback = int(void*, ktl::string_view); + + FILE() = default; + + constexpr FILE(Callback* write, void* ptr) : write_(write), ptr_(ptr) {} + + template <typename T> + explicit FILE(T* writer) + : write_([](void* ptr, ktl::string_view s) { return static_cast<T*>(ptr)->Write(s); }), + ptr_(writer) {} + + // This is what fprintf calls to do output. + int Write(ktl::string_view s) { return write_(ptr_, s); } + + constexpr explicit operator bool() const { return write_; } + + constexpr bool operator==(const FILE& other) const { + return write_ == other.write_ && ptr_ == other.ptr_; + } + + constexpr bool operator!=(const FILE& other) const { return !(*this == other); } + + // This is not defined by libc itself. The kernel defines it to point at + // the default console output mechanism. + static FILE stdout_; + + private: + Callback* write_ = nullptr; + void* ptr_ = nullptr; +}; + +#define stdout (&FILE::stdout_) + +inline int fputc(int c, FILE* f) { + const unsigned char uc = static_cast<unsigned char>(c); + return f->Write({reinterpret_cast<const char*>(&uc), 1}) == 1 ? uc : -1; +} + +inline int putc(int c, FILE* f) { return fputc(c, f); } + +inline int putchar(int c) { return fputc(c, stdout); } + +inline int fputs(const char* s, FILE* f) { + ktl::string_view str(s); + return f->Write(str) == static_cast<int>(str.size()) ? 0 : -1; +} + +inline int puts(const char* s) { return fputs(s, stdout) == 0 ? putchar('\n') : -1; } + +#else // !__cplusplus + +// C users just need the function declarations. +typedef struct _FILE_is_opaque FILE; + +#endif // __cplusplus + +__BEGIN_CDECLS + +int printf(const char*, ...) __PRINTFLIKE(1, 2); +int fprintf(FILE*, const char*, ...) __PRINTFLIKE(2, 3); +int snprintf(char* buf, size_t len, const char*, ...) __PRINTFLIKE(3, 4); + +int vprintf(const char*, va_list); +int vfprintf(FILE*, const char*, va_list); +int vsnprintf(char* buf, size_t len, const char*, va_list); + +__END_CDECLS + +#if DISABLE_DEBUG_OUTPUT +// The declarations stand so these can be used without parens to get +// the real functions (e.g. &printf or (printf)(...)). +#define printf(...) +#define vprintf(fmt, args) +#endif + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDIO_H_ diff --git a/lib/libc/include/stdlib.h b/lib/libc/include/stdlib.h new file mode 100644 index 0000000..45c5a21 --- /dev/null +++ b/lib/libc/include/stdlib.h @@ -0,0 +1,36 @@ +// Copyright 2016 The Fuchsia Authors +// Copyright (c) 2008-2014 Travis Geiselbrecht +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_ + +#include <stddef.h> +#include <stdint.h> +#include <zircon/compiler.h> + +#ifdef _KERNEL +#include <lib/heap.h> // lib/heap provides malloc/free definitions. +#endif + +__BEGIN_CDECLS + +long strtol(const char *nptr, char **endptr, int base); +unsigned long int strtoul(const char *nptr, char **endptr, int base); + +void abort(void) __attribute__((noreturn)); + +#define RAND_MAX (0x7fffffff) + +int rand(void); +void srand(unsigned int seed); + +// Note: POSIX.1 specifies unsigned int, but we use uintptr_t instead. +int rand_r(uintptr_t *seed); + +__END_CDECLS + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STDLIB_H_ diff --git a/lib/libc/include/string-file.h b/lib/libc/include/string-file.h new file mode 100644 index 0000000..1632933 --- /dev/null +++ b/lib/libc/include/string-file.h @@ -0,0 +1,79 @@ +// Copyright 2021 The Fuchsia Authors +// Copyright (c) 2008 Travis Geiselbrecht +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_ + +#ifdef __cplusplus +#include <stdio.h> + +#include <ktl/algorithm.h> +#include <ktl/span.h> +#include <ktl/string_view.h> + +// FILE* wrapper over a string. +class StringFile : public FILE { + public: + StringFile() = delete; + StringFile(const StringFile &) = delete; + StringFile operator=(const StringFile &) = delete; + + explicit StringFile(ktl::span<char> s) : FILE(this), buffer_(s) {} + + ~StringFile() = default; + + // Adds a null character at the end of the current buffer and returns a view + // into the written section. + ktl::span<char> take() &&; + + // Returns |str.size()| and writes as much of |str| as it would fit in the + // buffer [offest_, size - 1) while reserving the last byte for null + // character. + int Write(ktl::string_view str); + + // Returns a region representing the currently used portion of the buffer. + ktl::span<char> used_region() const { + return (offset_ > 0) ? ktl::span<char>{buffer_.data(), offset_} : ktl::span<char>{}; + } + + // Returns a region representing the remaining unused space in the buffer, + // _not_ including the space reserved for the final null character. + ktl::span<char> available_region() const { + const size_t available = ktl::max<size_t>(buffer_.size() - offset_, 1) - 1; + return (available > 0) ? ktl::span<char>{buffer_.data() + offset_, available} + : ktl::span<char>{}; + } + + // Skip up to |amt| bytes in the buffer, advancing the write pointer as if we + // had written data, but without actually changing the buffer. + void Skip(size_t amt) { + amt = ktl::min(amt, available_region().size()); + offset_ += amt; + } + + // Provide two ways for users to convert the currently used buffer into a + // string_view. Given a string file |S|, users may say either: + // + // 1) S.as_string_view(); // or + // 2) static_cast<ktl::string_view>(S); + // + // to perform the conversion. + // + ktl::string_view as_string_view() const { + return (offset_ > 0) ? ktl::string_view{buffer_.data(), offset_} : ktl::string_view{}; + } + + explicit operator ktl::string_view() const { return this->as_string_view(); } + + private: + ktl::span<char> buffer_; + size_t offset_ = 0; +}; + +#endif // __cplusplus + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_FILE_H_ diff --git a/lib/libc/include/string.h b/lib/libc/include/string.h new file mode 100644 index 0000000..3b55ccb --- /dev/null +++ b/lib/libc/include/string.h @@ -0,0 +1,97 @@ +// Copyright 2016 The Fuchsia Authors +// Copyright (c) 2008 Travis Geiselbrecht +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#ifndef ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_ +#define ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_ + +// Other libc++ headers use <cstring> but libc++'s <cstring> complains if it +// thinks <string.h> is not its own wrapper, which we do not need. We always +// get the kernel's <string.h> before the libc++ with the way the include paths +// are set up, which is necessary because of other headers where preempting +// libc++'s header is unavoidable for the kernel environment. So just we +// define the macro that <cstring> checks for to keep it happy. +#define _LIBCPP_STRING_H + +#include <stddef.h> +#include <zircon/compiler.h> + +__BEGIN_CDECLS + +int memcmp(const void*, const void*, size_t) __PURE; +void* memcpy(void*, const void*, size_t); +void* memmove(void*, const void*, size_t); +void* memset(void*, int, size_t); + +char* strcat(char*, const char*); +int strcmp(const char*, const char*) __PURE; +char* strcpy(char*, const char*); +size_t strlen(const char*) __PURE; +char* strncat(char*, const char*, size_t); +int strncmp(const char*, const char*, size_t) __PURE; +char* strncpy(char*, const char*, size_t); +size_t strspn(const char*, const char*) __PURE; +size_t strcspn(const char* s, const char*) __PURE; +char* strtok(char*, const char*); +int strcoll(const char* s1, const char* s2) __PURE; +size_t strxfrm(char* dest, const char* src, size_t n) __PURE; + +// Not actually defined in the kernel, but <cstring> expects the declaration. +char* strerror(int); + +// Nonstandard. +size_t strlcat(char*, const char*, size_t); +size_t strlcpy(char*, const char*, size_t); +int strncasecmp(const char*, const char*, size_t) __PURE; +int strnicmp(const char*, const char*, size_t) __PURE; +size_t strnlen(const char* s, size_t count) __PURE; + +// Used by address sanitizer. +__typeof(memcpy) __unsanitized_memcpy; +__typeof(memmove) __unsanitized_memmove; +__typeof(memset) __unsanitized_memset; + +__END_CDECLS + +// C++ wants overloads for const and non-const versions of some functions. +#ifdef __cplusplus + +const char* strchr(const char*, int) __asm__("strchr") __PURE; +inline char* strchr(char* s, int c) { + return const_cast<char*>(strchr(const_cast<const char*>(s), c)); +} + +const char* strpbrk(const char*, const char*) __asm__("strpbrk") __PURE; +inline char* strpbrk(char* s1, const char* s2) { + return const_cast<char*>(strpbrk(const_cast<const char*>(s1), s2)); +} + +const char* strrchr(const char*, int) __asm__("strrchr") __PURE; +inline char* strrchr(char* s, int c) { + return const_cast<char*>(strrchr(const_cast<const char*>(s), c)); +} + +const void* memchr(const void*, int, size_t) __asm__("memchr") __PURE; +inline void* memchr(void* s, int c, size_t n) { + return const_cast<void*>(memchr(const_cast<const void*>(s), c, n)); +} + +const char* strstr(const char*, const char*) __asm__("strstr") __PURE; +inline char* strstr(char* s1, const char* s2) { + return const_cast<char*>(strstr(const_cast<const char*>(s1), s2)); +} + +#else + +void* memchr(const void*, int, size_t); +char* strchr(const char*, int) __PURE; +char* strpbrk(const char*, const char*) __PURE; +char* strrchr(const char*, int) __PURE; +char* strstr(const char*, const char*) __PURE; + +#endif // __cplusplus + +#endif // ZIRCON_KERNEL_LIB_LIBC_INCLUDE_STRING_H_ |
