diff options
| author | Josh Blum <josh@joshknows.com> | 2010-06-16 18:40:44 -0700 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2010-06-16 18:40:44 -0700 | 
| commit | 168ab7279cec925e3db3e943e35d0d2bd220d8b3 (patch) | |
| tree | 6b86a586c332d2610ff2ae59ddda2a09c6ea7877 | |
| parent | a89d684ba2b81c6e18d348965dffb919edb56fea (diff) | |
| download | uhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.tar.gz uhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.tar.bz2 uhd-168ab7279cec925e3db3e943e35d0d2bd220d8b3.zip | |
uhd: work on thread priority scheduling
| -rw-r--r-- | host/docs/general.rst | 8 | ||||
| -rw-r--r-- | host/include/uhd/utils/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/include/uhd/utils/thread_priority.hpp | 58 | ||||
| -rw-r--r-- | host/lib/CMakeLists.txt | 41 | ||||
| -rw-r--r-- | host/lib/load_modules.cpp | 4 | ||||
| -rw-r--r-- | host/lib/sched.cpp | 45 | ||||
| -rw-r--r-- | host/lib/thread_priority.cpp | 93 | ||||
| -rw-r--r-- | host/lib/transport/if_addrs.cpp | 6 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 2 | 
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(); | 
