From 85cf7e1ad624fda7aa10816dd72148d038fdbc9b Mon Sep 17 00:00:00 2001 From: Stephen Roderick Date: Sun, 12 Jun 2011 08:51:33 -0400 Subject: [PATCH 1/3] Backport CPU affinity feature from v2 --- src/Activity.cpp | 21 ++++++++++++++++++--- src/Activity.hpp | 23 +++++++++++++++++++++++ src/ActivityInterface.hpp | 14 ++++++++++++++ src/NonPeriodicActivity.cpp | 16 ++++++++++++++++ src/NonPeriodicActivity.hpp | 16 ++++++++++++++++ src/PeriodicActivity.cpp | 17 +++++++++++++++++ src/PeriodicActivity.hpp | 23 +++++++++++++++++++++++ src/SequentialActivity.cpp | 10 ++++++++++ src/SequentialActivity.hpp | 4 ++++ src/SlaveActivity.cpp | 10 ++++++++++ src/SlaveActivity.hpp | 4 ++++ src/TaskContext.cpp | 6 ++++++ src/TaskCore.cpp | 10 ++++++++++ src/TaskCore.hpp | 13 +++++++++++++ src/Timer.cpp | 2 +- src/TimerThread.cpp | 15 ++++++++++----- src/TimerThread.hpp | 8 ++++++-- src/os/PeriodicThread.cpp | 21 +++++++++++++++++---- src/os/PeriodicThread.hpp | 20 +++++++++++++++++--- src/os/SingleThread.cpp | 21 +++++++++++++++++---- src/os/SingleThread.hpp | 20 +++++++++++++++++--- src/os/Thread.cpp | 19 +++++++++++++++---- src/os/Thread.hpp | 17 +++++++++++++++-- src/os/ecos/fosi_internal.cpp | 11 +++++++++++ src/os/fosi_internal_interface.hpp | 19 +++++++++++++++++++ src/os/gnulinux/fosi_internal.cpp | 33 +++++++++++++++++++++++++++++++++ src/os/lxrt/fosi_internal.cpp | 10 ++++++++++ src/os/macosx/fosi_internal.cpp | 11 +++++++++++ src/os/win32/fosi_internal.cpp | 11 +++++++++++ src/os/xenomai/fosi_internal.cpp | 11 +++++++++++ tests/buffers_test.cpp | 16 ++++++++-------- tests/logger_test.cpp | 4 ++-- tests/tasks_test.cpp | 6 +++--- 33 files changed, 418 insertions(+), 44 deletions(-) diff --git a/src/Activity.cpp b/src/Activity.cpp index 2c36432..a5bd69a 100644 --- a/src/Activity.cpp +++ b/src/Activity.cpp @@ -12,17 +12,22 @@ namespace RTT { Activity::Activity(RunnableInterface* _r, const std::string& name ) - : ActivityInterface(_r), OS::Thread(ORO_SCHED_OTHER, 0, 0.0, name ) + : ActivityInterface(_r), OS::Thread(ORO_SCHED_OTHER, 0, 0.0, ~0, name ) { } Activity::Activity(int priority, Seconds period, RunnableInterface* r, const std::string& name ) - : ActivityInterface(r), OS::Thread(ORO_SCHED_RT, priority, period, name ) + : ActivityInterface(r), OS::Thread(ORO_SCHED_RT, priority, period, ~0, name ) { } Activity::Activity(int scheduler, int priority, Seconds period, RunnableInterface* r, const std::string& name ) - : ActivityInterface(r), OS::Thread(scheduler, priority, period, name ) + : ActivityInterface(r), OS::Thread(scheduler, priority, period, ~0, name ) + { + } + + Activity::Activity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r, const std::string& name ) + : ActivityInterface(r), OS::Thread(scheduler, priority, period, cpu_affinity, name ) { } @@ -101,4 +106,14 @@ namespace RTT bool Activity::isPeriodic() const { return Thread::isPeriodic(); } + + unsigned Activity::getCpuAffinity() const + { + return Thread::getCpuAffinity(); + } + + bool Activity::setCpuAffinity(unsigned cpu) + { + return Thread::setCpuAffinity(cpu); + } } diff --git a/src/Activity.hpp b/src/Activity.hpp index 0cae807..2393ac9 100644 --- a/src/Activity.hpp +++ b/src/Activity.hpp @@ -70,6 +70,25 @@ namespace RTT RunnableInterface* r = 0, const std::string& name ="Activity"); /** + * @brief Create an Activity with a given scheduler type, priority, period and cpu affinity. + * + * @param scheduler + * The scheduler in which the activity's thread must run. Use ORO_SCHED_OTHER or + * ORO_SCHED_RT. + * @param priority + * The priority of this activity. + * @param period + * The periodicity of the Activity + * @param cpu_affinity + * The prefered cpu to run on (a mask) + * @param r + * The optional base::RunnableInterface to run exclusively within this Activity + * @param name The name of the underlying thread. + */ + Activity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, + RunnableInterface* r = 0, const std::string& name ="Activity"); + + /** * Stops and terminates a Activity */ virtual ~Activity(); @@ -92,6 +111,10 @@ namespace RTT virtual bool setPeriod(Seconds period); + virtual unsigned getCpuAffinity() const; + + virtual bool setCpuAffinity(unsigned cpu); + virtual OS::ThreadInterface* thread(); /** diff --git a/src/ActivityInterface.hpp b/src/ActivityInterface.hpp index 1310940..53cefc6 100644 --- a/src/ActivityInterface.hpp +++ b/src/ActivityInterface.hpp @@ -153,6 +153,19 @@ namespace RTT virtual bool isPeriodic() const = 0; /** + * Get the cpu affinity of this activity + * + * @return The cpu affinity of this activity. + */ + virtual unsigned getCpuAffinity() const = 0; + + /** + * Set the cpu affinity of this activity. + * @return true if it could be updated, false otherwise. + */ + virtual bool setCpuAffinity(unsigned cpu) = 0; + + /** * Execute this activity such that it \a executes a step or loop of the RunnableInterface. * When you invoke execute() you intend to call the step() or loop() methods. * Some activity implementations allow a user controlled execute, others ignore it, @@ -169,6 +182,7 @@ namespace RTT */ virtual bool execute() = 0; + /** * Trigger that work has to be done. When you invoke * trigger(), you intend to notify the mechanism that calls diff --git a/src/NonPeriodicActivity.cpp b/src/NonPeriodicActivity.cpp index cf99d16..b9aac72 100644 --- a/src/NonPeriodicActivity.cpp +++ b/src/NonPeriodicActivity.cpp @@ -56,6 +56,12 @@ namespace RTT { } + NonPeriodicActivity::NonPeriodicActivity(int scheduler, int priority, unsigned cpu_affinity, RunnableInterface* _r ) + : ActivityInterface(_r), + OS::SingleThread(scheduler, priority, "NonPeriodicActivity", cpu_affinity ) + { + } + NonPeriodicActivity::NonPeriodicActivity(int priority, const std::string& name, RunnableInterface* _r ) : ActivityInterface(_r), OS::SingleThread(priority, name ) @@ -69,6 +75,16 @@ namespace RTT Seconds NonPeriodicActivity::getPeriod() const { return 0; } + unsigned NonPeriodicActivity::getCpuAffinity() const + { + return SingleThread::getCpuAffinity(); + } + + bool NonPeriodicActivity::setCpuAffinity(unsigned cpu) + { + return SingleThread::setCpuAffinity(cpu); + } + OS::ThreadInterface* NonPeriodicActivity::thread() { return this; } bool NonPeriodicActivity::isPeriodic() const { return false; } diff --git a/src/NonPeriodicActivity.hpp b/src/NonPeriodicActivity.hpp index bb36b4b..aeecab9 100644 --- a/src/NonPeriodicActivity.hpp +++ b/src/NonPeriodicActivity.hpp @@ -87,6 +87,18 @@ namespace RTT NonPeriodicActivity(int scheduler, int priority, RunnableInterface* _r = 0 ); /** + * Create an NonPeriodicActivity with a given scheduler type, priority and + * RunnableInterface instance. + * @param scheduler + * The scheduler in which the activitie's thread must run. Use ORO_SCHED_OTHER or + * ORO_SCHED_RT. + * @param priority The priority of the underlying thread. + * @param cpu_affinity The prefered cpu to run on (a mask) + * @param _r The optional runner, if none, this->loop() is called. + */ + NonPeriodicActivity(int scheduler, int priority, unsigned cpu_affinity, RunnableInterface* _r = 0 ); + + /** * Create an NonPeriodicActivity with a given priority, name and * RunnableInterface instance. * @param priority The priority of the underlying thread. @@ -106,6 +118,10 @@ namespace RTT virtual Seconds getPeriod() const ; + virtual unsigned getCpuAffinity() const; + + virtual bool setCpuAffinity(unsigned cpu); + virtual ThreadInterface* thread(); virtual bool initialize(); diff --git a/src/PeriodicActivity.cpp b/src/PeriodicActivity.cpp index a09e25f..6a29d6b 100644 --- a/src/PeriodicActivity.cpp +++ b/src/PeriodicActivity.cpp @@ -62,6 +62,13 @@ namespace RTT this->init(); } + PeriodicActivity::PeriodicActivity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r ) + : ActivityInterface(r), running(false), active(false), + thread_( TimerThread::Instance(scheduler, priority, period, cpu_affinity) ) + { + this->init(); + } + PeriodicActivity::PeriodicActivity(TimerThreadPtr thread, RunnableInterface* r ) : ActivityInterface(r), running(false), active(false), thread_( thread ) @@ -153,6 +160,16 @@ namespace RTT return thread_->getPeriod(); } + unsigned PeriodicActivity::getCpuAffinity() const + { + return thread_->getCpuAffinity(); + } + + bool PeriodicActivity::setCpuAffinity(unsigned cpu) + { + return thread_->setCpuAffinity(cpu); + } + bool PeriodicActivity::initialize() { if (runner != 0) return runner->initialize(); diff --git a/src/PeriodicActivity.hpp b/src/PeriodicActivity.hpp index 4d9e61d..766fc9a 100644 --- a/src/PeriodicActivity.hpp +++ b/src/PeriodicActivity.hpp @@ -103,6 +103,25 @@ namespace RTT */ PeriodicActivity(int scheduler, int priority, Seconds period, RunnableInterface* r=0 ); + /** + * @brief Create a Periodic Activity with a given scheduler type, priority and period. + * + * @param scheduler + * The scheduler in which the activitie's thread must run. Use ORO_SCHED_OTHER or + * ORO_SCHED_RT. + * @param priority + * The priority of this activity. A lookup will be done to locate a suitable + * TimerThread with the same priority. If it exists and it has the same \a period, + * this activity will be executed in that thread. Otherwise, a new TimerThread is created. + * @param period + * The periodicity of the PeriodicActivity + * @param cpu_affinity + * The prefered cpu to run on (a mask) + * @param r + * The optional base::RunnableInterface to run exclusively within this Activity + */ + PeriodicActivity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r=0 ); + /** * @brief Create a Periodic Activity executing in a given thread. @@ -164,6 +183,10 @@ namespace RTT virtual Seconds getPeriod() const; + virtual unsigned getCpuAffinity() const; + + virtual bool setCpuAffinity(unsigned cpu); + virtual OS::ThreadInterface* thread(); /** diff --git a/src/SequentialActivity.cpp b/src/SequentialActivity.cpp index ab76704..03939a6 100644 --- a/src/SequentialActivity.cpp +++ b/src/SequentialActivity.cpp @@ -20,6 +20,16 @@ namespace RTT return 0.0; } + unsigned SequentialActivity::getCpuAffinity() const + { + return ~0; + } + + bool SequentialActivity::setCpuAffinity(unsigned cpu) + { + return false; + } + OS::ThreadInterface* SequentialActivity::thread() { return OS::MainThread::Instance(); diff --git a/src/SequentialActivity.hpp b/src/SequentialActivity.hpp index 61eb054..b3e4f16 100644 --- a/src/SequentialActivity.hpp +++ b/src/SequentialActivity.hpp @@ -46,6 +46,10 @@ namespace RTT Seconds getPeriod() const; + unsigned getCpuAffinity() const; + + bool setCpuAffinity(unsigned cpu); + OS::ThreadInterface* thread(); bool initialize(); diff --git a/src/SlaveActivity.cpp b/src/SlaveActivity.cpp index caf2be4..589e124 100644 --- a/src/SlaveActivity.cpp +++ b/src/SlaveActivity.cpp @@ -67,6 +67,16 @@ namespace RTT return mperiod; } + unsigned SlaveActivity::getCpuAffinity() const + { + return mmaster ? mmaster->getCpuAffinity() : ~0; + } + + bool SlaveActivity::setCpuAffinity(unsigned cpu) + { + return mmaster ? mmaster->setCpuAffinity(cpu) : false; + } + OS::ThreadInterface* SlaveActivity::thread() { return mmaster ? mmaster->thread() : OS::MainThread::Instance(); diff --git a/src/SlaveActivity.hpp b/src/SlaveActivity.hpp index 7b48703..e91213a 100644 --- a/src/SlaveActivity.hpp +++ b/src/SlaveActivity.hpp @@ -119,6 +119,10 @@ namespace RTT Seconds getPeriod() const; + virtual unsigned getCpuAffinity() const; + + virtual bool setCpuAffinity(unsigned cpu); + OS::ThreadInterface* thread(); bool initialize(); diff --git a/src/TaskContext.cpp b/src/TaskContext.cpp index ada9e41..a0d9301 100644 --- a/src/TaskContext.cpp +++ b/src/TaskContext.cpp @@ -144,6 +144,12 @@ namespace RTT ->addMethod( method("getPeriod",&TaskContext::getPeriod, this), "Get the configured execution period. -1.0: no thread associated, 0.0: non periodic, > 0.0: the period." ); this->methods() + ->addMethod( method("getCpuAffinity",&TaskContext::getCpuAffinity, this), + "Get the configured cpu affinity." ); + this->methods() + ->addMethod( method("setCpuAffinity",&TaskContext::setCpuAffinity, this), + "Set the cpu affinity.", "cpu", "Cpu mask."); + this->methods() ->addMethod( method("isActive",&TaskContext::isActive, this), "Is the Execution Engine of this TaskContext processing events and commands ?" ); this->methods() diff --git a/src/TaskCore.cpp b/src/TaskCore.cpp index 81a553c..ff3e278 100644 --- a/src/TaskCore.cpp +++ b/src/TaskCore.cpp @@ -210,6 +210,16 @@ namespace RTT return this->engine()->getActivity() ? this->engine()->getActivity()->getPeriod() : -1.0; } + unsigned TaskCore::getCpuAffinity() const + { + return this->engine()->getActivity() ? this->engine()->getActivity()->getCpuAffinity() : ~0; + } + + bool TaskCore::setCpuAffinity(unsigned cpu) + { + return this->engine()->getActivity() ? this->engine()->getActivity()->setCpuAffinity(cpu) : false; + } + bool TaskCore::configureHook() { return true; } diff --git a/src/TaskCore.hpp b/src/TaskCore.hpp index 2496b04..3293b9c 100644 --- a/src/TaskCore.hpp +++ b/src/TaskCore.hpp @@ -282,6 +282,19 @@ namespace RTT virtual double getPeriod() const; /** + * Get the configured cpu affinity of this component. + * @see ActivityInterface::getCpuAffinity() + */ + virtual unsigned getCpuAffinity() const; + + /** + * Sets the cpu affinity of this component. + * @return false if not allowed by the component's activity. + * @see ActivityInterface::setCpuAffinity() + */ + virtual bool setCpuAffinity(unsigned cpu); + + /** * Inspect if the component is in the FatalError state. */ virtual bool inFatalError() const; diff --git a/src/Timer.cpp b/src/Timer.cpp index 74a97e0..2b64cf2 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -125,7 +125,7 @@ namespace RTT mTimeserv = TimeService::Instance(); mtimers.resize(max_timers); if (scheduler != -1) { - mThread = new OS::SingleThread(scheduler, priority, "Timer", this); + mThread = new OS::SingleThread(scheduler, priority, "Timer", ~0, this); mThread->start(); } } diff --git a/src/TimerThread.cpp b/src/TimerThread.cpp index 843a3b6..9cf1269 100644 --- a/src/TimerThread.cpp +++ b/src/TimerThread.cpp @@ -59,6 +59,11 @@ namespace RTT TimerThreadPtr TimerThread::Instance(int scheduler, int pri, double per) { + return Instance(scheduler, pri, per, ~0); + } + + TimerThreadPtr TimerThread::Instance(int scheduler, int pri, double per, unsigned cpu_affinity) + { // Since the period is stored as nsecs, we convert per to NS in order // to get a match. OS::CheckPriority(scheduler, pri); @@ -76,19 +81,19 @@ namespace RTT } ++it; } - TimerThreadPtr ret( new TimerThread(scheduler, pri, "TimerThreadInstance", per) ); + TimerThreadPtr ret( new TimerThread(scheduler, pri, "TimerThreadInstance", per, cpu_affinity) ); TimerThreads.push_back( ret ); return ret; } - TimerThread::TimerThread(int priority, const std::string& name, double periodicity) - : PeriodicThread( priority, name, periodicity), cleanup(false) + TimerThread::TimerThread(int priority, const std::string& name, double periodicity, unsigned cpu_affinity) + : PeriodicThread( priority, name, periodicity, cpu_affinity), cleanup(false) { tasks.reserve(MAX_ACTIVITIES); } - TimerThread::TimerThread(int scheduler, int priority, const std::string& name, double periodicity) - : PeriodicThread(scheduler, priority, name, periodicity), cleanup(false) + TimerThread::TimerThread(int scheduler, int priority, const std::string& name, double periodicity, unsigned cpu_affinity) + : PeriodicThread(scheduler, priority, name, periodicity, cpu_affinity), cleanup(false) { tasks.reserve(MAX_ACTIVITIES); } diff --git a/src/TimerThread.hpp b/src/TimerThread.hpp index acc4f13..7233aae 100644 --- a/src/TimerThread.hpp +++ b/src/TimerThread.hpp @@ -84,7 +84,7 @@ namespace RTT * @param periodicity * The periodicity of this thread in seconds (e.g. 0.001 = 1000Hz ) */ - TimerThread(int priority, const std::string& name, double periodicity); + TimerThread(int priority, const std::string& name, double periodicity, unsigned cpu_affinity = ~0); /** * Create a periodic Timer thread with a given scheduler type. @@ -96,7 +96,7 @@ namespace RTT * @param periodicity * The periodicity of this thread in seconds (e.g. 0.001 = 1000Hz ) */ - TimerThread(int scheduler, int priority, const std::string& name, double periodicity); + TimerThread(int scheduler, int priority, const std::string& name, double periodicity, unsigned cpu_affinity = ~0); /** * Destructor @@ -120,6 +120,10 @@ namespace RTT * Create a TimerThread with a given scheduler, priority and periodicity. */ static TimerThreadPtr Instance(int scheduler, int priority, double periodicity); + /** + * Create a TimerThread with a given scheduler, priority and periodicity. + */ + static TimerThreadPtr Instance(int scheduler, int priority, double periodicity, unsigned cpu_affinity); protected: virtual bool initialize(); virtual void step(); diff --git a/src/os/PeriodicThread.cpp b/src/os/PeriodicThread.cpp index 4fe19f4..51775e2 100644 --- a/src/os/PeriodicThread.cpp +++ b/src/os/PeriodicThread.cpp @@ -168,6 +168,7 @@ namespace RTT PeriodicThread::PeriodicThread(int _priority, const std::string & name, Seconds periods, + unsigned cpu_affinity, RunnableInterface* r) : msched_type(ORO_SCHED_RT), running(false), prepareForExit(false), wait_for_step(true), runComp(r), @@ -177,12 +178,13 @@ namespace RTT ,d(NULL) #endif { - this->setup(_priority, name); + this->setup(_priority, cpu_affinity, name); } PeriodicThread::PeriodicThread(int scheduler, int _priority, const std::string & name, Seconds periods, + unsigned cpu_affinity, RunnableInterface* r) : msched_type(scheduler), running(false), prepareForExit(false), wait_for_step(true), runComp(r), @@ -192,10 +194,10 @@ namespace RTT ,d(NULL) #endif { - this->setup(_priority, name); + this->setup(_priority, cpu_affinity, name); } - void PeriodicThread::setup(int _priority, const std::string& name) + void PeriodicThread::setup(int _priority, unsigned cpu_affinity, const std::string& name) { Logger::In in("PeriodicThread"); int ret; @@ -236,7 +238,7 @@ namespace RTT } } #endif - int rv = rtos_task_create(&rtos_task, _priority, name.c_str(), msched_type, 0, periodicThread, this ); + int rv = rtos_task_create(&rtos_task, _priority, cpu_affinity, name.c_str(), msched_type, 0, periodicThread, this ); if ( rv != 0 ) { Logger::log() << Logger::Critical << "Could not create thread " << rtos_task_get_name(&rtos_task) <<"."<setup(_priority, name); + this->setup(_priority, cpu_affinity, name); } SingleThread::SingleThread(int scheduler, int _priority, const std::string& name, + unsigned cpu_affinity, RunnableInterface* r) : msched_type(scheduler), active(false), prepareForExit(false), @@ -158,10 +160,10 @@ namespace RTT , d(NULL) #endif { - this->setup(_priority, name); + this->setup(_priority, cpu_affinity, name); } - void SingleThread::setup(int _priority, const std::string& name) + void SingleThread::setup(int _priority, unsigned cpu_affinity, const std::string& name) { Logger::In in("SingleThread"); Logger::log() << Logger::Debug << "Creating." <setup(_priority, name); + this->setup(_priority, cpu_affinity, name); } - void Thread::setup(int _priority, const std::string& name) + void Thread::setup(int _priority, unsigned cpu_affinity, const std::string& name) { Logger::In in("Thread"); int ret; @@ -264,7 +264,7 @@ namespace RTT } } #endif - int rv = rtos_task_create(&rtos_task, _priority, name.c_str(), + int rv = rtos_task_create(&rtos_task, _priority, cpu_affinity, name.c_str(), msched_type, default_stack_size, thread_function, this); if (rv != 0) { @@ -283,6 +283,7 @@ namespace RTT Logger::In in2(modname); log(Info) << "Thread created with scheduler type '" << getScheduler() << "', priority " << getPriority() + << ", cpu affinity " << getCpuAffinity() << " and period " << getPeriod() << "." << endlog(); #ifdef OROPKG_OS_THREAD_SCOPE if (d) @@ -590,6 +591,16 @@ namespace RTT return period; } + bool Thread::setCpuAffinity(unsigned cpu_affinity) + { + return rtos_task_set_cpu_affinity(&rtos_task, cpu_affinity) == 0; + } + + unsigned Thread::getCpuAffinity() const + { + return rtos_task_get_cpu_affinity(&rtos_task); + } + void Thread::yield() { rtos_task_yield( &rtos_task ); diff --git a/src/os/Thread.hpp b/src/os/Thread.hpp index bcfa4be..72dbb77 100644 --- a/src/os/Thread.hpp +++ b/src/os/Thread.hpp @@ -124,11 +124,12 @@ namespace RTT * @param scheduler The scheduler, one of ORO_SCHED_RT or ORO_SCHED_OTHER. * @param priority The priority of the thread, this is interpreted by your RTOS. * @param period The period in seconds (eg 0.001) of the thread, or zero if not periodic. + * @param cpu_affinity The cpu affinity of the thread, this is interpreted by your RTOS. * @param name The name of the Thread. May be used by your OS to identify the thread. * @param r The optional RunnableInterface instance to run. If not present, * the thread's own virtual functions are executed. */ - Thread(int scheduler, int priority, double period, + Thread(int scheduler, int priority, double period, unsigned cpu_affinity, const std::string & name, OS::RunnableInterface* r = 0); @@ -193,6 +194,18 @@ namespace RTT virtual int getPriority() const; + /** + * Set cpu affinity for this thread + * @cpu_affinity The cpu affinity of the thread (@see rtos_task_set_cpu_affinity). + * @return true if the mask has been applied + */ + virtual bool setCpuAffinity(unsigned cpu_affinity); + + /** + * @return the cpu affinity (@see rtos_task_set_cpu_affinity) + */ + virtual unsigned getCpuAffinity() const; + virtual void yield(); void setMaxOverrun(int m); @@ -235,7 +248,7 @@ namespace RTT private: Thread(const Thread&); - void setup(int _priority, const std::string& name); + void setup(int _priority, unsigned cpu_affinity, const std::string& name); /** * Do configuration actions when the thread is stopped. diff --git a/src/os/ecos/fosi_internal.cpp b/src/os/ecos/fosi_internal.cpp index e5dd1f8..3f60845 100644 --- a/src/os/ecos/fosi_internal.cpp +++ b/src/os/ecos/fosi_internal.cpp @@ -57,6 +57,7 @@ namespace RTT INTERNAL_QUAL int rtos_task_create(RTOS_TASK * task, int priority, + unsigned cpu_affinity, const char * name, int sched_type, void * (*start_routine)(void *), @@ -200,6 +201,16 @@ namespace RTT return (int) cyg_thread_get_priority(t->handle); } + INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity) + { + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + return ~0; + } + INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* t, int sched_type) { if (sched_type == SCHED_ECOS_FIFO ) return 0; diff --git a/src/os/fosi_internal_interface.hpp b/src/os/fosi_internal_interface.hpp index 5cb6046..4b6e51b 100644 --- a/src/os/fosi_internal_interface.hpp +++ b/src/os/fosi_internal_interface.hpp @@ -81,6 +81,7 @@ namespace RTT { * @param task An uninitialised, by the user allocated struct which will be * used to store the task data in. * @param priority The priority of the thread, to be interpreted by the underlying RTOS. + * @param cpu_affinity The cpu affinity of the thread (@see rtos_task_set_cpu_affinity). * @param name The name for the thread, or null if none is given. * @param sched_type The scheduler type, one of ORO_SCHED_OTHER, ORO_SCHED_RT or a value * defined by your RTOS. @@ -92,6 +93,7 @@ namespace RTT { */ int rtos_task_create(RTOS_TASK* task, int priority, + unsigned cpu_affinity, const char * name, int sched_type, size_t stack_size, @@ -210,6 +212,23 @@ namespace RTT { int rtos_task_get_priority(const RTOS_TASK * task); /** + * Set the cpu affinity of a thread. + * @param task The thread to change the cpu affinity of + * @param cpu_affinity is a bit mask with the cpu this thread should be bound. + * The bit 0 is the cpu 0, the bit 1, the cpu 1 and so on. + * For example ((1 << 0) | (1 << 1)) will bound to cpu 0 and 1. + * @return 0 if the cpu affinity could be set. + */ + int rtos_task_set_cpu_affinity(RTOS_TASK * task,unsigned cpu_affinity); + + /** + * Return the cpu affinity of a thread. + * @param task The thread to get the cpu affinity + * @return the cpu affinity (@see rtos_task_set_cpu_affinity) + */ + unsigned rtos_task_get_cpu_affinity(const RTOS_TASK * task); + + /** * Returns the name by which a task is known in the RTOS. * @param task The task to query. * @return It's name. diff --git a/src/os/gnulinux/fosi_internal.cpp b/src/os/gnulinux/fosi_internal.cpp index 085f57c..1752021 100644 --- a/src/os/gnulinux/fosi_internal.cpp +++ b/src/os/gnulinux/fosi_internal.cpp @@ -76,6 +76,7 @@ namespace RTT INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task, int priority, + unsigned cpu_affinity, const char * name, int sched_type, size_t stack_size, @@ -121,6 +122,9 @@ namespace RTT rv = pthread_create(&(task->thread), &(task->attr), start_routine, obj); log(Debug) <<"Created Posix thread "<< task->thread <thread != 0) { + cpu_set_t cs; + CPU_ZERO(&cs); + for(unsigned i = 0; i < sizeof(cpu_affinity); i++) + { + if(cpu_affinity & (1 << i)) { CPU_SET(i, &cs); } + } + return pthread_setaffinity_np(task->thread, sizeof(cs), &cs); + } + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + if( task && task->thread != 0) { + unsigned cpu_affinity = 0; + cpu_set_t cs; + pthread_getaffinity_np(task->thread, sizeof(cs), &cs); + for(unsigned i = 0; i < sizeof(cpu_affinity); i++) + { + if(CPU_ISSET(i, &cs)) { cpu_affinity |= (1 << i); } + } + return cpu_affinity; + } + return ~0; + } + INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* task) { return task->name; diff --git a/src/os/lxrt/fosi_internal.cpp b/src/os/lxrt/fosi_internal.cpp index 3d1cf51..a6e630c 100644 --- a/src/os/lxrt/fosi_internal.cpp +++ b/src/os/lxrt/fosi_internal.cpp @@ -190,6 +190,7 @@ namespace RTT INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task, int priority, + unsigned cpu_affinity, const char* name, int sched_type, size_t stack_size, @@ -371,6 +372,15 @@ namespace RTT return t->priority; } + INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity) + { + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + return ~0; + } } }} #undef INTERNAL_QUAL diff --git a/src/os/macosx/fosi_internal.cpp b/src/os/macosx/fosi_internal.cpp index a75c0f4..2826cca 100644 --- a/src/os/macosx/fosi_internal.cpp +++ b/src/os/macosx/fosi_internal.cpp @@ -67,6 +67,7 @@ namespace RTT INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task, int priority, + unsigned cpu_affinity, const char * name, int sched_type, size_t stack_size, @@ -241,6 +242,16 @@ namespace RTT return param.sched_priority; } + INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity) + { + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + return ~0; + } + INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* task) { return task->name; diff --git a/src/os/win32/fosi_internal.cpp b/src/os/win32/fosi_internal.cpp index f40a9df..3e929cd 100644 --- a/src/os/win32/fosi_internal.cpp +++ b/src/os/win32/fosi_internal.cpp @@ -136,6 +136,7 @@ void ErrorHandler(LPTSTR lpszFunction) INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task, int priority, const char * name, + unsigned cpu_affinity, int sched_type, unsigned int stack_size, void * (*start_routine)(void *), @@ -309,6 +310,16 @@ void ErrorHandler(LPTSTR lpszFunction) return GetThreadPriority(t->handle); } + INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity) + { + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + return ~0; + } + INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* t) { /* printf("Get Name: "); diff --git a/src/os/xenomai/fosi_internal.cpp b/src/os/xenomai/fosi_internal.cpp index 85d6f3d..bc494a4 100644 --- a/src/os/xenomai/fosi_internal.cpp +++ b/src/os/xenomai/fosi_internal.cpp @@ -188,6 +188,7 @@ namespace RTT INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task, int priority, + unsigned cpu_affinity, const char* name, int sched_type, size_t stack_size, @@ -352,6 +353,16 @@ namespace RTT return 0; } + INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity) + { + return -1; + } + + INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task) + { + return ~0; + } + INTERNAL_QUAL const char* rtos_task_get_name(const RTOS_TASK* mytask) { return mytask->name; } diff --git a/tests/buffers_test.cpp b/tests/buffers_test.cpp index df01fe9..646ad16 100644 --- a/tests/buffers_test.cpp +++ b/tests/buffers_test.cpp @@ -684,10 +684,10 @@ BOOST_AUTO_TEST_CASE( testListLockFree ) LLFGrower* grower = new LLFGrower( listlockfree ); { - boost::scoped_ptr athread( new Thread(ORO_SCHED_OTHER, 0, 0, "ThreadA", aworker )); - boost::scoped_ptr bthread( new Thread(ORO_SCHED_OTHER, 0, 0, "ThreadB", bworker )); - boost::scoped_ptr cthread( new Thread(ORO_SCHED_OTHER, 0, 0, "ThreadC", cworker )); - boost::scoped_ptr gthread( new Thread(ORO_SCHED_OTHER, 0, 0, "ThreadG", grower )); + boost::scoped_ptr athread( new Thread(ORO_SCHED_OTHER, 0, 0, ~0, "ThreadA", aworker )); + boost::scoped_ptr bthread( new Thread(ORO_SCHED_OTHER, 0, 0, ~0, "ThreadB", bworker )); + boost::scoped_ptr cthread( new Thread(ORO_SCHED_OTHER, 0, 0, ~0, "ThreadC", cworker )); + boost::scoped_ptr gthread( new Thread(ORO_SCHED_OTHER, 0, 0, ~0, "ThreadG", grower )); athread->start(); bthread->start(); @@ -741,10 +741,10 @@ BOOST_AUTO_TEST_CASE( testAtomicQueue ) AQGrower* grower = new AQGrower( qt ); { - boost::scoped_ptr athread( new SingleThread(20,"ThreadA", aworker )); - boost::scoped_ptr bthread( new SingleThread(20,"ThreadB", bworker )); - boost::scoped_ptr cthread( new SingleThread(20,"ThreadC", cworker )); - boost::scoped_ptr gthread( new SingleThread(20,"ThreadG", grower )); + boost::scoped_ptr athread( new SingleThread(20,"ThreadA", ~0, aworker )); + boost::scoped_ptr bthread( new SingleThread(20,"ThreadB", ~0, bworker )); + boost::scoped_ptr cthread( new SingleThread(20,"ThreadC", ~0, cworker )); + boost::scoped_ptr gthread( new SingleThread(20,"ThreadG", ~0, grower )); // avoid system lock-ups athread->setScheduler(ORO_SCHED_OTHER); diff --git a/tests/logger_test.cpp b/tests/logger_test.cpp index e56dd3a..2c5533f 100644 --- a/tests/logger_test.cpp +++ b/tests/logger_test.cpp @@ -104,9 +104,9 @@ BOOST_AUTO_TEST_CASE( testNewLog ) BOOST_AUTO_TEST_CASE( testThreadLog ) { boost::scoped_ptr run( new TestLog() ); - boost::scoped_ptr t( new RTT::OS::PeriodicThread(25,"ORThread1", 0.001) ); + boost::scoped_ptr t( new RTT::OS::PeriodicThread(25,"ORThread1", 0.001, ~0) ); boost::scoped_ptr run2( new TestLog() ); - boost::scoped_ptr t2( new RTT::OS::PeriodicThread(25,"ORThread2", 0.001) ); + boost::scoped_ptr t2( new RTT::OS::PeriodicThread(25,"ORThread2", 0.001, ~0) ); t->run( run.get() ); t2->run( run2.get() ); diff --git a/tests/tasks_test.cpp b/tests/tasks_test.cpp index 26248ca..cc65e21 100644 --- a/tests/tasks_test.cpp +++ b/tests/tasks_test.cpp @@ -260,7 +260,7 @@ BOOST_AUTO_TEST_CASE( testOverrun ) bool r = false; // create boost::scoped_ptr run( new TestOverrun() ); - boost::scoped_ptr t( new RTT::OS::PeriodicThread(25,"ORThread", 0.1) ); + boost::scoped_ptr t( new RTT::OS::PeriodicThread(25,"ORThread", 0.1, ~0) ); //BOOST_CHECK_EQUAL(25,t->getPriority() ); BOOST_CHECK_EQUAL(0.1,t->getPeriod() ); t->setMaxOverrun(1); @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE( testThread ) // create boost::scoped_ptr run( new TestPeriodic() ); - boost::scoped_ptr t( new RTT::OS::Thread(ORO_SCHED_RT, RTT::OS::HighestPriority, 0.1, "PThread") ); + boost::scoped_ptr t( new RTT::OS::Thread(ORO_SCHED_RT, RTT::OS::HighestPriority, 0.1, ~0, "PThread") ); t->run( run.get() ); if ( t->getScheduler() == RTT::OS::HighestPriority) { @@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE( testThreads ) // create boost::scoped_ptr run( new TestPeriodic() ); - boost::scoped_ptr t( new RTT::OS::PeriodicThread(RTT::OS::HighestPriority,"PThread", 0.1) ); + boost::scoped_ptr t( new RTT::OS::PeriodicThread(RTT::OS::HighestPriority,"PThread", 0.1, ~0) ); t->run( run.get() ); if ( t->getScheduler() == RTT::OS::HighestPriority) { -- 1.7.4.4