1/* 2 * Copyright (c) 2022 Google Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23#pragma once 24 25#include <kernel/event.h> 26#include <kernel/mutex.h> 27#include <kernel/thread.h> 28#include <lk/compiler.h> 29 30_LIBCPP_BEGIN_NAMESPACE_STD 31 32// Mutex 33struct __libcpp_mutex_t { 34 mutex_t __m; 35 36 // Default constructor that can be used by _LIBCPP_MUTEX_INITIALIZER 37 constexpr __libcpp_mutex_t() noexcept : __m(MUTEX_INITIAL_VALUE(__m)) {} 38 39 // __m is self-referential so disable copies and moves 40 __libcpp_mutex_t(const __libcpp_mutex_t&) = delete; 41 __libcpp_mutex_t(__libcpp_mutex_t&&) = delete; 42 __libcpp_mutex_t& operator=(const __libcpp_mutex_t&) = delete; 43 __libcpp_mutex_t& operator=(__libcpp_mutex_t&&) = delete; 44}; 45#define _LIBCPP_MUTEX_INITIALIZER (__libcpp_mutex_t()) 46 47#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 48typedef void* __libcpp_recursive_mutex_t[6]; 49#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 50typedef void* __libcpp_recursive_mutex_t[5]; 51#else 52# error Unsupported architecture 53#endif 54 55// Condition Variable 56struct __libcpp_condvar_t { 57 event_t __e; 58 59 // Default constructor that can be used by _LIBCPP_CONDVAR_INITIALIZER 60 constexpr __libcpp_condvar_t() noexcept : __e(EVENT_INITIAL_VALUE(__e, false, 0)) {} 61 62 // __e is self-referential so disable copies and moves 63 __libcpp_condvar_t(const __libcpp_condvar_t&) = delete; 64 __libcpp_condvar_t(__libcpp_condvar_t&&) = delete; 65 __libcpp_condvar_t& operator=(const __libcpp_condvar_t&) = delete; 66 __libcpp_condvar_t& operator=(__libcpp_condvar_t&&) = delete; 67}; 68#define _LIBCPP_CONDVAR_INITIALIZER (__libcpp_condvar_t()) 69 70// Execute Once 71typedef void* __libcpp_exec_once_flag; 72#define _LIBCPP_EXEC_ONCE_INITIALIZER (nullptr) 73 74// Thread ID 75typedef thread_t* __libcpp_thread_id; 76 77// Thread 78#define _LIBCPP_NULL_THREAD (nullptr) 79 80typedef thread_t* __libcpp_thread_t; 81 82// Thread Local Storage 83typedef long __libcpp_tls_key; 84 85#define _LIBCPP_TLS_DESTRUCTOR_CC 86 87static inline _LIBCPP_INLINE_VISIBILITY 88int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 89 90static inline _LIBCPP_INLINE_VISIBILITY 91int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 92 93static inline _LIBCPP_INLINE_VISIBILITY 94bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 95 96static inline _LIBCPP_INLINE_VISIBILITY 97int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 98 99static inline _LIBCPP_INLINE_VISIBILITY 100int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 101 102static inline _LIBCPP_INLINE_VISIBILITY 103int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 104{ 105 mutex_acquire(&__m->__m); 106 return 0; 107} 108 109static inline _LIBCPP_INLINE_VISIBILITY 110bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 111 112static inline _LIBCPP_INLINE_VISIBILITY 113int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 114{ 115 mutex_release(&__m->__m); 116 return 0; 117} 118 119static inline _LIBCPP_INLINE_VISIBILITY 120int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 121 122// Condition Variable 123static inline _LIBCPP_INLINE_VISIBILITY 124int __libcpp_condvar_signal(__libcpp_condvar_t *__cv); 125 126static inline _LIBCPP_INLINE_VISIBILITY 127int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 128{ 129 event_signal(&__cv->__e, true); 130 event_unsignal(&__cv->__e); 131 return 0; 132} 133 134static inline _LIBCPP_INLINE_VISIBILITY 135int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 136{ 137 event_wait(&__cv->__e); 138 return 0; 139} 140 141static inline _LIBCPP_INLINE_VISIBILITY 142int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 143 timespec *__ts); 144 145static inline _LIBCPP_INLINE_VISIBILITY 146int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv); 147 148// Thread id 149// Returns non-zero if the thread ids are equal, otherwise 0 150static inline _LIBCPP_INLINE_VISIBILITY 151bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 152 153// Returns non-zero if t1 < t2, otherwise 0 154static inline _LIBCPP_INLINE_VISIBILITY 155bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 156 157// Thread 158static inline _LIBCPP_INLINE_VISIBILITY 159bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 160 161static inline _LIBCPP_INLINE_VISIBILITY 162int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 163 void *__arg); 164 165static inline _LIBCPP_INLINE_VISIBILITY 166__libcpp_thread_id __libcpp_thread_get_current_id(); 167 168static inline _LIBCPP_INLINE_VISIBILITY 169__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 170 171static inline _LIBCPP_INLINE_VISIBILITY 172int __libcpp_thread_join(__libcpp_thread_t *__t); 173 174static inline _LIBCPP_INLINE_VISIBILITY 175int __libcpp_thread_detach(__libcpp_thread_t *__t); 176 177static inline _LIBCPP_INLINE_VISIBILITY 178void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 179 180static inline _LIBCPP_INLINE_VISIBILITY 181void __libcpp_thread_yield(); 182 183// Thread local storage 184static inline _LIBCPP_INLINE_VISIBILITY 185int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)); 186 187static inline _LIBCPP_INLINE_VISIBILITY 188void *__libcpp_tls_get(__libcpp_tls_key __key); 189 190static inline _LIBCPP_INLINE_VISIBILITY 191int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 192 193_LIBCPP_END_NAMESPACE_STD 194