diff options
Diffstat (limited to 'gruel/src/lib/thread.cc')
-rw-r--r-- | gruel/src/lib/thread.cc | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/gruel/src/lib/thread.cc b/gruel/src/lib/thread.cc new file mode 100644 index 000000000..8ebe822fb --- /dev/null +++ b/gruel/src/lib/thread.cc @@ -0,0 +1,226 @@ +/* -*- 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 dword_mask = 0; + + std::vector<unsigned int> _mask = mask; + std::vector<unsigned int>::iterator itr; + for(itr = _mask.begin(); itr != _mask.end(); itr++) + dword_mask |= (1 << (*itr)); + + DWORD_PTR ret = SetThreadAffinityMask(thread, dword_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_unbind(get_current_thread_id()); + } + + void + thread_unbind(gr_thread_t thread) + { + DWORD_PTR dword_mask = sizeof(DWORD_PTR) - 1; + DWORD_PTR ret = SetThreadAffinityMask(thread, dword_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(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) + { + // Not implemented on OSX + } + + 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 |