/******************************************************************************* ** ** Function GKI_freebuf ** ** Description Called by an application to return a buffer to the free pool. ** ** Parameters p_buf - (input) address of the beginning of a buffer. ** ** Returns void ** *******************************************************************************/ void GKI_freebuf (void *p_buf) { FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) if (!p_buf || gki_chk_buf_damage(p_buf)) { GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted"); return; } #endif p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE); #if GKI_BUFFER_DEBUG LOGD("GKI_freebuf() freeing, %x, %x, func:%s(line=%d)", p_buf, p_hdr, p_hdr->_function, p_hdr->_line); #endif if (p_hdr->status != BUF_STATUS_UNLINKED) { GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf"); return; } if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS) { GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId"); return; } GKI_disable(); /* ** Release the buffer */ Q = &gki_cb.com.freeq[p_hdr->q_id]; if (Q->p_last) Q->p_last->p_next = p_hdr; else Q->p_first = p_hdr; Q->p_last = p_hdr; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_FREE; p_hdr->task_id = GKI_INVALID_TASK; if (Q->cur_cnt > 0) Q->cur_cnt--; GKI_enable(); return; }
/******************************************************************************* ** ** Function GKI_isend_msg ** ** Description Called from interrupt context to send a buffer to a task ** ** Returns Nothing ** *******************************************************************************/ void GKI_isend_msg (UINT8 task_id, UINT8 mbox, void *msg) { BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; /* If task non-existant or not started, drop buffer */ if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) { GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest"); GKI_freebuf (msg); return; } #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) if (gki_chk_buf_damage(msg)) { GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted"); return; } #endif #if (GKI_ENABLE_OWNER_CHECK == TRUE) if (gki_chk_buf_owner(msg)) { GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner"); return; } #endif p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE); if (p_hdr->status != BUF_STATUS_UNLINKED) { GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked"); return; } if (p_cb->OSTaskQFirst[task_id][mbox]) p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr; else p_cb->OSTaskQFirst[task_id][mbox] = p_hdr; p_cb->OSTaskQLast[task_id][mbox] = p_hdr; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_QUEUED; p_hdr->task_id = task_id; GKI_isend_event(task_id, (UINT16)EVENT_MASK(mbox)); return; }
/******************************************************************************* ** ** Function GKI_find_buf_start ** ** Description This function is called with an address inside a buffer, ** and returns the start address ofthe buffer. ** ** The buffer should be one allocated from one of GKI's pools. ** ** Parameters: p_user_area - (input) address of anywhere in a GKI buffer. ** ** Returns void * - Address of the beginning of the specified buffer if successful, ** otherwise NULL if unsuccessful ** *******************************************************************************/ void *GKI_find_buf_start (void *p_user_area) { UINT16 xx, size; UINT32 yy; tGKI_COM_CB *p_cb = &gki_cb.com; UINT8 *p_ua = (UINT8 *)p_user_area; for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) { if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx])) { yy = (UINT32)(p_ua - p_cb->pool_start[xx]); size = p_cb->pool_size[xx]; yy = (yy / size) * size; return ((void *) (p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)) ); } } /* If here, invalid address - not in one of our buffers */ GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr"); return (NULL); }
static BOOLEAN gki_alloc_free_queue(UINT8 id) { FREE_QUEUE_T *Q; tGKI_COM_CB *p_cb = &gki_cb.com; #if GKI_BUFFER_DEBUG ALOGD("\ngki_alloc_free_queue in, id:%d \n", id); #endif Q = &p_cb->freeq[p_cb->pool_list[id]]; if(Q->p_first == 0) { void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total); if(p_mem) { //re-initialize the queue with allocated memory #if GKI_BUFFER_DEBUG ALOGD("\ngki_alloc_free_queue calling gki_init_free_queue, id:%d size:%d, totol:%d\n", id, Q->size, Q->total); #endif gki_init_free_queue(id, Q->size, Q->total, p_mem); #if GKI_BUFFER_DEBUG ALOGD("\ngki_alloc_free_queue ret OK, id:%d size:%d, totol:%d\n", id, Q->size, Q->total); #endif return TRUE; } GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "gki_alloc_free_queue: Not enough memory"); } #if GKI_BUFFER_DEBUG ALOGD("\ngki_alloc_free_queue out failed, id:%d\n", id); #endif return FALSE; }
/******************************************************************************* ** ** 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)); }
/******************************************************************************* ** ** Function GKI_enqueue_head ** ** Description Enqueue a buffer at the head of the queue ** ** Parameters: p_q - (input) pointer to a queue. ** p_buf - (input) address of the buffer to enqueue ** ** Returns void ** *******************************************************************************/ void GKI_enqueue_head (BUFFER_Q *p_q, void *p_buf) { BUFFER_HDR_T *p_hdr; #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) if (gki_chk_buf_damage(p_buf)) { GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted"); return; } #endif p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); if (p_hdr->status != BUF_STATUS_UNLINKED) { GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue head - buf already linked"); return; } GKI_disable(); if (p_q->p_first) { p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE); p_q->p_first = p_buf; } else { p_q->p_first = p_buf; p_q->p_last = p_buf; p_hdr->p_next = NULL; } p_q->count++; p_hdr->status = BUF_STATUS_QUEUED; GKI_enable(); return; }
/******************************************************************************* ** ** Function GKI_enqueue ** ** Description Enqueue a buffer at the tail of the queue ** ** Parameters: p_q - (input) pointer to a queue. ** p_buf - (input) address of the buffer to enqueue ** ** Returns void ** *******************************************************************************/ void GKI_enqueue (BUFFER_Q *p_q, void *p_buf) { BUFFER_HDR_T *p_hdr; #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) if (gki_chk_buf_damage(p_buf)) { GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted"); return; } #endif p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE); if (p_hdr->status != BUF_STATUS_UNLINKED) { GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked"); return; } GKI_disable(); /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */ if (p_q->p_last) { BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE); p_last_hdr->p_next = p_hdr; } else p_q->p_first = p_buf; p_q->p_last = p_buf; p_q->count++; p_hdr->p_next = NULL; p_hdr->status = BUF_STATUS_QUEUED; GKI_enable(); return; }
/******************************************************************************* ** ** Function GKI_delete_pool ** ** Description Called by applications to delete a buffer pool. The function ** calls the operating specific function to free the actual memory. ** An exception is generated if an error is detected. ** ** Parameters: pool_id - (input) Id of the poll being deleted. ** ** Returns void ** *******************************************************************************/ void GKI_delete_pool (UINT8 pool_id) { FREE_QUEUE_T *Q; tGKI_COM_CB *p_cb = &gki_cb.com; if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id])) return; GKI_disable(); Q = &p_cb->freeq[pool_id]; if (!Q->cur_cnt) { Q->size = 0; Q->total = 0; Q->cur_cnt = 0; Q->max_cnt = 0; Q->p_first = NULL; Q->p_last = NULL; GKI_os_free (p_cb->pool_start[pool_id]); p_cb->pool_start[pool_id] = NULL; p_cb->pool_end[pool_id] = NULL; p_cb->pool_size[pool_id] = 0; gki_remove_from_pool_list(pool_id); p_cb->curr_total_no_of_pools--; } else GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool"); GKI_enable(); 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); }
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); }