]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
more timer changes
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 30 Dec 2009 20:55:04 +0000 (20:55 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 30 Dec 2009 20:55:04 +0000 (20:55 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16098 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/private/switch_core_pvt.h
src/include/switch_core.h
src/switch_core.c
src/switch_core_session.c
src/switch_time.c

index 5ad57b0c7ba4bfb38c0349e67b935d8b832c000c..6408920724c36c4f5bc267cdb8f5cfadf0eeb636 100644 (file)
@@ -218,6 +218,19 @@ struct switch_runtime {
 
 extern struct switch_runtime runtime;
 
+
+struct switch_session_manager {
+       switch_memory_pool_t *memory_pool;
+       switch_hash_t *session_table;
+       uint32_t session_count;
+       uint32_t session_limit;
+       switch_size_t session_id;
+};
+
+extern struct switch_session_manager session_manager;
+
+
+
 switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage);
 void switch_core_sqldb_stop(void);
 void switch_core_session_init(switch_memory_pool_t *pool);
index ea3553791023d3c8dfaca458512489cdeab4f6ad..9ec21f039ce4a90ff25dc8bf93fa599b1a45712a 100644 (file)
@@ -1942,6 +1942,7 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
 #define switch_check_network_list_ip(_ip_str, _list_name) switch_check_network_list_ip_token(_ip_str, _list_name, NULL)
 SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable);
 SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable);
+SWITCH_DECLARE(void) switch_time_set_matrix(switch_bool_t enable);
 SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable);
 SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration);
 SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration);
index abf58511e5153a568be46c12732e5ef0bc1f2495..184b6e1cb348ab041f2179539bf851854c3c58a8 100644 (file)
@@ -1415,6 +1415,8 @@ static void switch_load_core_config(const char *file)
                                        switch_time_set_nanosleep(switch_true(var));
                                } else if (!strcasecmp(var, "enable-cond-yield")) {
                                        switch_time_set_cond_yield(switch_true(var));
+                               } else if (!strcasecmp(var, "enable-timer-matrix")) {
+                                       switch_time_set_matrix(switch_true(var));
                                } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {
                                        switch_core_session_limit(atoi(val));
                                } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) {
index 30e0fa4bbfaf55f4e9589b35678f34f084280016..d2ef5490a11eedfa9388b71019c3d9db964cbeac 100644 (file)
 #include "switch_core.h"
 #include "private/switch_core_pvt.h"
 
-static struct {
-       switch_memory_pool_t *memory_pool;
-       switch_hash_t *session_table;
-       uint32_t session_count;
-       uint32_t session_limit;
-       switch_size_t session_id;
-} session_manager;
+struct switch_session_manager session_manager;
 
 #ifdef SWITCH_DEBUG_RWLOCKS
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line)
index 6d6a78f32d36954b4c9c42b5c18b5ddc9adb8f0e..cf142d59629b8a2b28805e15a7c78bad0724362c 100644 (file)
 
 #define MAX_TICK UINT32_MAX - 1024
 
+#define MAX_ELEMENTS 3600
+#define IDLE_SPEED 100
+
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+static int MONO = 1;
+#else
+static int MONO = 0;
+#endif
+
+#if defined(HAVE_CLOCK_NANOSLEEP) 
+static int NANO = 1;
+#else
+static int NANO = 0;
+#endif
+
+
+static int OFFSET = 0;
+
+static int COND = 0;
+
+static int MATRIX = 1;
+
+static int STEP_MS = 10;
+static int STEP_MIC = 10000;
+static int TICK_PER_SEC = 100;
+
 static int MS_PER_TICK = 10;
 
 static switch_memory_pool_t *module_pool = NULL;
@@ -66,12 +92,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown);
 SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime);
 SWITCH_MODULE_DEFINITION(CORE_SOFTTIMER_MODULE, softtimer_load, softtimer_shutdown, softtimer_runtime);
 
