diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/API/Syscall.h | 3 | ||||
-rw-r--r-- | Kernel/Process.h | 1 | ||||
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 43 |
3 files changed, 46 insertions, 1 deletions
diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 897d05d64d..0555851d7e 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -194,7 +194,8 @@ namespace Kernel { S(sysconf) \ S(set_process_name) \ S(disown) \ - S(adjtime) + S(adjtime) \ + S(allocate_tls) namespace Syscall { diff --git a/Kernel/Process.h b/Kernel/Process.h index f21a79be01..3e36c61d0e 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -372,6 +372,7 @@ public: int sys$recvfd(int sockfd); long sys$sysconf(int name); int sys$disown(ProcessID); + void* sys$allocate_tls(size_t); template<bool sockname, typename Params> int get_sock_or_peer_name(const Params&); diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 74dbe31edf..36aa2a1b67 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <AK/WeakPtr.h> #include <Kernel/FileSystem/FileDescription.h> #include <Kernel/Process.h> #include <Kernel/VM/PageDirectory.h> @@ -417,4 +418,46 @@ int Process::sys$munmap(void* addr, size_t size) return -EINVAL; } +void* Process::sys$allocate_tls(size_t size) +{ + REQUIRE_PROMISE(stdio); + + dbg() << "allocate TLS: " << size; + + if (!size) + return (void*)-EINVAL; + + if (!m_master_tls_region.is_null()) + return (void*)-EEXIST; + + if (thread_count() != 1) + return (void*)-EFAULT; + + Thread* main_thread = nullptr; + for_each_thread([&main_thread](auto& thread) { + main_thread = &thread; + return IterationDecision::Break; + }); + ASSERT(main_thread); + + auto tls_region = allocate_region({}, size, String(), PROT_READ | PROT_WRITE); + if (!tls_region) + return (void*)-EFAULT; + + m_master_tls_region = tls_region->make_weak_ptr(); + dbg() << "master_tls_region: " << m_master_tls_region->vaddr(); + m_master_tls_size = size; + m_master_tls_alignment = PAGE_SIZE; + + auto tsr_result = main_thread->make_thread_specific_region({}); + if (tsr_result.is_error()) + return (void*)-EFAULT; + + auto& tls_descriptor = Processor::current().get_gdt_entry(GDT_SELECTOR_TLS); + tls_descriptor.set_base(main_thread->thread_specific_data().as_ptr()); + tls_descriptor.set_limit(main_thread->thread_specific_region_size()); + + return m_master_tls_region.unsafe_ptr()->vaddr().as_ptr(); +} + } |