From 5cbdde2c97229a552852af57232c4e5bbe814a38 Mon Sep 17 00:00:00 2001 From: johannst Date: Sat, 26 Sep 2020 23:20:33 +0200 Subject: enhance comments in thread.cc --- lib/thread.cc | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/thread.cc b/lib/thread.cc index ad07d96..d665f49 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -11,40 +11,52 @@ #include // sysconf namespace { - static long get_pagesize() { return sysconf(_SC_PAGESIZE); } + static long get_pagesize() { return ::sysconf(_SC_PAGESIZE); } } // namespace namespace nMatcha { - Thread::Thread() { + Thread::Thread() : mStackPtr(nullptr), mExecutor(nullptr) { const long PAGE_SIZE = get_pagesize(); const long STACK_SIZE = 8 * PAGE_SIZE; - // create new stack - void* stack = mmap(nullptr, STACK_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */); + // Allocate new stack. + void* stack = ::mmap(nullptr, STACK_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */); assert(stack != MAP_FAILED); - // protect last stack page (lowest addr) - int ret = mprotect(stack, PAGE_SIZE, PROT_NONE); + // Simple stack overflow detection by removing permissions from last + // stack page (lowest addr). + // In theory stack pointer could be decremented by more than one page + // and the page below last stack page could be used. However we don't + // take care of that now and risk the memory corruption. + int ret = ::mprotect(stack, PAGE_SIZE, PROT_NONE); assert(ret == 0); - // stack grows downwards + // Adjust stack pointer, as stack grows downwards. mStackPtr = static_cast(stack) + STACK_SIZE; { + static_assert(sizeof(uint64_t) == sizeof(std::uintptr_t), "Pointer must be 64bit!"); + + // Setup initial stack frame which will be popped when yielding + // first time into the thread. + // Basic idea is to yield into Thread::entry() function which will + // then call the user function. + uint64_t* stack = static_cast(mStackPtr); - *(--stack) = (uint64_t)this; - *(--stack) = (uint64_t)Thread::entry; - - // initial values for yield epilog - *(--stack) = (uint64_t)thread_create; - *(--stack) = (uint64_t)0; - - // initial values for callee saved regs - *(--stack) = (uint64_t)0; // rbx - *(--stack) = (uint64_t)(static_cast(mStackPtr) - 4); // rbp - *(--stack) = (uint64_t)0; // r12 - *(--stack) = (uint64_t)0; // r13 - *(--stack) = (uint64_t)0; // r14 - *(--stack) = (uint64_t)0; // r15 + // Arguments for `thread_create`. + *(--stack) = reinterpret_cast(this); + *(--stack) = reinterpret_cast(Thread::entry); + + // Yield epilogue. + *(--stack) = reinterpret_cast(thread_create); // Return address + *(--stack) = static_cast(0); // rbp + + // Callee saved registers. + *(--stack) = static_cast(0); // rbx + *(--stack) = reinterpret_cast(static_cast(mStackPtr) - 4); // rbp + *(--stack) = static_cast(0); // r12 + *(--stack) = static_cast(0); // r13 + *(--stack) = static_cast(0); // r14 + *(--stack) = static_cast(0); // r15 mStackPtr = static_cast(stack); } -- cgit v1.2.3