-#define MAX_ELEMENTS 3600
-#define IDLE_SPEED 100
-#define STEP_MS 1
-#define STEP_MIC 1000
-#define TICK_PER_SEC 1000
-
 struct timer_private {
        switch_size_t reference;
        switch_size_t start;
@@ -92,6 +112,15 @@ typedef struct timer_matrix timer_matrix_t;
 
 static timer_matrix_t TIMER_MATRIX[MAX_ELEMENTS + 1];
 
+static void os_yield(void)
+{
+#if defined(WIN32)
+       SwitchToThread();
+#else
+       sched_yield();
+#endif
+}
+
 static void do_sleep(switch_interval_time_t t)
 {
 #if defined(HAVE_CLOCK_NANOSLEEP) || defined(DARWIN)
@@ -105,16 +134,18 @@ static void do_sleep(switch_interval_time_t t)
 #endif
 
 #if !defined(DARWIN)
-       if (t > 100000) {
+       if (t > 100000 || !NANO) {
                apr_sleep(t);
+               return;
        }
 #endif
        
-
 #if defined(HAVE_CLOCK_NANOSLEEP)
-       ts.tv_sec = t / APR_USEC_PER_SEC;
-       ts.tv_nsec = ((t % APR_USEC_PER_SEC) * 1000) - 1000000;
+       t -= OFFSET;
+       ts.tv_sec = t / 1000000;
+       ts.tv_nsec = ((t % 1000000) * 1000);
        clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+
 #elif defined(DARWIN)
        ts.tv_sec = t / APR_USEC_PER_SEC;
        ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000;
@@ -129,6 +160,48 @@ sched_yield();
 
 }
 
+static switch_interval_time_t average_time(switch_interval_time_t t, int reps)
+{
+       int x = 0;
+       switch_time_t start, stop, sum = 0;
+
+       for(x = 0; x < reps; x++) {
+               start = switch_time_now();
+               do_sleep(t);
+               stop = switch_time_now();
+               sum += (stop - start);
+       }
+
+       return sum / reps;
+       
+}
+
+static void calibrate_clock(void)
+{
+       int x;
+       switch_interval_time_t avg, val = 1000, want = 1000;
+       int over = 0, under = 0, good = 0;
+
+       for (x = 0; x < 500; x++) {
+               avg = average_time(val, 100);
+               
+               if (abs(want - avg) <= 2) {
+                       if (++good > 10) {
+                               break;
+                       }
+               } else if (avg > want) {
+                       val--;
+                       over++;
+               } else if (avg < want) {
+                       val++;
+                       under++;
+               }
+       }
+
+       OFFSET = want - val;
+}
+
+
 SWITCH_DECLARE(switch_time_t) switch_micro_time_now(void)
 {
        return (globals.RUNNING == 1 && runtime.timestamp) ? runtime.timestamp : switch_time_now();
@@ -144,33 +217,41 @@ SWITCH_DECLARE(time_t) switch_epoch_time_now(time_t *t)
        return now;
 }
 
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
-static int MONO = 1;
-#else
-static int MONO = 0;
-#endif
-
-#if defined(HAVE_CLOCK_NANOSLEEP)
-static int NANO = 1;
-#else
-static int NANO = 0;
-#endif
-
-
 SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable)
 {
        MONO = enable ? 1 : 0;
        switch_time_sync();
 }
 
+
+SWITCH_DECLARE(void) switch_time_set_matrix(switch_bool_t enable)
+{
+       MATRIX = enable ? 1 : 0;
+       if (MATRIX) {
+               STEP_MS = 1;
+               STEP_MIC = 1000;
+               TICK_PER_SEC = 1000;
+       } else {
+               STEP_MS = 10;
+               STEP_MIC = 10000;
+               TICK_PER_SEC = 100;
+       }
+       switch_time_sync();
+}
+
 SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable)
 {
+#if defined(HAVE_CLOCK_NANOSLEEP) 
        NANO = enable ? 1 : 0;
+#endif
 }
 
 SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable)
 {
-       globals.use_cond_yield = enable ? 1 : 0;
+       COND = enable ? 1 : 0;
+       if (COND) {
+               MATRIX = 1;
+       }
 }
 
 static switch_time_t time_now(int64_t offset)
