From 37edd9dbc173fd4f4bd1fde407eccc6885b61611 Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Fri, 21 Feb 2020 15:05:48 +0100 Subject: [PATCH 1/9] tbb library --- .gitmodules | 3 +++ 3rdparty/install-tbb.sh | 22 ++++++++++++++++++++++ 3rdparty/tbb | 1 + 3 files changed, 26 insertions(+) create mode 100755 3rdparty/install-tbb.sh create mode 160000 3rdparty/tbb diff --git a/.gitmodules b/.gitmodules index e9ec8162..84805ac4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,3 +12,6 @@ path = 3rdparty/ihk url = https://github.com/ManyThreads/ihk.git ignore = dirty +[submodule "3rdparty/tbb"] + path = 3rdparty/tbb + url = git@github.com:ManyThreads/tbb.git diff --git a/3rdparty/install-tbb.sh b/3rdparty/install-tbb.sh new file mode 100755 index 00000000..0001ea8d --- /dev/null +++ b/3rdparty/install-tbb.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +TBBDIR="${SCRIPTDIR}/tbb" +CXXDIR="${SCRIPTDIR}/cxx-amd64" +TBB_BUILD_PREFIX="my_tbb" + +MYFLAGS=" -std=c++11 -march=native -Wfatal-errors -g" +MYFLAGS+=" -fno-stack-protector" +MYFLAGS+=" -nostdlib -nostdinc -nostdinc++" +MYFLAGS+=" -isystem ${CXXDIR}/usr/include/c++/v1" +MYFLAGS+=" -isystem ${CXXDIR}/usr/include" + +export CXXFLAGS="${MYFLAGS} ${CPLUS_FLAGS}" +export tbb_build_prefix="${TBB_BUILD_PREFIX}" + +echo $CPLUS_FLAGS + +cd $TBBDIR +make clean default +make extra_inc=big_iron.inc +cd - diff --git a/3rdparty/tbb b/3rdparty/tbb new file mode 160000 index 00000000..18070344 --- /dev/null +++ b/3rdparty/tbb @@ -0,0 +1 @@ +Subproject commit 18070344d755ece04d169e6cc40775cae9288cee From 6a04dd9c09d3b5d6320220b5d1907bfc43923524 Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Fri, 21 Feb 2020 15:06:22 +0100 Subject: [PATCH 2/9] tbb test --- 3rdparty/tbb | 2 +- kernel-amd64.config | 2 ++ kernel-ihk.config | 2 ++ kernel-knc.config | 2 ++ kernel/app/init-example/app/init.cc | 33 +++++++++++++++++++----- kernel/runtime/cxx/mcconf.module | 6 ++--- kernel/runtime/cxx/runtime/cxxsupport.cc | 13 ++++++---- kernel/runtime/cxx/runtime/pthread.cc | 6 +++++ 8 files changed, 51 insertions(+), 15 deletions(-) diff --git a/3rdparty/tbb b/3rdparty/tbb index 18070344..dda6d323 160000 --- a/3rdparty/tbb +++ b/3rdparty/tbb @@ -1 +1 @@ -Subproject commit 18070344d755ece04d169e6cc40775cae9288cee +Subproject commit dda6d323f817d05a96f95612d3b158c43cfca241 diff --git a/kernel-amd64.config b/kernel-amd64.config index 84e3083f..a4994b39 100644 --- a/kernel-amd64.config +++ b/kernel-amd64.config @@ -23,3 +23,5 @@ [config.vars] mythos_root = ".." cxx_path = "../3rdparty/cxx-amd64/usr" + tbb_build_path = "../3rdparty/tbb/build/my_tbb_release" + tbb_inc_path = "../3rdparty/tbb/include" diff --git a/kernel-ihk.config b/kernel-ihk.config index 0364e525..f7a53ff3 100644 --- a/kernel-ihk.config +++ b/kernel-ihk.config @@ -22,3 +22,5 @@ [config.vars] mythos_root = ".." cxx_path = "../3rdparty/cxx-amd64/usr" + tbb_build_path = "../3rdparty/tbb/build/my_tbb_release" + tbb_inc_path = "../3rdparty/tbb/include" diff --git a/kernel-knc.config b/kernel-knc.config index 1a7b2262..ec7b4cb3 100644 --- a/kernel-knc.config +++ b/kernel-knc.config @@ -26,3 +26,5 @@ [config.vars] mythos_root = ".." cxx_path = "../3rdparty/cxx-knc/usr" + tbb_build_path = "../3rdparty/tbb/build/my_tbb_release" + tbb_inc_path = "../3rdparty/tbb/include" diff --git a/kernel/app/init-example/app/init.cc b/kernel/app/init-example/app/init.cc index b2602826..99c61bf6 100644 --- a/kernel/app/init-example/app/init.cc +++ b/kernel/app/init-example/app/init.cc @@ -49,6 +49,8 @@ #include #include +#include "tbb/tbb.h" + mythos::InvocationBuf* msg_ptr asm("msg_ptr"); int main() asm("main"); @@ -242,7 +244,7 @@ void test_heap() { MLOG_INFO(mlog::app, "Test heap"); mythos::PortalLock pl(portal); uintptr_t vaddr = 22*1024*1024; // choose address different from invokation buffer - auto size = 4*1024*1024; // 2 MB + auto size = 64*1024*1024; // 2 MB auto align = 2*1024*1024; // 2 MB // allocate a 2MiB frame mythos::Frame f(capAlloc()); @@ -434,6 +436,24 @@ void test_InterruptControl() { MLOG_INFO(mlog::app, "test_InterruptControl end"); } +void test_TBB(){ + class say_hello + { + int id; + public: + say_hello(int i) : id(i) { } + void operator( ) ( ) const + { + printf("hello from task %d\n",id); + } + }; + + tbb::task_group tg; + for(int i=0; i<100; i++){ + tg.run(say_hello(i)); // spawn 1st task and return + } + tg.wait( ); // wait for tasks to complete +} int main() { @@ -441,18 +461,19 @@ int main() mythos::syscall_debug(str, sizeof(str)-1); MLOG_ERROR(mlog::app, "application is starting :)", DVARhex(msg_ptr), DVARhex(initstack_top)); - test_float(); + //test_float(); test_Example(); test_Portal(); - test_memory_root(); + //test_memory_root(); test_heap(); // heap must be initialized for tls test test_tls(); test_exceptions(); //test_InterruptControl(); //test_HostChannel(portal, 24*1024*1024, 2*1024*1024); - test_ExecutionContext(); - test_pthreads(); - test_omp(); + //test_ExecutionContext(); + //test_pthreads(); + //test_omp(); + test_TBB(); char const end[] = "bye, cruel world!"; mythos::syscall_debug(end, sizeof(end)-1); diff --git a/kernel/runtime/cxx/mcconf.module b/kernel/runtime/cxx/mcconf.module index d3137089..f0a2d93d 100644 --- a/kernel/runtime/cxx/mcconf.module +++ b/kernel/runtime/cxx/mcconf.module @@ -2,9 +2,9 @@ [module.cxxabi-app] incfiles = [ "runtime/futex.hh" ] appfiles = [ "runtime/cxxsupport.cc", "runtime/pthread.cc", "runtime/futex.cc" ] - provides = [ "vector", "queue", "functional", "pthread.h", "endian.h", "errno.h", "sys/mman.h", "sys/types.h", "stdlib.h", "sys/time.h", "stdatomic.h", "omp.h", "sys/resource.h", "bits/alltypes.h" ] + provides = [ "vector", "queue", "functional", "pthread.h", "endian.h", "errno.h", "sys/mman.h", "sys/types.h", "stdlib.h", "sys/time.h", "stdatomic.h", "omp.h", "sys/resource.h", "bits/alltypes.h", "tbb/tbb.h" ] makefile_head = ''' -APP_CPPFLAGS += -nostdinc -nostdinc++ -isystem ${vars.cxx_path}/include/c++/v1 -isystem ${vars.cxx_path}/include +APP_CPPFLAGS += -nostdinc -nostdinc++ -isystem ${vars.cxx_path}/include/c++/v1 -isystem ${vars.cxx_path}/include -I ${vars.tbb_inc_path} APP_LDFLAGS += -Wl,--eh-frame-hdr --sysroot=${vars.cxx_path}/../ -APP_LIBS += ${vars.cxx_path}/lib/libomp.a ${vars.cxx_path}/lib/libc++.a ${vars.cxx_path}/lib/libc++abi.a ${vars.cxx_path}/lib/libunwind.a ${vars.cxx_path}/lib/libc.a -lgcc +APP_LIBS += ${vars.cxx_path}/lib/libomp.a ${vars.tbb_build_path}/libtbb.a ${vars.cxx_path}/lib/libc++.a ${vars.cxx_path}/lib/libc++abi.a ${vars.cxx_path}/lib/libunwind.a ${vars.cxx_path}/lib/libc.a -lgcc ''' diff --git a/kernel/runtime/cxx/runtime/cxxsupport.cc b/kernel/runtime/cxx/runtime/cxxsupport.cc index 4c7f130d..5272100a 100644 --- a/kernel/runtime/cxx/runtime/cxxsupport.cc +++ b/kernel/runtime/cxx/runtime/cxxsupport.cc @@ -102,14 +102,14 @@ int prlimit( return 0; } -int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) +int my_sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { //MLOG_DETAIL(mlog::app, "syscall sched_setaffinity", DVAR(pid), DVAR(cpusetsize), DVARhex(mask)); if(cpusetsize == NUM_CPUS && mask == NULL) return -EFAULT; return 0; } -int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) +int my_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { //MLOG_DETAIL(mlog::app, "syscall sched_getaffinity", DVAR(pid), DVAR(cpusetsize), DVARhex(mask)); if (mask) { @@ -165,6 +165,9 @@ extern "C" long mythos_musl_syscall( case 24: // sched_yield //MLOG_ERROR(mlog::app, "syscall sched_yield NYI"); return 0; + case 25: // mremap + //MLOG_ERROR(mlog::app, "syscall sched_yield NYI"); + return 0; case 28: //madvise MLOG_WARN(mlog::app, "syscall madvise NYI"); return 0; @@ -193,9 +196,9 @@ extern "C" long mythos_musl_syscall( nullptr /*uaddr2*/, val2/*val2*/, a6/*val3*/); } case 203: // sched_setaffinity - return sched_setaffinity(a1, a2, reinterpret_cast(a3)); + return my_sched_setaffinity(a1, a2, reinterpret_cast(a3)); case 204: // sched_getaffinity - return sched_getaffinity(a1, a2, reinterpret_cast(a3)); + return my_sched_getaffinity(a1, a2, reinterpret_cast(a3)); case 228: // clock_gettime //MLOG_ERROR(mlog::app, "Error: mythos_musl_syscall clock_gettime", DVAR(num), //DVARhex(a1), DVARhex(a2), DVARhex(a3), @@ -264,7 +267,7 @@ int myclone( int (*func)(void *), void *stack, int flags, void *arg, int* ptid, void* tls, int* ctid) { - //MLOG_DETAIL(mlog::app, "myclone"); + MLOG_DETAIL(mlog::app, "myclone"); ASSERT(tls != nullptr); static int nextThread = 1; diff --git a/kernel/runtime/cxx/runtime/pthread.cc b/kernel/runtime/cxx/runtime/pthread.cc index dca229b5..1f55ef10 100644 --- a/kernel/runtime/cxx/runtime/pthread.cc +++ b/kernel/runtime/cxx/runtime/pthread.cc @@ -37,10 +37,12 @@ extern "C" int pthread_create(pthread_t *res, const pthread_attr_t *attrp, void } #endif +#ifdef use_pthreads_stubs extern "C" int pthread_detach(pthread_t){ MLOG_ERROR(mlog::app, __PRETTY_FUNCTION__); return 0; } +#endif #ifdef use_pthreads_stubs extern "C" _Noreturn void pthread_exit(void *){ @@ -627,15 +629,19 @@ extern "C" void _pthread_cleanup_pop(struct __ptcb *, int){ #ifdef _GNU_SOURCE +#ifdef use_pthreads_stubs extern "C" int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *){ MLOG_ERROR(mlog::app, __PRETTY_FUNCTION__); return 0; } +#endif +#ifdef use_pthreads_stubs extern "C" int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *){ MLOG_ERROR(mlog::app, __PRETTY_FUNCTION__); return 0; } +#endif #ifdef use_pthreads_stubs extern "C" int pthread_getattr_np(pthread_t, pthread_attr_t *){ From af7b4c50a96c135b5551274278abd28bee867525 Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Fri, 1 Jan 2021 23:11:20 +0100 Subject: [PATCH 3/9] processor allocator --- Makefile.user | 1 + kernel-amd64.config | 1 + .../objects/processor-allocator/mcconf.module | 5 + .../mythos/protocol/ProcessorAllocator.hh | 91 +++++++++ .../objects/PluginProcessorAllocator.cc | 31 +++ .../objects/PluginProcessorAllocator.hh | 80 ++++++++ .../objects/ProcessorAllocator.cc | 65 ++++++ .../objects/ProcessorAllocator.hh | 187 ++++++++++++++++++ .../kobject/runtime/ProcessorAllocator.hh | 65 ++++++ 9 files changed, 526 insertions(+) create mode 100644 kernel/objects/processor-allocator/mcconf.module create mode 100644 kernel/objects/processor-allocator/mythos/protocol/ProcessorAllocator.hh create mode 100644 kernel/objects/processor-allocator/objects/PluginProcessorAllocator.cc create mode 100644 kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh create mode 100644 kernel/objects/processor-allocator/objects/ProcessorAllocator.cc create mode 100644 kernel/objects/processor-allocator/objects/ProcessorAllocator.hh create mode 100644 kernel/runtime/kobject/runtime/ProcessorAllocator.hh diff --git a/Makefile.user b/Makefile.user index bf438808..b5691caf 100644 --- a/Makefile.user +++ b/Makefile.user @@ -10,6 +10,7 @@ CPPFLAGS+= -DMLOG_PORTAL=FilterError CPPFLAGS+= -DMLOG_SCHED=FilterError CPPFLAGS+= -DMLOG_SYSCALL=FilterError CPPFLAGS+= -DMLOG_TASKLET=FilterError +CPPFLAGS+= -DMLOG_PROCESSORMGMT=FilterAny #CPPFLAGS+= -DTRACE #CPPFLAGS+= -DNDEBUG diff --git a/kernel-amd64.config b/kernel-amd64.config index 76a8bc4f..d311f6d9 100644 --- a/kernel-amd64.config +++ b/kernel-amd64.config @@ -19,6 +19,7 @@ "plugin-rapl-driver-intel", "app-init-example", "test-synchronous-task", + "plugin-processor-allocator" ] [config.vars] diff --git a/kernel/objects/processor-allocator/mcconf.module b/kernel/objects/processor-allocator/mcconf.module new file mode 100644 index 00000000..634a47fb --- /dev/null +++ b/kernel/objects/processor-allocator/mcconf.module @@ -0,0 +1,5 @@ +# -*- mode:toml; -*- +[module.plugin-processor-allocator] + incfiles = [ "objects/PluginProcessorAllocator.hh", "objects/ProcessorAllocator.hh", "mythos/protocol/ProcessorAllocator.hh" ] + kernelfiles = [ "objects/ProcessorAllocator.cc", "objects/PluginProcessorAllocator.cc"] + diff --git a/kernel/objects/processor-allocator/mythos/protocol/ProcessorAllocator.hh b/kernel/objects/processor-allocator/mythos/protocol/ProcessorAllocator.hh new file mode 100644 index 00000000..ab7a2571 --- /dev/null +++ b/kernel/objects/processor-allocator/mythos/protocol/ProcessorAllocator.hh @@ -0,0 +1,91 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ +#pragma once + +#include "mythos/protocol/common.hh" + +namespace mythos { + namespace protocol { + + struct ProcessorAllocator { + constexpr static uint8_t proto = PROCESSORALLOCATOR; + + enum Methods : uint8_t { + ALLOC, + RETALLOC, + FREE, + RETFREE + }; + + struct Alloc : public InvocationBase { + constexpr static uint16_t label = (proto<<8) + ALLOC; + Alloc(CapPtr dstMap = null_cap) : InvocationBase(label,getLength(this)) { + addExtraCap(dstMap); + } + + // target cap map + CapPtr dstSpace() const { return this->capPtrs[0]; } + }; + + struct RetAlloc : public InvocationBase { + constexpr static uint16_t label = (proto<<8) + RETALLOC; + RetAlloc(CapPtr sc) : InvocationBase(label,getLength(this)) { + addExtraCap(sc); + } + + // allocated scheduling context + CapPtr sc() const { return this->capPtrs[0]; } + }; + + struct Free : public InvocationBase { + constexpr static uint16_t label = (proto<<8) + FREE; + Free(CapPtr sc) : InvocationBase(label,getLength(this)) { + addExtraCap(sc); + } + + // scheduling context to be freed + CapPtr sc() const { return this->capPtrs[0]; } + }; + + struct RetFree : public InvocationBase { + constexpr static uint16_t label = (proto<<8) + RETFREE; + RetFree() : InvocationBase(label,getLength(this)) { + } + }; + + template + static Error dispatchRequest(IMPL* obj, uint8_t m, ARGS const&...args) { + switch(Methods(m)) { + case ALLOC: return obj->invokeAlloc(args...); + case FREE: return obj->invokeFree(args...); + default: return Error::NOT_IMPLEMENTED; + } + } + + }; + + }// namespace protocol +}// namespace mythos diff --git a/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.cc b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.cc new file mode 100644 index 00000000..02323d58 --- /dev/null +++ b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.cc @@ -0,0 +1,31 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ + +#include "objects/PluginProcessorAllocator.hh" + +mythos::PluginProcessorAllocator pluginProcessorAllocator; +mythos::PluginProcessorAllocatorActivator pluginProcessorAllocatorActivator; + diff --git a/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh new file mode 100644 index 00000000..5986988b --- /dev/null +++ b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh @@ -0,0 +1,80 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ +#pragma once + +#include "objects/ProcessorAllocator.hh" +#include "util/events.hh" +#include "boot/load_init.hh" +#include "mythos/init.hh" +#include "boot/mlog.hh" +#include "util/assert.hh" + +namespace mythos { + class PluginProcessorAllocatorActivator + : public EventHook + { + public: + PluginProcessorAllocatorActivator() { + event::initLoaderEarly.add(this); + } + virtual ~PluginProcessorAllocatorActivator() {} + + void processEvent(boot::InitLoader& loader) override { + MLOG_DETAIL(mlog::pm, "prevent mapping of all scheduling contexts into CSpace"); + loader.setSchedulingContexts = false; + } + }; + + class PluginProcessorAllocator + : public EventHook + { + public: + PluginProcessorAllocator() { + event::initLoader.add(this); + } + virtual ~PluginProcessorAllocator() {} + + void processEvent(boot::InitLoader& loader) override { + MLOG_DETAIL(mlog::pm, "Init processor allocator"); + pa.init(); + MLOG_DETAIL(mlog::pm, "CSset processor allocator"); + OOPS(loader.csSet(init::PROCESSOR_ALLOCATOR, pa)); + auto sc = pa.alloc(); + ASSERT(sc); + MLOG_DETAIL(mlog::pm, "allocated SC for init app", DVAR(init::SCHEDULERS_START+*sc)); + loader.initSC = init::SCHEDULERS_START+*sc; + MLOG_DETAIL(mlog::pm, "map SC for init app"); + loader.csSet(init::SCHEDULERS_START+*sc, boot::getScheduler(*sc)); + + } + + LiFoProcessorAllocator pa; + }; + +} // namespace mythos + +extern mythos::PluginProcessorAllocator pluginProcessorAllocator; +extern mythos::PluginProcessorAllocatorActivator pluginProcessorAllocatorActivator; diff --git a/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc new file mode 100644 index 00000000..0da7b420 --- /dev/null +++ b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc @@ -0,0 +1,65 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ + + +#include "objects/ProcessorAllocator.hh" +#include "objects/mlog.hh" + +namespace mythos { + +/* IKernelObject */ + optional ProcessorAllocator::deleteCap(CapEntry&, Cap, IDeleter&) + { + MLOG_DETAIL(mlog::pm, __func__); + RETURN(Error::SUCCESS); + } + + void ProcessorAllocator::deleteObject(Tasklet*, IResult*) + { + MLOG_DETAIL(mlog::pm, __func__); + } + + void ProcessorAllocator::invoke(Tasklet* t, Cap self, IInvocation* msg) + { + MLOG_DETAIL(mlog::pm, __func__, DVAR(t), DVAR(msg)); + monitor.request(t, [=](Tasklet* t){ + Error err = Error::NOT_IMPLEMENTED; + switch (msg->getProtocol()) { + //case protocol::KernelObject::proto: + //err = protocol::KernelObject::dispatchRequest(this, msg->getMethod(), self, msg); + //break; + case protocol::ProcessorAllocator::proto: + err = protocol::ProcessorAllocator::dispatchRequest(this, msg->getMethod(), t, self, msg); + break; + } + if (err != Error::INHIBIT) { + msg->replyResponse(err); + monitor.requestDone(); + } + } ); + } + +} // namespace mythos diff --git a/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh b/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh new file mode 100644 index 00000000..4b54428a --- /dev/null +++ b/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh @@ -0,0 +1,187 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ +#pragma once + +#include "async/NestedMonitorDelegating.hh" +#include "objects/IFactory.hh" +#include "objects/IKernelObject.hh" +#include "cpu/hwthreadid.hh" +#include "mythos/protocol/ProcessorAllocator.hh" +#include "boot/mlog.hh" +#include "objects/RevokeOperation.hh" +#include "async/IResult.hh" + +namespace mythos { + +class ProcessorAllocator + : public IKernelObject + , public IResult +{ + public: + ProcessorAllocator() + : sc(image2kernel(&mySC[0])) + {} + + /* IKernelObject */ + optional deleteCap(CapEntry&, Cap self, IDeleter& del) override; + void deleteObject(Tasklet* t, IResult* r) override; + void invoke(Tasklet* t, Cap self, IInvocation* msg) override; + + /* IResult */ + void response(Tasklet* /*t*/, optional res) override{ + MLOG_INFO(mlog::pm, "revoke response:", res.state()); + } + + void init(){ + MLOG_INFO(mlog::pm, "PM::init"); + for (cpu::ThreadID id = 0; id < cpu::getNumThreads(); ++id) { + sc[id].initRoot(Cap(image2kernel(&boot::getScheduler(id)))); + free(id); + } + } + + Error invokeAlloc(Tasklet*, Cap, IInvocation* msg){ + MLOG_DETAIL(mlog::pm, __func__); + auto id = alloc(); + + if(id){ + MLOG_DETAIL(mlog::pm, "allocated ", DVAR(*id)); + + auto data = msg->getMessage()->read(); + + optional dstEntry; + if(data.dstSpace() == null_cap){ // direct access + //dstEntry = msg->lookupEntry(data.dstPtr, 32, true); // lookup for write access + dstEntry = msg->lookupEntry(init::SCHEDULERS_START+*id, 32, true); // lookup for write access + if (!dstEntry){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstEntry!"); + free(*id); + return dstEntry.state(); + } + + }else{ // indirect access + TypedCap dstSpace(msg->lookupEntry(data.dstSpace())); + if (!dstSpace){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstSpace!"); + free(*id); + return dstSpace.state(); + } + + //auto dstEntryRef = dstSpace.lookup(data.dstPtr, data.dstDepth, true); // lookup for write + auto dstEntryRef = dstSpace.lookup(init::SCHEDULERS_START+*id, 32, true); // lookup for write + if (!dstEntryRef){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstEntryRef!"); + free(*id); + return dstEntryRef.state(); + } + + dstEntry = dstEntryRef->entry; + } + + auto res = cap::reference(sc[*id], **dstEntry, sc[*id].cap()); + if(res){ + msg->getMessage()->write(init::SCHEDULERS_START+*id); + MLOG_DETAIL(mlog::pm, "map new sc ", DVAR(*id)); + }else{ + MLOG_WARN(mlog::pm, "Warning: cannot create SC entry!"); + free(*id); + msg->getMessage()->write(null_cap); + } + + }else{ + MLOG_DETAIL(mlog::pm, "allocation failed: no free cores available!"); + msg->getMessage()->write(null_cap); + } + return Error::SUCCESS; + } + + Error invokeFree(Tasklet* t, Cap, IInvocation* msg){ + MLOG_ERROR(mlog::pm, __func__, ": NYI!"); + //auto data = msg->getMessage()->cast(); + //ASSERT(data->sc() >= init::SCHEDULERS_START); + //cpu::ThreadID id = data->sc() - init::SCHEDULERS_START; + //ASSERT(id < cpu::getNumThreads()); + //MLOG_ERROR(mlog::pm, "free SC", DVAR(data->sc()), DVAR(id)); + //revokeOp._revoke(t, this, sc[id], this); + //MLOG_ERROR(mlog::pm, "free", DVAR(data->sc()), DVAR(id)); + //free(id); + //return Error::SUCCESS; + return Error::NOT_IMPLEMENTED; + } + + void freeSC(Tasklet* t, cpu::ThreadID id){ + MLOG_ERROR(mlog::pm, "freeSC", DVAR(id)); + monitor.request(t, [=](Tasklet* t){ + MLOG_ERROR(mlog::pm, "monitor free", DVAR(id)); + //todo: use IResult to call free(id) after cap is revoked + revokeOp._revoke(t, this, sc[id], this); + free(id); + } + ); + } + + protected: + friend class PluginProcessorAllocator; + virtual optional alloc() = 0; + virtual void free(cpu::ThreadID id) = 0; + virtual unsigned numFree() = 0; + + private: + async::NestedMonitorDelegating monitor; + RevokeOperation revokeOp = {monitor}; + CapEntry *sc; + CapEntry mySC[MYTHOS_MAX_THREADS]; +}; + +class LiFoProcessorAllocator : public ProcessorAllocator +{ + public: + LiFoProcessorAllocator() + : nFree(0) + {} + + optional alloc() override { + optional ret; + if(nFree > 0){ + nFree--; + ret = freeList[nFree]; + } + return ret; + } + + unsigned numFree() override { return nFree; } + + void free(cpu::ThreadID id) override { + freeList[nFree] = id; + nFree++; + } + private: + unsigned nFree; + cpu::ThreadID freeList[MYTHOS_MAX_THREADS]; + +}; + +} // namespace mythos diff --git a/kernel/runtime/kobject/runtime/ProcessorAllocator.hh b/kernel/runtime/kobject/runtime/ProcessorAllocator.hh new file mode 100644 index 00000000..5f50e11b --- /dev/null +++ b/kernel/runtime/kobject/runtime/ProcessorAllocator.hh @@ -0,0 +1,65 @@ +/* -*- mode:C++; indent-tabs-mode:nil; -*- */ +/* MIT License -- MyThOS: The Many-Threads Operating System + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright 2020 Philipp Gypser and contributors, BTU Cottbus-Senftenberg + */ +#pragma once + +#include "runtime/PortalBase.hh" +#include "mythos/protocol/ProcessorAllocator.hh" +#include "mythos/init.hh" + +namespace mythos { + + class ProcessorAllocator : public KObject + { + public: + + ProcessorAllocator() {} + ProcessorAllocator(CapPtr cap) : KObject(cap) {} + + struct AllocResult{ + AllocResult() {} + AllocResult(InvocationBuf* ib) { + auto msg = ib->cast(); + cap = msg->sc(); + } + + CapPtr cap = null_cap; + }; + + PortalFuture alloc(PortalLock pr){ + return pr.invoke(_cap); + } + + PortalFuture alloc(PortalLock pr, CapPtr dstMap){ + return pr.invoke(_cap, dstMap); + } + + PortalFuture free(PortalLock pr, CapPtr sc){ + return pr.invoke(_cap, sc); + } + + }; + +} // namespace mythos From 4fccb2e03a0a77f68db4b2990f4203a80f3a23b1 Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Fri, 1 Jan 2021 23:12:11 +0100 Subject: [PATCH 4/9] worked on processor allocator --- 3rdparty/musl | 2 +- kernel/app/init-example/app/init.cc | 31 ++++++-- .../process_test/process_test/process_test.cc | 2 + kernel/async/monitor-common/async/Place.hh | 2 + .../boot/init-loader-amd64/boot/load_init.cc | 23 +++--- .../boot/init-loader-amd64/boot/load_init.hh | 5 ++ kernel/mythos/init/mythos/init.hh | 1 + .../invocation/mythos/protocol/common.hh | 1 + .../objects/RevokeOperation.hh | 2 +- kernel/objects/common/objects/mlog.cc | 1 + kernel/objects/common/objects/mlog.hh | 5 ++ .../objects/ExecutionContext.cc | 3 +- .../objects/SchedulingContext.cc | 8 ++- .../objects/SchedulingContext.hh | 2 + kernel/runtime/cxx/runtime/cxxsupport.cc | 72 ++++++++++++++++--- kernel/runtime/kobject/mcconf.module | 3 +- kernel/runtime/process/runtime/process.hh | 25 +++---- 17 files changed, 151 insertions(+), 37 deletions(-) diff --git a/3rdparty/musl b/3rdparty/musl index 9680582a..790bd394 160000 --- a/3rdparty/musl +++ b/3rdparty/musl @@ -1 +1 @@ -Subproject commit 9680582a257de9d20b94ee26ddf6f9dc10df948e +Subproject commit 790bd3943e419933cf56366197b9f6668ae8c53e diff --git a/kernel/app/init-example/app/init.cc b/kernel/app/init-example/app/init.cc index 5a009a4f..3a5c868f 100644 --- a/kernel/app/init-example/app/init.cc +++ b/kernel/app/init-example/app/init.cc @@ -36,6 +36,7 @@ #include "runtime/PageMap.hh" #include "runtime/KernelMemory.hh" #include "runtime/SimpleCapAlloc.hh" +#include "runtime/ProcessorAllocator.hh" #include "runtime/tls.hh" #include "runtime/mlog.hh" #include "runtime/InterruptControl.hh" @@ -73,6 +74,7 @@ mythos::KObject device_memory(mythos::init::DEVICE_MEM); mythos::SimpleCapAlloc< mythos::init::APP_CAP_START , mythos::init::SIZE-mythos::init::APP_CAP_START> capAlloc(myCS); mythos::RaplDriverIntel rapl(mythos::init::RAPL_DRIVER_INTEL); +mythos::ProcessorAllocator pa(mythos::init::PROCESSOR_ALLOCATOR); char threadstack[stacksize]; char* thread1stack_top = threadstack+stacksize/2; @@ -185,7 +187,9 @@ void test_tls() auto tls = mythos::setupNewTLS(); MLOG_INFO(mlog::app, "test_EC: create ec1 TLS", DVARhex(tls)); ASSERT(tls != nullptr); - auto res1 = ec1.create(kmem).as(myAS).cs(myCS).sched(mythos::init::SCHEDULERS_START + 1) + auto sc = pa.alloc(pl).wait(); + TEST(sc); + auto res1 = ec1.create(kmem).as(myAS).cs(myCS).sched(sc->cap) .prepareStack(thread1stack_top).startFun(threadFun, nullptr) .suspended(false).fs(tls) .invokeVia(pl).wait(); @@ -193,6 +197,7 @@ void test_tls() TEST(ec1.setFSGS(pl,(uint64_t) tls, 0).wait()); mythos::syscall_signal(ec1.cap()); MLOG_INFO(mlog::app, "End test tls"); + capAlloc.free(ec1.cap(), pl); } @@ -322,7 +327,9 @@ void test_ExecutionContext() auto tls1 = mythos::setupNewTLS(); ASSERT(tls1 != nullptr); - auto res1 = ec1.create(kmem).as(myAS).cs(myCS).sched(mythos::init::SCHEDULERS_START) + auto sc1 = pa.alloc(pl).wait(); + TEST(sc1); + auto res1 = ec1.create(kmem).as(myAS).cs(myCS).sched(sc1->cap) .prepareStack(thread1stack_top).startFun(&thread_main, nullptr) .suspended(false).fs(tls1) .invokeVia(pl).wait(); @@ -331,7 +338,9 @@ void test_ExecutionContext() MLOG_INFO(mlog::app, "test_EC: create ec2"); auto tls2 = mythos::setupNewTLS(); ASSERT(tls2 != nullptr); - auto res2 = ec2.create(kmem).as(myAS).cs(myCS).sched(mythos::init::SCHEDULERS_START+1) + auto sc2 = pa.alloc(pl).wait(); + TEST(sc2); + auto res2 = ec2.create(kmem).as(myAS).cs(myCS).sched(sc2->cap) .prepareStack(thread2stack_top).startFun(&thread_main, nullptr) .suspended(false).fs(tls2) .invokeVia(pl).wait(); @@ -345,6 +354,11 @@ void test_ExecutionContext() MLOG_INFO(mlog::app, "sending notifications"); mythos::syscall_signal(ec1.cap()); mythos::syscall_signal(ec2.cap()); + { + mythos::PortalLock pl(portal); + TEST(capAlloc.free(ec1, pl)); + TEST(capAlloc.free(ec2, pl)); + } MLOG_INFO(mlog::app, "End Test ExecutionContext"); } @@ -357,7 +371,9 @@ void test_InterruptControl() { mythos::ExecutionContext ec(capAlloc()); auto tls = mythos::setupNewTLS(); ASSERT(tls != nullptr); - auto res1 = ec.create(kmem).as(myAS).cs(myCS).sched(mythos::init::SCHEDULERS_START + 2) + auto sc = pa.alloc(pl).wait(); + TEST(sc); + auto res1 = ec.create(kmem).as(myAS).cs(myCS).sched(sc->cap) .prepareStack(thread3stack_top).startFun(&thread_main, nullptr) .suspended(false).fs(tls) .invokeVia(pl).wait(); @@ -484,6 +500,11 @@ void test_process(){ MLOG_INFO(mlog::app, "Test process"); mythos::PortalLock pl(portal); + //auto sc = pa.alloc(pl).wait(); + //TEST(sc); + //auto res = pa.free(pl, sc->cap).wait(); + //TEST(res); + Process p(&process_test_image_start); p.createProcess(pl); @@ -510,6 +531,8 @@ int main() test_process(); //test_CgaScreen(); +#warning event test cases + char const end[] = "bye, cruel world!"; mythos::syscall_debug(end, sizeof(end)-1); diff --git a/kernel/app/process_test/process_test/process_test.cc b/kernel/app/process_test/process_test/process_test.cc index 10a09766..4077a36b 100644 --- a/kernel/app/process_test/process_test/process_test.cc +++ b/kernel/app/process_test/process_test/process_test.cc @@ -34,6 +34,7 @@ #include "runtime/PageMap.hh" #include "runtime/KernelMemory.hh" #include "runtime/SimpleCapAlloc.hh" +#include "runtime/ProcessorAllocator.hh" #include "runtime/tls.hh" #include "runtime/mlog.hh" #include "runtime/InterruptControl.hh" @@ -58,6 +59,7 @@ mythos::KObject device_memory(mythos::init::DEVICE_MEM); mythos::SimpleCapAlloc< mythos::init::APP_CAP_START , mythos::init::SIZE-mythos::init::APP_CAP_START> capAlloc(myCS); mythos::RaplDriverIntel rapl(mythos::init::RAPL_DRIVER_INTEL); +mythos::ProcessorAllocator pa(mythos::init::PROCESSOR_ALLOCATOR); int main() diff --git a/kernel/async/monitor-common/async/Place.hh b/kernel/async/monitor-common/async/Place.hh index 571bbb8f..8b60fe9a 100644 --- a/kernel/async/monitor-common/async/Place.hh +++ b/kernel/async/monitor-common/async/Place.hh @@ -113,6 +113,8 @@ public: /** true if the hardware thread is currently in kernel mode and processing tasks. */ bool isActive() const { return nestingMonitor.load(std::memory_order_relaxed); } + cpu::ThreadID getThreadID(){ return threadID; } + protected: void pushPrivate(TaskletBase* msg) { ASSERT(isLocal()); diff --git a/kernel/boot/init-loader-amd64/boot/load_init.cc b/kernel/boot/init-loader-amd64/boot/load_init.cc index 5e00f6f3..7211df4b 100644 --- a/kernel/boot/init-loader-amd64/boot/load_init.cc +++ b/kernel/boot/init-loader-amd64/boot/load_init.cc @@ -49,6 +49,7 @@ namespace mythos { Event event::initLoader; +Event event::initLoaderEarly; namespace boot { @@ -59,6 +60,9 @@ InitLoader::InitLoader(char* image) , capAlloc(init::CAP_ALLOC_START, init::CAP_ALLOC_END-init::CAP_ALLOC_START) , memMapper(&capAlloc, mythos::init::KM) + // default: no processor allocator present + , setSchedulingContexts(true) + , initSC(init::SCHEDULERS_START) { MLOG_INFO(mlog::boot, "found init application image at", (void*)image); } @@ -69,6 +73,8 @@ optional InitLoader::load() { if (!_img.isValid()) RETURN(Error::GENERIC_ERROR); + event::initLoaderEarly.emit(*this); + // order matters here optional res(Error::SUCCESS); if (res) res = initCSpace(); @@ -157,12 +163,14 @@ optional InitLoader::initCSpace() if (!res) RETHROW(res); } - ASSERT(cpu::getNumThreads() <= init::SCHEDULERS_START - init::APP_CAP_START); - MLOG_INFO(mlog::boot, "... create scheduling context caps in caps", - init::SCHEDULERS_START, "till", init::SCHEDULERS_START+cpu::getNumThreads()-1); - for (cpu::ThreadID id = 0; id < cpu::getNumThreads(); ++id) { - auto res = csSet(init::SCHEDULERS_START+id, boot::getScheduler(id)); - if (!res) RETHROW(res); + if(setSchedulingContexts){ + ASSERT(cpu::getNumThreads() <= init::SCHEDULERS_START - init::APP_CAP_START); + MLOG_INFO(mlog::boot, "... create scheduling context caps in caps", + init::SCHEDULERS_START, "till", init::SCHEDULERS_START+cpu::getNumThreads()-1); + for (cpu::ThreadID id = 0; id < cpu::getNumThreads(); ++id) { + auto res = csSet(init::SCHEDULERS_START+id, boot::getScheduler(id)); + if (!res) RETHROW(res); + } } ASSERT(cpu::getNumThreads() <= init::INTERRUPT_CONTROL_START - init::APP_CAP_START); @@ -178,7 +186,6 @@ optional InitLoader::initCSpace() RETURN(Error::SUCCESS); } - optional InitLoader::createPortal(uintptr_t ipc_vaddr, CapPtr dstPortal) { auto size = 2*1024*1024; @@ -281,7 +288,7 @@ optional InitLoader::createEC(uintptr_t ipc_vaddr) optional res(Error::SUCCESS); if (res) res = ec->setCapSpace(capAlloc.get(init::CSPACE)); if (res) res = ec->setAddressSpace(capAlloc.get(init::PML4)); - if (res) res = ec->setSchedulingContext(capAlloc.get(init::SCHEDULERS_START)); + if (res) res = ec->setSchedulingContext(capAlloc.get(initSC)); if (!res) RETHROW(res); ec->getThreadState().rdi = ipc_vaddr; ec->setEntryPoint(_img.header()->entry); diff --git a/kernel/boot/init-loader-amd64/boot/load_init.hh b/kernel/boot/init-loader-amd64/boot/load_init.hh index 7a0c489b..f6bd6648 100644 --- a/kernel/boot/init-loader-amd64/boot/load_init.hh +++ b/kernel/boot/init-loader-amd64/boot/load_init.hh @@ -78,12 +78,17 @@ namespace mythos { MemMapper memMapper; Portal* _portal; + + /* to be manipulated by optional processor allocator */ + bool setSchedulingContexts; + CapPtr initSC; }; } // namespace boot namespace event { extern Event initLoader; + extern Event initLoaderEarly; } } // namespace mythos diff --git a/kernel/mythos/init/mythos/init.hh b/kernel/mythos/init/mythos/init.hh index 06c56ffd..4f4a5e1f 100644 --- a/kernel/mythos/init/mythos/init.hh +++ b/kernel/mythos/init/mythos/init.hh @@ -53,6 +53,7 @@ namespace init { SCHEDULERS_START, CPUDRIVER = SCHEDULERS_START+256, RAPL_DRIVER_INTEL, + PROCESSOR_ALLOCATOR, INTERRUPT_CONTROL_START, INTERRUPT_CONTROL_END = INTERRUPT_CONTROL_START+256, APP_CAP_START = 1024, diff --git a/kernel/mythos/invocation/mythos/protocol/common.hh b/kernel/mythos/invocation/mythos/protocol/common.hh index d20db802..2214f382 100644 --- a/kernel/mythos/invocation/mythos/protocol/common.hh +++ b/kernel/mythos/invocation/mythos/protocol/common.hh @@ -45,6 +45,7 @@ namespace mythos { EXAMPLE, CPUDRIVERKNC, RAPLDRIVERINTEL, + PROCESSORALLOCATOR, INTERRUPT_CONTROL, }; diff --git a/kernel/objects/capability-spinning/objects/RevokeOperation.hh b/kernel/objects/capability-spinning/objects/RevokeOperation.hh index abbfe817..6ad3a33c 100644 --- a/kernel/objects/capability-spinning/objects/RevokeOperation.hh +++ b/kernel/objects/capability-spinning/objects/RevokeOperation.hh @@ -101,7 +101,7 @@ public: }; private: - + friend class ProcessorAllocator; //need to directly access _revoke in deallocation sequence (todo: do it better!) void _revoke(Tasklet* t, result_t* res, CapEntry& entry, IKernelObject* guarded); void _delete(Tasklet* t, result_t* res, CapEntry& entry, IKernelObject* guarded); void _deleteObject(Tasklet* t); diff --git a/kernel/objects/common/objects/mlog.cc b/kernel/objects/common/objects/mlog.cc index 215e56ac..8ff32955 100644 --- a/kernel/objects/common/objects/mlog.cc +++ b/kernel/objects/common/objects/mlog.cc @@ -33,4 +33,5 @@ namespace mlog { Logger ec("ec"); Logger km("km"); Logger irq("irq"); + Logger pm("pm"); //processor management } // namespace mlog diff --git a/kernel/objects/common/objects/mlog.hh b/kernel/objects/common/objects/mlog.hh index c83f41ec..6545e605 100644 --- a/kernel/objects/common/objects/mlog.hh +++ b/kernel/objects/common/objects/mlog.hh @@ -59,4 +59,9 @@ namespace mlog { #endif extern Logger irq; +#ifndef MLOG_PM +#define MLOG_PM FilterWarning +#endif + extern Logger pm; //processor management + } // namespace mlog diff --git a/kernel/objects/execution-context/objects/ExecutionContext.cc b/kernel/objects/execution-context/objects/ExecutionContext.cc index 444e97a4..4f04b690 100644 --- a/kernel/objects/execution-context/objects/ExecutionContext.cc +++ b/kernel/objects/execution-context/objects/ExecutionContext.cc @@ -55,7 +55,7 @@ namespace mythos { DVARhex(flags.load()), isReady()); if (needPreemption(prev) && !isReady()) { auto place = currentPlace.load(); - ASSERT(place != nullptr); + //ASSERT(place != nullptr); /// @todo is place->preempt() sufficient without waiting? if (place) synchronousAt(place) << [this]() { MLOG_DETAIL(mlog::ec, "suspended", DVAR(this)); @@ -597,6 +597,7 @@ namespace mythos { auto place = currentPlace.load(); if (place) synchronousAt(place) << [this]() { this->saveState(); + this->_sched.reset(); MLOG_DETAIL(mlog::ec, "preempted and unloaded state", DVAR(this)); }; _as.reset(); diff --git a/kernel/objects/scheduling-context/objects/SchedulingContext.cc b/kernel/objects/scheduling-context/objects/SchedulingContext.cc index 7bedf186..2a1a9358 100644 --- a/kernel/objects/scheduling-context/objects/SchedulingContext.cc +++ b/kernel/objects/scheduling-context/objects/SchedulingContext.cc @@ -41,9 +41,15 @@ namespace mythos { void SchedulingContext::unbind(handle_t* ec) { ASSERT(ec != nullptr); - MLOG_DETAIL(mlog::sched, "unbind", DVAR(ec->get())); + MLOG_ERROR(mlog::sched, "unbind", DVAR(ec->get())); readyQueue.remove(ec); current_handle.store(nullptr); + if(readyQueue.empty()){ + MLOG_ERROR(mlog::sched, "call freeSC"); + pluginProcessorAllocator.pa.freeSC(&paTask, home->getThreadID()); + }else{ + MLOG_ERROR(mlog::sched, "ready queue not empty!"); + } } void SchedulingContext::ready(handle_t* ec) diff --git a/kernel/objects/scheduling-context/objects/SchedulingContext.hh b/kernel/objects/scheduling-context/objects/SchedulingContext.hh index e1ca8d9f..c9362fdb 100644 --- a/kernel/objects/scheduling-context/objects/SchedulingContext.hh +++ b/kernel/objects/scheduling-context/objects/SchedulingContext.hh @@ -97,6 +97,8 @@ namespace mythos { async::Place* home = nullptr; list_t readyQueue; //< the ready list of waiting execution contexts std::atomic current_handle = {nullptr}; //< the currently selected execution context + + Tasklet paTask; //task for communication with processor allocator }; } // namespace mythos diff --git a/kernel/runtime/cxx/runtime/cxxsupport.cc b/kernel/runtime/cxx/runtime/cxxsupport.cc index a4df70b7..da5da9d5 100644 --- a/kernel/runtime/cxx/runtime/cxxsupport.cc +++ b/kernel/runtime/cxx/runtime/cxxsupport.cc @@ -49,9 +49,11 @@ #include "runtime/PageMap.hh" #include "runtime/KernelMemory.hh" #include "runtime/SimpleCapAlloc.hh" +#include "runtime/ProcessorAllocator.hh" #include "runtime/tls.hh" #include "runtime/futex.hh" #include "runtime/umem.hh" +#include "runtime/thread-extra.hh" extern mythos::InvocationBuf* msg_ptr asm("msg_ptr"); extern mythos::Portal portal; @@ -60,6 +62,7 @@ extern mythos::PageMap myAS; extern mythos::KernelMemory kmem; extern mythos::SimpleCapAlloc< mythos::init::APP_CAP_START , mythos::init::SIZE-mythos::init::APP_CAP_START> capAlloc; +extern mythos::ProcessorAllocator pa; #ifndef NUM_CPUS #define NUM_CPUS (2) @@ -67,6 +70,45 @@ extern mythos::SimpleCapAlloc< mythos::init::APP_CAP_START #define PS_PER_TSC (0x0000000000000181) +struct PthreadCleanerSemaphore{ + PthreadCleanerSemaphore() + : flag(FREE) + { + //MLOG_ERROR(mlog::app, "PthreadCleaner"); + } + + enum state{ + UNKNOWN = 0, + FREE = 1, + EXITED = 2 + }; + + void exit(){ + //MLOG_DETAIL(mlog::app, "PthreadCleaner exit", DVARhex(this), DVARhex(pthread_self())); + auto ec = flag.exchange(EXITED); + if(ec != FREE){ + ASSERT(ec!=UNKNOWN); + mythos::syscall_signal(ec); + } + } + + void wait(pthread_t t){ + auto pcs = reinterpret_cast(t - (pthread_self() - reinterpret_cast(this))); + //MLOG_DETAIL(mlog::app, "PthreadCleaner wait", DVARhex(pcs), DVARhex(this), DVARhex(pthread_self()), DVARhex(t)); + while(pcs->flag.load() != EXITED){ + mythos::CapPtr exp = FREE; + if(pcs->flag.compare_exchange_weak(exp, mythos_get_pthread_ec_self())){ + //MLOG_DETAIL(mlog::app, "PthreadCleaner going to wait"); + mythos_wait(); + } + } + } + + std::atomic flag; +}; + +static thread_local PthreadCleanerSemaphore pthreadCleanerSemphore; + extern "C" [[noreturn]] void __assert_fail (const char *expr, const char *file, int line, const char *func) { mlog::Logger<> logassert("assert"); @@ -173,7 +215,8 @@ extern "C" long mythos_musl_syscall( MLOG_WARN(mlog::app, "syscall getpid NYI"); return 0; case 60: // exit(exit_code) - //MLOG_DETAIL(mlog::app, "syscall exit", DVAR(a1)); + MLOG_ERROR(mlog::app, "syscall exit", DVAR(a1)); + pthreadCleanerSemphore.exit(); asm volatile ("syscall" : : "D"(0), "S"(a1) : "memory"); return 0; case 186: // gettid @@ -266,7 +309,6 @@ int myclone( { //MLOG_DETAIL(mlog::app, "myclone"); ASSERT(tls != nullptr); - static int nextThread = 1; // The compiler expect a kinda strange alignment coming from clone: // -> rsp % 16 must be 8 @@ -278,15 +320,19 @@ int myclone( mythos::ExecutionContext ec(capAlloc()); if (ptid && (flags&CLONE_PARENT_SETTID)) *ptid = int(ec.cap()); // @todo store thread-specific ctid pointer, which should set to 0 by the OS on the thread's exit - // @todo needs interaction with a process internal scheduler or core manager in order to figure out where to schedule the new thread + + auto sc = pa.alloc(pl).wait(); + ASSERT(sc); + if(sc->cap == mythos::null_cap){ + MLOG_WARN(mlog::app, "Processor allocation failed!"); + //todo: set errno = EAGAIN + return (-1); + } + auto res1 = ec.create(kmem) .as(myAS) .cs(myCS) - // WARNING: This will lead to trouble if nextThread >= number of threads. - // It's also not thread safe. - // @TODO: More sensible thread placement. - .sched(mythos::init::SCHEDULERS_START + (nextThread++)) - // ^^^^^^^^^^^^ + .sched(sc->cap) .rawStack(rsp) .rawFun(func, arg) .suspended(false) @@ -309,6 +355,16 @@ extern "C" int clone(int (*func)(void *), void *stack, int flags, void *arg, ... return myclone(func, stack, flags, arg, ptid, tls, ctid); } +extern "C" void mythos_pthread_cleanup(pthread_t t){ + MLOG_ERROR(mlog::app, "mythos_pthread_cleanup", mythos_get_pthread_ec(t)); + pthreadCleanerSemphore.wait(t); + auto cap = mythos_get_pthread_ec(t); + mythos::PortalLock pl(portal); + //mythos::ExecutionContext ec(cap); + //ec.suspend(pl).wait(); + capAlloc.free(cap, pl); +} + struct dl_phdr_info { void* dlpi_addr; /* Base address of object */ diff --git a/kernel/runtime/kobject/mcconf.module b/kernel/runtime/kobject/mcconf.module index 458ad07d..2e50bece 100644 --- a/kernel/runtime/kobject/mcconf.module +++ b/kernel/runtime/kobject/mcconf.module @@ -9,5 +9,6 @@ incfiles = [ "runtime/KernelMemory.hh", "runtime/SimpleCapAlloc.hh", "runtime/InterruptControl.hh", - "runtime/RaplDriverIntel.hh" + "runtime/RaplDriverIntel.hh", + "runtime/ProcessorAllocator.hh" ] diff --git a/kernel/runtime/process/runtime/process.hh b/kernel/runtime/process/runtime/process.hh index b696abe2..dfff815c 100644 --- a/kernel/runtime/process/runtime/process.hh +++ b/kernel/runtime/process/runtime/process.hh @@ -13,6 +13,7 @@ extern mythos::PageMap myAS; extern mythos::KernelMemory kmem; extern mythos::SimpleCapAlloc< mythos::init::APP_CAP_START , mythos::init::SIZE-mythos::init::APP_CAP_START> capAlloc; +extern mythos::ProcessorAllocator pa; using namespace mythos; @@ -162,23 +163,17 @@ class Process{ res = myCS.reference(pl, init::DEVICE_MEM, max_cap_depth, cs.cap(), init::DEVICE_MEM, max_cap_depth, 0).wait(); TEST(res); - MLOG_DETAIL(mlog::app, " scheduling contexts"); - //todo: how to check whether cap is existing? - for(CapPtr ptr = init::SCHEDULERS_START; ptr < init::RAPL_DRIVER_INTEL; ptr++){ - res = myCS.reference(pl, ptr, max_cap_depth, cs.cap(), ptr, max_cap_depth, 0).wait(); - TEST(res); - } - MLOG_DETAIL(mlog::app, " RAPL driver"); res = myCS.reference(pl, init::RAPL_DRIVER_INTEL, max_cap_depth, cs.cap(), init::RAPL_DRIVER_INTEL, max_cap_depth, 0).wait(); TEST(res); MLOG_DETAIL(mlog::app, " Interrupt control"); //todo: how to check whether cap is existing? - for(CapPtr ptr = init::INTERRUPT_CONTROL_START; ptr < init::INTERRUPT_CONTROL_END; ptr++){ - res = myCS.reference(pl, ptr, max_cap_depth, cs.cap(), ptr, max_cap_depth, 0).wait(); - TEST(res); - } +#warning Process:createProcess do not copy Interrupt Controls + //for(CapPtr ptr = init::INTERRUPT_CONTROL_START; ptr < init::INTERRUPT_CONTROL_END; ptr++){ + //res = myCS.reference(pl, ptr, max_cap_depth, cs.cap(), ptr, max_cap_depth, 0).wait(); + //TEST(res); + //} /* create address space */ //todo: use dynamic table allocation in mmap! @@ -248,12 +243,18 @@ class Process{ /* create EC */ MLOG_DETAIL(mlog::app, "create EC ...", DVARhex(img.header()->entry)); + auto sc = pa.alloc(pl).wait(); + TEST(sc); + MLOG_DETAIL(mlog::app, "allocated SC", DVAR(sc->cap)); ExecutionContext ec(capAlloc()); - res = ec.create(kmem).as(pm4).cs(cs).sched(mythos::init::SCHEDULERS_START + 1) + res = ec.create(kmem).as(pm4).cs(cs).sched(sc->cap) .rawFun(reinterpret_cast(img.header()->entry), reinterpret_cast(*ipc_vaddr)) .suspended(true) .invokeVia(pl).wait(); TEST(res); + MLOG_DETAIL(mlog::app, "move SC"); + res = myCS.move(pl, sc->cap, max_cap_depth, cs.cap(), sc->cap, max_cap_depth).wait(); + TEST(res); /* create portal */ MLOG_DETAIL(mlog::app, "create Portal ..."); From e05070de4daf46633c7296172ba9aba5a2381d2c Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Sat, 2 Jan 2021 12:32:43 +0100 Subject: [PATCH 5/9] cleaning up --- Makefile.user | 2 +- kernel/app/init-example/app/init.cc | 19 +-- .../boot/init-loader-amd64/boot/load_init.cc | 4 +- .../boot/init-loader-amd64/boot/load_init.hh | 2 +- .../objects/PluginProcessorAllocator.hh | 2 +- .../objects/ProcessorAllocator.cc | 116 +++++++++++++++++ .../objects/ProcessorAllocator.hh | 119 ++---------------- .../objects/SchedulingContext.cc | 6 +- kernel/runtime/cxx/runtime/cxxsupport.cc | 9 +- kernel/runtime/process/runtime/process.hh | 2 +- 10 files changed, 150 insertions(+), 131 deletions(-) diff --git a/Makefile.user b/Makefile.user index b5691caf..56127727 100644 --- a/Makefile.user +++ b/Makefile.user @@ -10,7 +10,7 @@ CPPFLAGS+= -DMLOG_PORTAL=FilterError CPPFLAGS+= -DMLOG_SCHED=FilterError CPPFLAGS+= -DMLOG_SYSCALL=FilterError CPPFLAGS+= -DMLOG_TASKLET=FilterError -CPPFLAGS+= -DMLOG_PROCESSORMGMT=FilterAny +CPPFLAGS+= -DMLOG_PROCESSORMGMT=FilterWarning #CPPFLAGS+= -DTRACE #CPPFLAGS+= -DNDEBUG diff --git a/kernel/app/init-example/app/init.cc b/kernel/app/init-example/app/init.cc index 3a5c868f..d5544b7f 100644 --- a/kernel/app/init-example/app/init.cc +++ b/kernel/app/init-example/app/init.cc @@ -496,14 +496,20 @@ void test_CgaScreen(){ MLOG_INFO(mlog::app, "Test CGA finished"); } +void test_processor_allocator(){ + MLOG_INFO(mlog::app, "Test processor allocator"); + mythos::PortalLock pl(portal); + auto sc = pa.alloc(pl).wait(); + TEST(sc); + auto res = pa.free(pl, sc->cap).wait(); + TEST(res); + MLOG_INFO(mlog::app, "Test processor allocator finished"); +} + void test_process(){ MLOG_INFO(mlog::app, "Test process"); mythos::PortalLock pl(portal); - //auto sc = pa.alloc(pl).wait(); - //TEST(sc); - //auto res = pa.free(pl, sc->cap).wait(); - //TEST(res); Process p(&process_test_image_start); p.createProcess(pl); @@ -527,12 +533,11 @@ int main() //test_HostChannel(portal, 24*1024*1024, 2*1024*1024); test_ExecutionContext(); test_pthreads(); - //test_Rapl(); + //test_Rapl() + test_processor_allocator(); test_process(); //test_CgaScreen(); -#warning event test cases - char const end[] = "bye, cruel world!"; mythos::syscall_debug(end, sizeof(end)-1); diff --git a/kernel/boot/init-loader-amd64/boot/load_init.cc b/kernel/boot/init-loader-amd64/boot/load_init.cc index 7211df4b..508e659d 100644 --- a/kernel/boot/init-loader-amd64/boot/load_init.cc +++ b/kernel/boot/init-loader-amd64/boot/load_init.cc @@ -61,7 +61,7 @@ InitLoader::InitLoader(char* image) init::CAP_ALLOC_END-init::CAP_ALLOC_START) , memMapper(&capAlloc, mythos::init::KM) // default: no processor allocator present - , setSchedulingContexts(true) + , processorAllocatorPresent(false) , initSC(init::SCHEDULERS_START) { MLOG_INFO(mlog::boot, "found init application image at", (void*)image); @@ -163,7 +163,7 @@ optional InitLoader::initCSpace() if (!res) RETHROW(res); } - if(setSchedulingContexts){ + if(!processorAllocatorPresent){ ASSERT(cpu::getNumThreads() <= init::SCHEDULERS_START - init::APP_CAP_START); MLOG_INFO(mlog::boot, "... create scheduling context caps in caps", init::SCHEDULERS_START, "till", init::SCHEDULERS_START+cpu::getNumThreads()-1); diff --git a/kernel/boot/init-loader-amd64/boot/load_init.hh b/kernel/boot/init-loader-amd64/boot/load_init.hh index f6bd6648..c6f09195 100644 --- a/kernel/boot/init-loader-amd64/boot/load_init.hh +++ b/kernel/boot/init-loader-amd64/boot/load_init.hh @@ -80,7 +80,7 @@ namespace mythos { Portal* _portal; /* to be manipulated by optional processor allocator */ - bool setSchedulingContexts; + bool processorAllocatorPresent; CapPtr initSC; }; diff --git a/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh index 5986988b..1d0e6bbe 100644 --- a/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh +++ b/kernel/objects/processor-allocator/objects/PluginProcessorAllocator.hh @@ -44,7 +44,7 @@ namespace mythos { void processEvent(boot::InitLoader& loader) override { MLOG_DETAIL(mlog::pm, "prevent mapping of all scheduling contexts into CSpace"); - loader.setSchedulingContexts = false; + loader.processorAllocatorPresent = true; } }; diff --git a/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc index 0da7b420..40837ed5 100644 --- a/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc +++ b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc @@ -62,4 +62,120 @@ namespace mythos { } ); } +/* IResult */ + void ProcessorAllocator::response(Tasklet* /*t*/, optional res){ + MLOG_DETAIL(mlog::pm, "revoke response:", res.state()); + } + +/* ProcessorAllocator */ + ProcessorAllocator::ProcessorAllocator() + : sc(image2kernel(&mySC[0])) + {} + + void ProcessorAllocator::init(){ + MLOG_DETAIL(mlog::pm, "PM::init"); + for (cpu::ThreadID id = 0; id < cpu::getNumThreads(); ++id) { + sc[id].initRoot(Cap(image2kernel(&boot::getScheduler(id)))); + free(id); + } + } + + Error ProcessorAllocator::invokeAlloc(Tasklet*, Cap, IInvocation* msg){ + MLOG_DETAIL(mlog::pm, __func__); + auto id = alloc(); + + if(id){ + MLOG_DETAIL(mlog::pm, "allocated ", DVAR(*id)); + + auto data = msg->getMessage()->read(); + + optional dstEntry; + if(data.dstSpace() == null_cap){ // direct access + //dstEntry = msg->lookupEntry(data.dstPtr, 32, true); // lookup for write access + dstEntry = msg->lookupEntry(init::SCHEDULERS_START+*id, 32, true); // lookup for write access + if (!dstEntry){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstEntry!"); + free(*id); + return dstEntry.state(); + } + + }else{ // indirect access + TypedCap dstSpace(msg->lookupEntry(data.dstSpace())); + if (!dstSpace){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstSpace!"); + free(*id); + return dstSpace.state(); + } + + //auto dstEntryRef = dstSpace.lookup(data.dstPtr, data.dstDepth, true); // lookup for write + auto dstEntryRef = dstSpace.lookup(init::SCHEDULERS_START+*id, 32, true); // lookup for write + if (!dstEntryRef){ + MLOG_WARN(mlog::pm, "Warning: cannot find dstEntryRef!"); + free(*id); + return dstEntryRef.state(); + } + + dstEntry = dstEntryRef->entry; + } + + auto res = cap::reference(sc[*id], **dstEntry, sc[*id].cap()); + if(res){ + msg->getMessage()->write(init::SCHEDULERS_START+*id); + MLOG_DETAIL(mlog::pm, "map new sc ", DVAR(*id)); + }else{ + MLOG_WARN(mlog::pm, "Warning: cannot create SC entry!"); + free(*id); + msg->getMessage()->write(null_cap); + } + + }else{ + MLOG_WARN(mlog::pm, "allocation failed: no free cores available!"); + msg->getMessage()->write(null_cap); + } + return Error::SUCCESS; + } + + Error ProcessorAllocator::invokeFree(Tasklet* t, Cap, IInvocation* msg){ + MLOG_ERROR(mlog::pm, __func__, ": NYI!"); + //auto data = msg->getMessage()->cast(); + //ASSERT(data->sc() >= init::SCHEDULERS_START); + //cpu::ThreadID id = data->sc() - init::SCHEDULERS_START; + //ASSERT(id < cpu::getNumThreads()); + //MLOG_ERROR(mlog::pm, "free SC", DVAR(data->sc()), DVAR(id)); + //revokeOp._revoke(t, this, sc[id], this); + //MLOG_ERROR(mlog::pm, "free", DVAR(data->sc()), DVAR(id)); + //free(id); + //return Error::SUCCESS; + return Error::NOT_IMPLEMENTED; + } + + void ProcessorAllocator::freeSC(Tasklet* t, cpu::ThreadID id){ + MLOG_DETAIL(mlog::pm, "freeSC", DVAR(id)); + monitor.request(t, [=](Tasklet* t){ + MLOG_DETAIL(mlog::pm, "monitor free", DVAR(id)); + //todo: use IResult to call free(id) after cap is revoked + revokeOp._revoke(t, this, sc[id], this); + free(id); + } + ); + } + +/* LiFoProcessorAllocator */ + LiFoProcessorAllocator::LiFoProcessorAllocator() + : nFree(0) + {} + + optional LiFoProcessorAllocator::alloc(){ + optional ret; + if(nFree > 0){ + nFree--; + ret = freeList[nFree]; + } + return ret; + } + + void LiFoProcessorAllocator::free(cpu::ThreadID id) { + freeList[nFree] = id; + nFree++; + } } // namespace mythos diff --git a/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh b/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh index 4b54428a..d3fad13a 100644 --- a/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh +++ b/kernel/objects/processor-allocator/objects/ProcessorAllocator.hh @@ -41,9 +41,7 @@ class ProcessorAllocator , public IResult { public: - ProcessorAllocator() - : sc(image2kernel(&mySC[0])) - {} + ProcessorAllocator(); /* IKernelObject */ optional deleteCap(CapEntry&, Cap self, IDeleter& del) override; @@ -51,97 +49,12 @@ class ProcessorAllocator void invoke(Tasklet* t, Cap self, IInvocation* msg) override; /* IResult */ - void response(Tasklet* /*t*/, optional res) override{ - MLOG_INFO(mlog::pm, "revoke response:", res.state()); - } + void response(Tasklet* /*t*/, optional res) override; - void init(){ - MLOG_INFO(mlog::pm, "PM::init"); - for (cpu::ThreadID id = 0; id < cpu::getNumThreads(); ++id) { - sc[id].initRoot(Cap(image2kernel(&boot::getScheduler(id)))); - free(id); - } - } - - Error invokeAlloc(Tasklet*, Cap, IInvocation* msg){ - MLOG_DETAIL(mlog::pm, __func__); - auto id = alloc(); - - if(id){ - MLOG_DETAIL(mlog::pm, "allocated ", DVAR(*id)); - - auto data = msg->getMessage()->read(); - - optional dstEntry; - if(data.dstSpace() == null_cap){ // direct access - //dstEntry = msg->lookupEntry(data.dstPtr, 32, true); // lookup for write access - dstEntry = msg->lookupEntry(init::SCHEDULERS_START+*id, 32, true); // lookup for write access - if (!dstEntry){ - MLOG_WARN(mlog::pm, "Warning: cannot find dstEntry!"); - free(*id); - return dstEntry.state(); - } - - }else{ // indirect access - TypedCap dstSpace(msg->lookupEntry(data.dstSpace())); - if (!dstSpace){ - MLOG_WARN(mlog::pm, "Warning: cannot find dstSpace!"); - free(*id); - return dstSpace.state(); - } - - //auto dstEntryRef = dstSpace.lookup(data.dstPtr, data.dstDepth, true); // lookup for write - auto dstEntryRef = dstSpace.lookup(init::SCHEDULERS_START+*id, 32, true); // lookup for write - if (!dstEntryRef){ - MLOG_WARN(mlog::pm, "Warning: cannot find dstEntryRef!"); - free(*id); - return dstEntryRef.state(); - } - - dstEntry = dstEntryRef->entry; - } - - auto res = cap::reference(sc[*id], **dstEntry, sc[*id].cap()); - if(res){ - msg->getMessage()->write(init::SCHEDULERS_START+*id); - MLOG_DETAIL(mlog::pm, "map new sc ", DVAR(*id)); - }else{ - MLOG_WARN(mlog::pm, "Warning: cannot create SC entry!"); - free(*id); - msg->getMessage()->write(null_cap); - } - - }else{ - MLOG_DETAIL(mlog::pm, "allocation failed: no free cores available!"); - msg->getMessage()->write(null_cap); - } - return Error::SUCCESS; - } - - Error invokeFree(Tasklet* t, Cap, IInvocation* msg){ - MLOG_ERROR(mlog::pm, __func__, ": NYI!"); - //auto data = msg->getMessage()->cast(); - //ASSERT(data->sc() >= init::SCHEDULERS_START); - //cpu::ThreadID id = data->sc() - init::SCHEDULERS_START; - //ASSERT(id < cpu::getNumThreads()); - //MLOG_ERROR(mlog::pm, "free SC", DVAR(data->sc()), DVAR(id)); - //revokeOp._revoke(t, this, sc[id], this); - //MLOG_ERROR(mlog::pm, "free", DVAR(data->sc()), DVAR(id)); - //free(id); - //return Error::SUCCESS; - return Error::NOT_IMPLEMENTED; - } - - void freeSC(Tasklet* t, cpu::ThreadID id){ - MLOG_ERROR(mlog::pm, "freeSC", DVAR(id)); - monitor.request(t, [=](Tasklet* t){ - MLOG_ERROR(mlog::pm, "monitor free", DVAR(id)); - //todo: use IResult to call free(id) after cap is revoked - revokeOp._revoke(t, this, sc[id], this); - free(id); - } - ); - } + void init(); + Error invokeAlloc(Tasklet*, Cap, IInvocation* msg); + Error invokeFree(Tasklet* t, Cap, IInvocation* msg); + void freeSC(Tasklet* t, cpu::ThreadID id); protected: friend class PluginProcessorAllocator; @@ -159,29 +72,15 @@ class ProcessorAllocator class LiFoProcessorAllocator : public ProcessorAllocator { public: - LiFoProcessorAllocator() - : nFree(0) - {} + LiFoProcessorAllocator(); - optional alloc() override { - optional ret; - if(nFree > 0){ - nFree--; - ret = freeList[nFree]; - } - return ret; - } - unsigned numFree() override { return nFree; } + optional alloc() override; + void free(cpu::ThreadID id) override; - void free(cpu::ThreadID id) override { - freeList[nFree] = id; - nFree++; - } private: unsigned nFree; cpu::ThreadID freeList[MYTHOS_MAX_THREADS]; - }; } // namespace mythos diff --git a/kernel/objects/scheduling-context/objects/SchedulingContext.cc b/kernel/objects/scheduling-context/objects/SchedulingContext.cc index 2a1a9358..8835a3d5 100644 --- a/kernel/objects/scheduling-context/objects/SchedulingContext.cc +++ b/kernel/objects/scheduling-context/objects/SchedulingContext.cc @@ -41,14 +41,14 @@ namespace mythos { void SchedulingContext::unbind(handle_t* ec) { ASSERT(ec != nullptr); - MLOG_ERROR(mlog::sched, "unbind", DVAR(ec->get())); + MLOG_INFO(mlog::sched, "unbind", DVAR(ec->get())); readyQueue.remove(ec); current_handle.store(nullptr); if(readyQueue.empty()){ - MLOG_ERROR(mlog::sched, "call freeSC"); + MLOG_DETAIL(mlog::sched, "call freeSC"); pluginProcessorAllocator.pa.freeSC(&paTask, home->getThreadID()); }else{ - MLOG_ERROR(mlog::sched, "ready queue not empty!"); + MLOG_INFO(mlog::sched, "ready queue not empty!"); } } diff --git a/kernel/runtime/cxx/runtime/cxxsupport.cc b/kernel/runtime/cxx/runtime/cxxsupport.cc index da5da9d5..ee0318ab 100644 --- a/kernel/runtime/cxx/runtime/cxxsupport.cc +++ b/kernel/runtime/cxx/runtime/cxxsupport.cc @@ -215,7 +215,7 @@ extern "C" long mythos_musl_syscall( MLOG_WARN(mlog::app, "syscall getpid NYI"); return 0; case 60: // exit(exit_code) - MLOG_ERROR(mlog::app, "syscall exit", DVAR(a1)); + //MLOG_ERROR(mlog::app, "syscall exit", DVAR(a1)); pthreadCleanerSemphore.exit(); asm volatile ("syscall" : : "D"(0), "S"(a1) : "memory"); return 0; @@ -288,7 +288,8 @@ extern "C" int munmap(void *start, size_t len) extern "C" int unmapself(void *start, size_t len) { // dummy implementation - MLOG_DETAIL(mlog::app, "unmapself"); + MLOG_ERROR(mlog::app, "unmapself: NYI!"); + ASSERT(0); while(1); return 0; } @@ -356,12 +357,10 @@ extern "C" int clone(int (*func)(void *), void *stack, int flags, void *arg, ... } extern "C" void mythos_pthread_cleanup(pthread_t t){ - MLOG_ERROR(mlog::app, "mythos_pthread_cleanup", mythos_get_pthread_ec(t)); + MLOG_DETAIL(mlog::app, "mythos_pthread_cleanup", mythos_get_pthread_ec(t)); pthreadCleanerSemphore.wait(t); auto cap = mythos_get_pthread_ec(t); mythos::PortalLock pl(portal); - //mythos::ExecutionContext ec(cap); - //ec.suspend(pl).wait(); capAlloc.free(cap, pl); } diff --git a/kernel/runtime/process/runtime/process.hh b/kernel/runtime/process/runtime/process.hh index dfff815c..fe256151 100644 --- a/kernel/runtime/process/runtime/process.hh +++ b/kernel/runtime/process/runtime/process.hh @@ -168,8 +168,8 @@ class Process{ TEST(res); MLOG_DETAIL(mlog::app, " Interrupt control"); + MLOG_WARN(mlog::app, "SKIP: Interrupt control caps!"); //todo: how to check whether cap is existing? -#warning Process:createProcess do not copy Interrupt Controls //for(CapPtr ptr = init::INTERRUPT_CONTROL_START; ptr < init::INTERRUPT_CONTROL_END; ptr++){ //res = myCS.reference(pl, ptr, max_cap_depth, cs.cap(), ptr, max_cap_depth, 0).wait(); //TEST(res); From c674de1a7da7d7943f741e6828a24dd61ccf9420 Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Sat, 2 Jan 2021 12:41:52 +0100 Subject: [PATCH 6/9] removed warning --- .../objects/processor-allocator/objects/ProcessorAllocator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc index 40837ed5..b0e437f5 100644 --- a/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc +++ b/kernel/objects/processor-allocator/objects/ProcessorAllocator.cc @@ -135,7 +135,7 @@ namespace mythos { return Error::SUCCESS; } - Error ProcessorAllocator::invokeFree(Tasklet* t, Cap, IInvocation* msg){ + Error ProcessorAllocator::invokeFree(Tasklet* /*t*/, Cap, IInvocation* /*msg*/){ MLOG_ERROR(mlog::pm, __func__, ": NYI!"); //auto data = msg->getMessage()->cast(); //ASSERT(data->sc() >= init::SCHEDULERS_START); From 8b2aaeb20e0fc962811bedeb47c103eae00e2f0a Mon Sep 17 00:00:00 2001 From: Philipp Gypser Date: Sat, 2 Jan 2021 20:25:52 +0100 Subject: [PATCH 7/9] Info Frame --- kernel/app/init-example/app/init.cc | 13 ++-- .../process_test/process_test/process_test.cc | 6 +- .../boot/init-loader-amd64/boot/load_init.cc | 41 +++++++++--- .../boot/init-loader-amd64/boot/load_init.hh | 5 +- .../boot/kernel-amd64-ihk/boot/ihk-entry.cc | 12 +++- kernel/mythos/infoFrame/mcconf.module | 3 + kernel/mythos/infoFrame/mythos/InfoFrame.hh | 51 +++++++++++++++ kernel/mythos/init/mythos/init.hh | 1 + kernel/runtime/crt-init/runtime/start.S | 4 +- kernel/runtime/cxx/runtime/cxxsupport.cc | 20 +++--- kernel/runtime/memory/runtime/tls.cc | 5 +- kernel/runtime/process/runtime/process.hh | 63 +++++++++++++++++-- kernel/util/events/util/events.hh | 4 +- 13 files changed, 184 insertions(+), 44 deletions(-) create mode 100644 kernel/mythos/infoFrame/mcconf.module create mode 100644 kernel/mythos/infoFrame/mythos/InfoFrame.hh diff --git a/kernel/app/init-example/app/init.cc b/kernel/app/init-example/app/init.cc index d5544b7f..2e834cdc 100644 --- a/kernel/app/init-example/app/init.cc +++ b/kernel/app/init-example/app/init.cc @@ -28,6 +28,7 @@ #include "mythos/invocation.hh" #include "mythos/protocol/CpuDriverKNC.hh" #include "mythos/PciMsgQueueMPSC.hh" +#include "mythos/InfoFrame.hh" #include "runtime/Portal.hh" #include "runtime/ExecutionContext.hh" #include "runtime/CapMap.hh" @@ -57,7 +58,7 @@ #include -mythos::InvocationBuf* msg_ptr asm("msg_ptr"); +mythos::InfoFrame* info_ptr asm("info_ptr"); int main() asm("main"); extern char process_test_image_start SYMBOL("process_test_image_start"); @@ -66,7 +67,7 @@ constexpr uint64_t stacksize = 4*4096; char initstack[stacksize]; char* initstack_top = initstack+stacksize; -mythos::Portal portal(mythos::init::PORTAL, msg_ptr); +mythos::Portal portal(mythos::init::PORTAL, info_ptr->getInvocationBuf()); mythos::CapMap myCS(mythos::init::CSPACE); mythos::PageMap myAS(mythos::init::PML4); mythos::KernelMemory kmem(mythos::init::KM); @@ -105,7 +106,7 @@ void test_Portal() MLOG_ERROR(mlog::app, "test_Portal begin"); mythos::PortalLock pl(portal); // future access will fail if the portal is in use already MLOG_INFO(mlog::app, "test_Portal: allocate portal"); - uintptr_t vaddr = mythos::round_up(uintptr_t(msg_ptr) + 1, mythos::align2M); + uintptr_t vaddr = mythos::round_up(info_ptr->getInfoEnd(), mythos::align2M); // allocate a portal mythos::Portal p2(capAlloc(), (void*)vaddr); auto res1 = p2.create(pl, kmem).wait(); @@ -206,7 +207,7 @@ void test_heap() { mythos::PortalLock pl(portal); auto size = 4*1024*1024; // 2 MB auto align = 2*1024*1024; // 2 MB - uintptr_t vaddr = mythos::round_up(uintptr_t(msg_ptr) + 1, align); + uintptr_t vaddr = mythos::round_up(info_ptr->getInfoEnd() + align2M, align2M); // allocate a 2MiB frame mythos::Frame f(capAlloc()); auto res2 = f.create(pl, kmem, size, align).wait(); @@ -521,7 +522,7 @@ int main() { char const str[] = "Hello world!"; mythos::syscall_debug(str, sizeof(str)-1); - MLOG_ERROR(mlog::app, "application is starting :)", DVARhex(msg_ptr), DVARhex(initstack_top)); + MLOG_ERROR(mlog::app, "application is starting :)", DVARhex(info_ptr), DVARhex(initstack_top)); test_float(); test_Example(); @@ -533,7 +534,7 @@ int main() //test_HostChannel(portal, 24*1024*1024, 2*1024*1024); test_ExecutionContext(); test_pthreads(); - //test_Rapl() + test_Rapl(); test_processor_allocator(); test_process(); //test_CgaScreen(); diff --git a/kernel/app/process_test/process_test/process_test.cc b/kernel/app/process_test/process_test/process_test.cc index 4077a36b..1a23ffa0 100644 --- a/kernel/app/process_test/process_test/process_test.cc +++ b/kernel/app/process_test/process_test/process_test.cc @@ -26,6 +26,7 @@ #include "mythos/init.hh" #include "mythos/invocation.hh" +#include "mythos/InfoFrame.hh" #include "runtime/Portal.hh" #include "runtime/ExecutionContext.hh" #include "runtime/CapMap.hh" @@ -44,14 +45,14 @@ #include "runtime/Mutex.hh" -mythos::InvocationBuf* msg_ptr asm("msg_ptr"); +mythos::InfoFrame* info_ptr asm("info_ptr"); int main() asm("main"); constexpr uint64_t stacksize = 4*4096; char initstack[stacksize]; char* initstack_top = initstack+stacksize; -mythos::Portal portal(mythos::init::PORTAL, msg_ptr); +mythos::Portal portal(mythos::init::PORTAL, info_ptr->getInvocationBuf()); mythos::CapMap myCS(mythos::init::CSPACE); mythos::PageMap myAS(mythos::init::PML4); mythos::KernelMemory kmem(mythos::init::KM); @@ -65,6 +66,7 @@ mythos::ProcessorAllocator pa(mythos::init::PROCESSOR_ALLOCATOR); int main() { MLOG_ERROR(mlog::app, "New process started :)"); + MLOG_INFO(mlog::app, "info frame", DVARhex(info_ptr), DVAR(info_ptr->getNumThreads()), DVAR(info_ptr->getPsPerTSC())); return 0; } diff --git a/kernel/boot/init-loader-amd64/boot/load_init.cc b/kernel/boot/init-loader-amd64/boot/load_init.cc index 508e659d..4dbc9c75 100644 --- a/kernel/boot/init-loader-amd64/boot/load_init.cc +++ b/kernel/boot/init-loader-amd64/boot/load_init.cc @@ -44,12 +44,14 @@ #include "boot/mlog.hh" #include "boot/memory-root.hh" #include "boot/DeployHWThread.hh" +#include "mythos/InfoFrame.hh" namespace mythos { Event event::initLoader; Event event::initLoaderEarly; +Event event::initInfoFrame; namespace boot { @@ -80,8 +82,10 @@ optional InitLoader::load() if (res) res = initCSpace(); auto ipc_vaddr = loadImage(); res = ipc_vaddr; - if (res) MLOG_INFO(mlog::boot, "init invokation buffer", DVARhex(*ipc_vaddr)); - if (res) res = createPortal(*ipc_vaddr, init::PORTAL); + if (res) MLOG_INFO(mlog::boot, "init info frame/invokation buffer", DVARhex(*ipc_vaddr)); + auto infoFramePtr = createInfoFrame(*ipc_vaddr); + res = infoFramePtr; + if (res) res = createPortal(*infoFramePtr, init::PORTAL); if (res) res = createEC(*ipc_vaddr); RETURN(res); } @@ -186,19 +190,36 @@ optional InitLoader::initCSpace() RETURN(Error::SUCCESS); } -optional InitLoader::createPortal(uintptr_t ipc_vaddr, CapPtr dstPortal) +optional InitLoader::createInfoFrame(uintptr_t ipc_vaddr) +{ + auto size = round_up(sizeof(InfoFrame), align2M); + MLOG_INFO(mlog::boot, "... create info frame"); + auto frameCap = memMapper.createFrame(init::INFO_FRAME, size, align2M); + if (!frameCap) RETHROW(frameCap); + MLOG_INFO(mlog::boot, "... map info frame", + DVAR(*frameCap), DVARhex(ipc_vaddr)); + memMapper.mmap(ipc_vaddr, size, true, false, *frameCap, 0); + + auto frameEntry = capAlloc.get(*frameCap); + if (!frameEntry) RETHROW(frameEntry); + TypedCap