/** * The function is a thread loop that waits on SIP message queue * visible for the external components (sip_msgq). The thread is used * to avoid having the main task loop from having to set a small time * waiting on select() to poll inter-thread messages. The small waiting * time on select() to poll internal messages queue increases the * unnecessary of waking up when system is idle. On the platform that * power conservative is critical such as handheld phone, waking up * periodically is not good for battery life. * * This thread splits the message queue waiting function from the * main thread waiting on select(). This thread simply listens on the * internal message queue and signal to the main thread via IPC socket * or local socket trigger. Therefore the main thread can uniformly * process internal message event and the network event via select(). * The small internal poll time on select() can be * avoided. * * @param[in] arg - pointer to SIP main thread's message queue. * * @return None. * * @pre (arg != NULL) */ void sip_platform_task_msgqwait (void *arg) { const char *fname = "sip_platform_task_msgqwait"; cprMsgQueue_t *msgq = (cprMsgQueue_t *)arg; unsigned int wait_main_thread = 0; phn_syshdr_t *syshdr; void *msg; uint8_t num_messages = 0; uint8_t response = 0; boolean quit_thread = FALSE; char tempdir[sizeof(sip_serv_sock_addr.sun_path)]; if (msgq == NULL) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"task msgq is null, exiting", fname); return; } if (platThreadInit("SIP IPCQ task") != 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to attach thread to JVM", fname); return; } /* * Wait for SIP main thread ready for IPC connection. */ while (!main_thread_ready) { /* Pause for other threads to run while waiting */ cprSleep(SIP_PAUSE_WAIT_IPC_LISTEN_READY_TIME); wait_main_thread++; if (wait_main_thread > SIP_MAX_WAIT_FOR_IPC_LISTEN_READY) { /* Exceed the number of wait time */ CCSIP_DEBUG_ERROR(SIP_F_PREFIX"timeout waiting for listening IPC" " socket ready, exiting\n", fname); return; } } /* * Adjust relative priority of SIP thread. */ (void) cprAdjustRelativeThreadPriority(SIP_THREAD_RELATIVE_PRIORITY); /* * The main thread is ready. set global client socket address * so that the server can send back response. */ sip_get_sock_dir(tempdir, sizeof(tempdir), SIP_MSG_CLNT_SUFFIX); cpr_set_sockun_addr(&sip_clnt_sock_addr, tempdir, 0); sip_ipc_clnt_socket = sip_create_IPC_sock(sip_clnt_sock_addr.sun_path); if (sip_ipc_clnt_socket == INVALID_SOCKET) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_create_IPC_sock() failed," " exiting\n", fname); return; } while (quit_thread == FALSE) { msg = cprGetMessage(msgq, TRUE, (void **) &syshdr); while (msg != NULL) { /* * There is a message to be forwarded to the main SIP * thread for processing. */ sip_int_msgq_buf[num_messages].msg = msg; sip_int_msgq_buf[num_messages].syshdr = syshdr; num_messages++; switch (syshdr->Cmd) { case THREAD_UNLOAD: thread_ended(THREADMON_MSGQ); quit_thread = TRUE; break; default: break; } if (num_messages == MAX_SIP_MESSAGES) { /* * Limit the number of messages passed to the main SIP * thread to MAX_SIP_MESSAGES since SIP main thread only * process messages up to MAX_SIP_MESSAGES at a time. */ break; } /* * Check to see if there is more message on the queue * before sending IPC message trigger to the main SIP * thread. This is to minimize the overhead of the * the main SIP thread in processing select(). */ msg = cprGetMessage(msgq, 0, (void **) &syshdr); } if (num_messages) { CCSIP_DEBUG_TASK(DEB_F_PREFIX"%d msg available on msgq", DEB_F_PREFIX_ARGS(SIP_MSG_QUE, fname), num_messages); /* * There are some number of messages sent to the main thread, * trigger the main SIP thread via IPC to process the message. */ if (cprSendTo(sip_ipc_clnt_socket, (void *)&num_messages, sizeof(num_messages), 0, (cpr_sockaddr_t *)&sip_serv_sock_addr, cpr_sun_len(sip_serv_sock_addr)) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"send IPC failed errno=%d", fname, cpr_errno); } if (FALSE == quit_thread) { /* * Wait for main thread to signal us to get more message. */ if (cprRecvFrom(sip_ipc_clnt_socket, &response, sizeof(response), 0, NULL, NULL) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:" " errno=%d\n", fname, cpr_errno); } num_messages = 0; } } } cprCloseSocket(sip_ipc_clnt_socket); unlink(sip_clnt_sock_addr.sun_path); // removes tmp file }
void GSMTask (void *arg) { static const char fname[] = "GSMTask"; void *msg; phn_syshdr_t *syshdr; boolean release_msg = TRUE; MOZ_ASSERT (gsm_msgq == (cprMsgQueue_t) arg); if (!gsm_msgq) { GSM_ERR_MSG(GSM_F_PREFIX"invalid input, exiting\n", fname); return; } if (platThreadInit("GSMTask") != 0) { return; } /* * Adjust relative priority of GSM thread. */ (void) cprAdjustRelativeThreadPriority(GSM_THREAD_RELATIVE_PRIORITY); /* * Initialize all the GSM modules */ lsm_init(); fsm_init(); fim_init(); gsm_init(); dcsm_init(); cc_init(); fsmutil_init_shown_calls_ci_map(); /* * On Win32 platform, the random seed is stored per thread; therefore, * each thread needs to seed the random number. It is recommended by * MS to do the following to ensure randomness across application * restarts. */ cpr_srand((unsigned int)time(NULL)); /* * Cache random numbers for SRTP keys */ gsmsdp_cache_crypto_keys(); while (1) { release_msg = TRUE; msg = cprGetMessage(gsm_msgq, TRUE, (void **) &syshdr); if (msg) { switch (syshdr->Cmd) { case TIMER_EXPIRATION: gsm_process_timer_expiration(msg); break; case GSM_SIP: case GSM_GSM: release_msg = gsm_process_msg(syshdr->Cmd, msg); break; case DP_MSG_INIT_DIALING: case DP_MSG_DIGIT_STR: case DP_MSG_STORE_DIGIT: case DP_MSG_DIGIT: case DP_MSG_DIAL_IMMEDIATE: case DP_MSG_REDIAL: case DP_MSG_ONHOOK: case DP_MSG_OFFHOOK: case DP_MSG_UPDATE: case DP_MSG_DIGIT_TIMER: case DP_MSG_CANCEL_OFFHOOK_TIMER: dp_process_msg(syshdr->Cmd, msg); break; case SUB_MSG_B2BCNF_SUBSCRIBE_RESP: case SUB_MSG_B2BCNF_NOTIFY: case SUB_MSG_B2BCNF_TERMINATE: sub_process_b2bcnf_msg(syshdr->Cmd, msg); break; case SUB_MSG_FEATURE_SUBSCRIBE_RESP: case SUB_MSG_FEATURE_NOTIFY: case SUB_MSG_FEATURE_TERMINATE: sub_process_feature_msg(syshdr->Cmd, msg); break; case REG_MGR_STATE_CHANGE: gsm_reset(); break; case THREAD_UNLOAD: thread_ended(THREADMON_GSM); destroy_gsm_thread(); break; default: GSM_ERR_MSG(GSM_F_PREFIX"Unknown message\n", fname); break; } cprReleaseSysHeader(syshdr); if (release_msg == TRUE) { cpr_free(msg); } /* Check if there are pending messages for dcsm * if it in the right state perform its operation */ dcsm_process_jobs(); } } }