From 8e1575e9bc9ab9b78ae1620c15b8bf7a9ce8c25f Mon Sep 17 00:00:00 2001 From: eb Date: Fri, 19 Sep 2008 21:47:55 +0000 Subject: [PATCH] extend gruel:enable_realtime_scheduling interface to allow pri/policy git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9607 221aa14e-8319-0410-a670-987f0aec2ac5 --- gruel/src/include/gruel/Makefile.am | 1 + gruel/src/include/gruel/realtime.h | 60 +++++++++++++++++-- gruel/src/include/gruel/sys_pri.h | 41 +++++++++++++ gruel/src/lib/Makefile.am | 2 +- gruel/src/lib/realtime.cc | 93 ++++++++++++++++------------- gruel/src/lib/sys_pri.cc | 61 +++++++++++++++++++ 6 files changed, 211 insertions(+), 47 deletions(-) create mode 100644 gruel/src/include/gruel/sys_pri.h create mode 100644 gruel/src/lib/sys_pri.cc diff --git a/gruel/src/include/gruel/Makefile.am b/gruel/src/include/gruel/Makefile.am index 50fad253..648d53e2 100644 --- a/gruel/src/include/gruel/Makefile.am +++ b/gruel/src/include/gruel/Makefile.am @@ -29,5 +29,6 @@ gruelincludedir = $(prefix)/include/gruel gruelinclude_HEADERS = \ $(BUILT_SOURCES) \ realtime.h \ + sys_pri.h \ thread_body_wrapper.h \ thread_group.h diff --git a/gruel/src/include/gruel/realtime.h b/gruel/src/include/gruel/realtime.h index ded70ed0..8beec26d 100644 --- a/gruel/src/include/gruel/realtime.h +++ b/gruel/src/include/gruel/realtime.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,16 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_REALTIME_H -#define INCLUDED_REALTIME_H +#ifndef INCLUDED_GRUEL_REALTIME_H +#define INCLUDED_GRUEL_REALTIME_H + +#include + +/*! + * \brief System independent way to ask for realtime scheduling + * + * \sa sys_pri.h + */ namespace gruel { @@ -32,13 +40,53 @@ namespace gruel { RT_OTHER_ERROR } rt_status_t; + + enum rt_sched_policy { + RT_SCHED_RR = 0, // round robin + RT_SCHED_FIFO = 1, // first in first out + }; + + /* + * Define the range for our virtual priorities (don't change these) + * + * Processes (or threads) with numerically higher priority values + * are scheduled before processes with numerically lower priority + * values. Thus, the value returned by rt_priority_max() will be + * greater than the value returned by rt_priority_min(). + */ + static inline int rt_priority_min() { return 0; } + static inline int rt_priority_max() { return 15; } + static inline int rt_priority_default() { return 1; } + + struct rt_sched_param { + int priority; + rt_sched_policy policy; + + rt_sched_param() + : priority(rt_priority_default()), policy(RT_SCHED_RR){} + + rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR) + { + if (priority_ < rt_priority_min() || priority_ > rt_priority_max()) + throw std::invalid_argument("rt_sched_param: priority out of range"); + + priority = priority_; + policy = policy_; + } + }; + /*! - * \brief If possible, enable high-priority "real time" scheduling. + * \brief If possible, enable "realtime" scheduling. * \ingroup misc + * + * In general, this means that the code will be scheduled before any + * non-realtime (normal) processes. Note that if your code contains + * an non-blocking infinite loop and you enable realtime scheduling, + * it's possible to hang the system. */ rt_status_t - enable_realtime_scheduling(); + enable_realtime_scheduling(rt_sched_param = rt_sched_param()); } // namespace gruel -#endif /* INCLUDED_GR_REALTIME_H */ +#endif /* INCLUDED_GRUEL_REALTIME_H */ diff --git a/gruel/src/include/gruel/sys_pri.h b/gruel/src/include/gruel/sys_pri.h new file mode 100644 index 00000000..b0fd8365 --- /dev/null +++ b/gruel/src/include/gruel/sys_pri.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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. + */ + +#ifndef INCLUDED_GRUEL_SYS_PRI_H +#define INCLUDED_GRUEL_SYS_PRI_H + +#include + +/* + * A single place to define real-time priorities used by the system itself + */ +namespace gruel { + + struct sys_pri { + static rt_sched_param python(); // python code + static rt_sched_param normal(); // normal blocks + static rt_sched_param gcell_event_handler(); + static rt_sched_param usrp2_backend(); // thread that services the ethernet + }; + +} + +#endif /* INCLUDED_GRUEL_SYS_PRI_H */ diff --git a/gruel/src/lib/Makefile.am b/gruel/src/lib/Makefile.am index 7181c941..c2a008e4 100644 --- a/gruel/src/lib/Makefile.am +++ b/gruel/src/lib/Makefile.am @@ -31,11 +31,11 @@ libgruel_la_LDFLAGS = $(NO_UNDEFINED) $(BOOST_LDFLAGS) -version-info 0:0:0 # These are the source files that go into the gruel shared library libgruel_la_SOURCES = \ realtime.cc \ + sys_pri.cc \ thread_body_wrapper.cc \ thread_group.cc libgruel_la_LIBADD = \ $(BOOST_THREAD_LIB) - -lstdc++ noinst_HEADERS = diff --git a/gruel/src/lib/realtime.cc b/gruel/src/lib/realtime.cc index b84117fb..1de8b6dc 100644 --- a/gruel/src/lib/realtime.cc +++ b/gruel/src/lib/realtime.cc @@ -30,94 +30,107 @@ #include #endif +#include +#include #include #include #include -#if defined(HAVE_SCHED_SETSCHEDULER) +#if defined(HAVE_PTHREAD_SETSCHEDPARAM) || defined(HAVE_SCHED_SETSCHEDULER) +#include namespace gruel { - rt_status_t - enable_realtime_scheduling() + /*! + * Rescale our virtual priority so that it maps to the middle 1/2 of + * the priorities given by min_real_pri and max_real_pri. + */ + static int + rescale_virtual_pri(int virtual_pri, int min_real_pri, int max_real_pri) { - int policy = SCHED_FIFO; - int pri = (sched_get_priority_max (policy) + sched_get_priority_min (policy)) / 2; - int pid = 0; // this process + float rmin = min_real_pri + (0.25 * (max_real_pri - min_real_pri)); + float rmax = min_real_pri + (0.75 * (max_real_pri - min_real_pri)); + float m = (rmax - rmin) / (rt_priority_max() - rt_priority_min()); + float y = m * (virtual_pri - rt_priority_min()) + rmin; + int y_int = static_cast(rint(y)); + return std::max(min_real_pri, std::min(max_real_pri, y_int)); + } - if (0){ - fprintf(stderr, "sched_setscheduler version\n"); - fprintf(stderr, "pri_min(SCHED_FIFO) = %d\n", sched_get_priority_min(SCHED_FIFO)); - fprintf(stderr, "pri_max(SCHED_FIFO) = %d\n", sched_get_priority_max(SCHED_FIFO)); - fprintf(stderr, "pri = %d\n", pri); - } +} // namespace gruel + +#endif + + +#if defined(HAVE_PTHREAD_SETSCHEDPARAM) + +namespace gruel { + rt_status_t + enable_realtime_scheduling(rt_sched_param p) + { + int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; + int min_real_pri = sched_get_priority_min(policy); + int max_real_pri = sched_get_priority_min(policy); + int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); + + pthread_t this_thread = pthread_self (); // this process struct sched_param param; - memset(¶m, 0, sizeof(param)); + memset (¶m, 0, sizeof (param)); param.sched_priority = pri; - int result = sched_setscheduler(pid, policy, ¶m); - if (result != 0){ + int result = pthread_setschedparam (this_thread, policy, ¶m); + if (result != 0) { if (errno == EPERM) return RT_NO_PRIVS; else { - perror ("sched_setscheduler: failed to set real time priority"); + perror ("pthread_setschedparam: failed to set real time priority"); return RT_OTHER_ERROR; } } - + //printf("SCHED_FIFO enabled with priority = %d\n", pri); return RT_OK; } - } // namespace gruel -#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) -#include -#include +#elif defined(HAVE_SCHED_SETSCHEDULER) namespace gruel { rt_status_t - enable_realtime_scheduling() + enable_realtime_scheduling(rt_sched_param p) { - int policy = SCHED_FIFO; - int pri = (sched_get_priority_max (policy) + sched_get_priority_min (policy)) / 2; - - if (0){ - fprintf(stderr, "pthread_setschedparam version\n"); - fprintf(stderr, "pri_min(SCHED_FIFO) = %d\n", sched_get_priority_min(SCHED_FIFO)); - fprintf(stderr, "pri_max(SCHED_FIFO) = %d\n", sched_get_priority_max(SCHED_FIFO)); - fprintf(stderr, "pri = %d\n", pri); - } + int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; + int min_real_pri = sched_get_priority_min(policy); + int max_real_pri = sched_get_priority_min(policy); + int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); - pthread_t this_thread = pthread_self (); // this process + int pid = 0; // this process struct sched_param param; - memset (¶m, 0, sizeof (param)); + memset(¶m, 0, sizeof(param)); param.sched_priority = pri; - int result = pthread_setschedparam (this_thread, policy, ¶m); - if (result != 0) { + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ if (errno == EPERM) return RT_NO_PRIVS; else { - perror ("pthread_setschedparam: failed to set real time priority"); + perror ("sched_setscheduler: failed to set real time priority"); return RT_OTHER_ERROR; } } - + //printf("SCHED_FIFO enabled with priority = %d\n", pri); return RT_OK; } -} // namespace gruel -// #elif // could try negative niceness +} // namespace gruel #else namespace gruel { rt_status_t - enable_realtime_scheduling() + enable_realtime_scheduling(rt_sched_param p) { return RT_NOT_IMPLEMENTED; } diff --git a/gruel/src/lib/sys_pri.cc b/gruel/src/lib/sys_pri.cc new file mode 100644 index 00000000..dc0164d7 --- /dev/null +++ b/gruel/src/lib/sys_pri.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 +#endif +#include + +namespace gruel { + + /* + * These may need per-OS tweaking. + * + * Under linux virtual_pri -> system_pri + * 0 -> 0 + * 1 -> 5 + * 2 -> 10 + * 3 -> 15 + * 4 -> 20 // typically used by jack and pulse audio + * 5 -> 25 + * 6 -> 30 + * 7 -> 35 + * 8 -> 40 + * 9 -> 45 + * 10 -> 50 + * 11 -> 54 + * 12 -> 59 + * 13 -> 64 + * 14 -> 69 + * 15 -> 74 + */ + rt_sched_param + sys_pri::python() { return rt_sched_param(0, RT_SCHED_RR); } + + rt_sched_param + sys_pri::normal() { return rt_sched_param(2, RT_SCHED_RR); } + + rt_sched_param + sys_pri::gcell_event_handler(){ return rt_sched_param(5, RT_SCHED_FIFO); } + + rt_sched_param + sys_pri::usrp2_backend() { return rt_sched_param(6, RT_SCHED_FIFO); } +} -- 2.30.2