From 0a2bbc528b7865b08139155e0316738a717c4e42 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 00:05:25 +0000 Subject: * some commenting work * add new field "read_only" to memory blocks * add new API function pa_context_get_server() * filter capture data through mcalign on client * make module-tunnel use pa_socket_client_new_string() instead of using pa_resolve_server() directly. * remove pa_resolve_server() * remove debug.h and replace it by a macro definition on the gcc command line * some strbuf cleanups * small fixes in pa_stream for cleanup when server dies * new CLI command "load-sample-dir-lazy" * send FQDN as part of server info * rework mcalign, this time with memory block merging * fix iochannel cleanup when connection dies * check getaddrinfo() results git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@286 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cpulimit.c | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'polyp/cpulimit.c') diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index fcbbaf3d..78dc5e1f 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -32,30 +32,58 @@ #include "util.h" #include "log.h" + +/* This module implements a watchdog that makes sure that the current + * process doesn't consume more than 70% CPU time for 10 seconds. This + * is very useful when using SCHED_FIFO scheduling which effectively + * disables multitasking. */ + +/* Method of operation: Using SIGXCPU a signal handler is called every + * 10s process CPU time. That function checks if less than 14s system + * time have passed. In that case, it tries to contact the main event + * loop through a pipe. After two additional seconds it is checked + * whether the main event loop contact was successful. If not, the + * program is terminated forcibly. */ + /* Utilize this much CPU time at maximum */ #define CPUTIME_PERCENT 70 +/* Check every 10s */ #define CPUTIME_INTERVAL_SOFT (10) + +/* Recheck after 2s */ #define CPUTIME_INTERVAL_HARD (2) +/* Time of the last CPU load check */ static time_t last_time = 0; + +/* Pipe for communicating with the main loop */ static int the_pipe[2] = {-1, -1}; + +/* Main event loop and IO event for the FIFO */ static struct pa_mainloop_api *api = NULL; static struct pa_io_event *io_event = NULL; + +/* Saved sigaction struct for SIGXCPU */ static struct sigaction sigaction_prev; -static int installed = 0; +/* Nonzero after pa_cpu_limit_init() */ +static int installed = 0; + +/* The current state of operation */ static enum { - PHASE_IDLE, - PHASE_SOFT + PHASE_IDLE, /* Normal state */ + PHASE_SOFT /* After CPU overload has been detected */ } phase = PHASE_IDLE; +/* Reset the SIGXCPU timer to the next t seconds */ static void reset_cpu_time(int t) { int r; long n; struct rlimit rl; struct rusage ru; + /* Get the current CPU time of the current process */ r = getrusage(RUSAGE_SELF, &ru); assert(r >= 0); @@ -69,10 +97,12 @@ static void reset_cpu_time(int t) { assert(r >= 0); } +/* A simple, thread-safe puts() work-alike */ static void write_err(const char *p) { pa_loop_write(2, p, strlen(p)); } +/* The signal handler, called on every SIGXCPU */ static void signal_handler(int sig) { assert(sig == SIGXCPU); @@ -109,23 +139,26 @@ static void signal_handler(int sig) { } else if (phase == PHASE_SOFT) { write_err("Hard CPU time limit exhausted, terminating forcibly.\n"); - _exit(1); + _exit(1); /* Forced exit */ } } +/* Callback for IO events on the FIFO */ static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { char c; assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); read(the_pipe[0], &c, sizeof(c)); - m->quit(m, 1); + m->quit(m, 1); /* Quit the main loop */ } +/* Initializes CPU load limiter */ int pa_cpu_limit_init(struct pa_mainloop_api *m) { struct sigaction sa; - assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1); + assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed); time(&last_time); + /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); return -1; @@ -141,6 +174,7 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { phase = PHASE_IDLE; + /* Install signal handler for SIGXCPU */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); @@ -158,6 +192,7 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { return 0; } +/* Shutdown CPU load limiter */ void pa_cpu_limit_done(void) { int r; -- cgit