]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-4836 try this
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 15 Nov 2012 18:54:35 +0000 (12:54 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 15 Nov 2012 18:54:40 +0000 (12:54 -0600)
src/include/switch_channel.h
src/include/switch_core.h
src/switch_channel.c
src/switch_core_session.c
src/switch_core_state_machine.c

index bddfb0f2d21e0628ea8a35e5e97a452abc40f924..cd8cbb47f0bc21d3acd8a076b808e7e14ec32118 100644 (file)
@@ -643,6 +643,8 @@ SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(
 SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
 SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *channel);
 SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel);
+SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel);
+SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel);
 
 SWITCH_END_EXTERN_C
 #endif
index ead85fdf4af4b961d0159a583c9b9ce7eaa12b30..210b676b1e86c64bce88cb3af14600eaca562002 100644 (file)
@@ -722,6 +722,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_pool_launch(switch_co
 /*! 
   \brief Signal a session's state machine thread that a state change has occured
 */
+SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_session_t *session);
 SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(_In_ switch_core_session_t *session);
 SWITCH_DECLARE(void) switch_core_session_signal_state_change(_In_ switch_core_session_t *session);
 
index 9e40829f823a608fe1f86dbaf713108ab0637d11..a057f9deb8ad144b260ec7bdb71229096f0e51ec 100644 (file)
@@ -129,6 +129,7 @@ struct switch_channel {
        switch_mutex_t *dtmf_mutex;
        switch_mutex_t *flag_mutex;
        switch_mutex_t *state_mutex;
+       switch_mutex_t *thread_mutex;
        switch_mutex_t *profile_mutex;
        switch_core_session_t *session;
        switch_channel_state_t state;
@@ -352,6 +353,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel,
        switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
        switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
        switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);
+       switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool);
        switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
        (*channel)->hangup_cause = SWITCH_CAUSE_NONE;
        (*channel)->name = "";
@@ -1925,6 +1927,32 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(const char *nam
        return CS_DESTROY;
 }
 
+static inline void careful_set(switch_channel_t *channel, switch_channel_state_t *state, switch_channel_state_t val) {
+
+       if (switch_mutex_trylock(channel->thread_mutex)) {
+               *state = val;
+               switch_mutex_unlock(channel->thread_mutex);
+       } else {
+               switch_mutex_t *mutex = switch_core_session_get_mutex(channel->session);
+               int x = 0;
+
+               for (x = 0; x < 100; x++) {
+                       if (switch_mutex_trylock(mutex) == SWITCH_STATUS_SUCCESS) {
+                               *state = val;
+                               switch_mutex_unlock(mutex);
+                               break;
+                       } else {
+                               switch_cond_next();
+                       }
+               }
+
+               if (x == 100) {
+                       *state = val;
+               }
+
+       }
+}
+
 SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state,
                                                                                                                                                                const char *file, const char *func, int line)
 {
@@ -1950,7 +1978,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(
 
        switch_mutex_lock(channel->state_mutex);
 
-       channel->running_state = state;
+       careful_set(channel, &channel->running_state, state);
 
        if (state <= CS_DESTROY) {
                switch_event_t *event;
@@ -2218,7 +2246,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c
                switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n",
                                                  channel->name, state_names[last_state], state_names[state]);
 
-               channel->state = state;
+               careful_set(channel, &channel->state, state);
 
                if (state == CS_HANGUP && !channel->hangup_cause) {
                        channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
@@ -2240,6 +2268,16 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c
        return channel->state;
 }
 
+SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel)
+{
+       switch_mutex_lock(channel->thread_mutex);
+}
+
+SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel)
+{
+       switch_mutex_unlock(channel->thread_mutex);
+}
+
 SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event)
 {
        switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL;
index 449cd1c3c4d5ec8865e2cdb646f59e4cf4105adf..eb250b8dead51b772f5eef35d71dcb74e2c57663 100644 (file)
@@ -1245,6 +1245,11 @@ SWITCH_DECLARE(switch_channel_t *) switch_core_session_get_channel(switch_core_s
        return session->channel;
 }
 
+SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_session_t *session)
+{
+       return session->mutex;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_core_session_t *session)
 {
        switch_status_t status;
index 87b8a32a207d974ac1c86ebc789ca4e4ff6eea1a..daa5bf37d4c8b16cfe012ed1661dffede36f981c 100644 (file)
@@ -521,11 +521,13 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
                                switch_ivr_parse_all_events(session);
 
                                if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
+                                       switch_channel_state_thread_lock(session->channel);
                                        switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
                                        if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
                                                switch_thread_cond_wait(session->cond, session->mutex);
                                        }
                                        switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING);
+                                       switch_channel_state_thread_unlock(session->channel);
                                }
 
                                switch_ivr_parse_all_events(session);