diff --git a/base-codezero/src/core/include/platform_thread.h b/base-codezero/src/core/include/platform_thread.h index e46554b08..f9c8cf27c 100644 --- a/base-codezero/src/core/include/platform_thread.h +++ b/base-codezero/src/core/include/platform_thread.h @@ -134,12 +134,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu); + void affinity(Affinity::Location) { } /** * Get the executing CPU for this thread */ - unsigned affinity(); + Affinity::Location affinity() { return Affinity::Location(); } /** * Get thread name diff --git a/base-codezero/src/core/platform_thread.cc b/base-codezero/src/core/platform_thread.cc index a09ef3142..b4e377784 100644 --- a/base-codezero/src/core/platform_thread.cc +++ b/base-codezero/src/core/platform_thread.cc @@ -27,19 +27,6 @@ using namespace Genode; using namespace Codezero; -void Platform_thread::affinity(unsigned int cpu_no) -{ - PDBG("'%s' not yet implemented", __PRETTY_FUNCTION__); -} - - -unsigned Platform_thread::affinity() -{ - PDBG("'%s' not yet implemented", __PRETTY_FUNCTION__); - return 0; -} - - int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) { Native_thread_id pager = _pager ? _pager->cap().dst() : THREAD_INVALID; diff --git a/base-fiasco/src/core/include/platform_thread.h b/base-fiasco/src/core/include/platform_thread.h index 742d46a29..762d1f9f6 100644 --- a/base-fiasco/src/core/include/platform_thread.h +++ b/base-fiasco/src/core/include/platform_thread.h @@ -121,12 +121,12 @@ namespace Genode { * * SMP is not supported on L4/Fiasco. */ - void affinity(unsigned) { } + void affinity(Affinity::Location) { } /** * Request the affinity of this thread */ - unsigned affinity() { return 0; } + Affinity::Location affinity() { return Affinity::Location(); } /** * Return the address space to which the thread is bound diff --git a/base-fiasco/src/core/platform.cc b/base-fiasco/src/core/platform.cc index 41dfca0e5..53105239e 100644 --- a/base-fiasco/src/core/platform.cc +++ b/base-fiasco/src/core/platform.cc @@ -130,7 +130,7 @@ static void _core_pager_loop() } -Platform::Sigma0::Sigma0() : Pager_object(0, 0) +Platform::Sigma0::Sigma0() : Pager_object(0, Affinity::Location()) { cap(reinterpret_cap_cast(Native_capability(Fiasco::sigma0_threadid, 0))); } @@ -145,7 +145,7 @@ Platform::Sigma0 *Platform::sigma0() Platform::Core_pager::Core_pager(Platform_pd *core_pd) : - Platform_thread("core.pager"), Pager_object(0, 0) + Platform_thread("core.pager"), Pager_object(0, Affinity::Location()) { Platform_thread::pager(sigma0()); diff --git a/base-foc/include/foc_cpu_session/client.h b/base-foc/include/foc_cpu_session/client.h index f59275a10..7b93eeb5e 100644 --- a/base-foc/include/foc_cpu_session/client.h +++ b/base-foc/include/foc_cpu_session/client.h @@ -67,11 +67,11 @@ namespace Genode { void single_step(Thread_capability thread, bool enable) { call(thread, enable); } - unsigned num_cpus() const { - return call(); } + Affinity::Space affinity_space() const { + return call(); } - void affinity(Thread_capability thread, unsigned cpu) { - call(thread, cpu); } + void affinity(Thread_capability thread, Affinity::Location location) { + call(thread, location); } void enable_vcpu(Thread_capability cap, addr_t vcpu_state) { call(cap, vcpu_state); } diff --git a/base-foc/src/core/include/cpu_session_component.h b/base-foc/src/core/include/cpu_session_component.h index ac4d9e13e..28a650a76 100644 --- a/base-foc/src/core/include/cpu_session_component.h +++ b/base-foc/src/core/include/cpu_session_component.h @@ -159,8 +159,8 @@ namespace Genode { Thread_state state(Thread_capability); void state(Thread_capability, Thread_state const &); void exception_handler(Thread_capability, Signal_context_capability); - unsigned num_cpus() const; - void affinity(Thread_capability, unsigned); + Affinity::Space affinity_space() const; + void affinity(Thread_capability, Affinity::Location); /*********************************** diff --git a/base-foc/src/core/include/platform.h b/base-foc/src/core/include/platform.h index b62ecf4d7..516e664c6 100644 --- a/base-foc/src/core/include/platform.h +++ b/base-foc/src/core/include/platform.h @@ -159,7 +159,7 @@ namespace Genode { addr_t vm_start() const { return _vm_start; } size_t vm_size() const { return _vm_size; } Rom_fs *rom_fs() { return &_rom_fs; } - unsigned num_cpus() const; + Affinity::Space affinity_space() const; void wait_for_exit(); }; diff --git a/base-foc/src/core/include/platform_thread.h b/base-foc/src/core/include/platform_thread.h index 273d4ad00..a4e407417 100644 --- a/base-foc/src/core/include/platform_thread.h +++ b/base-foc/src/core/include/platform_thread.h @@ -37,20 +37,22 @@ namespace Genode { friend class Platform_pd; - State _state; - bool _core_thread; - Cap_mapping _thread; - Cap_mapping _gate; - Cap_mapping _pager; - Cap_mapping _irq; - Native_utcb _utcb; - char _name[32]; /* thread name that will be - registered at the kernel - debugger */ - Platform_pd *_platform_pd; /* protection domain thread - is bound to */ - Pager_object *_pager_obj; - unsigned _prio; + State _state; + bool _core_thread; + Cap_mapping _thread; + Cap_mapping _gate; + Cap_mapping _pager; + Cap_mapping _irq; + Native_utcb _utcb; + char _name[32]; /* thread name that will be + registered at the kernel + debugger */ + Platform_pd *_platform_pd; /* protection domain thread + is bound to */ + Pager_object *_pager_obj; + unsigned _prio; + + Affinity::Location _location; void _create_thread(void); void _finalize_construction(const char *name); @@ -136,12 +138,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu); + void affinity(Affinity::Location location); /** * Get the executing CPU for this thread */ - unsigned affinity(); + Affinity::Location affinity(); /** * Return the address space to which the thread is bound diff --git a/base-foc/src/core/platform.cc b/base-foc/src/core/platform.cc index 2e2db6d98..2a6acfbd1 100644 --- a/base-foc/src/core/platform.cc +++ b/base-foc/src/core/platform.cc @@ -121,7 +121,7 @@ static void _core_pager_loop() } -Platform::Sigma0::Sigma0(Cap_index* i) : Pager_object(0, 0) +Platform::Sigma0::Sigma0(Cap_index* i) : Pager_object(0, Affinity::Location()) { /* * We use the Pager_object here in a slightly different manner, @@ -132,7 +132,7 @@ Platform::Sigma0::Sigma0(Cap_index* i) : Pager_object(0, 0) Platform::Core_pager::Core_pager(Platform_pd *core_pd, Sigma0 *sigma0) -: Platform_thread("core.pager"), Pager_object(0, 0) +: Platform_thread("core.pager"), Pager_object(0, Affinity::Location()) { Platform_thread::pager(sigma0); @@ -512,11 +512,11 @@ void Platform::wait_for_exit() } -unsigned Platform::num_cpus() const { - +Affinity::Space Platform::affinity_space() const +{ using namespace Genode; using namespace Fiasco; - + l4_sched_cpu_set_t cpus = l4_sched_cpu_set(0, 0, 1); l4_umword_t cpus_max; l4_msgtag_t res = l4_scheduler_info(L4_BASE_SCHEDULER_CAP, &cpus_max, @@ -530,8 +530,12 @@ unsigned Platform::num_cpus() const { for (unsigned i = 0; i < sizeof(cpus.map) * 8; i++) if ((cpus.map >> i) & 0x1) cpus_online ++; - - return cpus_online; + + /* + * Currently, we do not gather any information about the topology of CPU + * nodes but just return a one-dimensional affinity space. + */ + return Affinity::Space(cpus_online, 1); } diff --git a/base-foc/src/core/platform_thread.cc b/base-foc/src/core/platform_thread.cc index 6e793b66f..ae7cc527e 100644 --- a/base-foc/src/core/platform_thread.cc +++ b/base-foc/src/core/platform_thread.cc @@ -198,8 +198,12 @@ void Platform_thread::cancel_blocking() } -void Platform_thread::affinity(unsigned cpu) +void Platform_thread::affinity(Affinity::Location location) { + _location = location; + + int const cpu = location.xpos(); + l4_sched_param_t params = l4_sched_param(_prio); params.affinity = l4_sched_cpu_set(cpu, 0, 1); l4_msgtag_t tag = l4_scheduler_run_thread(L4_BASE_SCHEDULER_CAP, @@ -209,10 +213,9 @@ void Platform_thread::affinity(unsigned cpu) } -unsigned Platform_thread::affinity() +Affinity::Location Platform_thread::affinity() { - PERR("'%s' not yet implemented", __PRETTY_FUNCTION__); - return 0; + return _location; } diff --git a/base-hw/src/core/include/platform_thread.h b/base-hw/src/core/include/platform_thread.h index a8246052e..aa0e9bcdd 100644 --- a/base-hw/src/core/include/platform_thread.h +++ b/base-hw/src/core/include/platform_thread.h @@ -151,18 +151,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu) { - kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; }; + void affinity(Affinity::Location) { } /** * Get the executing CPU for this thread */ - unsigned affinity() - { - kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; - return 0; - }; - + Affinity::Location affinity() { return Affinity::Location(); }; /** * Return the address space to which the thread is bound diff --git a/base-linux/include/linux_cpu_session/client.h b/base-linux/include/linux_cpu_session/client.h index f81d53370..f6e61cd8a 100644 --- a/base-linux/include/linux_cpu_session/client.h +++ b/base-linux/include/linux_cpu_session/client.h @@ -60,11 +60,11 @@ namespace Genode { void single_step(Thread_capability thread, bool enable) { call(thread, enable); } - unsigned num_cpus() const { - return call(); } + Affinity::Space affinity_space() const { + return call(); } - void affinity(Thread_capability thread, unsigned cpu) { - call(thread, cpu); } + void affinity(Thread_capability thread, Affinity::Location location) { + call(thread, location); } /***************************** diff --git a/base-linux/src/core/include/cpu_session_component.h b/base-linux/src/core/include/cpu_session_component.h index 789c8ea62..015ab6d80 100644 --- a/base-linux/src/core/include/cpu_session_component.h +++ b/base-linux/src/core/include/cpu_session_component.h @@ -150,8 +150,8 @@ namespace Genode { Thread_state state(Thread_capability); void state(Thread_capability, Thread_state const &); void exception_handler(Thread_capability, Signal_context_capability); - unsigned num_cpus() const; - void affinity(Thread_capability, unsigned); + Affinity::Space affinity_space() const; + void affinity(Thread_capability, Affinity::Location); /******************************* diff --git a/base-linux/src/core/include/platform_thread.h b/base-linux/src/core/include/platform_thread.h index 7c2b4c5f2..4b2d1cd73 100644 --- a/base-linux/src/core/include/platform_thread.h +++ b/base-linux/src/core/include/platform_thread.h @@ -114,7 +114,7 @@ namespace Genode { } const char *name() { return _name; } - void affinity(unsigned) { } + void affinity(Affinity::Location) { } /** * Register process ID and thread ID of thread diff --git a/base-nova/include/base/pager.h b/base-nova/include/base/pager.h index f589306f3..fe1163e45 100644 --- a/base-nova/include/base/pager.h +++ b/base-nova/include/base/pager.h @@ -81,7 +81,7 @@ namespace Genode { static Nova::Utcb * _check_handler(Thread_base *&, Pager_object *&); public: - Pager_object(unsigned long badge, unsigned affinity); + Pager_object(unsigned long badge, Affinity::Location location); virtual ~Pager_object(); diff --git a/base-nova/include/cpu_session/client.h b/base-nova/include/cpu_session/client.h index 4c1e6e669..50d7423a5 100644 --- a/base-nova/include/cpu_session/client.h +++ b/base-nova/include/cpu_session/client.h @@ -76,17 +76,16 @@ namespace Genode { Native_capability native_cap(Thread_capability cap) { return call(cap); } - unsigned num_cpus() const { - return call(); } + Affinity::Space affinity_space() const { + return call(); } - void affinity(Thread_capability thread, unsigned cpu) { - call(thread, cpu); } + void affinity(Thread_capability thread, Affinity::Location location) { + call(thread, location); } private: - Native_capability pause_sync(Thread_capability target) { - return Native_capability::invalid_cap(); } - + Native_capability pause_sync(Thread_capability target) { + return Native_capability::invalid_cap(); } }; } diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 2d005d74b..3159db1ab 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -261,7 +261,7 @@ static uint8_t create_portal(addr_t pt, addr_t pd, addr_t ec, Mtd mtd, return res; } -Pager_object::Pager_object(unsigned long badge, unsigned affinity) +Pager_object::Pager_object(unsigned long badge, Affinity::Location location) : Thread_base("pager:", PF_HANDLER_STACK_SIZE), _badge(badge) { class Create_exception_pt_failed { }; @@ -280,7 +280,8 @@ Pager_object::Pager_object(unsigned long badge, unsigned affinity) _state.sel_client_ec = Native_thread::INVALID_INDEX; /* tell thread starting code on which CPU to let run the pager */ - *reinterpret_cast(stack_top()) = affinity; + reinterpret_cast(stack_top())[-1] = location; + /* creates local EC */ Thread_base::start(); diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index 26e3cacb5..a4aa0a4b2 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -199,7 +199,7 @@ void Rpc_entrypoint::activate() Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, const char *name, bool start_on_construction, - unsigned affinity) + Affinity::Location location) : Thread_base(name, stack_size), _curr_obj(start_on_construction ? 0 : (Rpc_object_base *)~0UL), @@ -222,9 +222,9 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, if (env()->cpu_session()->set_pager(_thread_cap, _pager_cap)) throw Cpu_session::Thread_creation_failed(); - /* place new thread on the specified CPU - ~0UL means default CPU */ - if (affinity != ~0UL) - env()->cpu_session()->affinity(_thread_cap, affinity); + /* place new thread on the specified CPU, if specified */ + if (location.valid()) + env()->cpu_session()->affinity(_thread_cap, location); addr_t thread_sp = (addr_t)&_context->stack[-4]; @@ -260,7 +260,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, } else { /* tell thread starting code to use a specific CPU */ - *reinterpret_cast(stack_top()) = affinity; + reinterpret_cast(stack_top())[-1] = location; /* * Required for core threads (creates local EC) diff --git a/base-nova/src/core/include/cpu_session_component.h b/base-nova/src/core/include/cpu_session_component.h index 5d33e743c..8d2f2d9f0 100644 --- a/base-nova/src/core/include/cpu_session_component.h +++ b/base-nova/src/core/include/cpu_session_component.h @@ -156,8 +156,8 @@ namespace Genode { Thread_state state(Thread_capability); void state(Thread_capability, Thread_state const &); void exception_handler(Thread_capability, Signal_context_capability); - unsigned num_cpus() const; - void affinity(Thread_capability, unsigned); + Affinity::Space affinity_space() const; + void affinity(Thread_capability, Affinity::Location); /****************************** diff --git a/base-nova/src/core/include/platform.h b/base-nova/src/core/include/platform.h index 17c308b05..676b45064 100644 --- a/base-nova/src/core/include/platform.h +++ b/base-nova/src/core/include/platform.h @@ -43,7 +43,7 @@ namespace Genode { size_t _vm_size; /* available CPUs */ - unsigned _cpus; + Affinity::Space _cpus; addr_t _map_page(addr_t const phys_page, addr_t const pages, bool const extra_page); @@ -74,7 +74,8 @@ namespace Genode { void wait_for_exit(); bool supports_unmap() { return true; } - unsigned num_cpus() const { return _cpus; } + + Affinity::Space affinity_space() const { return _cpus; } /******************* diff --git a/base-nova/src/core/include/platform_thread.h b/base-nova/src/core/include/platform_thread.h index 5a1212409..16ea70215 100644 --- a/base-nova/src/core/include/platform_thread.h +++ b/base-nova/src/core/include/platform_thread.h @@ -32,17 +32,17 @@ namespace Genode { { private: - Platform_pd *_pd; - Pager_object *_pager; - addr_t _id_base; - addr_t _sel_exc_base; - unsigned _cpu_no; - bool _is_main_thread; - bool _is_vcpu; - char _name[Thread_base::Context::NAME_LEN]; + Platform_pd *_pd; + Pager_object *_pager; + addr_t _id_base; + addr_t _sel_exc_base; + Affinity::Location _location; + bool _is_main_thread; + bool _is_vcpu; + char _name[Thread_base::Context::NAME_LEN]; - addr_t _sel_ec() { return _id_base; } - addr_t _sel_sc() { return _id_base + 1; } + addr_t _sel_ec() const { return _id_base; } + addr_t _sel_sc() const { return _id_base + 1; } public: @@ -129,12 +129,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu); + void affinity(Affinity::Location location); /** * Get the executing CPU for this thread */ - unsigned affinity(); + Affinity::Location affinity(); /** * Get thread name diff --git a/base-nova/src/core/platform.cc b/base-nova/src/core/platform.cc index 21450f97f..2917588b7 100644 --- a/base-nova/src/core/platform.cc +++ b/base-nova/src/core/platform.cc @@ -287,15 +287,23 @@ static void init_core_page_fault_handler() Platform::Platform() : _io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()), _irq_alloc(core_mem_alloc()), - _vm_base(0x1000), _vm_size(0), _cpus(1) + _vm_base(0x1000), _vm_size(0), _cpus(Affinity::Space(1,1)) { Hip *hip = (Hip *)__initial_sp; /* check for right API version */ if (hip->api_version != 6) nova_die(); - /* determine number of available CPUs */ - _cpus = hip->cpus(); + /* + * Determine number of available CPUs + * + * XXX As of now, we assume a one-dimensional affinity space, ignoring + * the y component of the affinity location. When adding support + * for two-dimensional affinity spaces, look out and adjust the use of + * 'Platform_thread::_location' in 'platform_thread.cc'. Also look + * at the 'Thread_base::start' function in core/thread_start.cc. + */ + _cpus = Affinity::Space(hip->cpus(), 1); /* register UTCB of main thread */ __main_thread_utcb = (Utcb *)(__initial_sp - get_page_size()); @@ -339,8 +347,8 @@ Platform::Platform() : if (verbose_boot_info) { printf("Hypervisor %s VMX\n", hip->has_feature_vmx() ? "features" : "does not feature"); printf("Hypervisor %s SVM\n", hip->has_feature_svm() ? "features" : "does not feature"); - printf("Hypervisor reports %u CPU%c - boot CPU is %lu\n", - _cpus, _cpus > 1 ? 's' : ' ', boot_cpu()); + printf("Hypervisor reports %ux%u CPU%c - boot CPU is %lu\n", + _cpus.width(), _cpus.height(), _cpus.total() > 1 ? 's' : ' ', boot_cpu()); } /* initialize core allocators */ diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index f0dc2d049..7c1087446 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -35,18 +35,18 @@ using namespace Genode; ** Platform thread ** *********************/ -void Platform_thread::affinity(unsigned int cpu_no) +void Platform_thread::affinity(Affinity::Location location) { if (_sel_exc_base != Native_thread::INVALID_INDEX) { PERR("Failure - affinity of thread could not be set"); return; } - _cpu_no = cpu_no; + _location = location; } -unsigned Platform_thread::affinity() { return _cpu_no; } +Affinity::Location Platform_thread::affinity() { return _location; } int Platform_thread::start(void *ip, void *sp) @@ -88,7 +88,7 @@ int Platform_thread::start(void *ip, void *sp) /* ip == 0 means that caller will use the thread as worker */ bool thread_global = ip; - res = create_ec(_sel_ec(), _pd->pd_sel(), _cpu_no, utcb, + res = create_ec(_sel_ec(), _pd->pd_sel(), _location.xpos(), utcb, initial_sp, _sel_exc_base, thread_global); if (res != Nova::NOVA_OK) { revoke(Obj_crd(sm, 0)); @@ -182,7 +182,7 @@ int Platform_thread::start(void *ip, void *sp) /* create first thread in task */ enum { THREAD_GLOBAL = true }; - res = create_ec(_sel_ec(), pd_sel, _cpu_no, pd_utcb, 0, 0, + res = create_ec(_sel_ec(), pd_sel, _location.xpos(), pd_utcb, 0, 0, THREAD_GLOBAL); if (res != NOVA_OK) { PERR("create_ec returned %d", res); @@ -326,7 +326,7 @@ Weak_ptr Platform_thread::address_space() Platform_thread::Platform_thread(const char *name, unsigned, int thread_id) : _pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)), - _sel_exc_base(Native_thread::INVALID_INDEX), _cpu_no(boot_cpu()), + _sel_exc_base(Native_thread::INVALID_INDEX), _location(boot_cpu(), 0), _is_main_thread(false), _is_vcpu(false) { strncpy(_name, name, sizeof(_name)); diff --git a/base-nova/src/core/thread_start.cc b/base-nova/src/core/thread_start.cc index a5a50f401..edddb9781 100644 --- a/base-nova/src/core/thread_start.cc +++ b/base-nova/src/core/thread_start.cc @@ -77,20 +77,20 @@ void Thread_base::start() */ using namespace Nova; - addr_t sp = reinterpret_cast(&_context->stack[-4]); - sp &= ~0xf; /* align initial stack to 16 byte boundary */ - addr_t utcb = reinterpret_cast(&_context->utcb); - Utcb * utcb_obj = reinterpret_cast(&_context->utcb); - addr_t pd_sel = Platform_pd::pd_core_sel(); - addr_t cpu_no = *reinterpret_cast(stack_top()); + addr_t sp = reinterpret_cast(&_context->stack[-4]); + sp &= ~0xf; /* align initial stack to 16 byte boundary */ + addr_t utcb = reinterpret_cast(&_context->utcb); + Utcb * utcb_obj = reinterpret_cast(&_context->utcb); + addr_t pd_sel = Platform_pd::pd_core_sel(); + Affinity::Location location = reinterpret_cast(stack_top())[-1]; /* server code sets this value */ - if (cpu_no == ~0UL) - cpu_no = boot_cpu(); + if (!location.valid()) + location = Affinity::Location(boot_cpu(), 0); /* create local EC */ enum { LOCAL_THREAD = false }; - uint8_t res = create_ec(_tid.ec_sel, pd_sel, cpu_no, + uint8_t res = create_ec(_tid.ec_sel, pd_sel, location.xpos(), utcb, sp, _tid.exc_pt_sel, LOCAL_THREAD); if (res != NOVA_OK) { PERR("create_ec returned %d", res); diff --git a/base-okl4/src/core/include/platform_thread.h b/base-okl4/src/core/include/platform_thread.h index 971486f03..98b2b8192 100644 --- a/base-okl4/src/core/include/platform_thread.h +++ b/base-okl4/src/core/include/platform_thread.h @@ -140,12 +140,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu); + void affinity(Affinity::Location) { } /** * Request the affinity of this thread */ - unsigned affinity(); + Affinity::Location affinity() { return Affinity::Location(); } /***************************** diff --git a/base-okl4/src/core/platform_thread.cc b/base-okl4/src/core/platform_thread.cc index 1678a489b..47fe8ddd7 100644 --- a/base-okl4/src/core/platform_thread.cc +++ b/base-okl4/src/core/platform_thread.cc @@ -36,19 +36,6 @@ using namespace Genode; using namespace Okl4; -void Platform_thread::affinity(unsigned int cpu_no) -{ - PERR("'%s' not yet implemented", __PRETTY_FUNCTION__); -} - - -unsigned Platform_thread::affinity() -{ - PERR("'%s' not yet implemented", __PRETTY_FUNCTION__); - return 0; -} - - int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) { if (!_platform_pd) { diff --git a/base-pistachio/src/core/include/platform.h b/base-pistachio/src/core/include/platform.h index 69ef20fba..dfdd14c6a 100644 --- a/base-pistachio/src/core/include/platform.h +++ b/base-pistachio/src/core/include/platform.h @@ -150,8 +150,15 @@ namespace Genode { Rom_fs *rom_fs() { return &_rom_fs; } void wait_for_exit(); - unsigned num_cpus() const { - return L4_NumProcessors(Pistachio::get_kip()); } + + Affinity::Space affinity_space() const + { + /* + * Ignore topology of CPU nodes, just return a one-dimensional + * affinity space. + */ + return Affinity::Space(L4_NumProcessors(Pistachio::get_kip()), 1); + } }; } diff --git a/base-pistachio/src/core/include/platform_thread.h b/base-pistachio/src/core/include/platform_thread.h index 91146994e..d4b2daefd 100644 --- a/base-pistachio/src/core/include/platform_thread.h +++ b/base-pistachio/src/core/include/platform_thread.h @@ -35,19 +35,21 @@ namespace Genode { { private: - int _thread_id; /* plain thread number */ - Native_thread_id _l4_thread_id; /* L4 thread ID */ - char _name[32]; /* thread name that will be - registered at the kernel - debugger */ - Platform_pd *_platform_pd; /* protection domain thread - is bound to */ - unsigned _priority; /* thread priority */ - Pager_object *_pager; + int _thread_id; /* plain thread number */ + Native_thread_id _l4_thread_id; /* L4 thread ID */ + char _name[32]; /* thread name that will be + registered at the kernel + debugger */ + Platform_pd *_platform_pd; /* protection domain thread + is bound to */ + unsigned _priority; /* thread priority */ + Pager_object *_pager; + + Affinity::Location _location; public: - enum { THREAD_INVALID = -1 }; /* invalid thread number */ + enum { THREAD_INVALID = -1 }; /* invalid thread number */ enum { DEFAULT_PRIORITY = 128 }; /** @@ -140,12 +142,12 @@ namespace Genode { /** * Set the executing CPU for this thread */ - void affinity(unsigned cpu); + void affinity(Affinity::Location location); /** * Request the affinity of this thread */ - unsigned affinity(); + Affinity::Location affinity(); /********************************** diff --git a/base-pistachio/src/core/platform.cc b/base-pistachio/src/core/platform.cc index ccb0889d6..07428a30a 100644 --- a/base-pistachio/src/core/platform.cc +++ b/base-pistachio/src/core/platform.cc @@ -199,7 +199,7 @@ static void _core_pager_loop() } -Platform::Sigma0::Sigma0() : Pager_object(0, 0) +Platform::Sigma0::Sigma0() : Pager_object(0, Affinity::Location()) { cap(Native_capability(Pistachio::get_sigma0(), 0)); } @@ -214,7 +214,7 @@ Platform::Sigma0 *Platform::sigma0() Platform::Core_pager::Core_pager(Platform_pd *core_pd) : - Platform_thread("core.pager"), Pager_object(0, 0) + Platform_thread("core.pager"), Pager_object(0, Affinity::Location()) { Platform_thread::pager(sigma0()); diff --git a/base-pistachio/src/core/platform_thread.cc b/base-pistachio/src/core/platform_thread.cc index 47e69f453..2e489dd0f 100644 --- a/base-pistachio/src/core/platform_thread.cc +++ b/base-pistachio/src/core/platform_thread.cc @@ -39,8 +39,12 @@ static const bool verbose2 = true; #define PT_DBG(args...) if (verbose) { PDBG(args); } else { } -void Platform_thread::affinity(unsigned int cpu_no) +void Platform_thread::affinity(Affinity::Location location) { + _location = location; + + unsigned const cpu_no = location.xpos(); + if (cpu_no >= L4_NumProcessors(get_kip())) { PERR("Invalid processor number."); return; @@ -51,10 +55,9 @@ void Platform_thread::affinity(unsigned int cpu_no) } -unsigned Platform_thread::affinity() +Affinity::Location Platform_thread::affinity() { - PERR("'%s' not yet implemented", __PRETTY_FUNCTION__); - return 0; + return _location; } @@ -105,7 +108,7 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) } /* get the thread running on the right cpu */ - affinity(cpu_no); + affinity(Affinity::Location(cpu_no, 0)); /* assign priority */ if (!L4_Set_Priority(thread, diff --git a/base/include/base/affinity.h b/base/include/base/affinity.h new file mode 100644 index 000000000..19014029e --- /dev/null +++ b/base/include/base/affinity.h @@ -0,0 +1,167 @@ +/* + * \brief Representation of CPU affinities + * \author Norman Feske + * \date 2013-08-07 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__BASE__AFFINITY_H_ +#define _INCLUDE__BASE__AFFINITY_H_ + +namespace Genode { + + /** + * Affinity to CPU nodes + * + * The entity of CPU nodes is expected to form a grid where the Euclidean + * distance between nodes roughly correlate to the locality of their + * respective resources. Closely interacting processes are supposed to + * perform best when using nodes close to each other. To allow a relatively + * simple specification of such constraints, the affinity of a subsystem + * (e.g., a process) to CPU nodes is expressed as a rectangle within the + * grid of available CPU nodes. The dimensions of the grid are represented + * by 'Affinity::Space'. The rectangle within the grid is represented by + * 'Affinity::Location'. + */ + class Affinity + { + public: + + class Location; + + /** + * Bounds of the affinity name space + * + * An 'Affinity::Space' defines the bounds of a Cartesian + * coordinate space that expresses the entity of available CPU + * nodes. The dimension values do not necessarily correspond to + * physical CPU numbers. They solely represent the range the + * 'Affinity::Location' is relative to. + */ + class Space + { + private: + + unsigned _width, _height; + + public: + + Space() : _width(0), _height(0) { } + + /** + * Construct a two-dimensional affinity space + */ + Space(unsigned width, unsigned height) + : _width(width), _height(height) { } + + /** + * Constuct one-dimensional affinity space + */ + Space(unsigned size) : _width(size), _height(1) { } + + unsigned width() const { return _width; } + unsigned height() const { return _height; } + unsigned total() const { return _width*_height; } + + /** + * Return location of a single CPU of specified index + */ + inline Location location_of_index(int index); + }; + + + /** + * Location within 'Space' + */ + class Location + { + private: + + int _xpos, _ypos; + unsigned _width, _height; + + public: + + /** + * Default constructor creates invalid location + */ + Location() : _xpos(0), _ypos(0), _width(0), _height(0) { } + + /** + * Constructor to express the affinity to a single CPU + */ + Location(int xpos, unsigned ypos) + : _xpos(xpos), _ypos(ypos), _width(1), _height(1) { } + + /** + * Constructor to express the affinity to a set of CPUs + */ + Location(int xpos, int ypos, unsigned width, unsigned height) + : _xpos(xpos), _ypos(ypos), _width(width), _height(height) { } + + int xpos() const { return _xpos; } + int ypos() const { return _ypos; } + unsigned width() const { return _width; } + unsigned height() const { return _height; } + bool valid() const { return _width*_height > 0; } + }; + + private: + + Space _space; + Location _location; + + Affinity(Space const &space, Location const &location) + : _space(space), _location(location) { } + + Affinity() { } + + Space space() const { return _space; } + Location location() const { return _location; } + + /** + * Return location scaled to specified affinity space + */ + Location scale_to(Space const &space) const + { + if (_space.total() == 0) + return Location(); + + /* + * Calculate coordinates of rectangle corners + * + * P1 is the upper left corner, inside the rectangle. + * P2 is the lower right corner, outside the rectangle. + */ + int const x1 = _location.xpos(), + y1 = _location.ypos(), + x2 = _location.width() + x1, + y2 = _location.height() + y1; + + /* scale corner positions */ + int const scaled_x1 = (x1*space.width()) / _space.width(), + scaled_y1 = (y1*space.height()) / _space.height(), + scaled_x2 = (x2*space.width()) / _space.width(), + scaled_y2 = (y2*space.height()) / _space.height(); + + /* make sure to not scale the location size to zero */ + return Location(scaled_x1, scaled_y1, + max(scaled_x2 - scaled_x1, 1), + max(scaled_y2 - scaled_y1, 1)); + } + }; + + + Affinity::Location Affinity::Space::location_of_index(int index) + { + return Location(index % _width, index / _width, 1, 1); + } +} + +#endif /* _INCLUDE__BASE__AFFINITY_H_ */ diff --git a/base/include/base/pager.h b/base/include/base/pager.h index c51baebec..38e84e0dd 100644 --- a/base/include/base/pager.h +++ b/base/include/base/pager.h @@ -58,7 +58,14 @@ namespace Genode { */ Thread_state state; - Pager_object(unsigned long badge, unsigned affinity) : _badge(badge) { } + /** + * Constructor + * + * \param location affinity of paged thread to physical CPU + */ + Pager_object(unsigned long badge, Affinity::Location location) + : _badge(badge) { } + virtual ~Pager_object() { } unsigned long badge() const { return _badge; } diff --git a/base/include/base/rpc_server.h b/base/include/base/rpc_server.h index 133feb815..02cdf58a9 100644 --- a/base/include/base/rpc_server.h +++ b/base/include/base/rpc_server.h @@ -316,10 +316,11 @@ namespace Genode { * point * \param stack_size stack size of entrypoint thread * \param name name of entrypoint thread + * \param location CPU affinity */ Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, char const *name, bool start_on_construction = true, - unsigned affinity = ~0U); + Affinity::Location location = Affinity::Location()); ~Rpc_entrypoint(); diff --git a/base/include/cpu_session/client.h b/base/include/cpu_session/client.h index b9cf941b7..b3ecb7ac2 100644 --- a/base/include/cpu_session/client.h +++ b/base/include/cpu_session/client.h @@ -60,11 +60,11 @@ namespace Genode { void single_step(Thread_capability thread, bool enable) { call(thread, enable); } - unsigned num_cpus() const { - return call(); } + Affinity::Space affinity_space() const { + return call(); } - void affinity(Thread_capability thread, unsigned cpu) { - call(thread, cpu); } + void affinity(Thread_capability thread, Affinity::Location location) { + call(thread, location); } }; } diff --git a/base/include/cpu_session/cpu_session.h b/base/include/cpu_session/cpu_session.h index 93b47323e..7f338627f 100644 --- a/base/include/cpu_session/cpu_session.h +++ b/base/include/cpu_session/cpu_session.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -173,17 +174,23 @@ namespace Genode { virtual void single_step(Thread_capability, bool) {} /** - * Return number of CPUs available via the CPU session + * Return affinity space of CPU nodes available to the CPU session + * + * The dimension of the affinity space as returned by this function + * represent the physical CPUs that are available. */ - virtual unsigned num_cpus() const = 0; + virtual Affinity::Space affinity_space() const = 0; /** - * Assign thread to a CPU + * Define affinity of thread to one or multiple CPU nodes * - * The 'cpu' argument is a CPU index starting at 0. It must be - * smaller than the value returned by 'num_cpus()'. + * In the normal case, a thread is assigned to a single CPU. + * Specifying more than one CPU node is supposed to principally + * allow a CPU service to balance the load of threads among + * multiple CPUs. */ - virtual void affinity(Thread_capability thread, unsigned cpu) = 0; + virtual void affinity(Thread_capability thread, + Affinity::Location affinity) = 0; /** * Translate generic priority value to kernel-specific priority levels @@ -238,8 +245,8 @@ namespace Genode { GENODE_RPC(Rpc_exception_handler, void, exception_handler, Thread_capability, Signal_context_capability); GENODE_RPC(Rpc_single_step, void, single_step, Thread_capability, bool); - GENODE_RPC(Rpc_num_cpus, unsigned, num_cpus); - GENODE_RPC(Rpc_affinity, void, affinity, Thread_capability, unsigned); + GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space); + GENODE_RPC(Rpc_affinity, void, affinity, Thread_capability, Affinity::Location); /* * 'GENODE_RPC_INTERFACE' declaration done manually @@ -261,7 +268,7 @@ namespace Genode { Meta::Type_tuple > > > > > > > > > > > > > Rpc_functions; diff --git a/base/run/affinity.run b/base/run/affinity.run index 2a550a80a..f0d10221a 100644 --- a/base/run/affinity.run +++ b/base/run/affinity.run @@ -4,7 +4,7 @@ # \author Alexander Boettcher # -if {![have_spec nova] && ![have_spec foc]} { +if {[have_spec platform_pbxa9] || (![have_spec nova] && ![have_spec foc])} { puts "Platform is unsupported." exit 0 } @@ -33,9 +33,11 @@ install_config { build_boot_image "core init test-affinity" if {[is_qemu_available]} { - set want_cpus 4 - set rounds "05" - append qemu_args "-nographic -m 64 -smp $want_cpus,cores=$want_cpus " + set want_cpus_x 4 + set want_cpus_y 1 + set want_cpus_total [expr $want_cpus_x*$want_cpus_y] + set rounds "03" + append qemu_args "-nographic -m 64 -smp $want_cpus_total,cores=$want_cpus_total " } else { set rounds "10" if {[have_spec x86]} { set rounds "40" } @@ -43,12 +45,13 @@ if {[is_qemu_available]} { run_genode_until "Round $rounds:.*\n" 90 -set cpus [regexp -inline {Detected [0-9]+ CPU[ s].*\n} $output] -set cpus [regexp -inline {[0-9]+} $cpus] +set cpus [regexp -inline {Detected [0-9x]+ CPU[ s]\.} $output] +set cpus [regexp -all -inline {[0-9]+} $cpus] +set cpus [expr [lindex $cpus 0] * [lindex $cpus 1]] if {[is_qemu_available]} { - if {$want_cpus != $cpus} { - puts "CPU count is not as expected: $want_cpus != $cpus" + if {$want_cpus_total != $cpus} { + puts "CPU count is not as expected: $want_cpus_total != $cpus" exit 1; } } diff --git a/base/run/mp_server.run b/base/run/mp_server.run index 6d4816bae..c505c05b2 100644 --- a/base/run/mp_server.run +++ b/base/run/mp_server.run @@ -4,7 +4,7 @@ # \author Alexander Boettcher # -if {![have_spec nova] && ![have_spec foc]} { +if {[have_spec platform_pbxa9] || (![have_spec nova] && ![have_spec foc])} { puts "Platform is unsupported." exit 0 } @@ -38,10 +38,11 @@ if {[is_qemu_available]} { } # run the test -run_genode_until {\[init -\> test-server-mp\] done.*\n} 20 +run_genode_until {\[init -\> test-server-mp\] done.*\n} 60 -set cpus [regexp -inline {Detected [0-9]+ CPU[ s].*\n} $output] -set cpus [regexp -inline {[0-9]+} $cpus] +set cpus [regexp -inline {Detected [0-9x]+ CPU[ s]\.} $output] +set cpus [regexp -all -inline {[0-9]+} $cpus] +set cpus [expr [lindex $cpus 0] * [lindex $cpus 1]] if {[is_qemu_available]} { if {$want_cpus != $cpus} { @@ -59,7 +60,7 @@ unify_output {\- received cap [a-f0-9]+} "- received cap UNIFIED" compare_output_to { [init -> test-server-mp] --- test-mp_server started --- - [init -> test-server-mp] Detected 2 CPUs. + [init -> test-server-mp] Detected 2x1 CPUs. [init -> test-server-mp] call server on CPU 0 [init -> test-server-mp] function test_untyped: got value 0 [init -> test-server-mp] call server on CPU 1 diff --git a/base/src/base/server/common.cc b/base/src/base/server/common.cc index 7cc66a189..ee7b6d16b 100644 --- a/base/src/base/server/common.cc +++ b/base/src/base/server/common.cc @@ -14,6 +14,7 @@ #include #include #include +#include using namespace Genode; @@ -99,7 +100,7 @@ bool Rpc_entrypoint::is_myself() const Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, char const *name, bool start_on_construction, - unsigned affinity) + Affinity::Location location) : Thread_base(name, stack_size), _cap(Untyped_capability()), @@ -107,6 +108,10 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, _delay_exit(Lock::LOCKED), _cap_session(cap_session) { + /* set CPU affinity, if specified */ + if (location.valid()) + env()->cpu_session()->affinity(Thread_base::cap(), location); + Thread_base::start(); _block_until_cap_valid(); diff --git a/base/src/core/cpu_session_component.cc b/base/src/core/cpu_session_component.cc index 4e6845d59..94b9e5be9 100644 --- a/base/src/core/cpu_session_component.cc +++ b/base/src/core/cpu_session_component.cc @@ -180,18 +180,19 @@ Cpu_session_component::exception_handler(Thread_capability thread_cap, } -unsigned Cpu_session_component::num_cpus() const +Affinity::Space Cpu_session_component::affinity_space() const { - return platform()->num_cpus(); + return platform()->affinity_space(); } -void Cpu_session_component::affinity(Thread_capability thread_cap, unsigned cpu) +void Cpu_session_component::affinity(Thread_capability thread_cap, + Affinity::Location location) { Object_pool::Guard thread(_thread_ep->lookup_and_lock(thread_cap)); if (!thread) return; - thread->platform_thread()->affinity(cpu); + thread->platform_thread()->affinity(location); } diff --git a/base/src/core/include/cpu_session_component.h b/base/src/core/include/cpu_session_component.h index d108368fe..3c71103c8 100644 --- a/base/src/core/include/cpu_session_component.h +++ b/base/src/core/include/cpu_session_component.h @@ -149,8 +149,8 @@ namespace Genode { Thread_state state(Thread_capability); void state(Thread_capability, Thread_state const &); void exception_handler(Thread_capability, Signal_context_capability); - unsigned num_cpus() const; - void affinity(Thread_capability, unsigned); + Affinity::Space affinity_space() const; + void affinity(Thread_capability, Affinity::Location); }; } diff --git a/base/src/core/include/platform_generic.h b/base/src/core/include/platform_generic.h index 42bc39251..2367b2313 100644 --- a/base/src/core/include/platform_generic.h +++ b/base/src/core/include/platform_generic.h @@ -18,6 +18,7 @@ /* Genode includes */ #include #include +#include /* core includes */ #include @@ -91,8 +92,13 @@ namespace Genode { /** * Return number of physical CPUs present in the platform + * + * The default implementation returns a single CPU. */ - virtual unsigned num_cpus() const { return 1; } + virtual Affinity::Space affinity_space() const + { + return Affinity::Space(1); + } }; diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h index 732afd9cf..52a5b8941 100644 --- a/base/src/core/include/rm_session_component.h +++ b/base/src/core/include/rm_session_component.h @@ -197,13 +197,13 @@ namespace Genode { * \param session RM session to which the client belongs * \param badge pager-object badge used of identifying the client * when a page-fault occurs - * \param affinity cpu affinity + * \param location affinity to physical CPU */ Rm_client(Rm_session_component *session, unsigned long badge, Weak_ptr &address_space, - unsigned affinity) + Affinity::Location location) : - Pager_object(badge, affinity), Rm_member(session), + Pager_object(badge, location), Rm_member(session), Rm_faulter(this), _address_space(address_space) { } int pager(Ipc_pager &pager); diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc index a3419a328..b7f886bfe 100644 --- a/base/src/core/rm_session_component.cc +++ b/base/src/core/rm_session_component.cc @@ -605,7 +605,7 @@ void Rm_session_component::detach(Local_addr local_addr) Pager_capability Rm_session_component::add_client(Thread_capability thread) { unsigned long badge; - unsigned affinity; + Affinity::Location location; Weak_ptr address_space; { @@ -616,8 +616,9 @@ Pager_capability Rm_session_component::add_client(Thread_capability thread) /* determine identification of client when faulting */ badge = cpu_thread->platform_thread()->pager_object_badge(); + /* determine cpu affinity of client thread */ - affinity = cpu_thread->platform_thread()->affinity(); + location = cpu_thread->platform_thread()->affinity(); address_space = cpu_thread->platform_thread()->address_space(); if (!Locked_ptr(address_space).is_valid()) @@ -628,7 +629,7 @@ Pager_capability Rm_session_component::add_client(Thread_capability thread) Lock::Guard lock_guard(_lock); Rm_client *cl; - try { cl = new(&_client_slab) Rm_client(this, badge, address_space, affinity); } + try { cl = new(&_client_slab) Rm_client(this, badge, address_space, location); } catch (Allocator::Out_of_memory) { throw Out_of_metadata(); } catch (Cpu_session::Thread_creation_failed) { throw Out_of_metadata(); } catch (Thread_base::Stack_alloc_failed) { throw Out_of_metadata(); } diff --git a/base/src/test/affinity/main.cc b/base/src/test/affinity/main.cc index 1038c4499..b290979e4 100644 --- a/base/src/test/affinity/main.cc +++ b/base/src/test/affinity/main.cc @@ -22,7 +22,7 @@ enum { STACK_SIZE = sizeof(long)*1024, COUNT_VALUE = 10 * 1024 * 1024 }; struct Spinning_thread : Genode::Thread { - unsigned const _cpu_number; + Genode::Affinity::Location const _location; Genode::uint64_t volatile cnt; @@ -32,7 +32,8 @@ struct Spinning_thread : Genode::Thread { barrier.unlock(); - PINF("thread started on CPU %u, spinning...", _cpu_number); + PINF("thread started on CPU %d,%d, spinning...", + _location.xpos(), _location.ypos()); unsigned round = 0; @@ -41,18 +42,18 @@ struct Spinning_thread : Genode::Thread /* show a life sign every now and then... */ if (cnt % COUNT_VALUE == 0) { - PINF("thread on CPU %u keeps counting - round %u...\n", - _cpu_number, round++); + PINF("thread on CPU %d,%d keeps counting - round %u...\n", + _location.xpos(), _location.ypos(), round++); } } } - Spinning_thread(unsigned cpu_number, char const *name) + Spinning_thread(Genode::Affinity::Location location, char const *name) : - Genode::Thread(name), _cpu_number(cpu_number), cnt(0ULL), + Genode::Thread(name), _location(location), cnt(0ULL), barrier(Genode::Lock::LOCKED) { - Genode::env()->cpu_session()->affinity(Thread_base::cap(), cpu_number); + Genode::env()->cpu_session()->affinity(Thread_base::cap(), location); start(); } }; @@ -64,19 +65,21 @@ int main(int argc, char **argv) printf("--- test-affinity started ---\n"); - unsigned cpus = env()->cpu_session()->num_cpus(); - printf("Detected %u CPU%c.\n", cpus, cpus > 1 ? 's' : ' '); + Affinity::Space cpus = env()->cpu_session()->affinity_space(); + printf("Detected %ux%u CPU%s\n", + cpus.width(), cpus.height(), cpus.total() > 1 ? "s." : "."); /* get some memory for the thread objects */ - Spinning_thread ** threads = new (env()->heap()) Spinning_thread*[cpus]; - uint64_t * thread_cnt = new (env()->heap()) uint64_t[cpus]; + Spinning_thread ** threads = new (env()->heap()) Spinning_thread*[cpus.total()]; + uint64_t * thread_cnt = new (env()->heap()) uint64_t[cpus.total()]; /* construct the thread objects */ - for (unsigned i = 0; i < cpus; i++) - threads[i] = new (env()->heap()) Spinning_thread(i, "thread"); + for (unsigned i = 0; i < cpus.total(); i++) + threads[i] = new (env()->heap()) + Spinning_thread(cpus.location_of_index(i), "thread"); /* wait until all threads are up and running */ - for (unsigned i = 0; i < cpus; i++) + for (unsigned i = 0; i < cpus.total(); i++) threads[i]->barrier.lock(); printf("Threads started on a different CPU each.\n"); @@ -89,7 +92,7 @@ int main(int argc, char **argv) char const text_cpu[] = " CPU: "; char const text_round[] = "Round %2u: "; - char * output_buffer = new (env()->heap()) char [sizeof(text_cpu) + 3 * cpus]; + char * output_buffer = new (env()->heap()) char [sizeof(text_cpu) + 3 * cpus.total()]; for (;;) { cnt++; @@ -99,7 +102,7 @@ int main(int argc, char **argv) char * output = output_buffer; snprintf(output, sizeof(text_cpu), text_cpu); output += sizeof(text_cpu) - 1; - for (unsigned i = 0; i < cpus; i++) { + for (unsigned i = 0; i < cpus.total(); i++) { snprintf(output, 4, "%2u ", i); output += 3; } @@ -109,7 +112,7 @@ int main(int argc, char **argv) snprintf(output, sizeof(text_round), text_round, round); output += sizeof(text_round) - 2; - for (unsigned i = 0; i < cpus; i++) { + for (unsigned i = 0; i < cpus.total(); i++) { snprintf(output, 4, "%s ", thread_cnt[i] == threads[i]->cnt ? " D" : " A"); output += 3; diff --git a/base/src/test/mp_server/main.cc b/base/src/test/mp_server/main.cc index 2fbfa8a95..d9037ae51 100644 --- a/base/src/test/mp_server/main.cc +++ b/base/src/test/mp_server/main.cc @@ -89,43 +89,44 @@ int main(int argc, char **argv) printf("--- test-mp_server started ---\n"); - unsigned cpus = env()->cpu_session()->num_cpus(); - printf("Detected %u CPU%c.\n", cpus, cpus > 1 ? 's' : ' '); + Affinity::Space cpus = env()->cpu_session()->affinity_space(); + printf("Detected %ux%u CPU%s\n", + cpus.width(), cpus.height(), cpus.total() > 1 ? "s." : "."); enum { STACK_SIZE = 4096 }; static Cap_connection cap; - Rpc_entrypoint ** eps = new (env()->heap()) Rpc_entrypoint*[cpus]; - for (unsigned i = 0; i < cpus; i++) + Rpc_entrypoint ** eps = new (env()->heap()) Rpc_entrypoint*[cpus.total()]; + for (unsigned i = 0; i < cpus.total(); i++) eps[i] = new (env()->heap()) Rpc_entrypoint(&cap, STACK_SIZE, "rpc en", - true, i); + true, cpus.location_of_index(i)); /* XXX using the same object and putting it to different queues fails XXX */ - Test::Component * components = new (env()->heap()) Test::Component[cpus]; + Test::Component * components = new (env()->heap()) Test::Component[cpus.total()]; - Test::Capability * caps = new (env()->heap()) Test::Capability[cpus]; - for (unsigned i = 0; i < cpus; i++) + Test::Capability * caps = new (env()->heap()) Test::Capability[cpus.total()]; + for (unsigned i = 0; i < cpus.total(); i++) caps[i] = eps[i]->manage(&components[i]); - Test::Client ** clients = new (env()->heap()) Test::Client*[cpus]; - for (unsigned i = 0; i < cpus; i++) + Test::Client ** clients = new (env()->heap()) Test::Client*[cpus.total()]; + for (unsigned i = 0; i < cpus.total(); i++) clients[i] = new (env()->heap()) Test::Client(caps[i]); /* Test: Invoke RPC entrypoint on different CPUs */ - for (unsigned i = 0; i < cpus; i++) { + for (unsigned i = 0; i < cpus.total(); i++) { printf("call server on CPU %u\n", i); clients[i]->test_untyped(i); } /* Test: Transfer a capability to RPC Entrypoints on different CPUs */ - for (unsigned i = 0; i < cpus; i++) { + for (unsigned i = 0; i < cpus.total(); i++) { Native_capability cap = caps[0]; printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name()); clients[i]->test_cap(cap); } /* Test: Transfer a capability to RPC Entrypoints and back */ - for (unsigned i = 0; i < cpus; i++) { + for (unsigned i = 0; i < cpus.total(); i++) { Native_capability cap = caps[0]; printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name()); Native_capability rcap = clients[i]->test_cap_reply(cap); diff --git a/ports-foc/src/lib/l4lx/include/vcpu.h b/ports-foc/src/lib/l4lx/include/vcpu.h index d51c6045e..0b4422e51 100644 --- a/ports-foc/src/lib/l4lx/include/vcpu.h +++ b/ports-foc/src/lib/l4lx/include/vcpu.h @@ -81,14 +81,18 @@ namespace L4lx { Genode::addr_t sp() { return ((Genode::addr_t)&_context->stack[-4]) & ~0xf; } + Genode::addr_t ip() { return (Genode::addr_t)_func; } Fiasco::l4_utcb_t *utcb() { return _context->utcb; }; Timer::Connection* timer() { return &_timer; } - void set_affinity(unsigned i) { - vcpu_connection()->affinity(_thread_cap, i); } + void set_affinity(unsigned i) + { + vcpu_connection()->affinity(_thread_cap, + Genode::Affinity::Location(i, 0)); + } }; } diff --git a/ports/src/app/gdb_monitor/cpu_session_component.cc b/ports/src/app/gdb_monitor/cpu_session_component.cc index 284f3e428..a4c78794e 100644 --- a/ports/src/app/gdb_monitor/cpu_session_component.cc +++ b/ports/src/app/gdb_monitor/cpu_session_component.cc @@ -191,15 +191,16 @@ void Cpu_session_component::single_step(Thread_capability thread_cap, bool enabl } -unsigned Cpu_session_component::num_cpus() const +Affinity::Space Cpu_session_component::affinity_space() const { - return _parent_cpu_session.num_cpus(); + return _parent_cpu_session.affinity_space(); } -void Cpu_session_component::affinity(Thread_capability thread_cap, unsigned cpu) +void Cpu_session_component::affinity(Thread_capability thread_cap, + Affinity::Location location) { - _parent_cpu_session.affinity(thread_cap, cpu); + _parent_cpu_session.affinity(thread_cap, location); } diff --git a/ports/src/app/gdb_monitor/cpu_session_component.h b/ports/src/app/gdb_monitor/cpu_session_component.h index 3aa036082..192a1b994 100644 --- a/ports/src/app/gdb_monitor/cpu_session_component.h +++ b/ports/src/app/gdb_monitor/cpu_session_component.h @@ -70,8 +70,8 @@ class Cpu_session_component : public Rpc_object void exception_handler(Thread_capability thread, Signal_context_capability handler); void single_step(Thread_capability thread, bool enable); - unsigned num_cpus() const; - void affinity(Thread_capability, unsigned); + Affinity::Space affinity_space() const; + void affinity(Thread_capability, Affinity::Location); }; #endif /* _CPU_SESSION_COMPONENT_H_ */ diff --git a/ports/src/noux/cpu_session_component.h b/ports/src/noux/cpu_session_component.h index a689dfb39..5b3a53849 100644 --- a/ports/src/noux/cpu_session_component.h +++ b/ports/src/noux/cpu_session_component.h @@ -129,11 +129,11 @@ namespace Noux { void single_step(Thread_capability thread, bool enable) { _cpu.single_step(thread, enable); } - unsigned num_cpus() const { - return _cpu.num_cpus(); } + Affinity::Space affinity_space() const { + return _cpu.affinity_space(); } - void affinity(Thread_capability thread, unsigned cpu) { - _cpu.affinity(thread, cpu); } + void affinity(Thread_capability thread, Affinity::Location location) { + _cpu.affinity(thread, location); } }; }