diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index a90da6659e..b322d65138 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -72,7 +72,8 @@ $(SRC)/libteletone_detect.c \ $(SRC)/libteletone_generate.c \ $(SRC)/ftdm_buffer.c \ $(SRC)/ftdm_threadmutex.c \ -$(SRC)/ftdm_dso.c +$(SRC)/ftdm_dso.c \ +$(SRC)/ftdm_cpu_monitor.c library_include_HEADERS = \ $(SRC)/include/fsk.h \ @@ -90,7 +91,8 @@ $(SRC)/include/ftdm_buffer.h \ $(SRC)/include/ftdm_config.h \ $(SRC)/include/ftdm_threadmutex.h \ $(SRC)/include/ftdm_dso.h \ -$(SRC)/include/ftdm_types.h +$(SRC)/include/ftdm_types.h \ +$(SRC)/include/ftdm_cpu_monitor.h lib_LTLIBRARIES = libfreetdm.la libfreetdm_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 468bcf10de..cf7ddad007 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3142,6 +3142,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load) module_pool = pool; ftdm_global_set_logger(ftdm_logger); + + ftdm_cpu_monitor_disable(); if (ftdm_global_init() != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n"); diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c new file mode 100644 index 0000000000..eebf922b98 --- /dev/null +++ b/libs/freetdm/src/ftdm_cpu_monitor.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * Moises Silva + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * David Yat Sin + * + */ + +#ifdef WIN32 +#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h +#include +#else /* LINUX */ + +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "freetdm.h" +#include "ftdm_cpu_monitor.h" +struct ftdm_cpu_monitor_stats +{ + /* bool, just used to retrieve the values for the first time and not calculate the percentage of idle time */ + int valid_last_times; + + /* last calculated percentage of idle time */ + double last_percentage_of_idle_time; + +#ifdef __linux__ + /* all of these are the Linux jiffies last retrieved count */ + unsigned long long last_user_time; + unsigned long long last_system_time; + unsigned long long last_idle_time; + + unsigned long long last_nice_time; + unsigned long long last_irq_time; + unsigned long long last_soft_irq_time; + unsigned long long last_io_wait_time; + unsigned long long last_steal_time; + + /* /proc/stat file descriptor used to retrieve the counters */ + int procfd; + int initd; +#elif defined (WIN32) || defined (WIN64) + __int64 i64LastUserTime; + __int64 i64LastKernelTime; + __int64 i64LastIdleTime; +#else +/* Unsupported */ +#endif +}; + +#ifdef __linux__ +static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p, + unsigned long long *user, + unsigned long long *nice, + unsigned long long *system, + unsigned long long *idle, + unsigned long long *iowait, + unsigned long long *irq, + unsigned long long *softirq, + unsigned long long *steal) +{ +// the output of proc should not change that often from one kernel to other +// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details +// also man 5 proc is useful +#define CPU_ELEMENTS 8 // change this if you change the format string +#define CPU_INFO_FORMAT "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu" + static const char procfile[] = "/proc/stat"; + int rc = 0; + int myerrno = 0; + int elements = 0; + const char *cpustr = NULL; + char statbuff[1024]; + + if (!p->initd) { + p->procfd = open(procfile, O_RDONLY, 0); + if(p->procfd == -1) { + ftdm_log(FTDM_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno)); + return FTDM_FAIL; + } + p->initd = 1; + } else { + lseek(p->procfd, 0L, SEEK_SET); + } + + rc = read(p->procfd, statbuff, sizeof(statbuff) - 1); + if (rc <= 0) { + myerrno = errno; + ftdm_log(FTDM_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno)); + return FTDM_FAIL; + } + + cpustr = strstr(statbuff, "cpu "); + if (!cpustr) { + ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n"); + return FTDM_FAIL; + } + + elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal); + if (elements != CPU_ELEMENTS) { + ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements); + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} +#endif + +#ifdef __linux__ +FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage) +{ + unsigned long long user, nice, system, idle, iowait, irq, softirq, steal; + unsigned long long usertime, kerneltime, idletime, totaltime, halftime; + + if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) { + ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n"); + return FTDM_FAIL; + } + + if (!p->valid_last_times) { + // we dont strictly need to save all of them but I feel code is more clear if we do + p->valid_last_times = 1; + p->last_user_time = user; + p->last_nice_time = nice; + p->last_system_time = system; + p->last_irq_time = irq; + p->last_soft_irq_time = softirq; + p->last_io_wait_time = iowait; + p->last_steal_time = steal; + p->last_idle_time = idle; + p->last_percentage_of_idle_time = 100.0; + *idle_percentage = p->last_percentage_of_idle_time; + return FTDM_SUCCESS; + } + + usertime = (user - p->last_user_time) + (nice - p->last_nice_time); + kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time); + kerneltime += (iowait - p->last_io_wait_time); + kerneltime += (steal - p->last_steal_time); + idletime = (idle - p->last_idle_time); + + totaltime = usertime + kerneltime + idletime; + + if (totaltime <= 0) { + // this may happen if not enough time has elapsed and the jiffies counters are the same than the last time we checked + // jiffies depend on timer interrupts which depend on the number of HZ compile time setting of the kernel + // typical configs set HZ to 100 (that means, 100 jiffies updates per second, that is one each 10ms) + // avoid an arithmetic exception and return the same values + *idle_percentage = p->last_percentage_of_idle_time; + return FTDM_SUCCESS; + } + + halftime = totaltime / 2UL; + + p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime); + *idle_percentage = p->last_percentage_of_idle_time; + + p->last_user_time = user; + p->last_nice_time = nice; + p->last_system_time = system; + p->last_irq_time = irq; + p->last_soft_irq_time = softirq; + p->last_io_wait_time = iowait; + p->last_steal_time = steal; + p->last_idle_time = idle; + + return FTDM_SUCCESS; +} + +#elif defined (WIN32) || defined (WIN64) +FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) +{ + FILETIME idleTime; + FILETIME kernelTime; + FILETIME userTime; + + if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) { + return false; + } + + __int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32); + + __int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32); + + __int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)idleTime.dwHighDateTime << 32); + + if (p->valid_last_times) { + __int64 i64User = i64UserTime - p->i64LastUserTime; + __int64 i64Kernel = i64KernelTime - p->i64LastKernelTime; + __int64 i64Idle = i64IdleTime - p->i64LastIdleTime; + __int64 i64System = i64User + i64Kernel; + *idle_percentage = 100.0 * i64Idle / i64System; + } else { + *idle_percentage = 100.0; + p->valid_last_times = 1; + } + + /* Remember current value for the next call */ + p->i64LastUserTime = i64UserTime; + p->i64LastKernelTime = i64KernelTime; + p->i64LastIdleTime = i64IdleTime; + + /* Success */ + return FTDM_SUCCESS; +} +#else +/* Unsupported */ +FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage) +{ + return FTDM_FAIL; +} +#endif + +FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void) +{ + return calloc(1, sizeof(struct ftdm_cpu_monitor_stats)); +} + +FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p) +{ +#ifdef __linux__ + close(p->procfd); +#endif + free(p); +} + + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1b27f91130..65f5e7b706 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -48,6 +48,7 @@ #ifdef FTDM_PIKA_SUPPORT #include "ftdm_pika.h" #endif +#include "ftdm_cpu_monitor.h" #define SPAN_PENDING_CHANS_QUEUE_SIZE 1000 @@ -80,6 +81,16 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void) #endif } +typedef struct { + uint8_t running; + uint8_t alarm; + uint32_t interval; + uint8_t alarm_action_flags; + uint8_t set_alarm_threshold; + uint8_t reset_alarm_threshold; + ftdm_interrupt_t *interrupt; +} cpu_monitor_t; + static struct { ftdm_hash_t *interface_hash; ftdm_hash_t *module_hash; @@ -93,8 +104,16 @@ static struct { uint32_t running; ftdm_span_t *spans; ftdm_group_t *groups; + cpu_monitor_t cpu_monitor; } globals; +static uint8_t ftdm_cpu_monitor_disabled = 0; + +enum ftdm_enum_cpu_alarm_action_flags +{ + FTDM_CPU_ALARM_ACTION_WARN = (1 << 0), + FTDM_CPU_ALARM_ACTION_REJECT = (1 << 1) +}; /* enum lookup funcs */ FTDM_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS) @@ -1470,6 +1489,14 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); return FTDM_FAIL; } + + if (globals.cpu_monitor.alarm && + globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) { + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n"); + ftdm_log(FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n"); + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION; + return FTDM_FAIL; + } if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY) || (status = ftdm_mutex_trylock(ftdmchan->mutex)) != FTDM_SUCCESS) { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Channel is not ready or is in use %d %d", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY), status); @@ -2988,6 +3015,44 @@ static ftdm_status_t load_config(void) } else { ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var); } + } else if (!strncasecmp(cfg.category, "general", 7)) { + if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) { + if (atoi(val) > 0) { + globals.cpu_monitor.interval = atoi(val); + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val); + } + } else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) { + if (atoi(val) > 0 && atoi(val) < 100) { + globals.cpu_monitor.set_alarm_threshold = atoi(val); + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val); + } + } else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) { + if (atoi(val) > 0 && atoi(val) < 100) { + globals.cpu_monitor.reset_alarm_threshold = atoi(val); + if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) { + globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10; + ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold" + ", setting threshold to %d\n", globals.cpu_monitor.reset_alarm_threshold); + } + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val); + } + } else if (!strncasecmp(var, "cpu_alarm_action", sizeof("cpu_alarm_action")-1)) { + char* p = val; + do { + if (!strncasecmp(p, "reject", sizeof("reject")-1)) { + globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_REJECT; + } else if (!strncasecmp(p, "warn", sizeof("warn")-1)) { + globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN; + } + p = strchr(p, ','); + if (p) { + while(*p++) if (*p != 0x20) break; + } + } while (p); + } } else { ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val); } @@ -3516,6 +3581,71 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t return status; } +static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj) +{ + cpu_monitor_t *monitor = (cpu_monitor_t *)obj; + struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor(); + if (!cpu_stats) { + return NULL; + } + monitor->running = 1; + + while(ftdm_running()) { + double time; + if (ftdm_cpu_get_system_idle_time(cpu_stats, &time)) { + break; + } + + if (monitor->alarm) { + if ((int)time >= (100 - monitor->set_alarm_threshold)) { + ftdm_log(FTDM_LOG_DEBUG, "CPU alarm OFF (idle:%d)\n", (int) time); + monitor->alarm = 0; + } + if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) { + ftdm_log(FTDM_LOG_WARNING, "CPU alarm is ON (cpu usage:%d)\n", (int) (100-time)); + } + } else { + if ((int)time <= (100-monitor->reset_alarm_threshold)) { + ftdm_log(FTDM_LOG_DEBUG, "CPU alarm ON (idle:%d)\n", (int) time); + monitor->alarm = 1; + } + } + ftdm_interrupt_wait(monitor->interrupt, monitor->interval); + } + + ftdm_delete_cpu_monitor(cpu_stats); + monitor->running = 0; + return NULL; +} + +static ftdm_status_t ftdm_cpu_monitor_start(cpu_monitor_t* monitor) +{ + if (ftdm_interrupt_create(&monitor->interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n"); + return FTDM_FAIL; + } + + if (ftdm_thread_create_detached(ftdm_cpu_monitor_run, monitor) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "Failed to create cpu monitor thread!!\n"); + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + +static void ftdm_cpu_monitor_stop(cpu_monitor_t* monitor) +{ + ftdm_interrupt_signal(monitor->interrupt); + while(monitor->running) { + ftdm_sleep(10); + } +} + +FT_DECLARE(void) ftdm_cpu_monitor_disable(void) +{ + ftdm_cpu_monitor_disabled = 1; +} + + FT_DECLARE(ftdm_status_t) ftdm_global_init(void) { memset(&globals, 0, sizeof(globals)); @@ -3538,14 +3668,34 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void) FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void) { - int modcount = ftdm_load_modules(); + int modcount = 0; + + if (!globals.running) { + return FTDM_FAIL; + } + + modcount = ftdm_load_modules(); + ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount); + globals.cpu_monitor.interval = 1000; + globals.cpu_monitor.alarm_action_flags = FTDM_CPU_ALARM_ACTION_WARN | FTDM_CPU_ALARM_ACTION_REJECT; + globals.cpu_monitor.set_alarm_threshold = 80; + globals.cpu_monitor.reset_alarm_threshold = 70; + if (load_config() != FTDM_SUCCESS) { globals.running = 0; ftdm_log(FTDM_LOG_ERROR, "FreeTDM global configuration failed!\n"); return FTDM_FAIL; } + + if (!ftdm_cpu_monitor_disabled) { + if (ftdm_cpu_monitor_start(&globals.cpu_monitor) != FTDM_SUCCESS) { + return FTDM_FAIL; + } + } + + return FTDM_SUCCESS; } @@ -3563,6 +3713,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void) globals.running = 0; + ftdm_cpu_monitor_stop(&globals.cpu_monitor); + globals.span_index = 0; ftdm_span_close_all(); @@ -3596,6 +3748,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void) ftdm_mutex_unlock(globals.mutex); ftdm_mutex_destroy(&globals.mutex); ftdm_mutex_destroy(&globals.span_mutex); + ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt); memset(&globals, 0, sizeof(globals)); return FTDM_SUCCESS; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index c2ca3db7c4..baaa301818 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -880,8 +880,8 @@ static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan); */ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_event_t *event) { - ftdm_channel_t *ftdmchan; - + ftdm_channel_t *ftdmchan = NULL; + int hangup_cause = FTDM_CAUSE_CALL_REJECTED; if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) { if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) { int r; @@ -896,7 +896,7 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s } ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG); - ftdmchan=NULL; + ftdmchan = NULL; } ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1); goto error; @@ -953,12 +953,13 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s return; error: + hangup_cause = ftdmchan ? ftdmchan->caller_data.hangup_cause : FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL; sangomabc_exec_command(mcon, event->span, event->chan, 0, SIGBOOST_EVENT_CALL_START_NACK, - 0, 0); + hangup_cause, 0); } diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 04c30abc67..0b8b43dbf8 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -824,6 +824,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_find_by_name(const char *name, ftdm_span_t * FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd); FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap); FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data); +FT_DECLARE(void) ftdm_cpu_monitor_disable(void); FIO_CODEC_FUNCTION(fio_slin2ulaw); FIO_CODEC_FUNCTION(fio_ulaw2slin); diff --git a/libs/freetdm/src/include/ftdm_cpu_monitor.h b/libs/freetdm/src/include/ftdm_cpu_monitor.h new file mode 100644 index 0000000000..5d6bfb7eba --- /dev/null +++ b/libs/freetdm/src/include/ftdm_cpu_monitor.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * Moises Silva + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Contributors: + * David Yat Sin + * + */ + +/*! \brief opaque cpu stats structure */ +struct ftdm_cpu_monitor_stats; + +/*! + * \brief create a new cpu monitor + * \return profile timer structure previously created with new_profile_timer, NULL on error + */ +FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void); + +/*! + * \brief Deletes cpu_monitor + */ +FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p); + +/*! + * \brief provides the percentage of idle system time + * \param p cpu_stats structure previously created with ftdm_new_cpu_monitor + * \param pointer to store the percentage of idle time + * \return -1 on error 0 for success + */ +FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage); + + + + + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */