/******************************************************************************* ** ** Function GKI_igetpoolbuf ** ** Description Called by an interrupt service routine to get a free buffer from ** a specific buffer pool. ** ** Parameters pool_id - (input) pool ID to get a buffer out of. ** ** Returns A pointer to the buffer, or NULL if none available ** *******************************************************************************/ void *GKI_igetpoolbuf (UINT8 pool_id) { FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL); Q = &gki_cb.com.freeq[pool_id]; if(Q->cur_cnt < Q->total) { p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } return (NULL); }
/******************************************************************************* ** ** Function GKI_stop_timer ** ** Description An application can call this function to stop one of ** it's four general purpose timers. There is no harm in ** stopping a timer that is already stopped. ** ** Parameters tnum - (input) timer number to be started (TIMER_0, ** TIMER_1, TIMER_2, or TIMER_3) ** Returns void ** *******************************************************************************/ void GKI_stop_timer (UINT8 tnum) { UINT8 task_id = GKI_get_taskid(); switch (tnum) { #if (GKI_NUM_TIMERS > 0) case TIMER_0: gki_cb.com.OSTaskTmr0R[task_id] = 0; gki_cb.com.OSTaskTmr0 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 1) case TIMER_1: gki_cb.com.OSTaskTmr1R[task_id] = 0; gki_cb.com.OSTaskTmr1 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 2) case TIMER_2: gki_cb.com.OSTaskTmr2R[task_id] = 0; gki_cb.com.OSTaskTmr2 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 3) case TIMER_3: gki_cb.com.OSTaskTmr3R[task_id] = 0; gki_cb.com.OSTaskTmr3 [task_id] = 0; break; #endif } }
/******************************************************************************* ** ** Function GKI_read_mbox ** ** Description Called by applications to read a buffer from one of ** the task mailboxes. A task can only read its own mailbox. ** ** Parameters: mbox - (input) mailbox ID to read (0, 1, 2, or 3) ** ** Returns NULL if the mailbox was empty, else the address of a buffer ** *******************************************************************************/ void *GKI_read_mbox (UINT8 mbox) { UINT8 task_id = GKI_get_taskid(); void *p_buf = NULL; BUFFER_HDR_T *p_hdr; if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX)) return (NULL); GKI_disable(); if (gki_cb.com.OSTaskQFirst[task_id][mbox]) { p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox]; gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_UNLINKED; p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE; } GKI_enable(); return (p_buf); }
/******************************************************************************* ** ** Function nfc_hal_main_start_quick_timer ** ** Description Start a timer for the specified amount of time. ** NOTE: The timeout resolution depends on including modules. ** QUICK_TIMER_TICKS_PER_SEC should be used to convert from ** time to ticks. ** ** ** Returns void ** *******************************************************************************/ void nfc_hal_main_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) { NFC_HDR *p_msg; /* if timer list is currently empty, start periodic GKI timer */ if (nfc_hal_cb.quick_timer_queue.p_first == NULL) { /* if timer starts on other than NCIT task (script wrapper) */ if(GKI_get_taskid () != NFC_HAL_TASK) { /* post event to start timer in NCIT task */ if ((p_msg = (NFC_HDR *) GKI_getbuf (NFC_HDR_SIZE)) != NULL) { p_msg->event = NFC_HAL_EVT_TO_START_QUICK_TIMER; GKI_send_msg (NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg); } } else { GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); } } GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); p_tle->event = type; p_tle->ticks = timeout; /* Save the number of ticks for the timer */ GKI_add_to_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle); }
/******************************************************************************* ** ** Function nfc_start_timer ** ** Description Start a timer for the specified amount of time. ** NOTE: The timeout resolution is in SECONDS! (Even ** though the timer structure field is ticks) ** ** Returns void ** *******************************************************************************/ void nfc_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) { BT_HDR *p_msg; /* if timer list is currently empty, start periodic GKI timer */ if (nfc_cb.timer_queue.p_first == NULL) { /* if timer starts on other than NFC task (scritp wrapper) */ if (GKI_get_taskid () != NFC_TASK) { /* post event to start timer in NFC task */ if ((p_msg = (BT_HDR *) GKI_getbuf (BT_HDR_SIZE)) != NULL) { p_msg->event = BT_EVT_TO_START_TIMER; GKI_send_msg (NFC_TASK, NFC_MBOX_ID, p_msg); } } else { /* Start nfc_task 1-sec resolution timer */ GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE); } } GKI_remove_from_timer_list (&nfc_cb.timer_queue, p_tle); p_tle->event = type; p_tle->ticks = timeout; /* Save the number of seconds for the timer */ GKI_add_to_timer_list (&nfc_cb.timer_queue, p_tle); }
void GKI_delay (UINT32 timeout) { UINT8 rtask = GKI_get_taskid(); struct timespec delay; int err; GKI_TRACE("GKI_delay %d %d", (int)rtask, (int)timeout); delay.tv_sec = timeout / 1000; delay.tv_nsec = 1000 * 1000 * (timeout%1000); /* [u]sleep can't be used because it uses SIGALRM */ do { err = nanosleep(&delay, &delay); } while (err < 0 && errno ==EINTR); /* Check if task was killed while sleeping */ /* NOTE : if you do not implement task killing, you do not need this check */ if (rtask && gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) { } GKI_TRACE("GKI_delay %d %d done", (int)rtask, (int)timeout); return; }
/******************************************************************************* ** ** Function btu_start_quick_timer ** ** Description Start a timer for the specified amount of time. ** NOTE: The timeout resolution depends on including modules. ** QUICK_TIMER_TICKS_PER_SEC should be used to convert from ** time to ticks. ** ** ** Returns void ** *******************************************************************************/ void btu_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) { BT_HDR *p_msg; /* if timer list is currently empty, start periodic GKI timer */ if (btu_cb.quick_timer_queue.p_first == NULL) { /* script test calls stack API without posting event */ if (GKI_get_taskid() != BTU_TASK) { /* post event to start timer in BTU task */ if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL) { p_msg->event = BT_EVT_TO_START_QUICK_TIMER; GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg); } } else GKI_start_timer(TIMER_2, QUICK_TIMER_TICKS, TRUE); } GKI_remove_from_timer_list (&btu_cb.quick_timer_queue, p_tle); p_tle->event = type; p_tle->ticks = timeout; /* Save the number of ticks for the timer */ GKI_add_to_timer_list (&btu_cb.quick_timer_queue, p_tle); }
/******************************************************************************* ** ** Function btu_start_timer ** ** Description Start a timer for the specified amount of time. ** NOTE: The timeout resolution is in SECONDS! (Even ** though the timer structure field is ticks) ** ** Returns void ** *******************************************************************************/ void btu_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout) { BT_HDR *p_msg; /* if timer list is currently empty, start periodic GKI timer */ if (btu_cb.timer_queue.p_first == NULL) { /* if timer starts on other than BTU task */ if (GKI_get_taskid() != BTU_TASK) { /* post event to start timer in BTU task */ if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL) { p_msg->event = BT_EVT_TO_START_TIMER; GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg); } } else { /* Start free running 1 second timer for list management */ GKI_start_timer (TIMER_0, GKI_SECS_TO_TICKS (1), TRUE); } } GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle); p_tle->event = type; p_tle->ticks = timeout; /* Save the number of seconds for the timer */ GKI_add_to_timer_list (&btu_cb.timer_queue, p_tle); }
/******************************************************************************* ** ** Function GKI_stop_timer ** ** Description An application can call this function to stop one of ** it's four general purpose timers. There is no harm in ** stopping a timer that is already stopped. ** ** Parameters tnum - (input) timer number to be started (TIMER_0, ** TIMER_1, TIMER_2, or TIMER_3) ** Returns void ** *******************************************************************************/ void GKI_stop_timer (UINT8 tnum) { UINT8 task_id = GKI_get_taskid(); GKI_disable(); switch (tnum) { #if (GKI_NUM_TIMERS > 0) case TIMER_0: gki_cb.com.OSTaskTmr0R[task_id] = 0; gki_cb.com.OSTaskTmr0 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 1) case TIMER_1: gki_cb.com.OSTaskTmr1R[task_id] = 0; gki_cb.com.OSTaskTmr1 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 2) case TIMER_2: gki_cb.com.OSTaskTmr2R[task_id] = 0; gki_cb.com.OSTaskTmr2 [task_id] = 0; break; #endif #if (GKI_NUM_TIMERS > 3) case TIMER_3: gki_cb.com.OSTaskTmr3R[task_id] = 0; gki_cb.com.OSTaskTmr3 [task_id] = 0; break; #endif } if (gki_timers_is_timer_running() == FALSE) { if (gki_cb.com.p_tick_cb) { #if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) /* if inactivity delay timer is not running */ if ((gki_cb.com.system_tick_running)&&(gki_cb.com.OSTicksTilStop == 0)) { /* set inactivity delay timer */ /* when timer expires, system tick will be stopped */ gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK; } #else gki_cb.com.system_tick_running = FALSE; gki_cb.com.p_tick_cb(FALSE); /* stop system tick */ #endif } } GKI_enable(); }
/******************************************************************************* ** ** Function GKI_getpoolbuf ** ** Description Called by an application to get a free buffer from ** a specific buffer pool. ** ** Note: If there are no more buffers available from the pool, ** the public buffers are searched for an available buffer. ** ** Parameters pool_id - (input) pool ID to get a buffer out of. ** ** Returns A pointer to the buffer, or NULL if none available ** *******************************************************************************/ void *GKI_getpoolbuf (UINT8 pool_id) { FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) { GKI_exception(GKI_ERROR_GETPOOLBUF_BAD_QID, "getpoolbuf bad pool"); return (NULL); } /* Make sure the buffers aren't disturbed til finished with allocation */ GKI_disable(); Q = &p_cb->freeq[pool_id]; if(Q->cur_cnt < Q->total) { // btla-specific ++ #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE) { GKI_enable(); return NULL; } #endif // btla-specific -- p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; GKI_enable(); p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } /* If here, no buffers in the specified pool */ GKI_enable(); /* try for free buffers in public pools */ return (GKI_getbuf(p_cb->freeq[pool_id].size)); }
void GKI_exception (UINT16 code, char *msg) { UINT8 task_id; int i = 0; FREE_QUEUE_T *Q; tGKI_COM_CB *p_cb = &gki_cb.com; ALOGE( "GKI_exception(): Task State Table"); for(task_id = 0; task_id < GKI_MAX_TASKS; task_id++) { ALOGE( "TASK ID [%d] task name [%s] state [%d]", task_id, gki_cb.com.OSTName[task_id], gki_cb.com.OSRdyTbl[task_id]); } ALOGE("GKI_exception %d %s", code, msg); ALOGE( "********************************************************************"); ALOGE( "* GKI_exception(): %d %s", code, msg); ALOGE( "********************************************************************"); #if 0//(GKI_DEBUG == TRUE) GKI_disable(); if (gki_cb.com.ExceptionCnt < GKI_MAX_EXCEPTION) { EXCEPTION_T *pExp; pExp = &gki_cb.com.Exception[gki_cb.com.ExceptionCnt++]; pExp->type = code; pExp->taskid = GKI_get_taskid(); strncpy((char *)pExp->msg, msg, GKI_MAX_EXCEPTION_MSGLEN - 1); } GKI_enable(); #endif if (code == GKI_ERROR_OUT_OF_BUFFERS) { for(i=0; i<p_cb->curr_total_no_of_pools; i++) { Q = &p_cb->freeq[p_cb->pool_list[i]]; if (Q !=NULL) ALOGE("GKI_exception Buffer current cnt:%x, Total:%x", Q->cur_cnt, Q->total); } } GKI_TRACE("GKI_exception %d %s done", code, msg); return; }
/******************************************************************************* ** ** Function GKI_task_self_cleanup ** ** Description This function is used in the case when the calling thread ** is exiting itself. The GKI_destroy_task function can not be ** used in this case due to the pthread_join call. The function ** cleans up GKI control block associated to the terminating ** thread. ** ** Parameters: task_id - (input) Task id is used for sanity check to ** make sure the calling thread is in the right ** context. ** ** Returns None ** *******************************************************************************/ void GKI_task_self_cleanup(UINT8 task_id) { UINT8 my_task_id = GKI_get_taskid(); if (task_id != my_task_id) { GKI_ERROR_LOG("%s: Wrong context - current task %d is not the given task id %d",\ __FUNCTION__, my_task_id, task_id); return; } if (gki_cb.com.OSRdyTbl[task_id] != TASK_DEAD) { /* paranoi settings, make sure that we do not execute any mailbox events */ gki_cb.com.OSWaitEvt[task_id] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); #if (GKI_NUM_TIMERS > 0) gki_cb.com.OSTaskTmr0R[task_id] = 0; gki_cb.com.OSTaskTmr0 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 1) gki_cb.com.OSTaskTmr1R[task_id] = 0; gki_cb.com.OSTaskTmr1 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 2) gki_cb.com.OSTaskTmr2R[task_id] = 0; gki_cb.com.OSTaskTmr2 [task_id] = 0; #endif #if (GKI_NUM_TIMERS > 3) gki_cb.com.OSTaskTmr3R[task_id] = 0; gki_cb.com.OSTaskTmr3 [task_id] = 0; #endif GKI_exit_task(task_id); /* Calling pthread_detach here to mark the thread as detached. Once the thread terminates, the system can reclaim its resources without waiting for another thread to join with. */ pthread_detach(gki_cb.os.thread_id[task_id]); } }
/******************************************************************************* ** ** Function: NfcAdaptation::Thread() ** ** Description: Creates work threads ** ** Returns: none ** *******************************************************************************/ UINT32 NfcAdaptation::Thread (UINT32 arg) { const char* func = "NfcAdaptation::Thread"; ALOGD ("%s: enter", func); { ThreadCondVar CondVar; AutoThreadMutex guard(CondVar); GKI_create_task ((TASKPTR)nfc_task, NFC_TASK, (INT8*)"NFC_TASK", 0, 0, (pthread_cond_t*)CondVar, (pthread_mutex_t*)CondVar); CondVar.wait(); } NfcAdaptation::GetInstance().signal(); GKI_exit_task (GKI_get_taskid ()); ALOGD ("%s: exit", func); return NULL; }
INT8 *GKI_map_taskname (UINT8 task_id) { GKI_TRACE("GKI_map_taskname %d", task_id); if (task_id < GKI_MAX_TASKS) { GKI_TRACE("GKI_map_taskname %d %s done", task_id, gki_cb.com.OSTName[task_id]); return (gki_cb.com.OSTName[task_id]); } else if (task_id == GKI_MAX_TASKS ) { return (gki_cb.com.OSTName[GKI_get_taskid()]); } else { return (INT8*)"BAD"; } }
void GKI_exception (UINT16 code, char *msg) { UINT8 task_id; int i = 0; GKI_TRACE_ERROR_0( "GKI_exception(): Task State Table"); for(task_id = 0; task_id < GKI_MAX_TASKS; task_id++) { GKI_TRACE_ERROR_3( "TASK ID [%d] task name [%s] state [%d]", task_id, gki_cb.com.OSTName[task_id], gki_cb.com.OSRdyTbl[task_id]); } GKI_TRACE_ERROR_2("GKI_exception %d %s", code, msg); GKI_TRACE_ERROR_0( "********************************************************************"); GKI_TRACE_ERROR_2( "* GKI_exception(): %d %s", code, msg); GKI_TRACE_ERROR_0( "********************************************************************"); #if (GKI_DEBUG == TRUE) GKI_disable(); if (gki_cb.com.ExceptionCnt < GKI_MAX_EXCEPTION) { EXCEPTION_T *pExp; pExp = &gki_cb.com.Exception[gki_cb.com.ExceptionCnt++]; pExp->type = code; pExp->taskid = GKI_get_taskid(); strncpy((char *)pExp->msg, msg, GKI_MAX_EXCEPTION_MSGLEN - 1); } GKI_enable(); #endif GKI_TRACE_ERROR_2("GKI_exception %d %s done", code, msg); return; }
/******************************************************************************* ** ** Function GKI_getbuf ** ** Description Called by an application to get a free buffer which ** is of size greater or equal to the requested size. ** ** Note: This routine only takes buffers from public pools. ** It will not use any buffers from pools ** marked GKI_RESTRICTED_POOL. ** ** Parameters size - (input) number of bytes needed. ** ** Returns A pointer to the buffer, or NULL if none available ** *******************************************************************************/ void *GKI_getbuf (UINT16 size) { UINT8 i; FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; if (size == 0) { GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero"); return (NULL); } /* Find the first buffer pool that is public that can hold the desired size */ for (i=0; i < p_cb->curr_total_no_of_pools; i++) { if ( size <= p_cb->freeq[p_cb->pool_list[i]].size ) break; } if(i == p_cb->curr_total_no_of_pools) { GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big"); return (NULL); } /* Make sure the buffers aren't disturbed til finished with allocation */ GKI_disable(); /* search the public buffer pools that are big enough to hold the size * until a free buffer is found */ for ( ; i < p_cb->curr_total_no_of_pools; i++) { /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */ if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask) continue; Q = &p_cb->freeq[p_cb->pool_list[i]]; if(Q->cur_cnt < Q->total) { // btla-specific ++ #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE) return NULL; #endif // btla-specific -- p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; GKI_enable(); p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } } GKI_enable(); GKI_exception (GKI_ERROR_OUT_OF_BUFFERS, "getbuf: out of buffers"); return (NULL); }
/******************************************************************************* ** ** Function GKI_start_timer ** ** Description An application can call this function to start one of ** it's four general purpose timers. Any of the four timers ** can be 1-shot or continuous. If a timer is already running, ** it will be reset to the new parameters. ** ** Parameters tnum - (input) timer number to be started (TIMER_0, ** TIMER_1, TIMER_2, or TIMER_3) ** ticks - (input) the number of system ticks til the ** timer expires. ** is_continuous - (input) TRUE if timer restarts automatically, ** else FALSE if it is a 'one-shot'. ** ** Returns void ** *******************************************************************************/ void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous) { INT32 reload; INT32 orig_ticks; UINT8 task_id = GKI_get_taskid(); BOOLEAN bad_timer = FALSE; if (ticks <= 0) ticks = 1; orig_ticks = ticks; /* save the ticks in case adjustment is necessary */ /* If continuous timer, set reload, else set it to 0 */ if (is_continuous) reload = ticks; else reload = 0; GKI_disable(); if(gki_timers_is_timer_running() == FALSE) { #if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) /* if inactivity delay timer is not running, start system tick */ if(gki_cb.com.OSTicksTilStop == 0) { #endif if(gki_cb.com.p_tick_cb) { /* start system tick */ gki_cb.com.system_tick_running = TRUE; (gki_cb.com.p_tick_cb) (TRUE); } #if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) } else { /* clear inactivity delay timer */ gki_cb.com.OSTicksTilStop = 0; } #endif } /* Add the time since the last task timer update. ** Note that this works when no timers are active since ** both OSNumOrigTicks and OSTicksTilExp are 0. */ if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks) { ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp; } else ticks = GKI_MAX_INT32; switch (tnum) { #if (GKI_NUM_TIMERS > 0) case TIMER_0: gki_cb.com.OSTaskTmr0R[task_id] = reload; gki_cb.com.OSTaskTmr0 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 1) case TIMER_1: gki_cb.com.OSTaskTmr1R[task_id] = reload; gki_cb.com.OSTaskTmr1 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 2) case TIMER_2: gki_cb.com.OSTaskTmr2R[task_id] = reload; gki_cb.com.OSTaskTmr2 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 3) case TIMER_3: gki_cb.com.OSTaskTmr3R[task_id] = reload; gki_cb.com.OSTaskTmr3 [task_id] = ticks; break; #endif default: bad_timer = TRUE; /* Timer number is bad, so do not use */ } /* Update the expiration timeout if a legitimate timer */ if (!bad_timer) { /* Only update the timeout value if it is less than any other newly started timers */ gki_adjust_timer_count (orig_ticks); } GKI_enable(); }
/******************************************************************************* ** ** Function GKI_wait ** ** Description This function is called by tasks to wait for a specific ** event or set of events. The task may specify the duration ** that it wants to wait for, or 0 if infinite. ** ** Parameters: flag - (input) the event or set of events to wait for ** timeout - (input) the duration that the task wants to wait ** for the specific events (in system ticks) ** ** ** Returns the event mask of received events or zero if timeout ** *******************************************************************************/ UINT16 GKI_wait (UINT16 flag, UINT32 timeout) { UINT16 evt; UINT8 rtask; struct timespec abstime = { 0, 0 }; int sec; int nano_sec; rtask = GKI_get_taskid(); GKI_TRACE("GKI_wait %d %x %d", (int)rtask, (int)flag, (int)timeout); gki_cb.com.OSWaitForEvt[rtask] = flag; /* protect OSWaitEvt[rtask] from modification from an other thread */ pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]); if (!(gki_cb.com.OSWaitEvt[rtask] & flag)) { if (timeout) { clock_gettime(CLOCK_MONOTONIC, &abstime); /* add timeout */ sec = timeout / 1000; nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC; abstime.tv_nsec += nano_sec; if (abstime.tv_nsec > NSEC_PER_SEC) { abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC); abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC; } abstime.tv_sec += sec; pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask], &abstime); } else { pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]); } /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation, e.g. it looks like it is implemented as a counter in which case multiple cond_signal should NOT be lost! */ /* we are waking up after waiting for some events, so refresh variables no need to call GKI_disable() here as we know that we will have some events as we've been waking up after condition pending or timeout */ if (gki_cb.com.OSTaskQFirst[rtask][0]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][1]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][2]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][3]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK; if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) { gki_cb.com.OSWaitEvt[rtask] = 0; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); return (EVENT_MASK(GKI_SHUTDOWN_EVT)); } } /* Clear the wait for event mask */ gki_cb.com.OSWaitForEvt[rtask] = 0; /* Return only those bits which user wants... */ evt = gki_cb.com.OSWaitEvt[rtask] & flag; /* Clear only those bits which user wants... */ gki_cb.com.OSWaitEvt[rtask] &= ~flag; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); GKI_TRACE("GKI_wait %d %x %d %x done", (int)rtask, (int)flag, (int)timeout, (int)evt); return (evt); }
void *GKI_getbuf (UINT16 size) #endif { UINT8 i; FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; #if GKI_BUFFER_DEBUG UINT8 x; #endif if (size == 0) { GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero"); return (NULL); } #if GKI_BUFFER_DEBUG LOGD("GKI_getbuf() requesting %d func:%s(line=%d)", size, _function_, _line_); #endif /* Find the first buffer pool that is public that can hold the desired size */ for (i=0; i < p_cb->curr_total_no_of_pools; i++) { if ( size <= p_cb->freeq[p_cb->pool_list[i]].size ) break; } if(i == p_cb->curr_total_no_of_pools) { GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big"); return (NULL); } /* Make sure the buffers aren't disturbed til finished with allocation */ GKI_disable(); /* search the public buffer pools that are big enough to hold the size * until a free buffer is found */ for ( ; i < p_cb->curr_total_no_of_pools; i++) { /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */ if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask) continue; Q = &p_cb->freeq[p_cb->pool_list[i]]; if(Q->cur_cnt < Q->total) { #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE) { GKI_TRACE_ERROR_0("GKI_getbuf() out of buffer"); GKI_enable(); return NULL; } #endif if(Q->p_first == 0) { /* gki_alloc_free_queue() failed to alloc memory */ GKI_TRACE_ERROR_0("GKI_getbuf() fail alloc free queue"); GKI_enable(); return NULL; } p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; GKI_enable(); p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; #if GKI_BUFFER_DEBUG LOGD("GKI_getbuf() allocated, %x, %x (%d of %d used) %d", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[i].total); strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN); p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0'; p_hdr->_line = _line_; #endif return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } } GKI_TRACE_ERROR_0("GKI_getbuf() unable to allocate buffer!!!!!"); #if GKI_BUFFER_DEBUG LOGD("GKI_getbuf() unable to allocate buffer!!!!!"); LOGD("******************** GKI Memory Pool Dump ********************"); p_cb = &gki_cb.com; LOGD("Dumping total of %d buffer pools", p_cb->curr_total_no_of_pools); for (i=0 ; i < p_cb->curr_total_no_of_pools; i++) { p_hdr = (BUFFER_HDR_T *)p_cb->pool_start[i]; LOGD("pool %d has a total of %d buffers (start=%p)", i, p_cb->freeq[i].total, p_hdr); for (x=0; p_hdr && x < p_cb->freeq[i].total; x++) { if (p_hdr->status != BUF_STATUS_FREE) { LOGD("pool:%d, buf[%d]:%x, hdr:%x status=%d func:%s(line=%d)", i, x, (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, p_hdr->status, p_hdr->_function, p_hdr->_line); } p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_hdr + p_cb->pool_size[i]); } } LOGD("**************************************************************"); #endif GKI_TRACE_ERROR_0("Failed to allocate GKI buffer"); GKI_enable(); return (NULL); }
void *GKI_getpoolbuf (UINT8 pool_id) #endif { FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL); #if GKI_BUFFER_DEBUG LOGD("GKI_getpoolbuf() requesting from %d func:%s(line=%d)", pool_id, _function_, _line_); #endif /* Make sure the buffers aren't disturbed til finished with allocation */ GKI_disable(); Q = &p_cb->freeq[pool_id]; if(Q->cur_cnt < Q->total) { #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE) return NULL; #endif if(Q->p_first == 0) { /* gki_alloc_free_queue() failed to alloc memory */ GKI_TRACE_ERROR_0("GKI_getpoolbuf() fail alloc free queue"); return NULL; } p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; GKI_enable(); p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; #if GKI_BUFFER_DEBUG LOGD("GKI_getpoolbuf() allocated, %x, %x (%d of %d used) %d", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[pool_id].total); strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN); p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0'; p_hdr->_line = _line_; #endif return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } /* If here, no buffers in the specified pool */ GKI_enable(); #if GKI_BUFFER_DEBUG /* try for free buffers in public pools */ return (GKI_getbuf_debug(p_cb->freeq[pool_id].size, _function_, _line_)); #else /* try for free buffers in public pools */ return (GKI_getbuf(p_cb->freeq[pool_id].size)); #endif }
/******************************************************************************* ** ** Function nfc_task ** ** Description NFC event processing task ** ** Returns nothing ** *******************************************************************************/ UINT32 nfc_task (UINT32 param) { UINT16 event; BT_HDR *p_msg; BOOLEAN free_buf; /* Initialize the nfc control block */ memset (&nfc_cb, 0, sizeof (tNFC_CB)); nfc_cb.trace_level = NFC_INITIAL_TRACE_LEVEL; NFC_TRACE_DEBUG0 ("NFC_TASK started."); /* main loop */ while (TRUE) { event = GKI_wait (0xFFFF, 0); /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */ if (event & NFC_TASK_EVT_TRANSPORT_READY) { NFC_TRACE_DEBUG0 ("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY."); /* Reset the NFC controller. */ nfc_set_state (NFC_STATE_CORE_INIT); nci_snd_core_reset (NCI_RESET_TYPE_RESET_CFG); } if (event & NFC_MBOX_EVT_MASK) { /* Process all incoming NCI messages */ while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL) { free_buf = TRUE; /* Determine the input message type. */ switch (p_msg->event & BT_EVT_MASK) { case BT_EVT_TO_NFC_NCI: free_buf = nfc_ncif_process_event (p_msg); break; case BT_EVT_TO_START_TIMER : /* Start nfc_task 1-sec resolution timer */ GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE); break; case BT_EVT_TO_START_QUICK_TIMER : /* Quick-timer is required for LLCP */ GKI_start_timer (NFC_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); break; case BT_EVT_TO_NFC_MSGS: nfc_main_handle_hal_evt ((tNFC_HAL_EVT_MSG*)p_msg); break; default: NFC_TRACE_DEBUG1 ("nfc_task: unhandle mbox message, event=%04x", p_msg->event); break; } if (free_buf) { GKI_freebuf (p_msg); } } } /* Process gki timer tick */ if (event & NFC_TIMER_EVT_MASK) { nfc_process_timer_evt (); } /* Process quick timer tick */ if (event & NFC_QUICK_TIMER_EVT_MASK) { nfc_process_quick_timer_evt (); } #if (defined (NFA_INCLUDED) && NFA_INCLUDED == TRUE) if (event & NFA_MBOX_EVT_MASK) { while ((p_msg = (BT_HDR *) GKI_read_mbox (NFA_MBOX_ID)) != NULL) { nfa_sys_event (p_msg); } } if (event & NFA_TIMER_EVT_MASK) { nfa_sys_timer_update (); } #endif } NFC_TRACE_DEBUG0 ("nfc_task terminated"); GKI_exit_task (GKI_get_taskid ()); return 0; }
/******************************************************************************* ** ** Function nfc_hal_main_task ** ** Description NFC HAL NCI transport event processing task ** ** Returns 0 ** *******************************************************************************/ UINT32 nfc_hal_main_task (UINT32 param) { UINT16 event; UINT8 byte; UINT8 num_interfaces; UINT8 *p; NFC_HDR *p_msg; BOOLEAN free_msg; HAL_TRACE_DEBUG0 ("NFC_HAL_TASK started"); /* Main loop */ while (TRUE) { event = GKI_wait (0xFFFF, 0); /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */ if (event & NFC_HAL_TASK_EVT_INITIALIZE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport..."); nfc_hal_main_open_transport (); } /* Check for terminate event */ if (event & NFC_HAL_TASK_EVT_TERMINATE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); if (nfc_hal_cb.p_stack_cback) { nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK); nfc_hal_cb.p_stack_cback = NULL; } continue; } /* Check for power cycle event */ if (event & NFC_HAL_TASK_EVT_POWER_CYCLE) { HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE"); nfc_hal_main_handle_terminate (); /* Close uart */ USERIAL_Close (USERIAL_NFC_PORT); /* power cycle timeout */ nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE, (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000); continue; } /* NCI message ready to be sent to NFCC */ if (event & NFC_HAL_TASK_EVT_MBOX) { while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL) { free_msg = TRUE; switch (p_msg->event & NFC_EVT_MASK) { case NFC_HAL_EVT_TO_NFC_NCI: nfc_hal_main_send_message (p_msg); /* do not free buffer. NCI VS code may keep it for processing later */ free_msg = FALSE; break; case NFC_HAL_EVT_POST_CORE_RESET: NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE); /* set NCI Control packet size from CORE_INIT_RSP */ p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE; p += 5; STREAM_TO_UINT8 (num_interfaces, p); p += (num_interfaces + 3); nfc_hal_cb.ncit_cb.nci_ctrl_size = *p; /* start post initialization */ nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD; nfc_hal_cb.dev_cb.next_startup_vsc = 1; nfc_hal_dm_config_nfcc (); break; case NFC_HAL_EVT_TO_START_QUICK_TIMER: GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE); break; case NFC_HAL_EVT_HCI: nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg); break; case NFC_HAL_EVT_PRE_DISCOVER: NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE); nfa_hal_send_pre_discover_cfg (); break; case NFC_HAL_EVT_CONTROL_GRANTED: nfc_hal_dm_send_pend_cmd (); break; default: break; } if (free_msg) GKI_freebuf (p_msg); } } /* Data waiting to be read from serial port */ if (event & NFC_HAL_TASK_EVT_DATA_RDY) { while (TRUE) { /* Read one byte to see if there is anything waiting to be read */ if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0) { break; } if (nfc_hal_nci_receive_msg (byte)) { /* complete of receiving NCI message */ nfc_hal_nci_assemble_nci_msg (); if (nfc_hal_cb.ncit_cb.p_rcv_msg) { if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg)) { /* Send NCI message to the stack */ nfc_hal_send_nci_msg_to_nfc_task (nfc_hal_cb.ncit_cb.p_rcv_msg); } else { if (nfc_hal_cb.ncit_cb.p_rcv_msg) GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg); } nfc_hal_cb.ncit_cb.p_rcv_msg = NULL; } } } /* while (TRUE) */ } /* Process quick timer tick */ if (event & NFC_HAL_QUICK_TIMER_EVT_MASK) { nfc_hal_main_process_quick_timer_evt (); } } HAL_TRACE_DEBUG0 ("nfc_hal_main_task terminated"); GKI_exit_task (GKI_get_taskid ()); return 0; }
/******************************************************************************* ** ** Function GKI_wait ** ** Description This function is called by tasks to wait for a specific ** event or set of events. The task may specify the duration ** that it wants to wait for, or 0 if infinite. ** ** Parameters: flag - (input) the event or set of events to wait for ** timeout - (input) the duration that the task wants to wait ** for the specific events (in system ticks) ** ** ** Returns the event mask of received events or zero if timeout ** *******************************************************************************/ UINT16 GKI_wait (UINT16 flag, UINT32 timeout) { UINT16 evt; UINT8 rtask; struct timespec abstime = { 0, 0 }; int sec; int nano_sec; rtask = GKI_get_taskid(); GKI_TRACE_3("GKI_wait %d %x %d", rtask, flag, timeout); if (rtask >= GKI_MAX_TASKS) { pthread_exit(NULL); return 0; } gki_pthread_info_t* p_pthread_info = &gki_pthread_info[rtask]; if (p_pthread_info->pCond != NULL && p_pthread_info->pMutex != NULL) { int ret; GKI_TRACE_3("GKI_wait task=%i, pCond/pMutex = %x/%x", rtask, p_pthread_info->pCond, p_pthread_info->pMutex); ret = pthread_mutex_lock(p_pthread_info->pMutex); ret = pthread_cond_signal(p_pthread_info->pCond); ret = pthread_mutex_unlock(p_pthread_info->pMutex); p_pthread_info->pMutex = NULL; p_pthread_info->pCond = NULL; } gki_cb.com.OSWaitForEvt[rtask] = flag; /* protect OSWaitEvt[rtask] from modification from an other thread */ pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]); #if 0 /* for clean scheduling we probably should always call pthread_cond_wait() */ /* Check if anything in any of the mailboxes. There is a potential race condition where OSTaskQFirst[rtask] has been modified. however this should only result in addtional call to pthread_cond_wait() but as the cond is met, it will exit immediately (depending on schedulling) */ if (gki_cb.com.OSTaskQFirst[rtask][0]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][1]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][2]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][3]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK; #endif if (!(gki_cb.com.OSWaitEvt[rtask] & flag)) { if (timeout) { // timeout = GKI_MS_TO_TICKS(timeout); /* convert from milliseconds to ticks */ /* get current system time */ // clock_gettime(CLOCK_MONOTONIC, &currSysTime); // abstime.tv_sec = currSysTime.time; // abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; clock_gettime(CLOCK_MONOTONIC, &abstime); /* add timeout */ sec = timeout / 1000; nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC; abstime.tv_nsec += nano_sec; if (abstime.tv_nsec > NSEC_PER_SEC) { abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC); abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC; } abstime.tv_sec += sec; pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask], &abstime); } else { pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]); } /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation, e.g. it looks like it is implemented as a counter in which case multiple cond_signal should NOT be lost! */ // we are waking up after waiting for some events, so refresh variables // no need to call GKI_disable() here as we know that we will have some events as we've been waking up after condition pending or timeout if (gki_cb.com.OSTaskQFirst[rtask][0]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][1]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][2]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK; if (gki_cb.com.OSTaskQFirst[rtask][3]) gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK; if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) { gki_cb.com.OSWaitEvt[rtask] = 0; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); BT_TRACE_1( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, "GKI TASK_DEAD received. exit thread %d...", rtask ); gki_cb.os.thread_id[rtask] = 0; pthread_exit(NULL); return (EVENT_MASK(GKI_SHUTDOWN_EVT)); } } /* Clear the wait for event mask */ gki_cb.com.OSWaitForEvt[rtask] = 0; /* Return only those bits which user wants... */ evt = gki_cb.com.OSWaitEvt[rtask] & flag; /* Clear only those bits which user wants... */ gki_cb.com.OSWaitEvt[rtask] &= ~flag; /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */ pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); GKI_TRACE_4("GKI_wait %d %x %d %x resumed", rtask, flag, timeout, evt); return (evt); }
/******************************************************************************* ** ** Function GKI_start_timer ** ** Description An application can call this function to start one of ** it's four general purpose timers. Any of the four timers ** can be 1-shot or continuous. If a timer is already running, ** it will be reset to the new parameters. ** ** Parameters tnum - (input) timer number to be started (TIMER_0, ** TIMER_1, TIMER_2, or TIMER_3) ** ticks - (input) the number of system ticks til the ** timer expires. ** is_continuous - (input) TRUE if timer restarts automatically, ** else FALSE if it is a 'one-shot'. ** ** Returns void ** *******************************************************************************/ void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous) { INT32 reload; INT32 orig_ticks; UINT8 task_id = GKI_get_taskid(); BOOLEAN bad_timer = FALSE; if (ticks <= 0) ticks = 1; orig_ticks = ticks; /* save the ticks in case adjustment is necessary */ /* If continuous timer, set reload, else set it to 0 */ if (is_continuous) reload = ticks; else reload = 0; GKI_disable(); /* Add the time since the last task timer update. ** Note that this works when no timers are active since ** both OSNumOrigTicks and OSTicksTilExp are 0. */ if (INT32_MAX - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks) { ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp; } else ticks = INT32_MAX; switch (tnum) { #if (GKI_NUM_TIMERS > 0) case TIMER_0: gki_cb.com.OSTaskTmr0R[task_id] = reload; gki_cb.com.OSTaskTmr0 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 1) case TIMER_1: gki_cb.com.OSTaskTmr1R[task_id] = reload; gki_cb.com.OSTaskTmr1 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 2) case TIMER_2: gki_cb.com.OSTaskTmr2R[task_id] = reload; gki_cb.com.OSTaskTmr2 [task_id] = ticks; break; #endif #if (GKI_NUM_TIMERS > 3) case TIMER_3: gki_cb.com.OSTaskTmr3R[task_id] = reload; gki_cb.com.OSTaskTmr3 [task_id] = ticks; break; #endif default: bad_timer = TRUE; /* Timer number is bad, so do not use */ } /* Update the expiration timeout if a legitimate timer */ if (!bad_timer) { /* Only update the timeout value if it is less than any other newly started timers */ gki_adjust_timer_count (orig_ticks); } GKI_enable(); }