diff options
Diffstat (limited to 'lib/mlibc/options/internal/include/mlibc')
19 files changed, 0 insertions, 1141 deletions
diff --git a/lib/mlibc/options/internal/include/mlibc/all-sysdeps.hpp b/lib/mlibc/options/internal/include/mlibc/all-sysdeps.hpp deleted file mode 100644 index 7189286..0000000 --- a/lib/mlibc/options/internal/include/mlibc/all-sysdeps.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MLIBC_ALL_SYSDEPS -#define MLIBC_ALL_SYSDEPS - -#include <mlibc-config.h> -#include <internal-config.h> - -#if __MLIBC_ANSI_OPTION -# include <mlibc/ansi-sysdeps.hpp> -#endif /* __MLIBC_ANSI_OPTION */ - -#if __MLIBC_POSIX_OPTION -# include <mlibc/posix-sysdeps.hpp> -#endif /* __MLIBC_POSIX_OPTION */ - -#if __MLIBC_LINUX_OPTION -# include <mlibc/linux-sysdeps.hpp> -#endif /* __MLIBC_LINUX_OPTION */ - -#if __MLIBC_GLIBC_OPTION -# include <mlibc/glibc-sysdeps.hpp> -#endif /* __MLIBC_GLIBC_OPTION */ - -#if __MLIBC_BSD_OPTION -# include <mlibc/bsd-sysdeps.hpp> -#endif /* __MLIBC_BSD_OPTION */ - -#if MLIBC_BUILDING_RTDL -# include <mlibc/rtdl-sysdeps.hpp> -#endif /* MLIBC_BUILDING_RTDL */ - -#include <mlibc/internal-sysdeps.hpp> - -#endif /* MLIBC_ALL_SYSDEPS */ diff --git a/lib/mlibc/options/internal/include/mlibc/allocator.hpp b/lib/mlibc/options/internal/include/mlibc/allocator.hpp deleted file mode 100644 index 5f9617e..0000000 --- a/lib/mlibc/options/internal/include/mlibc/allocator.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MLIBC_FRIGG_ALLOC -#define MLIBC_FRIGG_ALLOC - -#include <mlibc/lock.hpp> -#include <bits/ensure.h> -#include <frg/slab.hpp> -#include <internal-config.h> - -#if !MLIBC_DEBUG_ALLOCATOR - -struct VirtualAllocator { -public: - uintptr_t map(size_t length); - - void unmap(uintptr_t address, size_t length); -}; - -typedef frg::slab_pool<VirtualAllocator, FutexLock> MemoryPool; - -typedef frg::slab_allocator<VirtualAllocator, FutexLock> MemoryAllocator; - -MemoryAllocator &getAllocator(); - -#else - -struct MemoryAllocator { - void *allocate(size_t size); - void free(void *ptr); - void deallocate(void *ptr, size_t size); - void *reallocate(void *ptr, size_t size); -}; - -MemoryAllocator &getAllocator(); - -#endif // !MLIBC_DEBUG_ALLOCATOR - -#endif // MLIBC_FRIGG_ALLOC diff --git a/lib/mlibc/options/internal/include/mlibc/bitutil.hpp b/lib/mlibc/options/internal/include/mlibc/bitutil.hpp deleted file mode 100644 index 6d2b25e..0000000 --- a/lib/mlibc/options/internal/include/mlibc/bitutil.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef MLIBC_BITUTIL -#define MLIBC_BITUTIL - -#include <stdint.h> - -namespace mlibc { - -template<typename T> -struct bit_util; - -template<> -struct bit_util<uint64_t> { - static uint64_t byteswap(uint64_t x) { - return __builtin_bswap64(x); - } -}; - -template<> -struct bit_util<uint32_t> { - static uint32_t byteswap(uint32_t x) { - return __builtin_bswap32(x); - } -}; - -template<> -struct bit_util<uint16_t> { - static uint16_t byteswap(uint16_t x) { - return __builtin_bswap16(x); - } -}; - -} // namespace mlibc - -#endif // MLIBC_BITUTIL diff --git a/lib/mlibc/options/internal/include/mlibc/charcode.hpp b/lib/mlibc/options/internal/include/mlibc/charcode.hpp deleted file mode 100644 index 67bd03d..0000000 --- a/lib/mlibc/options/internal/include/mlibc/charcode.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef MLIBC_CHARCODE_HPP -#define MLIBC_CHARCODE_HPP - -#include <stddef.h> -#include <stdint.h> -#include <bits/ensure.h> -#include <bits/mbstate.h> -#include <mlibc/debug.hpp> - -namespace mlibc { - -enum class charcode_error { - null, - dirty, - illegal_input, - input_underflow, - output_overflow -}; - -template<typename C> -struct code_seq { - C *it; - const C *end; - - explicit operator bool () { - return it != end; - } -}; - -// Some encodings (e.g. the one defined in RFC 1843) have "shift states", -// i.e. escape sequences that switch between different encodings (e.g. between single-byte ASCII -// and 2-byte encoding of Chinese characters). -// TODO: Implement that using the __shift member of __mlibc_mbstate. - -typedef uint32_t codepoint; - -// The following class deals with decoding/encoding "code units" (of type char) -// to "code points" that are defined by unicode (of type codepoint). -// It also offers convenience functions to transcode to wchar_t, char16_t and char32_t. -// We assume that the encoding of wchar_t (and char16_t, char32_t) is fixed. -// char is allowed to have an arbitrary encoding. -// TODO: char16_t and char32_t variants are missing. -// TODO: For iconv(), first decode and then encode to the destination encoding. -struct polymorphic_charcode { - virtual ~polymorphic_charcode(); - - // Helper function to decode a single char. - charcode_error promote(char nc, codepoint &wc) { - auto uc = static_cast<unsigned char>(nc); - if(uc <= 0x7F && preserves_7bit_units) { - wc = uc; - return charcode_error::null; - } - - code_seq<const char> nseq{&nc, &nc + 1}; - code_seq<codepoint> wseq{&wc, &wc + 1}; - __mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER; - - if(auto e = decode(nseq, wseq, st); e != charcode_error::null) - return e; - // This should have read/written exactly one code unit/code point. - __ensure(nseq.it == nseq.end); - __ensure(wseq.it == wseq.end); - return charcode_error::null; - } - - // Helper function to decode a single char. - charcode_error promote_wtranscode(char nc, wchar_t &wc) { - auto uc = static_cast<unsigned char>(nc); - if(uc <= 0x7F && preserves_7bit_units) { // TODO: Use "wtranscode_preserves_7bit_units". - wc = uc; - return charcode_error::null; - } - - code_seq<const char> nseq{&nc, &nc + 1}; - code_seq<wchar_t> wseq{&wc, &wc + 1}; - __mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER; - - if(auto e = decode_wtranscode(nseq, wseq, st); e != charcode_error::null) - return e; - // This should have read/written exactly one code unit/code point. - __ensure(nseq.it == nseq.end); - __ensure(wseq.it == wseq.end); - return charcode_error::null; - } - - polymorphic_charcode(bool preserves_7bit_units_, bool has_shift_states_) - : preserves_7bit_units{preserves_7bit_units_}, has_shift_states{has_shift_states_} { } - - virtual charcode_error decode(code_seq<const char> &nseq, code_seq<codepoint> &wseq, - __mlibc_mbstate &st) = 0; - - virtual charcode_error decode_wtranscode(code_seq<const char> &nseq, code_seq<wchar_t> &wseq, - __mlibc_mbstate &st) = 0; - - virtual charcode_error decode_wtranscode_length(code_seq<const char> &nseq, size_t *n, - __mlibc_mbstate &st) = 0; - - virtual charcode_error encode_wtranscode(code_seq<char> &nseq, code_seq<const wchar_t> &wseq, - __mlibc_mbstate &st) = 0; - - virtual charcode_error encode_wtranscode_length(code_seq<const wchar_t> &wseq, size_t *n, - __mlibc_mbstate &st) = 0; - - // True if promotion only zero-extends units below 0x7F. - const bool preserves_7bit_units; - - // Whether the encoding has shift states. - const bool has_shift_states; -}; - -polymorphic_charcode *current_charcode(); - -// Similar to polymorphic_charcode but for wchar_t. Note that this encoding is fixed per-platform; -// thus, it does not need to be polymorphic. -struct wide_charcode { - charcode_error promote(wchar_t nc, codepoint &wc); -}; - -wide_charcode *platform_wide_charcode(); - -} // namespace mlibc - -#endif // MLIBC_CHARCODE_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/charset.hpp b/lib/mlibc/options/internal/include/mlibc/charset.hpp deleted file mode 100644 index a068f05..0000000 --- a/lib/mlibc/options/internal/include/mlibc/charset.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef MLIBC_CHARSET_HPP -#define MLIBC_CHARSET_HPP - -#include <mlibc/charcode.hpp> - -namespace mlibc { - -// Represents the charset of a certain locale. We define the charset as -// a set of characters, together with their properties and conversion rules -// *but not* their encoding (e.g. to UTF-8 or UTF-16). -struct charset { - // Returns true iif the meaning of the first 0x7F characters matches ASCII. - bool is_ascii_superset(); - - bool is_alpha(codepoint c); - bool is_digit(codepoint c); - bool is_xdigit(codepoint c); - bool is_alnum(codepoint c); - bool is_punct(codepoint c); - bool is_graph(codepoint c); - bool is_blank(codepoint c); - bool is_space(codepoint c); - bool is_print(codepoint c); - - bool is_lower(codepoint c); - bool is_upper(codepoint c); - codepoint to_lower(codepoint c); - codepoint to_upper(codepoint c); -}; - -charset *current_charset(); - -// The property if a character is a control character is locale-independent. -inline bool generic_is_control(codepoint c) { - return (c <= 0x1F) || (c == 0x7F) || (c >= 0x80 && c <= 0x9F); -} - -} // namespace mlibc - -#endif // MLIBC_CHARSET_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/debug.hpp b/lib/mlibc/options/internal/include/mlibc/debug.hpp deleted file mode 100644 index 7067039..0000000 --- a/lib/mlibc/options/internal/include/mlibc/debug.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MLIBC_DEBUG_HPP -#define MLIBC_DEBUG_HPP - -#include <frg/logging.hpp> - -namespace mlibc { - -struct InfoSink { - // constexpr so that this can be initialized statically. - constexpr InfoSink() = default; - - void operator() (const char *message); -}; - -struct PanicSink { - // constexpr so that this can be initialized statically. - constexpr PanicSink() = default; - - void operator() (const char *message); -}; - -extern frg::stack_buffer_logger<InfoSink, 512> infoLogger; -extern frg::stack_buffer_logger<PanicSink, 512> panicLogger; - -} // namespace mlibc - -#endif // MLIBC_DEBUG_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/file-window.hpp b/lib/mlibc/options/internal/include/mlibc/file-window.hpp deleted file mode 100644 index 68c3ebf..0000000 --- a/lib/mlibc/options/internal/include/mlibc/file-window.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef MLIBC_FILE_WINDOW -#define MLIBC_FILE_WINDOW - -#include <abi-bits/fcntl.h> -#include <mlibc/allocator.hpp> -#include <mlibc/debug.hpp> -#include <mlibc/internal-sysdeps.hpp> -#include <internal-config.h> - -struct file_window { - file_window(const char *path) { - int fd; - if(mlibc::sys_open("/etc/localtime", O_RDONLY, 0, &fd)) - mlibc::panicLogger() << "mlibc: Error opening file_window to " - << path << frg::endlog; - - if(!mlibc::sys_stat) { - MLIBC_MISSING_SYSDEP(); - __ensure(!"cannot proceed without sys_stat"); - } - struct stat info; - if(mlibc::sys_stat(mlibc::fsfd_target::fd, fd, "", 0, &info)) - mlibc::panicLogger() << "mlibc: Error getting TZinfo stats" << frg::endlog; - -#if MLIBC_MAP_FILE_WINDOWS - if(mlibc::sys_vm_map(nullptr, (size_t)info.st_size, PROT_READ, MAP_PRIVATE, - fd, 0, &_ptr)) - mlibc::panicLogger() << "mlibc: Error mapping TZinfo" << frg::endlog; -#else - _ptr = getAllocator().allocate(info.st_size); - __ensure(_ptr); - - size_t progress = 0; - size_t st_size = static_cast<size_t>(info.st_size); - while(progress < st_size) { - ssize_t chunk; - if(int e = mlibc::sys_read(fd, reinterpret_cast<char *>(_ptr) + progress, - st_size - progress, &chunk); e) - mlibc::panicLogger() << "mlibc: Read from file_window failed" << frg::endlog; - if(!chunk) - break; - progress += chunk; - } - if(progress != st_size) - mlibc::panicLogger() << "stat reports " << info.st_size << " but we only read " - << progress << " bytes" << frg::endlog; -#endif - - if(mlibc::sys_close(fd)) - mlibc::panicLogger() << "mlibc: Error closing TZinfo" << frg::endlog; - } - - // TODO: Write destructor to deallocate/unmap memory. - - void *get() { - return _ptr; - } - -private: - void *_ptr; -}; - -#endif // MLIBC_FILE_WINDOW - diff --git a/lib/mlibc/options/internal/include/mlibc/fsfd_target.hpp b/lib/mlibc/options/internal/include/mlibc/fsfd_target.hpp deleted file mode 100644 index b577325..0000000 --- a/lib/mlibc/options/internal/include/mlibc/fsfd_target.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MLIBC_FSFD_TARGET -#define MLIBC_FSFD_TARGET - -namespace mlibc { - -enum class fsfd_target { - none, - path, - fd, - fd_path -}; - -} // namespace mlibc - -#endif // MLIBC_FSFD_TARGET diff --git a/lib/mlibc/options/internal/include/mlibc/global-config.hpp b/lib/mlibc/options/internal/include/mlibc/global-config.hpp deleted file mode 100644 index 7eaed3c..0000000 --- a/lib/mlibc/options/internal/include/mlibc/global-config.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MLIBC_GLOBAL_CONFIG -#define MLIBC_GLOBAL_CONFIG - -namespace mlibc { - -struct GlobalConfig { - GlobalConfig(); - - bool debugMalloc; -}; - -inline const GlobalConfig &globalConfig() { - static GlobalConfig cached; - return cached; -} - -} - -#endif // MLIBC_GLOBAL_CONFIG diff --git a/lib/mlibc/options/internal/include/mlibc/internal-sysdeps.hpp b/lib/mlibc/options/internal/include/mlibc/internal-sysdeps.hpp deleted file mode 100644 index 02df713..0000000 --- a/lib/mlibc/options/internal/include/mlibc/internal-sysdeps.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MLIBC_INTERNAL_SYSDEPS -#define MLIBC_INTERNAL_SYSDEPS - -#include <stddef.h> - -#include <abi-bits/seek-whence.h> -#include <abi-bits/vm-flags.h> -#include <bits/off_t.h> -#include <bits/ssize_t.h> -#include <abi-bits/stat.h> -#include <mlibc/fsfd_target.hpp> - -namespace [[gnu::visibility("hidden")]] mlibc { - -void sys_libc_log(const char *message); -[[noreturn]] void sys_libc_panic(); - -int sys_tcb_set(void *pointer); - -[[gnu::weak]] int sys_futex_tid(); -int sys_futex_wait(int *pointer, int expected, const struct timespec *time); -int sys_futex_wake(int *pointer); - -int sys_anon_allocate(size_t size, void **pointer); -int sys_anon_free(void *pointer, size_t size); - -int sys_open(const char *pathname, int flags, mode_t mode, int *fd); -int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read); -int sys_seek(int fd, off_t offset, int whence, off_t *new_offset); -int sys_close(int fd); - -[[gnu::weak]] int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, - struct stat *statbuf); -// mlibc assumes that anonymous memory returned by sys_vm_map() is zeroed by the kernel / whatever is behind the sysdeps -int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window); -int sys_vm_unmap(void *pointer, size_t size); -[[gnu::weak]] int sys_vm_protect(void *pointer, size_t size, int prot); - -} //namespace mlibc - -#endif // MLIBC_INTERNAL_SYSDEPS diff --git a/lib/mlibc/options/internal/include/mlibc/locale.hpp b/lib/mlibc/options/internal/include/mlibc/locale.hpp deleted file mode 100644 index a46a2c3..0000000 --- a/lib/mlibc/options/internal/include/mlibc/locale.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MLIBC_LOCALE -#define MLIBC_LOCALE - -#include <bits/nl_item.h> - -namespace mlibc { - -char *nl_langinfo(nl_item item); - -} // namespace mlibc - -#endif // MLIBC_LOCALE diff --git a/lib/mlibc/options/internal/include/mlibc/lock.hpp b/lib/mlibc/options/internal/include/mlibc/lock.hpp deleted file mode 100644 index aa05079..0000000 --- a/lib/mlibc/options/internal/include/mlibc/lock.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef MLIBC_LOCK_HPP -#define MLIBC_LOCK_HPP - -#include <errno.h> -#include <stdint.h> -#include <mlibc/internal-sysdeps.hpp> -#include <mlibc/debug.hpp> -#include <mlibc/tid.hpp> -#include <bits/ensure.h> - -template<bool Recursive> -struct FutexLockImpl { - FutexLockImpl() : _state{0}, _recursion{0} { } - - FutexLockImpl(const FutexLockImpl &) = delete; - - FutexLockImpl &operator= (const FutexLockImpl &) = delete; - - static constexpr uint32_t waitersBit = (1 << 31); - static constexpr uint32_t ownerMask = (static_cast<uint32_t>(1) << 30) - 1; - - void lock() { - unsigned int this_tid = mlibc::this_tid(); - unsigned int expected = 0; - - while(true) { - if(!expected) { - // Try to take the mutex here. - if(__atomic_compare_exchange_n(&_state, - &expected, this_tid, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { - if constexpr (Recursive) { - __ensure(!_recursion); - _recursion = 1; - } - return; - } - }else{ - // If this (recursive) mutex is already owned by us, increment the recursion level. - if((expected & ownerMask) == this_tid) { - if constexpr (Recursive) - ++_recursion; - else - mlibc::panicLogger() << "mlibc: FutexLock deadlock detected!" << frg::endlog; - return; - } - - // Wait on the futex if the waiters flag is set. - if(expected & waitersBit) { - int e = mlibc::sys_futex_wait((int *)&_state, expected, nullptr); - - // If the wait returns EAGAIN, that means that the waitersBit was just unset by - // some other thread. In this case, we should loop back around. - if (e && e != EAGAIN) - mlibc::panicLogger() << "sys_futex_wait() failed with error code " << e << frg::endlog; - - // Opportunistically try to take the lock after we wake up. - expected = 0; - }else{ - // Otherwise we have to set the waiters flag first. - unsigned int desired = expected | waitersBit; - if(__atomic_compare_exchange_n((int *)&_state, - reinterpret_cast<int*>(&expected), desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) - expected = desired; - } - } - } - } - - bool try_lock() { - unsigned int this_tid = mlibc::this_tid(); - unsigned int expected = __atomic_load_n(&_state, __ATOMIC_RELAXED); - - if(!expected) { - // Try to take the mutex here. - if(__atomic_compare_exchange_n(&_state, - &expected, this_tid, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { - if constexpr (Recursive) - _recursion = 1; - return true; - } - } else { - // If this (recursive) mutex is already owned by us, increment the recursion level. - if((expected & ownerMask) == this_tid) { - if constexpr (Recursive) { - __ensure(!_recursion); - ++_recursion; - return true; - } else { - return false; - } - } - } - - return false; - } - - void unlock() { - // Decrement the recursion level and unlock if we hit zero. - if constexpr (Recursive) { - __ensure(_recursion); - if(--_recursion) - return; - } - - // Reset the mutex to the unlocked state. - auto state = __atomic_exchange_n(&_state, 0, __ATOMIC_RELEASE); - __ensure((state & ownerMask) == mlibc::this_tid()); - - if(state & waitersBit) { - // Wake the futex if there were waiters. Since the mutex might not exist at this location - // anymore, we must conservatively ignore EACCES and EINVAL which may occur as a result. - int e = mlibc::sys_futex_wake((int *)&_state); - __ensure(e >= 0 || e == EACCES || e == EINVAL); - } - } -private: - uint32_t _state; - uint32_t _recursion; -}; - -using FutexLock = FutexLockImpl<false>; -using RecursiveFutexLock = FutexLockImpl<true>; - -#endif diff --git a/lib/mlibc/options/internal/include/mlibc/stack_protector.hpp b/lib/mlibc/options/internal/include/mlibc/stack_protector.hpp deleted file mode 100644 index 47290fc..0000000 --- a/lib/mlibc/options/internal/include/mlibc/stack_protector.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef MLIBC_STACK_PROTECTOR_HPP -#define MLIBC_STACK_PROTECTOR_HPP - -namespace mlibc { - -void initStackGuard(void *); - -} // namespace mlibc - -#endif // MLIBC_STACK_PROTECTOR_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/strings.hpp b/lib/mlibc/options/internal/include/mlibc/strings.hpp deleted file mode 100644 index 5a93c7c..0000000 --- a/lib/mlibc/options/internal/include/mlibc/strings.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MLIBC_STRINGS -#define MLIBC_STRINGS - -#include <bits/size_t.h> - -namespace mlibc { - -int strncasecmp(const char *a, const char *b, size_t size); - -} // namespace mlibc - -#endif // MLIBC_STRINGS diff --git a/lib/mlibc/options/internal/include/mlibc/strtofp.hpp b/lib/mlibc/options/internal/include/mlibc/strtofp.hpp deleted file mode 100644 index f9c5e20..0000000 --- a/lib/mlibc/options/internal/include/mlibc/strtofp.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef MLIBC_STRTOFP_HPP -#define MLIBC_STRTOFP_HPP - -#include <string.h> -#include <bits/ensure.h> -#include <type_traits> - -namespace mlibc { - -template<typename T> -T strtofp(const char *str, char **endptr) { - if (strcmp(str, "INF") == 0 || strcmp(str, "inf") == 0) { - if (endptr) - *endptr = (char *)str + 3; - if constexpr (std::is_same_v<T, float>) - return __builtin_inff(); - else if constexpr (std::is_same_v<T, double>) - return __builtin_inf(); - else - return __builtin_infl(); - } else if (strcmp(str, "INFINITY") == 0 || strcmp(str, "infinity") == 0) { - if (endptr) - *endptr = (char *)str + 8; - if constexpr (std::is_same_v<T, float>) - return __builtin_inff(); - else if constexpr (std::is_same_v<T, double>) - return __builtin_inf(); - else - return __builtin_infl(); - } else if (strncmp(str, "NAN", 3) == 0 || strncmp(str, "nan", 3) == 0) { - if (endptr) - *endptr = (char *)str + 3; - if constexpr (std::is_same_v<T, float>) - return __builtin_nanf(""); - else if constexpr (std::is_same_v<T, double>) - return __builtin_nan(""); - else - return __builtin_nanl(""); - } - - bool negative = *str == '-'; - if (*str == '+' || *str == '-') - str++; - - bool hex = false; - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { - str += 2; - hex = true; - } - - T result = static_cast<T>(0); - - const char *tmp = str; - - if (!hex) { - while (true) { - if (!isdigit(*tmp)) - break; - result *= static_cast<T>(10); - result += static_cast<T>(*tmp - '0'); - tmp++; - } - } else { - while (true) { - if (!isxdigit(*tmp)) - break; - result *= static_cast<T>(16); - result += static_cast<T>(*tmp <= '9' ? (*tmp - '0') : (tolower(*tmp) - 'a' + 10)); - tmp++; - } - } - - if (*tmp == '.') { - tmp++; - - if (!hex) { - T d = static_cast<T>(10); - - while (true) { - if (!isdigit(*tmp)) - break; - result += static_cast<T>(*tmp - '0') / d; - d *= static_cast<T>(10); - tmp++; - } - } else { - T d = static_cast<T>(16); - - while (true) { - if (!isxdigit(*tmp)) - break; - result += static_cast<T>(*tmp <= '9' ? (*tmp - '0') : (tolower(*tmp) - 'a' + 10)) / d; - d *= static_cast<T>(16); - tmp++; - } - } - } - - if (!hex) { - if (*tmp == 'e' || *tmp == 'E') { - tmp++; - - bool exp_negative = *tmp == '-'; - if (*tmp == '+' || *tmp == '-') - tmp++; - - int exp = 0; - while (true) { - if (!isdigit(*tmp)) - break; - exp *= 10; - exp += *tmp - '0'; - tmp++; - } - - if (!exp_negative) { - for (int i = 0; i < exp; ++i) { - result *= static_cast<T>(10); - } - } else { - for (int i = 0; i < exp; ++i) { - result /= static_cast<T>(10); - } - } - } - } else { - if (*tmp == 'p' || *tmp == 'P') { - tmp++; - - bool exp_negative = *tmp == '-'; - if (*tmp == '+' || *tmp == '-') - tmp++; - - int exp = 0; - while (true) { - if (!isdigit(*tmp)) - break; - exp *= 10; - exp += *tmp - '0'; - tmp++; - } - - if (!exp_negative) { - for (int i = 0; i < exp; ++i) { - result *= static_cast<T>(2); - } - } else { - for (int i = 0; i < exp; ++i) { - result /= static_cast<T>(2); - } - } - } - } - - if (endptr) - *endptr = const_cast<char *>(tmp); - if (negative) - result = -result; - - return result; -} - -} - -#endif // MLIBC_STRTOFP_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/strtol.hpp b/lib/mlibc/options/internal/include/mlibc/strtol.hpp deleted file mode 100644 index 3b8fca9..0000000 --- a/lib/mlibc/options/internal/include/mlibc/strtol.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef MLIBC_STRTOL_HPP -#define MLIBC_STRTOL_HPP - -#include <type_traits> -#include <ctype.h> -#include <wctype.h> -#include <limits.h> - -namespace mlibc { - -template<typename T> struct int_limits {}; - -template<> -struct int_limits<long> { - static long max() { return LONG_MAX; } - static long min() { return LONG_MIN; } -}; - -template<> -struct int_limits<unsigned long> { - static unsigned long max() { return ULONG_MAX; } - static unsigned long min() { return 0; } -}; - -template<> -struct int_limits<long long> { - static long long max() { return LLONG_MAX; } - static long long min() { return LLONG_MIN; } -}; - -template<> -struct int_limits<unsigned long long> { - static unsigned long long max() { return ULLONG_MAX; } - static unsigned long long min() { return 0; } -}; - -template<typename T> struct char_detail {}; - -template<> -struct char_detail<char> { - static bool isSpace(char c) { return isspace(c); } - static bool isDigit(char c) { return isdigit(c); } - static bool isHexDigit(char c) { return isxdigit(c); } - static bool isLower(char c) { return islower(c); } - static bool isUpper(char c) { return isupper(c); } -}; - -template<> -struct char_detail<wchar_t> { - static bool isSpace(wchar_t c) { return iswspace(c); } - static bool isDigit(wchar_t c) { return iswdigit(c); } - static bool isHexDigit(wchar_t c) { return iswxdigit(c); } - static bool isLower(wchar_t c) { return iswlower(c); } - static bool isUpper(wchar_t c) { return iswupper(c); } -}; - -template<typename Char> Char widen(char c) { return static_cast<Char>(c); } - -template<typename Return, typename Char> -Return stringToInteger(const Char *__restrict nptr, Char **__restrict endptr, int baseInt) { - using UnsignedReturn = std::make_unsigned_t<Return>; - - auto base = static_cast<Return>(baseInt); - auto s = nptr; - - if (base < 0 || base == 1) { - if (endptr) - *endptr = const_cast<Char *>(nptr); - return 0; - } - - while (char_detail<Char>::isSpace(*s)) - s++; - - bool negative = false; - if (*s == widen<Char>('-')) { - negative = true; - s++; - } else if (*s == widen<Char>('+')) { - s++; - } - - - bool hasOctalPrefix = s[0] == widen<Char>('0'); - bool hasHexPrefix = hasOctalPrefix && (s[1] == widen<Char>('x') || s[1] == widen<Char>('X')); - - // There's two tricky cases we need to keep in mind here: - // 1. We should interpret "0x5" as hex 5 rather than octal 0. - // 2. We should interpret "0x" as octal 0 (and set endptr correctly). - // To deal with 2, we check the charcacter following the hex prefix. - if ((base == 0 || base == 16) && hasHexPrefix && char_detail<Char>::isHexDigit(s[2])) { - s += 2; - base = 16; - } else if ((base == 0 || base == 8) && hasOctalPrefix) { - base = 8; - } else if (base == 0) { - base = 10; - } - - // Compute the range of acceptable values. - UnsignedReturn cutoff, cutlim; - if (std::is_unsigned_v<Return>) { - cutoff = int_limits<Return>::max() / base; - cutlim = int_limits<Return>::max() % base; - } else { - Return co = negative ? int_limits<Return>::min() : int_limits<Return>::max(); - cutlim = negative ? -(co % base) : co % base; - co /= negative ? -base : base; - cutoff = co; - } - - UnsignedReturn totalValue = 0; - bool convertedAny = false; - bool outOfRange = false; - for (Char c = *s; c != widen<Char>('\0'); c = *++s) { - UnsignedReturn digitValue; - if (char_detail<Char>::isDigit(c)) - digitValue = c - widen<Char>('0'); - else if (char_detail<Char>::isUpper(c)) - digitValue = c - widen<Char>('A') + 10; - else if (char_detail<Char>::isLower(c)) - digitValue = c - widen<Char>('a') + 10; - else - break; - - if (digitValue >= static_cast<UnsignedReturn>(base)) - break; - - if (outOfRange) { - // The value is already known to be out of range, but we need to keep - // consuming characters until we can't (to set endptr correctly). - } else if (totalValue > cutoff || (totalValue == cutoff && digitValue > cutlim)) { - // The value will be out of range if we accumulate digitValue. - outOfRange = true; - } else { - totalValue = (totalValue * base) + digitValue; - convertedAny = true; - } - } - - if (endptr) - *endptr = const_cast<Char *>(convertedAny ? s : nptr); - - if (outOfRange) { - errno = ERANGE; - - if (std::is_unsigned_v<Return>) { - return int_limits<Return>::max(); - } else { - return negative ? int_limits<Return>::min() : int_limits<Return>::max(); - } - } - - return negative ? -totalValue : totalValue; -} - -} - -#endif // MLIBC_STRTOL_HPP diff --git a/lib/mlibc/options/internal/include/mlibc/tcb.hpp b/lib/mlibc/options/internal/include/mlibc/tcb.hpp deleted file mode 100644 index 92aad7a..0000000 --- a/lib/mlibc/options/internal/include/mlibc/tcb.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <limits.h> -#include <bits/size_t.h> -#include <frg/array.hpp> - -#include "elf.hpp" - -/* - * Explanation of cancellation bits: - * - * tcbCancelEnableBit and tcbCancelAsyncBit should be self-explanatory, - * they are set if cancellation is enabled, or asynchronous, respectively. - * - * tcbCancelTriggerBit is set whenever a cancellation is triggered, which is - * in pthread_cancel() or in the signal handler. This bit is used by - * pthread_testcancel() to check whether a cancellation has been requested, - * and also by cancellable syscalls. - * - * tcbCancelingBit is set when a cancellation is currently being handled. This - * is to avoid a situation in which a cancellation handler gets interrupted by - * a SIGCANCEL and a second cancellation handler gets executed on top of the - * previous one. Right now this cannot happen, since we stay in signal handler - * context when canceling/exiting. In the future this might be done outside - * of a signal handler, in which case we shouldn't restart the cancellation process. - * - * tcbExitingBit is set when the thread starts the exit procedure. Currently - * this is just an exit, but in the future this will be a stack unwinding - * procedure, which shouldn't be reentered. Not currently set anywhere, - * may be done so in the future. - * - * TODO(geert): update this comment when we do unwinding in the exit procedure. - */ - -namespace { - // Set when the cancellation is enabled - constexpr unsigned int tcbCancelEnableBit = 1 << 0; - // 1 - cancellation is asynchronous, 0 - cancellation is deferred - constexpr unsigned int tcbCancelAsyncBit = 1 << 1; - // Set when the thread has been cancelled - constexpr unsigned int tcbCancelTriggerBit = 1 << 2; - // Set when the thread is in the process of being cancelled. - constexpr unsigned int tcbCancelingBit = 1 << 3; - // Set when the thread is exiting. - constexpr unsigned int tcbExitingBit = 1 << 4; -} - -namespace mlibc { - // Returns true when bitmask indicates thread has been asynchronously - // cancelled. - static constexpr bool tcb_async_cancelled(int value) { - return (value & (tcbCancelEnableBit | tcbCancelAsyncBit - | tcbCancelTriggerBit)) == (tcbCancelEnableBit - | tcbCancelAsyncBit | tcbCancelTriggerBit); - } - - // Returns true when bitmask indicates async cancellation is enabled. - static constexpr bool tcb_async_cancel(int value) { - return (value & (tcbCancelEnableBit | tcbCancelAsyncBit)) - == (tcbCancelEnableBit | tcbCancelAsyncBit); - } - - // Returns true when bitmask indicates cancellation is enabled. - static constexpr bool tcb_cancel_enabled(int value) { - return (value & tcbCancelEnableBit); - } - - // Returns true when bitmask indicates threas has been cancelled. - static constexpr bool tcb_cancelled(int value) { - return (value & (tcbCancelEnableBit | tcbCancelTriggerBit)) - == (tcbCancelEnableBit | tcbCancelTriggerBit); - } - -#if !MLIBC_STATIC_BUILD && !MLIBC_BUILDING_RTDL - // In non-static builds, libc.so always has a TCB available. - constexpr bool tcb_available_flag = true; -#else - // Otherwise this will be set to true after RTDL has initialized the TCB. - extern bool tcb_available_flag; -#endif -} - -enum class TcbThreadReturnValue { - Pointer, - Integer, -}; - -struct Tcb { - Tcb *selfPointer; - size_t dtvSize; - void **dtvPointers; - int tid; - int didExit; -#if defined(__x86_64__) - uint8_t padding[8]; -#endif - uintptr_t stackCanary; - int cancelBits; - - union { - void *voidPtr; - int intVal; - } returnValue; - TcbThreadReturnValue returnValueType; - - struct AtforkHandler { - void (*prepare)(void); - void (*parent)(void); - void (*child)(void); - - AtforkHandler *next; - AtforkHandler *prev; - }; - - AtforkHandler *atforkBegin; - AtforkHandler *atforkEnd; - - struct CleanupHandler { - void (*func)(void *); - void *arg; - - CleanupHandler *next; - CleanupHandler *prev; - }; - - CleanupHandler *cleanupBegin; - CleanupHandler *cleanupEnd; - int isJoinable; - - struct LocalKey { - void *value; - uint64_t generation; - }; - frg::array<LocalKey, PTHREAD_KEYS_MAX> *localKeys; - - size_t stackSize; - void *stackAddr; - size_t guardSize; - - inline void invokeThreadFunc(void *entry, void *user_arg) { - if(returnValueType == TcbThreadReturnValue::Pointer) { - auto func = reinterpret_cast<void *(*)(void *)>(entry); - returnValue.voidPtr = func(user_arg); - } else { - auto func = reinterpret_cast<int (*)(void *)>(entry); - returnValue.intVal = func(user_arg); - } - } -}; - -// There are a few places where we assume the layout of the TCB: -#if defined(__x86_64__) -// GCC expects the stack canary to be at fs:0x28. -static_assert(offsetof(Tcb, stackCanary) == 0x28); -// sysdeps/linux/x86_64/cp_syscall.S uses the offset of cancelBits. -static_assert(offsetof(Tcb, cancelBits) == 0x30); -#elif defined(__i386__) -// GCC expects the stack canary to be at gs:0x14. -// The offset differs from x86_64 due to the change in the pointer size -// and removed padding before the stack canary. -static_assert(offsetof(Tcb, stackCanary) == 0x14); -// sysdeps/linux/x86/cp_syscall.S uses the offset of cancelBits. -// It differs from x86_64 for the same reasons as the stack canary. -static_assert(offsetof(Tcb, cancelBits) == 0x18); -#elif defined(__aarch64__) -// The thread pointer on AArch64 points to 16 bytes before the end of the TCB. -// options/linker/aarch64/runtime.S uses the offset of dtvPointers. -static_assert(sizeof(Tcb) - offsetof(Tcb, dtvPointers) - TP_TCB_OFFSET == 104); -// sysdeps/linux/aarch64/cp_syscall.S uses the offset of cancelBits. -static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) - TP_TCB_OFFSET == 80); -#elif defined(__riscv) && __riscv_xlen == 64 -// The thread pointer on RISC-V points to *after* the TCB, and since -// we need to access specific fields that means that the value in -// sysdeps/linux/riscv64/cp_syscall.S needs to be updated whenever -// the struct is expanded. -static_assert(sizeof(Tcb) - offsetof(Tcb, cancelBits) == 96); -#else -#error "Missing architecture specific code." -#endif diff --git a/lib/mlibc/options/internal/include/mlibc/threads.hpp b/lib/mlibc/options/internal/include/mlibc/threads.hpp deleted file mode 100644 index 989a8e5..0000000 --- a/lib/mlibc/options/internal/include/mlibc/threads.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <bits/ansi/timespec.h> -#include <bits/threads.h> - -namespace mlibc { - -int thread_create(struct __mlibc_thread_data **__restrict thread, const struct __mlibc_threadattr *__restrict attrp, void *entry, void *__restrict user_arg, bool returns_int); -int thread_attr_init(struct __mlibc_threadattr *attr); -int thread_join(struct __mlibc_thread_data *thread, void *res); - -int thread_mutex_init(struct __mlibc_mutex *__restrict mutex, const struct __mlibc_mutexattr *__restrict attr); -int thread_mutex_destroy(struct __mlibc_mutex *mutex); -int thread_mutex_lock(struct __mlibc_mutex *mutex); -int thread_mutex_unlock(struct __mlibc_mutex *mutex); - -int thread_mutexattr_init(struct __mlibc_mutexattr *attr); -int thread_mutexattr_destroy(struct __mlibc_mutexattr *attr); -int thread_mutexattr_gettype(const struct __mlibc_mutexattr *__restrict attr, int *__restrict type); -int thread_mutexattr_settype(struct __mlibc_mutexattr *attr, int type); - -int thread_cond_init(struct __mlibc_cond *__restrict cond, const struct __mlibc_condattr *__restrict attr); -int thread_cond_destroy(struct __mlibc_cond *cond); -int thread_cond_broadcast(struct __mlibc_cond *cond); -int thread_cond_timedwait(struct __mlibc_cond *__restrict cond, __mlibc_mutex *__restrict mutex, const struct timespec *__restrict abstime); - -} diff --git a/lib/mlibc/options/internal/include/mlibc/tid.hpp b/lib/mlibc/options/internal/include/mlibc/tid.hpp deleted file mode 100644 index e85c19f..0000000 --- a/lib/mlibc/options/internal/include/mlibc/tid.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include <mlibc/thread.hpp> -#include <mlibc/internal-sysdeps.hpp> - -namespace mlibc { - inline unsigned int this_tid() { - // During RTDL initialization, we don't have a TCB. - if (mlibc::tcb_available_flag) { - auto tcb = get_current_tcb(); - return tcb->tid; - } else if (mlibc::sys_futex_tid) { - return mlibc::sys_futex_tid(); - } else { - return 1; - } - } -} |