From 6f53918f87fae34a813b69284d5816dc9a2885b1 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 12 Aug 2010 19:15:29 +0200 Subject: [PATCH] Fixed: #1069 Thread/process CPU affinity Implementation for Linux --- code/nel/include/nel/misc/p_thread.h | 2 - code/nel/include/nel/misc/thread.h | 6 +-- code/nel/src/misc/p_thread.cpp | 61 +++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/code/nel/include/nel/misc/p_thread.h b/code/nel/include/nel/misc/p_thread.h index 470fdecff..cd027aa37 100644 --- a/code/nel/include/nel/misc/p_thread.h +++ b/code/nel/include/nel/misc/p_thread.h @@ -62,7 +62,6 @@ private: uint8 _State; // 0=not created, 1=started, 2=finished uint32 _StackSize; pthread_t _ThreadHandle; - }; /** @@ -77,7 +76,6 @@ public: virtual ~CPProcess() {} virtual uint64 getCPUMask(); virtual bool setCPUMask(uint64 mask); - }; } // NLMISC diff --git a/code/nel/include/nel/misc/thread.h b/code/nel/include/nel/misc/thread.h index 280f31d32..1db92cbff 100644 --- a/code/nel/include/nel/misc/thread.h +++ b/code/nel/include/nel/misc/thread.h @@ -111,20 +111,18 @@ public: /** * Set the CPU mask of this thread. Thread must have been started before. * The mask must be a subset of the CPU mask returned by IProcess::getCPUMask() thread process. - * Not implemented under Linux. */ virtual bool setCPUMask(uint64 cpuMask)=0; /** * Get the CPU mask of this thread. Thread must have been started before. * The mask should be a subset of the CPU mask returned by IProcess::getCPUMask() thread process. - * Not implemented under Linux. */ virtual uint64 getCPUMask()=0; /** * Get the thread user name. - * Not implemented under linux, under windows return the name of the logon user. + * Under Linux return thread owner, under windows return the name of the logon user. */ virtual std::string getUserName()=0; }; @@ -158,13 +156,11 @@ public: /** * Return process CPU mask. Each bit stand for a CPU usable by the process threads. - * Not implemented under Linux. */ virtual uint64 getCPUMask()=0; /** * Set the process CPU mask. Each bit stand for a CPU usable by the process threads. - * Not implemented under Linux. */ virtual bool setCPUMask(uint64 mask)=0; }; diff --git a/code/nel/src/misc/p_thread.cpp b/code/nel/src/misc/p_thread.cpp index ec6c6dfba..9b246e89d 100644 --- a/code/nel/src/misc/p_thread.cpp +++ b/code/nel/src/misc/p_thread.cpp @@ -21,6 +21,8 @@ #include "nel/misc/p_thread.h" +#include +#include namespace NLMISC { @@ -147,6 +149,16 @@ void CPThread::wait () */ bool CPThread::setCPUMask(uint64 cpuMask) { +#ifdef __USE_GNU + sint res = pthread_setaffinity_np(_ThreadHandle, sizeof(uint64), (const cpu_set_t*)&cpuMask); + + if (res) + { + nlwarning("pthread_setaffinity_np() returned %d", res); + return false; + } +#endif // __USE_GNU + return true; } @@ -155,7 +167,19 @@ bool CPThread::setCPUMask(uint64 cpuMask) */ uint64 CPThread::getCPUMask() { - return 1; + uint64 cpuMask = 1; + +#ifdef __USE_GNU + sint res = pthread_getaffinity_np(_ThreadHandle, sizeof(uint64), (cpu_set_t*)&cpuMask); + + if (res) + { + nlwarning("pthread_getaffinity_np() returned %d", res); + return 0; + } +#endif // __USE_GNU + + return cpuMask; } /* @@ -163,7 +187,12 @@ uint64 CPThread::getCPUMask() */ std::string CPThread::getUserName() { - return "Not implemented"; + struct passwd *pw = getpwuid(getuid()); + + if (!pw) + return ""; + + return pw->pw_name; } @@ -183,13 +212,35 @@ IProcess *IProcess::getCurrentProcess () */ uint64 CPProcess::getCPUMask() { - return 1; + uint64 cpuMask = 1; + +#ifdef __USE_GNU + sint res = sched_getaffinity(getpid(), sizeof(uint64), (cpu_set_t*)&cpuMask); + + if (res) + { + nlwarning("sched_getaffinity() returned %d, errno = %d: %s", res, errno, strerror(errno)); + return 0; + } +#endif // __USE_GNU + + return cpuMask; } /// set the CPU mask -bool CPProcess::setCPUMask(uint64 mask) +bool CPProcess::setCPUMask(uint64 cpuMask) { - return 1; +#ifdef __USE_GNU + sint res = sched_setaffinity(getpid(), sizeof(uint64), (const cpu_set_t*)&cpuMask); + + if (res) + { + nlwarning("sched_setaffinity() returned %d, errno = %d: %s", res, errno, strerror(errno)); + return false; + } +#endif // __USE_GNU + + return true; }