diff options
author | Tom Rondeau | 2012-12-19 13:37:39 -0500 |
---|---|---|
committer | Nicholas Corgan | 2013-02-06 12:35:06 -0800 |
commit | 7bc415bd2875132ce321c5913950d23e7c9ad8b1 (patch) | |
tree | 5ec7d0123da3e94e6ed8d99c4daa83073acb15fb /gruel | |
parent | bb156c4879fadecbe9ab45085736c1b52552efe6 (diff) | |
download | gnuradio-7bc415bd2875132ce321c5913950d23e7c9ad8b1.tar.gz gnuradio-7bc415bd2875132ce321c5913950d23e7c9ad8b1.tar.bz2 gnuradio-7bc415bd2875132ce321c5913950d23e7c9ad8b1.zip |
gruel: adding wrapper layer for gruel threads to enable setting thread affinity.
Working in Linux; programmed for Windows (but untested); nops for OSX.
Diffstat (limited to 'gruel')
-rw-r--r-- | gruel/src/include/gruel/thread.h | 19 | ||||
-rw-r--r-- | gruel/src/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gruel/src/lib/thread.cc | 223 |
3 files changed, 242 insertions, 1 deletions
diff --git a/gruel/src/include/gruel/thread.h b/gruel/src/include/gruel/thread.h index 63143c8b4..72499808c 100644 --- a/gruel/src/include/gruel/thread.h +++ b/gruel/src/include/gruel/thread.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2009-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,6 +26,7 @@ #include <boost/thread/mutex.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/condition_variable.hpp> +#include <vector> namespace gruel { @@ -34,6 +35,22 @@ namespace gruel { typedef boost::mutex::scoped_lock scoped_lock; typedef boost::condition_variable condition_variable; +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + typedef HANDLE gr_thread_t; +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + typedef pthread_t gr_thread_t; +#else + typedef pthread_t gr_thread_t; +#endif + + GRUEL_API gr_thread_t get_current_thread_id(); + GRUEL_API void thread_bind_to_processor(const std::vector<unsigned int> &mask); + GRUEL_API void thread_bind_to_processor(unsigned int n); + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask); + GRUEL_API void thread_bind_to_processor(gr_thread_t thread, unsigned int n); + GRUEL_API void thread_unbind(); + GRUEL_API void thread_unbind(gr_thread_t thread); + } /* namespace gruel */ #endif /* INCLUDED_THREAD_H */ diff --git a/gruel/src/lib/CMakeLists.txt b/gruel/src/lib/CMakeLists.txt index e33b80d64..717d56660 100644 --- a/gruel/src/lib/CMakeLists.txt +++ b/gruel/src/lib/CMakeLists.txt @@ -76,6 +76,7 @@ link_directories(${Boost_LIBRARY_DIRS}) list(APPEND gruel_sources realtime.cc sys_pri.cc + thread.cc thread_body_wrapper.cc thread_group.cc ) diff --git a/gruel/src/lib/thread.cc b/gruel/src/lib/thread.cc new file mode 100644 index 000000000..46ba1745a --- /dev/null +++ b/gruel/src/lib/thread.cc @@ -0,0 +1,223 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gruel/thread.h> + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#include <Windows.h> + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + return GetCurrentThread(); + } + + void + thread_bind_to_processor(unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(const std::vector<unsigned int> &mask) + { + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(thread, mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + //DWORD_PTR mask = (1 << n); + DWORD_PTR mask = 0; + + std::vector<unsigned int> _mask = mask; + std::vector<unsigned int>::iterator itr; + for(itr = _mask.begin(); itr != _mask.end(); itr++) + mask |= (1 << (*itr)); + + DWORD_PTR ret = SetThreadAffinityMask(thread, mask); + if(ret == 0) { + std::stringstream s; + s << "thread_bind_to_processor failed with error: " << GetLastError() << std::endl; + throw std::runtime_error(s.str()); + } + } + + void + thread_unbind() + { + thread_bind_unbind(get_current_thread_id()); + } + + void + thread_unbind(gr_thread_t thread) + { + DWORD_PTR mask = sizeof(DWORD_PTR) - 1; + DWORD_PTR ret = SetThreadAffinityMask(thread, mask); + if(ret == 0) { + std::stringstream s; + s << "thread_unbind failed with error: " << GetLastError() << std::endl; + throw std::runtime_error(s.str()); + } + } +} /* namespace gruel */ + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(unsigned int n) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + // Not implemented on OSX + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + + void + thread_unbind() + { + // Not implemented on OSX + } + + void + thread_unbind(gr_thread_t thread) + { + // Not implemented on OSX + } +} /* namespace gruel */ + +#else + +#include <sstream> +#include <stdexcept> +#include <pthread.h> + +namespace gruel { + + gr_thread_t + get_current_thread_id() + { + return pthread_self(); + } + + void + thread_bind_to_processor(unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(const std::vector<unsigned int> &mask) + { + thread_bind_to_processor(get_current_thread_id(), mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, unsigned int n) + { + std::vector<unsigned int> mask(1, n); + thread_bind_to_processor(thread, mask); + } + + void + thread_bind_to_processor(gr_thread_t thread, const std::vector<unsigned int> &mask) + { + cpu_set_t set; + size_t len = sizeof(cpu_set_t); + std::vector<unsigned int> _mask = mask; + std::vector<unsigned int>::iterator itr; + + CPU_ZERO(&set); + for(itr = _mask.begin(); itr != _mask.end(); itr++) + CPU_SET(*itr, &set); + + int ret = pthread_setaffinity_np(thread, len, &set); + if(ret != 0) { + std::stringstream s; + s << "thread_bind_to_processor failed with error: " << ret << std::endl; + throw std::runtime_error(s.str()); + } + } + + void + thread_unbind() + { + thread_unbind(get_current_thread_id()); + } + + void + thread_unbind(gr_thread_t thread) + { + cpu_set_t set; + size_t len = sizeof(cpu_set_t); + + CPU_ZERO(&set); + long ncpus = sysconf(_SC_NPROCESSORS_ONLN); + for(long n = 0; n < ncpus; n++) { + CPU_SET(n, &set); + } + + int ret = pthread_setaffinity_np(thread, len, &set); + if(ret != 0) { + std::stringstream s; + s << "thread_unbind failed with error: " << ret << std::endl; + throw std::runtime_error(s.str()); + } + } +} /* namespace gruel */ + +#endif |