diff --git a/ethread/tools.cpp b/ethread/tools.cpp new file mode 100644 index 0000000..5e55f5e --- /dev/null +++ b/ethread/tools.cpp @@ -0,0 +1,180 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include + +static std::mutex g_lock; +static std::map& getThreadList() { + static std::map g_val; + return g_val; +} + +static uint32_t getThreadHumanId(std::thread::id _id) { + uint32_t out = 0; + uint64_t iddd = std::hash()(_id); + g_lock.lock(); + static std::map g_list; + std::map::iterator it = g_list.find(iddd); + if (it == g_list.end()) { + // attribute new ID : + static uint32_t tmpId = 0; + g_list.insert(std::pair(iddd,tmpId)); + out = tmpId; + tmpId++; + } else { + out = it->second; + } + g_lock.unlock(); + return out; + +} + +static std::string getThreadName(std::thread::id _id) { + std::map& list = getThreadList(); + uint32_t threadID = getThreadHumanId(_id); + std::string out; + g_lock.lock(); + std::map::iterator it = list.find(threadID); + if (it != list.end()) { + out = it->second; + } + g_lock.unlock(); + return out; +} + +static void setThreadName(std::thread* _thread, const std::string& _name) { + std::map& list = getThreadList(); + uint32_t threadID = ethread::getId(); + g_lock.lock(); + std::map::iterator it = list.find(threadID); + if (it == list.end()) { + list.insert(std::pair(threadID, _name)); + } else { + it->second = _name; + } + g_lock.unlock(); + // try now to set the thread name with Pthread + #if defined(__TARGET_OS__Linux) + pthread_t pthreadID; + if (_thread == nullptr) { + pthreadID = pthread_self(); + } else { + pthreadID = (pthread_t) _thread->native_handle(); + } + std::string name = _name; + if (name.size() > 15) { + name.resize(15); + } + if (pthread_setname_np(pthreadID, name.c_str()) < 0) { + //TODO: TK_ERROR("Error when setting the Name in the OS thread naming"); + } + #else + //TODO: TK_INFO("Can not set the thread name in this OS (local set)"); + #endif +} + +uint32_t ethread::getId() { + return getThreadHumanId(std::this_thread::get_id()); +} + +uint32_t ethread::getId(std::thread& _thread) { + return getThreadHumanId(_thread.get_id()); +} + +void ethread::setName(const std::string& _name) { + setThreadName(nullptr, _name); +} + +void ethread::setName(std::thread& _thread, const std::string& _name) { + setThreadName(&_thread, _name); +} + +std::string ethread::getName() { + return getThreadName(std::this_thread::get_id()); +} + +std::string ethread::getName(std::thread& _thread) { + return getThreadName(_thread.get_id()); +} + +#if defined(__TARGET_OS__Linux) + static void setThreadPriority(pthread_t _threadID, int32_t _priority) { + int retcode; + int policy; + struct sched_param param; + retcode = pthread_getschedparam(_threadID, &policy, ¶m); + if (retcode != 0) { + //TODO: TK_ERROR("Can not get prioriry " << ((retcode == ESRCH) ? "WRONG THREAD ID (ESRCH)" :"???") ); + return; + } + //TODO: TK_INFO("Try to set the thread proiority at :" << _priority); + policy = SCHED_OTHER; + if (_priority < 0) { + _priority *= -1; + policy = SCHED_FIFO; + } + param.sched_priority = _priority; + retcode = pthread_setschedparam(_threadID, policy, ¶m); + if (retcode != 0) { + /* TODO: TK_ERROR("Can not set prioriry " << ((retcode == ESRCH) ? "WRONG THREAD ID (ESRCH)" : + (retcode == EINVAL) ? "WRONG POLICY (EINVAL)" : + (retcode == EPERM) ? "NO PRIVILEGE (EPERM)" : + "???") ); + */ + } + } + static int32_t getThreadPriority(pthread_t _threadID) { + int retcode; + int policy; + struct sched_param param; + retcode = pthread_getschedparam(_threadID, &policy, ¶m); + if (retcode != 0) { + //TODO: TK_ERROR("Can not get prioriry " << ((retcode == ESRCH) ? "WRONG THREAD ID (ESRCH)" : "???") ); + return 20; + } + if (policy != SCHED_OTHER) { + return -param.sched_priority; + } + return param.sched_priority; + } +#endif + + +void ethread::setPriority(int32_t _priority) { + #if defined(__TARGET_OS__Linux) + pthread_t threadID = pthread_self(); + setThreadPriority(threadID, _priority); + #endif +} + +void ethread::setPriority(std::thread& _thread, int32_t _priority) { + #if defined(__TARGET_OS__Linux) + pthread_t threadID = (pthread_t) _thread.native_handle(); + setThreadPriority(threadID, _priority); + #endif +} + +int32_t ethread::getPriority() { + #if defined(__TARGET_OS__Linux) + pthread_t threadID = pthread_self(); + return getThreadPriority(threadID); + #else + return 20; + #endif +} + +int32_t ethread::getPriority(std::thread& _thread) { + #if defined(__TARGET_OS__Linux) + pthread_t threadID = static_cast(_thread.native_handle()); + return getThreadPriority(threadID); + #else + return 20; + #endif +} diff --git a/ethread/tools.h b/ethread/tools.h new file mode 100644 index 0000000..63be3c6 --- /dev/null +++ b/ethread/tools.h @@ -0,0 +1,70 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include + +namespace ethread { + /** + * @brief get human readable thread ID. (not the std::thread::get_id()) + * @return the ID of the thread. + */ + uint32_t getId(); + /** + * @brief get human readable thread ID. (not the std::thread::get_id()) + * @param[in] _thread Thread handle + * @return the ID of the thread. + */ + uint32_t getId(std::thread& _thread); + /** + * @brief Set the Current thread name + * @param[in] _name New name of the thread + */ + void setName(const std::string& _name); + /** + * @brief Set an other thread name + * @param[in] _thread Thread handle + * @param[in] _name New name of the thread + */ + void setName(std::thread& _thread, const std::string& _name); + /** + * @brief Set the Current thread name + * @return The current name of the thread + */ + std::string getName(); + /** + * @brief Get an other thread name + * @praram[in] _thread Thread handle + * @return The external thread name of the thread + */ + std::string getName(std::thread& _thread); + /** + * @brief Set the Current thread priority [-20..0] for RT and ]0..50] for normal priority + * @param[in] _priority New priority of the thread + * @note If your process have not the right to change thread name, it does not work + */ + void setPriority(int32_t _priority); + /** + * @brief Set an other thread priority [-20..0] for RT and ]0..50] for normal priority + * @param[in] _thread Thread handle + * @param[in] _priority New priority of the thread + * @note If your process have not the right to change thread name, it does not work + */ + void setPriority(std::thread& _thread, int32_t _priority); + /** + * @brief get the Current thread priority [-20..0] for RT and ]0..50] for normal priority + * @return current priority of the thread + */ + int32_t getPriority(); + /** + * @brief Get an other thread priority [-20..0] for RT and ]0..50] for normal priority + * @param[in] _thread Thread handle + * @return current priority of the thread + */ + int32_t getPriority(std::thread& _thread); +} diff --git a/lutin_ethread.py b/lutin_ethread.py new file mode 100644 index 0000000..dafbb91 --- /dev/null +++ b/lutin_ethread.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "LIBRARY" + +def get_desc(): + return "Ewol thread tools" + +def get_licence(): + return "APACHE-2" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def get_version(): + return [0,1,"dev"] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.add_extra_compile_flags() + # add the file to compile: + my_module.add_src_file([ + 'ethread/tools.cpp', + ]) + + my_module.add_header_file([ + 'ethread/tools.h', + ]) + + # build in C++ mode + my_module.compile_version("c++", 2011) + # add dependency of the generic C++ library: + my_module.add_module_depend('cxx') + + my_module.add_path(tools.get_current_path(__file__)) + return my_module + +