Browse Source

TT#36302 support scheduling settings

Change-Id: I490fde10a5ae44d25b95e4368af70003716040b7
changes/75/21175/2
Richard Fuchs 8 years ago
parent
commit
fa5c265045
6 changed files with 114 additions and 7 deletions
  1. +27
    -0
      README.md
  2. +69
    -1
      daemon/aux.c
  3. +2
    -1
      daemon/call.c
  4. +8
    -4
      daemon/main.c
  5. +4
    -0
      daemon/main.h
  6. +4
    -1
      include/aux.h

+ 27
- 0
README.md View File

@ -228,6 +228,10 @@ option and which are reproduced below:
--recording-format=raw|eth PCAP file format for recorded calls. --recording-format=raw|eth PCAP file format for recorded calls.
--iptables-chain=STRING Add explicit firewall rules to this iptables chain --iptables-chain=STRING Add explicit firewall rules to this iptables chain
--codecs Print a list of supported codecs and exit --codecs Print a list of supported codecs and exit
--scheduling=default|... Thread scheduling policy
--priority=INT Thread scheduling priority
--idle-scheduling=default|... Idle thread scheduling policy
--idle-priority=INT Idle thread scheduling priority
Most of these options are indeed optional, with two exceptions. It's mandatory to specify at least one local Most of these options are indeed optional, with two exceptions. It's mandatory to specify at least one local
IP address through `--interface`, and at least one of the `--listen-...` options must be given. IP address through `--interface`, and at least one of the `--listen-...` options must be given.
@ -646,6 +650,29 @@ The options are described in more detail below.
and its API implementation in the Linux kernel. In such a case, it is recommended to and its API implementation in the Linux kernel. In such a case, it is recommended to
add a static iptables rule for the entire media port range instead, and not use this option. add a static iptables rule for the entire media port range instead, and not use this option.
* --scheduling, --priority, --idle-scheduling, --idle-priority
These options control various thread scheduling parameters. The `scheduling` and `priority`
settings are applied to the main worker threads, while the `idle-` versions of these
settings are applied to various lower priority threads, such as timer runs.
The `scheduling` settings take the name of one of the supported scheduler policies. Setting
it to `default` or `none` is equivalent to not setting the option at all and leaves the
system default in place. The strings `fifo` and `rr` refer to realtime scheduling policies.
`other` is the Linux default scheduling policy. `batch` is similar to `other` except for
a small wake-up scheduling penalty. `idle` is an extremely low priority scheduling policy.
The Linux-specific `deadline` policy is not supported by *rtpengine*. Not all systems
necessarily supports all scheduling policies; refer to your system's `sched(7)` man page
for details.
The `priority` settings correspond to the scheduling priority for realtime (`fifo` or `rr`)
scheduling policies and must be in the range of 1 (low) through 99 (high). For all other
scheduling policies (including no policy specified), the `priority` settings correspond
to the `nice` value and should be in the range of -20 (high) through 19 (low). Not all systems
support thread-specific `nice` values; on such a system, using these settings might have
unexpected results. (Linux does support thread-specific `nice values.)
Refer to your system's `sched(7)` man page.
A typical command line (enabling both UDP and NG protocols) thus may look like: A typical command line (enabling both UDP and NG protocols) thus may look like:
/usr/sbin/rtpengine --table=0 --interface=10.64.73.31 --interface=2001:db8::4f3:3d \ /usr/sbin/rtpengine --table=0 --interface=10.64.73.31 --interface=2001:db8::4f3:3d \


+ 69
- 1
daemon/aux.c View File

@ -5,6 +5,10 @@
#include <pcre.h> #include <pcre.h>
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h> #include <pthread.h>
#include <sys/resource.h>
#include <errno.h>
#include <unistd.h>
#include "log.h"
@ -20,10 +24,17 @@
struct detach_thread { struct detach_thread {
void (*func)(void *); void (*func)(void *);
void *data; void *data;
const char *scheduler;
int priority;
}; };
struct thread_buf { struct thread_buf {
char buf[THREAD_BUF_SIZE]; char buf[THREAD_BUF_SIZE];
}; };
struct scheduler {
const char *name;
int num;
int nice;
};
static mutex_t threads_lists_lock = MUTEX_STATIC_INIT; static mutex_t threads_lists_lock = MUTEX_STATIC_INIT;
@ -41,6 +52,29 @@ volatile int rtpe_shutdown;
mutex_t __atomic64_mutex = MUTEX_STATIC_INIT; mutex_t __atomic64_mutex = MUTEX_STATIC_INIT;
#endif #endif
static const struct scheduler schedulers[] = {
{ "default", -1, 1 },
{ "none", -1, 1 },
#ifdef SCHED_FIFO
{ "fifo", SCHED_FIFO, 0 },
#endif
#ifdef SCHED_RR
{ "rr", SCHED_RR, 0 },
#endif
//#ifdef SCHED_DEADLINE
// { "deadline", SCHED_DEADLINE, 0 },
//#endif
#ifdef SCHED_OTHER
{ "other", SCHED_OTHER, 1 },
#endif
#ifdef SCHED_BATCH
{ "batch", SCHED_BATCH, 1 },
#endif
#ifdef SCHED_IDLE
{ "idle", SCHED_IDLE, 0 },
#endif
};
GList *g_list_link(GList *list, GList *el) { GList *g_list_link(GList *list, GList *el) {
@ -140,6 +174,38 @@ static void *thread_detach_func(void *d) {
threads_running = g_list_prepend(threads_running, t); threads_running = g_list_prepend(threads_running, t);
mutex_unlock(&threads_lists_lock); mutex_unlock(&threads_lists_lock);
const struct scheduler *scheduler = NULL;
if (dt->scheduler) {
for (int i = 0; i < G_N_ELEMENTS(schedulers); i++) {
if (!strcmp(dt->scheduler, schedulers[i].name)) {
scheduler = &schedulers[i];
break;
}
}
if (!scheduler)
ilog(LOG_ERR, "Specified scheduler policy '%s' not found", dt->scheduler);
else {
struct sched_param param = { 0 };
if (!scheduler->nice)
param.sched_priority = dt->priority;
if (pthread_setschedparam(*t, scheduler->num, &param))
ilog(LOG_ERR, "Failed to set thread scheduling paramaters to '%s' (%i) / %i: %s",
dt->scheduler, scheduler->num, param.sched_priority,
strerror(errno));
}
}
if ((!scheduler && dt->priority) || (scheduler && scheduler->nice)) {
if (setpriority(PRIO_PROCESS, 0, dt->priority))
ilog(LOG_ERR, "Failed to set thread nice value: %s",
strerror(errno));
}
dt->func(dt->data); dt->func(dt->data);
g_slice_free1(sizeof(*dt), dt); g_slice_free1(sizeof(*dt), dt);
thread_join_me(); thread_join_me();
@ -165,12 +231,14 @@ static int thread_create(void *(*func)(void *), void *arg, int joinable, pthread
return 0; return 0;
} }
void thread_create_detach(void (*f)(void *), void *d) {
void thread_create_detach_prio(void (*f)(void *), void *d, const char *scheduler, int priority) {
struct detach_thread *dt; struct detach_thread *dt;
dt = g_slice_alloc(sizeof(*dt)); dt = g_slice_alloc(sizeof(*dt));
dt->func = f; dt->func = f;
dt->data = d; dt->data = d;
dt->scheduler = scheduler;
dt->priority = priority;
if (thread_create(thread_detach_func, dt, 1, NULL)) if (thread_create(thread_detach_func, dt, 1, NULL))
abort(); abort();


+ 2
- 1
daemon/call.c View File

@ -468,7 +468,8 @@ destroy:
} }
if (xh) if (xh)
thread_create_detach(xmlrpc_kill_calls, xh);
thread_create_detach_prio(xmlrpc_kill_calls, xh, rtpe_config.idle_scheduling,
rtpe_config.idle_priority);
} }


+ 8
- 4
daemon/main.c View File

@ -305,6 +305,10 @@ static void options(int *argc, char ***argv) {
{ "iptables-chain",0,0, G_OPTION_ARG_STRING, &rtpe_config.iptables_chain,"Add explicit firewall rules to this iptables chain","STRING" }, { "iptables-chain",0,0, G_OPTION_ARG_STRING, &rtpe_config.iptables_chain,"Add explicit firewall rules to this iptables chain","STRING" },
#endif #endif
{ "codecs", 0, 0, G_OPTION_ARG_NONE, &codecs, "Print a list of supported codecs and exit", NULL }, { "codecs", 0, 0, G_OPTION_ARG_NONE, &codecs, "Print a list of supported codecs and exit", NULL },
{ "scheduling", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.scheduling,"Thread scheduling policy", "default|none|fifo|rr|other|batch|idle" },
{ "priority", 0, 0, G_OPTION_ARG_INT, &rtpe_config.priority, "Thread scheduling priority", "INT" },
{ "idle-scheduling",0, 0,G_OPTION_ARG_STRING, &rtpe_config.idle_scheduling,"Idle thread scheduling policy", "default|none|fifo|rr|other|batch|idle" },
{ "idle-priority",0, 0, G_OPTION_ARG_INT, &rtpe_config.idle_priority,"Idle thread scheduling priority", "INT" },
{ NULL, } { NULL, }
}; };
@ -327,7 +331,7 @@ static void options(int *argc, char ***argv) {
die("Invalid interface specification: %s", *iter); die("Invalid interface specification: %s", *iter);
g_queue_push_tail(&rtpe_config.interfaces, ifa); g_queue_push_tail(&rtpe_config.interfaces, ifa);
} }
if (!&rtpe_config.interfaces)
if (!rtpe_config.interfaces.length)
die("Cannot start without any configured interfaces"); die("Cannot start without any configured interfaces");
if (ks_a) { if (ks_a) {
@ -725,8 +729,8 @@ int main(int argc, char **argv) {
ilog(LOG_INFO, "Startup complete, version %s", RTPENGINE_VERSION); ilog(LOG_INFO, "Startup complete, version %s", RTPENGINE_VERSION);
thread_create_detach(sighandler, NULL); thread_create_detach(sighandler, NULL);
thread_create_detach(poller_timer_loop, rtpe_poller);
thread_create_detach(load_thread, NULL);
thread_create_detach_prio(poller_timer_loop, rtpe_poller, rtpe_config.idle_scheduling, rtpe_config.idle_priority);
thread_create_detach_prio(load_thread, NULL, rtpe_config.idle_scheduling, rtpe_config.idle_priority);
if (!is_addr_unspecified(&rtpe_config.redis_ep.address)) if (!is_addr_unspecified(&rtpe_config.redis_ep.address))
thread_create_detach(redis_notify_loop, NULL); thread_create_detach(redis_notify_loop, NULL);
@ -745,7 +749,7 @@ int main(int argc, char **argv) {
} }
for (;idx<rtpe_config.num_threads;++idx) { for (;idx<rtpe_config.num_threads;++idx) {
thread_create_detach(poller_loop, rtpe_poller);
thread_create_detach_prio(poller_loop, rtpe_poller, rtpe_config.scheduling, rtpe_config.priority);
} }
while (!rtpe_shutdown) { while (!rtpe_shutdown) {


+ 4
- 0
daemon/main.h View File

@ -71,6 +71,10 @@ struct rtpengine_config {
int load_limit; int load_limit;
int cpu_limit; int cpu_limit;
uint64_t bw_limit; uint64_t bw_limit;
char *scheduling;
int priority;
char *idle_scheduling;
int idle_priority;
}; };


+ 4
- 1
include/aux.h View File

@ -401,7 +401,10 @@ INLINE int __debug_rwlock_unlock_w(rwlock_t *m, const char *file, unsigned int l
/*** THREAD HELPERS ***/ /*** THREAD HELPERS ***/
void threads_join_all(int); void threads_join_all(int);
void thread_create_detach(void (*)(void *), void *);
void thread_create_detach_prio(void (*)(void *), void *, const char *, int);
INLINE void thread_create_detach(void (*f)(void *), void *a) {
thread_create_detach_prio(f, a, NULL, 0);
}


Loading…
Cancel
Save