/** * * CCApp Provider main routine. * * @param arg - CCApp msg queue * * @return void * * @pre None */ void CCApp_task(void * arg) { static const char fname[] = "CCApp_task"; phn_syshdr_t *syshdr = NULL; appListener *listener = NULL; void * msg; //initialize the listener list sll_lite_init(&sll_list); CCAppInit(); while (1) { msg = cprGetMessage(ccapp_msgq, TRUE, (void **) &syshdr); if ( msg) { #if DEBUG dump_msg("CCAPPTASKDUMPMSG", (unsigned int *)msg, syshdr->Len, syshdr->Cmd); #else CCAPP_DEBUG(DEB_F_PREFIX"Received Cmd[%d] for app[%d]\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), syshdr->Cmd, syshdr->Usr.UsrInfo); #endif listener = getCcappListener(syshdr->Usr.UsrInfo); if (listener != NULL) { (* ((appListener)(listener)))(msg, syshdr->Cmd); } else { CCAPP_DEBUG(DEB_F_PREFIX"Event[%d] doesn't have a dedicated listener.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), syshdr->Usr.UsrInfo); } cprReleaseSysHeader(syshdr); cprReleaseBuffer(msg); } } }
/** * Removes all messages from the queue and then destroy the message queue * * @param msgQueue - message queue to destroy * * @return CPR_SUCCESS or CPR_FAILURE, errno provided */ cprRC_t cprDestroyMessageQueue (cprMsgQueue_t msgQueue) { static const char fname[] = "cprDestroyMessageQueue"; cpr_msg_queue_t *msgq; void *msg; msgq = (cpr_msg_queue_t *) msgQueue; if (msgq == NULL) { /* Bad application! */ CPR_ERROR("%s: Invalid input\n", fname); errno = EINVAL; return CPR_FAILURE; } /* Drain message queue */ msg = cprGetMessage(msgQueue, FALSE, NULL); while (msg != NULL) { cpr_free(msg); msg = cprGetMessage(msgQueue, FALSE, NULL); } /* Remove message queue from list */ pthread_mutex_lock(&msgQueueListMutex); if (msgq == msgQueueList) { msgQueueList = msgq->next; } else { cpr_msg_queue_t *msgql = msgQueueList; while ((msgql->next != NULL) && (msgql->next != msgq)) { msgql = msgql->next; } if (msgql->next == msgq) { msgql->next = msgq->next; } } pthread_mutex_unlock(&msgQueueListMutex); /* Remove message queue mutex */ if (pthread_mutex_destroy(&msgq->mutex) != 0) { CPR_ERROR("%s: Failed to destroy msg queue (%s) mutex: %d\n", fname, msgq->name, errno); } cpr_free(msgq); return CPR_SUCCESS; }
/** * * CCApp Provider main routine. * * @param arg - CCApp msg queue * * @return void * * @pre None */ void CCApp_task(void * arg) { static const char fname[] = "CCApp_task"; phn_syshdr_t *syshdr = NULL; appListener *listener = NULL; void * msg; // If the "ready to start" condition variable has been created // (is non-null), we're going to wait for it to be signaled // before we start processing messages. if (ccAppReadyToStartCond) { PR_Lock(ccAppReadyToStartLock); while (!ccAppReadyToStart) { PR_WaitCondVar(ccAppReadyToStartCond, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(ccAppReadyToStartLock); } //initialize the listener list sll_lite_init(&sll_list); CCAppInit(); while (1) { msg = cprGetMessage(ccapp_msgq, TRUE, (void **) &syshdr); if ( msg) { CCAPP_DEBUG(DEB_F_PREFIX"Received Cmd[%d] for app[%d]\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), syshdr->Cmd, syshdr->Usr.UsrInfo); listener = getCcappListener(syshdr->Usr.UsrInfo); if (listener != NULL) { (* ((appListener)(listener)))(msg, syshdr->Cmd); } else { CCAPP_DEBUG(DEB_F_PREFIX"Event[%d] doesn't have a dedicated listener.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), syshdr->Usr.UsrInfo); } cprReleaseSysHeader(syshdr); cpr_free(msg); } } }
/** * 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; /* * Get the GSM message queue handle * A hack until the tasks in irx are * CPRized. */ gsm_msg_queue = (cprMsgQueue_t) arg; if (!gsm_msg_queue) { 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_msg_queue, 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 SUB_MSG_KPML_SUBSCRIBE: case SUB_MSG_KPML_TERMINATE: case SUB_MSG_KPML_NOTIFY_ACK: case SUB_MSG_KPML_SUBSCRIBE_TIMER: case SUB_MSG_KPML_DIGIT_TIMER: kpml_process_msg(syshdr->Cmd, msg); break; case REG_MGR_STATE_CHANGE: gsm_reset(); break; case THREAD_UNLOAD: destroy_gsm_thread(); break; default: GSM_ERR_MSG(GSM_F_PREFIX"Unknown message\n", fname); break; } cprReleaseSysHeader(syshdr); if (release_msg == TRUE) { cprReleaseBuffer(msg); } /* Check if there are pending messages for dcsm * if it in the right state perform its operation */ dcsm_process_jobs(); } } }