@@ -226,6 +307,11 @@ SWITCH_DECLARE(void) switch_sleep(switch_interval_time_t t)
 
 SWITCH_DECLARE(void) switch_cond_next(void)
 {
+       if (session_manager.session_count > 1000) {
+               os_yield();
+               return;
+       }
+
 #ifdef DISABLE_1MS_COND
        do_sleep(1000);
 #else
@@ -291,6 +377,10 @@ static switch_status_t timer_init(switch_timer_t *timer)
 
                if (timer->interval > 0 && timer->interval < MS_PER_TICK) {
                        MS_PER_TICK = timer->interval;
+                       STEP_MS = 1;
+                       STEP_MIC = 1000;
+                       TICK_PER_SEC = 1000;
+                       switch_time_sync();
                }
 
                return SWITCH_STATUS_SUCCESS;
@@ -366,33 +456,31 @@ static switch_status_t timer_next(switch_timer_t *timer)
        }
        timer_step(timer);
 
+       if (!MATRIX) {
+               do_sleep(1000 * timer->interval);
+               goto end;
+       }
+
        while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) {
                check_roll();
-                       
-               if (NANO) {
-                       do_sleep(1000 * timer->interval);
-                       continue;
-               }
-
+               
                if (globals.use_cond_yield == 1) {
-                       if (switch_mutex_lock(TIMER_MATRIX[cond_index].mutex) == SWITCH_STATUS_SUCCESS) {
-                               if (TIMER_MATRIX[timer->interval].tick < private_info->reference) {
-                                       switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); 
-                               }
-                               switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex);
+                       switch_mutex_lock(TIMER_MATRIX[cond_index].mutex);
+                       if (TIMER_MATRIX[timer->interval].tick < private_info->reference) {
+                               switch_thread_cond_wait(TIMER_MATRIX[cond_index].cond, TIMER_MATRIX[cond_index].mutex); 
+                       }
+                       switch_mutex_unlock(TIMER_MATRIX[cond_index].mutex);
+               } else {
+                       if (session_manager.session_count > 1000) {
+                               os_yield();
                        } else {
                                do_sleep(1000);
                        }
-               } else {
-                       do_sleep(1000);
                }
        }
 
-       if (globals.RUNNING == 1) {
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-       return SWITCH_STATUS_FALSE;
+ end:
+       return globals.RUNNING == 1 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
 }
 
 static switch_status_t timer_check(switch_timer_t *timer, switch_bool_t step)
@@ -492,7 +580,11 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
        }
 #endif
 
-       globals.use_cond_yield = globals.RUNNING = 1;
+       calibrate_clock();
+       switch_time_sync();
+       
+       globals.use_cond_yield = COND;
+       globals.RUNNING = 1;
        
        while (globals.RUNNING == 1) {
                runtime.reference += STEP_MIC;
@@ -513,7 +605,13 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
                        } else {
                                rev_errs = 0;
                        }
-                       do_sleep(STEP_MIC);             
+
+                       if (session_manager.session_count > 1000) {
+                               os_yield();
+                       } else {
+                               do_sleep(STEP_MIC);
+                       }
+
                        last = ts;
                }
 
@@ -570,18 +668,18 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
 #endif
 
 
-               if ((current_ms % MS_PER_TICK) == 0) {
+               if (MATRIX && (current_ms % MS_PER_TICK) == 0) {
                        for (x = MS_PER_TICK; x <= MAX_ELEMENTS; x += MS_PER_TICK) {
                                if ((current_ms % x) == 0) {
                                        if (TIMER_MATRIX[x].count) {
                                                TIMER_MATRIX[x].tick++;
 #ifdef DISABLE_1MS_COND
-                                               if (!NANO) {
-                                                       if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
-                                                               switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
-                                                               switch_mutex_unlock(TIMER_MATRIX[x].mutex);
-                                                       }
+                                               
+                                               if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
+                                                       switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
+                                                       switch_mutex_unlock(TIMER_MATRIX[x].mutex);
                                                }
+                                               
 #endif
                                                if (TIMER_MATRIX[x].tick == MAX_TICK) {
                                                        TIMER_MATRIX[x].tick = 0;