summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-06-16 18:40:44 -0700
committerJosh Blum <josh@joshknows.com>2010-06-16 18:40:44 -0700
commit168ab7279cec925e3db3e943e35d0d2bd220d8b3 (patch)
tree6b86a586c332d2610ff2ae59ddda2a09c6ea7877 /host
parenta89d684ba2b81c6e18d348965dffb919edb56fea (diff)
downloaduhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.tar.gz
uhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.tar.bz2
uhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.zip
uhd: work on thread priority scheduling
Diffstat (limited to 'host')
-rw-r--r--host/docs/general.rst8
-rw-r--r--host/include/uhd/utils/CMakeLists.txt1
-rw-r--r--host/include/uhd/utils/thread_priority.hpp58
-rw-r--r--host/lib/CMakeLists.txt41
-rw-r--r--host/lib/load_modules.cpp4
-rw-r--r--host/lib/sched.cpp45
-rw-r--r--host/lib/thread_priority.cpp93
-rw-r--r--host/lib/transport/if_addrs.cpp6
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp2
9 files changed, 193 insertions, 65 deletions
diff --git a/host/docs/general.rst b/host/docs/general.rst
index 7d1f467a0..6b309cba0 100644
--- a/host/docs/general.rst
+++ b/host/docs/general.rst
@@ -58,14 +58,12 @@ Misc notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Process scheduling
+Thread priority scheduling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The UHD will try to automatically boost the process's scheduling priority.
-Currently, this is only supported on platforms with *sched.h*.
-
+When the UHD spawns a new thread it may try to boost the thread's scheduling priority.
When setting the priority fails, the UHD prints out an error.
-This error is harmless, it simply means that your process will have a normal scheduling priority.
+This error is harmless, it simply means that the thread will have a normal scheduling priority.
**Linux Notes:**
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt
index 3684fd6e7..c98eec639 100644
--- a/host/include/uhd/utils/CMakeLists.txt
+++ b/host/include/uhd/utils/CMakeLists.txt
@@ -25,5 +25,6 @@ INSTALL(FILES
props.hpp
safe_main.hpp
static.hpp
+ thread_priority.hpp
DESTINATION ${INCLUDE_DIR}/uhd/utils
)
diff --git a/host/include/uhd/utils/thread_priority.hpp b/host/include/uhd/utils/thread_priority.hpp
new file mode 100644
index 000000000..988fc3012
--- /dev/null
+++ b/host/include/uhd/utils/thread_priority.hpp
@@ -0,0 +1,58 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP
+#define INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ static const float default_thread_priority = float(0.5);
+
+ /*!
+ * Set the scheduling priority on the current thread.
+ *
+ * A new thread or calling process should make this call
+ * with the defailts this to enable realtime scheduling.
+ *
+ * A priority of zero corresponds to normal priority.
+ * Positive priority values are higher than normal.
+ * Negative priority values are lower than normal.
+ *
+ * \param priority a value between -1 and 1
+ * \param realtime true to use realtime mode
+ * \throw exception on set priority failure
+ */
+ UHD_API void set_thread_priority(
+ float priority = default_thread_priority,
+ bool realtime = true
+ );
+
+ /*!
+ * Set the scheduling priority on the current thread.
+ * Same as set_thread_priority but does not throw on failure.
+ * \return true on success, false on failure
+ */
+ UHD_API bool set_thread_priority_safe(
+ float priority = default_thread_priority,
+ bool realtime = true
+ );
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 50787f6a2..d13c43bfb 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -76,17 +76,38 @@ INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp2/CMakeLists.txt)
########################################################################
# Setup defines for process scheduling
########################################################################
-MESSAGE(STATUS "Configuring process scheduling...")
+MESSAGE(STATUS "Configuring priority scheduling...")
+
+INCLUDE(CheckCXXSourceCompiles)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <pthread.h>
+ int main(){
+ struct sched_param sp;
+ pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
+ return 0;
+ }
+ " HAVE_PTHREAD_SETSCHEDPARAM
+)
-INCLUDE(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(sched.h HAVE_SCHED_H)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <windows.h>
+ int main(){
+ SetThreadPriority(GetCurrentThread(), 0);
+ SetPriorityClass(GetCurrentProcess(), 0);
+ return 0;
+ }
+ " HAVE_WIN_SETTHREADPRIORITY
+)
-IF(HAVE_SCHED_H)
- MESSAGE(STATUS " Process scheduling supported through sched_setscheduler.")
- ADD_DEFINITIONS(-DHAVE_SCHED_H)
-ELSE(HAVE_SCHED_H)
- MESSAGE(STATUS " Process scheduling not supported.")
-ENDIF(HAVE_SCHED_H)
+IF(HAVE_PTHREAD_SETSCHEDPARAM)
+ MESSAGE(STATUS " Priority scheduling supported through pthread_setschedparam.")
+ ADD_DEFINITIONS(-DHAVE_PTHREAD_SETSCHEDPARAM)
+ELSEIF(HAVE_WIN_SETTHREADPRIORITY)
+ MESSAGE(STATUS " Priority scheduling supported through windows SetThreadPriority.")
+ ADD_DEFINITIONS(-DHAVE_WIN_SETTHREADPRIORITY)
+ELSE(HAVE_PTHREAD_SETSCHEDPARAM)
+ MESSAGE(STATUS " Priority scheduling not supported.")
+ENDIF(HAVE_PTHREAD_SETSCHEDPARAM)
########################################################################
# Setup defines for module loading
@@ -114,7 +135,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gain_handler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/sched.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp
${CMAKE_CURRENT_SOURCE_DIR}/types.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
index d6bfe1369..dbb8d0695 100644
--- a/host/lib/load_modules.cpp
+++ b/host/lib/load_modules.cpp
@@ -30,7 +30,7 @@ namespace fs = boost::filesystem;
/***********************************************************************
* Module Load Function
**********************************************************************/
-#ifdef HAVE_DLFCN_H
+#if defined(HAVE_DLFCN_H)
#include <dlfcn.h>
static const std::string env_path_sep = ":";
@@ -42,7 +42,7 @@ static void load_module(const std::string &file_name){
}
}
-#elif HAVE_WINDOWS_H
+#elif defined(HAVE_WINDOWS_H)
#include <windows.h>
static const std::string env_path_sep = ";";
diff --git a/host/lib/sched.cpp b/host/lib/sched.cpp
deleted file mode 100644
index 712014c9c..000000000
--- a/host/lib/sched.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program 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 of the License, or
-// (at your option) any later version.
-//
-// This program 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, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/static.hpp>
-#include <stdexcept>
-#include <iostream>
-
-#ifdef HAVE_SCHED_H
-#include <sched.h>
-
-/*
- * # /etc/security/limits.conf
-#
-@usrp - rtprio 99
-*/
-
-UHD_STATIC_BLOCK(setup_process_sched){
- try{
- int policy = SCHED_RR;
- int max_pri = sched_get_priority_max(policy);
- if (max_pri == -1) throw std::runtime_error("sched_get_priority_max with SCHED_RR failed");
- sched_param sp; sp.sched_priority = max_pri;
- int ss_ret = sched_setscheduler(0, policy, &sp);
- if (ss_ret == -1) throw std::runtime_error("sched_setscheduler with SCHED_RR failed");
- }
- catch(const std::exception &e){
- std::cerr << "Process scheduling error: " << e.what() << std::endl;
- }
-}
-
-#endif /* HAVE_SCHED_H */
diff --git a/host/lib/thread_priority.cpp b/host/lib/thread_priority.cpp
new file mode 100644
index 000000000..ff3c1528b
--- /dev/null
+++ b/host/lib/thread_priority.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program 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 of the License, or
+// (at your option) any later version.
+//
+// This program 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <stdexcept>
+#include <iostream>
+
+bool uhd::set_thread_priority_safe(float priority, bool realtime){
+ try{
+ set_thread_priority(priority, realtime);
+ return true;
+ }catch(const std::exception &e){
+ std::cerr << "set_thread_priority: " << e.what() << std::endl;
+ return false;
+ }
+}
+
+static void check_priority_range(float priority){
+ if (priority > +1.0 or priority < -1.0)
+ throw std::range_error("priority out of range [-1.0, +1.0]");
+}
+
+/***********************************************************************
+ * Pthread API to set priority
+ **********************************************************************/
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM)
+ #include <pthread.h>
+
+ void uhd::set_thread_priority(float priority, bool realtime){
+ check_priority_range(priority);
+
+ //when realtime is not enabled, use sched other
+ int policy = (realtime)? SCHED_RR : SCHED_OTHER;
+
+ //we cannot have below normal priority, set to zero and use other policy
+ if (priority < 0){
+ priority = 0;
+ policy = SCHED_OTHER;
+ }
+
+ //get the priority bounds for the selected policy
+ int min_pri = sched_get_priority_min(policy);
+ int max_pri = sched_get_priority_max(policy);
+ if (min_pri == -1 or max_pri == -1) throw std::runtime_error("error in sched_get_priority_min/max");
+
+ //set the new priority and policy
+ sched_param sp;
+ sp.sched_priority = int(priority*(max_pri - min_pri)) + min_pri;
+ int ret = pthread_setschedparam(pthread_self(), policy, &sp);
+ if (ret == -1) throw std::runtime_error("error in pthread_setschedparam");
+ }
+
+/***********************************************************************
+ * Windows API to set priority
+ **********************************************************************/
+#elif defined(HAVE_WIN_SETTHREADPRIORITY)
+ #include <windows.h>
+
+ void uhd::set_thread_priority(float priority, bool realtime){
+ //set the priority class on the process
+ int pri_class = (realtime)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;
+ if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0)
+ throw std::runtime_error("error in SetPriorityClass");
+
+ //set the thread priority on the thread
+ int pri_int = int(pri*(THREAD_PRIORITY_TIME_CRITICAL - THREAD_PRIORITY_IDLE)) + THREAD_PRIORITY_IDLE;
+ if (SetThreadPriority(GetCurrentThread(), pri_int) == 0)
+ throw std::runtime_error("error in SetThreadPriority");
+ }
+
+/***********************************************************************
+ * Unimplemented API to set priority
+ **********************************************************************/
+#else
+ void uhd::set_thread_priority(float, bool){
+ throw std::runtime_error("set thread priority not implemented");
+ }
+
+#endif /* HAVE_PTHREAD_SETSCHEDPARAM */
diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp
index 5c8c8a176..ad9a2325b 100644
--- a/host/lib/transport/if_addrs.cpp
+++ b/host/lib/transport/if_addrs.cpp
@@ -27,7 +27,7 @@ uhd::transport::if_addrs_t::if_addrs_t(void){
/***********************************************************************
* Interface address discovery through ifaddrs api
**********************************************************************/
-#ifdef HAVE_IFADDRS_H
+#if defined(HAVE_IFADDRS_H)
#include <ifaddrs.h>
static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){
@@ -59,9 +59,9 @@ std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
}
/***********************************************************************
- * Interface address discovery through windows api (TODO)
+ * Interface address discovery through windows api
**********************************************************************/
-#elif HAVE_WINSOCK2_H
+#elif defined(HAVE_WINSOCK2_H)
#include <winsock2.h>
std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 6cb2a735b..aa0f63321 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -18,6 +18,7 @@
#include "../../transport/vrt_packet_handler.hpp"
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
+#include <uhd/utils/thread_priority.hpp>
#include <uhd/transport/convert_types.hpp>
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/format.hpp>
@@ -78,6 +79,7 @@ managed_recv_buffer::sptr usrp2_impl::io_impl::get_recv_buff(void){
}
void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if){
+ set_thread_priority_safe();
recv_pirate_running = true;
while(recv_pirate_running){
managed_recv_buffer::sptr buff = zc_if->get_recv_buff();