Revision
16098
Author
anthm
Date
2009-12-30 14:55:04 -0600 (Wed, 30 Dec 2009)

Log Message

more timer changes

Modified Paths

Diff

Modified: freeswitch/trunk/src/include/private/switch_core_pvt.h (16097 => 16098)


--- freeswitch/trunk/src/include/private/switch_core_pvt.h	2009-12-30 20:45:37 UTC (rev 16097)
+++ freeswitch/trunk/src/include/private/switch_core_pvt.h	2009-12-30 20:55:04 UTC (rev 16098)
@@ -218,6 +218,19 @@
 
 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);

Modified: freeswitch/trunk/src/include/switch_core.h (16097 => 16098)


--- freeswitch/trunk/src/include/switch_core.h	2009-12-30 20:45:37 UTC (rev 16097)
+++ freeswitch/trunk/src/include/switch_core.h	2009-12-30 20:55:04 UTC (rev 16098)
@@ -1942,6 +1942,7 @@
 #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);

Modified: freeswitch/trunk/src/switch_core.c (16097 => 16098)


--- freeswitch/trunk/src/switch_core.c	2009-12-30 20:45:37 UTC (rev 16097)
+++ freeswitch/trunk/src/switch_core.c	2009-12-30 20:55:04 UTC (rev 16098)
@@ -1415,6 +1415,8 @@
 					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)) {

Modified: freeswitch/trunk/src/switch_core_session.c (16097 => 16098)


--- freeswitch/trunk/src/switch_core_session.c	2009-12-30 20:45:37 UTC (rev 16097)
+++ freeswitch/trunk/src/switch_core_session.c	2009-12-30 20:55:04 UTC (rev 16098)
@@ -36,13 +36,7 @@
 #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)

Modified: freeswitch/trunk/src/switch_time.c (16097 => 16098)


--- freeswitch/trunk/src/switch_time.c	2009-12-30 20:45:37 UTC (rev 16097)
+++ freeswitch/trunk/src/switch_time.c	2009-12-30 20:55:04 UTC (rev 16098)
@@ -45,6 +45,32 @@
 
 #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_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 @@
 
 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 @@
 #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 @@
 
 }
 
+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 @@
 	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_cond_next(void)
 {
+	if (session_manager.session_count > 1000) {
+		os_yield();
+		return;
+	}
+
 #ifdef DISABLE_1MS_COND
 	do_sleep(1000);
 #else
@@ -291,6 +377,10 @@
 
 		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 @@
 	}
 	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,8 +580,12 @@
 	}
 #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;
 		while ((ts = time_now(runtime.offset)) < runtime.reference) {
@@ -513,7 +605,13 @@
 			} 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 @@
 #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;