summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/API/Syscall.h3
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/Syscalls/mmap.cpp43
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();
+}
+
}