line source
+ − /****************************************************************************/
+ − /* */
+ − /* Name rvf_buffer.c */
+ − /* */
+ − /* Function this file contains rvf buffer handling functions */
+ − /* */
+ − /* Version 0.1 */
+ − /* */
+ − /* Date Modification */
+ − /* ------------------------------------ */
+ − /* 3/12/99 Create */
+ − /* 10/27/1999 remove all non-nucleus sections (#ifdef) */
+ − /* 30/11/1999 compliant to RV coding guidelines */
+ − /* 12/23/1999 change buffer management, add memory bank handling and */
+ − /* remove useless functions */
+ − /* 07/12/2000 implement dynamic memory allocation. */
+ − /* */
+ − /* Author David Lamy-Charrier (dlamy@tif.ti.com) */
+ − /* */
+ − /* (C) Copyright 1999 by Texas Instruments Incorporated, All Rights Reserved*/
+ − /****************************************************************************/
+ −
+ − #ifndef _WINDOWS
+ − #include "config/board.cfg"
+ − #endif
+ −
+ − #include "nucleus.h"
+ − #include "rvm/rvm_use_id_list.h"
+ − #include "rvf/rvf_api.h"
+ − #include "rvf/rvf_i.h"
+ − #include "support/exception.h"
+ − #include "rvf/rvf_pool_size.h"
+ −
+ − #include <string.h>
+ − #include <stdio.h>
+ −
+ −
+ − #if RVF_ENABLE_STATS /* conditional inclusion of stdio.h for sprintf() function */
+ − #ifdef _WINDOWS
+ − #include <stdio.h>
+ − #endif
+ − #endif
+ −
+ − #include "rv/rv_defined_swe.h"
+ −
+ − #ifdef RVM_DAR_SWE
+ − #include "dar/dar_api.h"
+ − #endif
+ − #define RVF_INVALID_MD_ID_ERRROR ("RVF: Invalid MB ID")
+ −
+ − #define INC_END_INITIALIZE 2
+ − #define RVF_INVALID_INDEX 0xFFFF
+ −
+ − /************* TASK MAILBOXES *******************/
+ − /* chained lists for task mailboxes */
+ − T_RVF_INTERNAL_BUF *OSTaskQFirst[1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX];
+ − T_RVF_INTERNAL_BUF *OSTaskQLast [1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX];
+ −
+ − extern INC_Initialize_State;
+ −
+ − T_RVF_RT_ADDR_ID_DATA* pRtAddrIdTable[MAX_RVF_G_ADDR_ID];
+ −
+ −
+ − /******** MEMORY POOLS ******************/
+ − /* Define the buffer pools */
+ − extern T_RVF_POOL _rvf_pools[];
+ −
+ − /*********** MEMORY BANKS ***********/
+ − /* array of memory bank */
+ − static T_RVF_MB rvf_banks[RVF_MAX_REAL_MB];
+ −
+ − /* array of waiting buffers */
+ − static T_RVF_BUFFER * waiting_buffers[RVF_MAX_WAITING_BUF];
+ − static UINT16 next_buffer[RVF_MAX_WAITING_BUF];
+ − static UINT16 first_free_element;
+ −
+ − /* array of memory bank name and id*/
+ − static T_RVF_MB_NAME_ID rvf_name_id[RVF_MAX_TOTAL_MB] = RVF_MB_MAPPING;
+ −
+ −
+ − /* variable for statistics */
+ − #if RVF_ENABLE_STATS
+ − static UINT32 required_size = 0;
+ − static UINT32 obtained_size = 0;
+ − static UINT32 used_size = 0;
+ − static UINT32 mem_in_use = 0;
+ − #endif
+ −
+ − /* lists of free buffers */
+ − static T_RVF_INTERNAL_BUF * lists[RVF_NB_FREE_LISTS];
+ −
+ − /* last split-off buffer */
+ − T_RVF_INTERNAL_BUF * last_remainder = NULL;
+ −
+ − /* allocated static buffer pools */
+ − extern UINT8 Buf0[];
+ − extern UINT8 Buf1[];
+ −
+ − /********Internal windows function used to display memory status *******/
+ − #ifdef _WINDOWS
+ − extern void AddNewState(void *s,char *name,
+ − unsigned long current,unsigned long peak,
+ − unsigned long water,unsigned long bank);
+ − #endif
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _rvf_init_free_queue
+ − **
+ − ** Description Function called at startup to initialize a free
+ − ** pool (statically or dynamically allocated).
+ − ** It is called once for each free pool.
+ − **
+ − ** Returns void
+ − **
+ − *******************************************************************************/
+ − void _rvf_init_free_queue (UINT8 id, UINT32 size, void *p_mem)
+ − {
+ − T_RVF_INTERNAL_BUF *hdr;
+ − UINT8 list_idx;
+ −
+ − /* round to up size to a multiple of 4 */
+ − size = (size + 3) & ~0x0003;
+ −
+ − /* store pool start address and size */
+ − _rvf_pools[id].start_address = p_mem;
+ −
+ − _rvf_pools[id].pool_size = size;
+ −
+ − /* Initialize the pool as a big free buffer */
+ − hdr = (T_RVF_INTERNAL_BUF *) p_mem;
+ − hdr->buf_size = size - sizeof(T_RVF_INTERNAL_BUF) - sizeof(UINT32); /* last 4 bytes of the pool losts*/
+ − hdr->header.p_prev = NULL;
+ − RVF_SET_PREV_IN_USE(hdr);
+ −
+ − NEXTCHUNK(hdr)->buf_size = 0;
+ −
+ − ENDSIZE(hdr) = hdr->buf_size;
+ −
+ −
+ − /* get the corresponding list and insert the buffer */
+ − list_idx = RVF_BUF_LIST_INDEX( hdr->buf_size);
+ − hdr->p_next = lists[list_idx];
+ − lists[list_idx] = hdr;
+ −
+ − last_remainder = hdr;
+ −
+ − }
+ −
+ − void rvf_mbox_buffer_init(T_RVF_RT_ADDR_ID_DATA* pRtAddrIdElement) {
+ − UINT8 task_num, mbox_num;
+ − /* Initialize all mailboxes queues of all tasks*/
+ − for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++) {
+ − for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++) {
+ − pRtAddrIdElement->OSTaskQFirst[mbox_num] = NULL;
+ − pRtAddrIdElement->OSTaskQLast[mbox_num] = NULL;
+ − }
+ − }
+ − }
+ − /*******************************************************************************
+ − **
+ − ** Function _rvf_buffer_init
+ − **
+ − ** Description Called once internally by rvf at startup to initialize all
+ − ** buffers and free buffer pools.
+ − **
+ − ** Returns void
+ − **
+ − *******************************************************************************/
+ − void _rvf_buffer_init(void)
+ − {
+ − UINT8 list_num;
+ − UINT16 memory_bank_num;
+ −
+ − /* Initialize all mailboxes queues of all tasks*/
+ − /* for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++)
+ − {
+ − for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++)
+ − {
+ − OSTaskQFirst[task_num][mbox_num] = NULL;
+ − OSTaskQLast [task_num][mbox_num] = NULL;
+ − //pRtAddrIdTable[task_num]->OSTaskQFirst[mbox_num] = NULL; // only if static
+ − //pRtAddrIdTable[task_num]->OSTaskQLast[mbox_num] = NULL; // only if static
+ − }
+ − } */
+ −
+ − /* initialize free lists */
+ − for (list_num = 0; list_num < RVF_NB_FREE_LISTS; list_num++)
+ − {
+ − lists[list_num] = NULL;
+ − }
+ −
+ −
+ − /* initialize buffer pools */
+ − _rvf_init_mem_pool();
+ −
+ − /* Initialize real memory banks */
+ − for (memory_bank_num = 0; memory_bank_num < RVF_MAX_REAL_MB; memory_bank_num++)
+ − {
+ − rvf_banks[memory_bank_num].cur_memory_used = 0;
+ − rvf_banks[memory_bank_num].watermark = 0;
+ − rvf_banks[memory_bank_num].max = 0;
+ − rvf_banks[memory_bank_num].first_buffer_index = RVF_INVALID_INDEX;
+ − rvf_banks[memory_bank_num].last_buffer_index = RVF_INVALID_INDEX;
+ − rvf_banks[memory_bank_num].func = 0;
+ − rvf_banks[memory_bank_num].returned_red = FALSE;
+ − #if RVF_ENABLE_STATS
+ − rvf_banks[memory_bank_num].max_reached = 0;
+ − rvf_banks[memory_bank_num].required_size = 0;
+ − rvf_banks[memory_bank_num].num_buf = 0;
+ − #endif
+ − }
+ −
+ − /* Initialize total memory banks */
+ − for (memory_bank_num = 0; memory_bank_num < RVF_MAX_TOTAL_MB; memory_bank_num++)
+ − {
+ − rvf_name_id[memory_bank_num].mb_params.size = 0;
+ − rvf_name_id[memory_bank_num].mb_params.watermark = 0;
+ − }
+ −
+ −
+ − /* initialize array of waiting buffers */
+ − first_free_element = 0;
+ − for( memory_bank_num = 0; memory_bank_num < RVF_MAX_WAITING_BUF; memory_bank_num++)
+ − { waiting_buffers[memory_bank_num] = NULL;
+ − next_buffer[memory_bank_num] = memory_bank_num + 1;
+ − }
+ − next_buffer[RVF_MAX_WAITING_BUF-1] = RVF_INVALID_INDEX;
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _rvf_send_msg_to_mbox
+ − **
+ − ** Description Called by applications to send a buffer to a SWE.
+ − ** (Temporary internal use - DO NOT USE IT !)
+ − ** (Presently, only for Christophe )
+ − ** Returns RVF_OK if successful, else an error code.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_G_ADDR_ID addr_id, UINT8 mbox,void *msg){
+ − return rvf_adapt_send_msg(addr_id, msg, mbox);
+ − }
+ −
+ − /*T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_ADDR_ID addr_id, UINT8 mbox,void *msg)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ − UINT8 task_id = (UINT8)addr_id;
+ −
+ −
+ − if ((task_id >= MAX_RVF_TASKS) )
+ − {
+ − rvf_send_trace( "RVF: rvf_send_msg(): invalid taskid", 35, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − rvf_free_buf (msg);
+ − return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − #if RVF_ENABLE_BUF_CORRUPTION_CHECK
+ −
+ − if (_rvf_chk_buf_damage(msg) == TRUE)
+ − { rvf_send_trace( "RVF: rvf_send_msg(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − }
+ − #endif
+ −
+ −
+ − ((T_RV_HDR *)msg)->dest_addr_id = addr_id;
+ − p_hdr = USER2MEM(msg);
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ −
+ − if ( RVF_BUF_IS_LINKED( p_hdr) )
+ − {
+ − rvf_send_trace( "RVF: rvf_send_msg(): buffer already enqueued", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return RVF_MEMORY_ERR;
+ − }
+ − #endif
+ −
+ − rvf_disable(8);
+ −
+ −
+ − if (OSTaskQFirst[task_id][mbox])
+ − { OSTaskQLast[task_id][mbox]->p_next = p_hdr;
+ − }
+ − else
+ − { OSTaskQFirst[task_id][mbox] = p_hdr;
+ − }
+ − OSTaskQLast[task_id][mbox] = p_hdr;
+ −
+ − p_hdr->p_next = NULL;
+ −
+ − if (pRtAddrIdTable[task_id]->OSTaskQFirst[mbox]) {
+ − pRtAddrIdTable[task_id]->OSTaskQLast[mbox]->p_next = p_hdr;
+ − } else {
+ − pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr;
+ − }
+ − pRtAddrIdTable[task_id]->OSTaskQLast[mbox] = p_hdr;
+ −
+ − p_hdr->p_next = NULL;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − RVF_SET_BUF_LINKED(p_hdr);
+ − #endif
+ −
+ − rvf_enable();
+ −
+ − rvf_send_event(task_id, (UINT16) (EVENT_MASK(mbox)) );
+ − return RVF_OK;
+ − }*/
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_read_mbox
+ − **
+ − ** Description Called by applications to read a buffer from one of
+ − ** the task mailboxes.
+ − **
+ − ** Returns NULL if the mailbox was empty, else the address of a buffer
+ − **
+ − *******************************************************************************/
+ − void * rvf_read_mbox (UINT8 mbox) {
+ − T_RVF_G_ADDR_ID task_id = rvf_get_taskid();
+ −
+ − return rvf_read_addr_mbox (task_id, mbox) ;
+ − }
+ − void * rvf_read_addr_mbox (T_RVF_G_ADDR_ID task_id, UINT8 mbox) {
+ − void * p_buf = NULL;
+ − T_RVF_INTERNAL_BUF * p_hdr;
+ −
+ − mbox=resolveHostAddrId(mbox);
+ −
+ − if ((task_id >= MAX_RVF_TASKS) || (mbox >= RVF_NUM_TASK_MBOX))
+ − { rvf_send_trace( "RVF: rvf_read_mbox(): invalid taskid or mbox", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return NULL;
+ − }
+ −
+ − rvf_disable(9); /* enter critical section */
+ −
+ − /* if the chained list is not empty */
+ − /*if ( OSTaskQFirst[task_id][mbox] )
+ − { p_hdr = OSTaskQFirst[task_id][mbox];
+ − OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
+ −
+ − p_hdr->p_next = NULL;*/
+ − if ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] ) {
+ − p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox];
+ − pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr->p_next;
+ −
+ − p_hdr->p_next = NULL;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */
+ − #endif
+ − p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF);
+ − }
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − return (p_buf);
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_enqueue
+ − **
+ − ** Description Enqueue a buffer at the tail of the queue
+ − **
+ − ** Returns RVF_OK if successful, else an error code.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_enqueue (T_RVF_BUFFER_Q *p_q, void *p_buf)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ −
+ − #if RVF_ENABLE_BUF_CORRUPTION_CHECK
+ − if ( _rvf_chk_buf_damage(p_buf) )
+ − { rvf_send_trace( "RVF: rvf_enqueue(): buffer corrupted", 36, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID);
+ − }
+ − #endif
+ −
+ − /* check if the buffer has been already enqueued */
+ − p_hdr = USER2MEM(p_buf);
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − if( RVF_BUF_IS_LINKED(p_hdr) )
+ − {
+ − rvf_send_trace( "RVF: rvf_enqueue(): buffer already enqueued", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID);
+ − return RVF_MEMORY_ERR;
+ − }
+ − #endif
+ −
+ − rvf_disable(10); /* enter critical section */
+ −
+ − /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
+ − /* p_q->p_last and p_q->p_first point to the user buffer, since p_hdr->p_next points to the T_RVF_INTERNAL_BUF */
+ − if (p_q->p_first) /* if the queue is not empty */
+ − {
+ − T_RVF_INTERNAL_BUF * p_last_hdr = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_q->p_last - sizeof(T_RVF_INTERNAL_BUF) );
+ − 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;
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */
+ − #endif
+ −
+ − rvf_enable(); /* exit critical section */
+ − return RVF_OK;
+ − }
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_dequeue
+ − **
+ − ** Description Dequeue a buffer from the head of a queue
+ − **
+ − ** Returns NULL if queue is empty, else buffer
+ − **
+ − *******************************************************************************/
+ − void * rvf_dequeue (T_RVF_BUFFER_Q *p_q)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ −
+ − if (!p_q->count) /* if the queue is empty */
+ − return (NULL);
+ −
+ − rvf_disable(12); /* enter critical section */
+ −
+ − p_hdr = USER2MEM(p_q->p_first );
+ −
+ −
+ − /* Keep buffers such that RVF header is invisible */
+ − if (p_hdr->p_next)
+ − p_q->p_first = ((UINT8 *)p_hdr->p_next + sizeof(T_RVF_INTERNAL_BUF));
+ − else
+ − {
+ − p_q->p_first = NULL;
+ − p_q->p_last = NULL;
+ − }
+ −
+ − p_q->count--;
+ −
+ − p_hdr->p_next = NULL;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */
+ − #endif
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − return (MEM2USER(p_hdr) );
+ − }
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_enqueue_head
+ − **
+ − ** Description Enqueue a buffer at the head of the queue
+ − **
+ − ** Returns RVF_OK if successful, else an error code.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_enqueue_head (T_RVF_BUFFER_Q *p_q, void *p_buf)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ −
+ − #if RVF_ENABLE_BUF_CORRUPTION_CHECK
+ − if ( _rvf_chk_buf_damage(p_buf) )
+ − { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer corrupted", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − }
+ − #endif
+ −
+ − p_hdr = USER2MEM(p_buf);
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − if( RVF_BUF_IS_LINKED(p_hdr) )
+ − { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer already enqueued", 48, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return RVF_MEMORY_ERR;
+ − }
+ − #endif
+ −
+ − rvf_disable(11); /* enter critical section */
+ −
+ − if (p_q->p_first) /* if the queue is not empty */
+ − { p_hdr->p_next = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_q->p_first - sizeof(T_RVF_INTERNAL_BUF) );
+ − 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++;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */
+ − #endif
+ −
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_buf_size
+ − **
+ − ** Description Called by an application to get the size of a buffer.
+ − **
+ − ** Returns the size of the buffer or 0 if the address is invalid.
+ − **
+ − *******************************************************************************/
+ − INLINE UINT32 rvf_get_buf_size (void *bptr)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ −
+ − p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *) bptr - sizeof(T_RVF_INTERNAL_BUF) );
+ −
+ − if ((UINT32)p_hdr & 1) return 0; /* invalid pointer: odd address*/
+ −
+ − return (GETSIZE(p_hdr) - RVF_CORRUPT_OVERHEAD) ;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _rvf_chk_buf_damage
+ − **
+ − ** Description Called internally by rvf to check for buffer corruption.
+ − **
+ − ** Returns TRUE if there is a problem, else FALSE
+ − **
+ − *******************************************************************************/
+ − #if RVF_ENABLE_BUF_CORRUPTION_CHECK
+ − BOOLEAN _rvf_chk_buf_damage(void *bptr)
+ − {
+ − UINT32 *lg;
+ − T_RVF_INTERNAL_BUF * p_hdr;
+ −
+ − if((UINT32)bptr & 1) /* odd address */
+ − { return TRUE;
+ − }
+ −
+ − p_hdr = USER2MEM(bptr); /* get the internal header */
+ −
+ − lg = (UINT32*)( (UINT8*)bptr + GETSIZE(p_hdr) - sizeof(UINT32) );
+ −
+ − if (lg == 0)
+ − return TRUE;
+ −
+ − if(*lg == GETSIZE(p_hdr) )
+ − {
+ − return FALSE;
+ − }
+ − return TRUE;
+ − }
+ − #endif
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _find_buf
+ − **
+ − ** Description Internal function which is in charge of finding a free buffer
+ − ** of the requested size in one of the lists.
+ − **
+ − ** Returns A pointer to the buffer header, or NULL if none available
+ − **
+ − *******************************************************************************/
+ − INLINE void * _find_buf (UINT32 size)
+ − {
+ − T_RVF_INTERNAL_BUF * p_hdr;
+ − UINT8 idx;
+ −
+ − if (size == 0) /* if user requires a 0 byte buffer !! */
+ − { return (NULL);
+ − }
+ −
+ − /* add the overhead for buffer corruption check */
+ − size = REQ2SIZE(size);
+ −
+ − /* find the corresponding list */
+ − idx = RVF_BUF_LIST_INDEX(size);
+ −
+ − /* 1. try in the bin corresponding to the requested size. */
+ − /* 2. try to use the last_remainder chunk. */
+ − /* 3. try in the others bins of greater size. */
+ −
+ − if( (lists[idx] == NULL) || ( GETSIZE(lists[idx]) < size) )
+ − /* if the first buffer in the appropriate bin is not big enough. */
+ − {
+ − rvf_disable(4); /* enter critical section */
+ −
+ − if( last_remainder != NULL)
+ − {
+ − p_hdr = last_remainder;
+ −
+ − /* if the last remainder is big enough */
+ − if( GETSIZE(p_hdr) >= size )
+ − {
+ −
+ − if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */
+ − { /* create a new free buffer and link it in the appropriate list*/
+ −
+ − T_RVF_INTERNAL_BUF * new_buf;
+ − UINT8 new_idx;
+ −
+ − new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF));
+ − new_buf->buf_size = GETSIZE(p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF);
+ − ENDSIZE(new_buf) = new_buf->buf_size;
+ −
+ − /* remove the used buffer from the list */
+ − if( p_hdr->header.p_prev != NULL)
+ − { (p_hdr->header.p_prev)->p_next = p_hdr->p_next;
+ − }
+ − else
+ − { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next;
+ − }
+ − if( p_hdr->p_next != NULL)
+ − { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev;
+ − }
+ − p_hdr->p_next = NULL;
+ −
+ − SETSIZE(p_hdr, size);
+ − ENDSIZE(p_hdr) = size; /* to CHANGE */
+ −
+ − /* insert the new buffer in the appropriate list */
+ − new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size);
+ − new_buf->p_next = lists[new_idx];
+ − lists[new_idx] = new_buf;
+ − new_buf->header.p_prev = NULL;
+ − if( new_buf->p_next != NULL)
+ − { (new_buf->p_next)->header.p_prev = new_buf;
+ − }
+ − RVF_SET_PREV_IN_USE(new_buf);
+ −
+ − last_remainder = new_buf;
+ −
+ − rvf_enable(); /* exit critical section */
+ − return p_hdr;
+ −
+ − }
+ − else /* return the entire buffer */
+ − {
+ − /* remove the used buffer from the list */
+ − if( p_hdr->header.p_prev != NULL)
+ − { (p_hdr->header.p_prev)->p_next = p_hdr->p_next;
+ − }
+ − else
+ − { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next;
+ − }
+ − if( p_hdr->p_next != NULL)
+ − { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev;
+ − }
+ − p_hdr->p_next = NULL;
+ −
+ − RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) );
+ −
+ − last_remainder = NULL;
+ −
+ − rvf_enable(); /* exit critical section */
+ − return p_hdr;
+ − }
+ − }
+ − else /* the last remainder is too small */
+ − {
+ − /* clear the last remainder */
+ − last_remainder = NULL;
+ − }
+ −
+ − }
+ − rvf_enable(); /* exit critical section */
+ − }
+ −
+ − while( idx < RVF_NB_FREE_LISTS )
+ − {
+ − rvf_disable(4); /* enter critical section */
+ −
+ − if( lists[idx] != NULL ) /*if the list is not empty */
+ − { /* remove the first buffer from the list */
+ −
+ − p_hdr = lists[idx];
+ − if( GETSIZE(p_hdr) >= size)
+ − {
+ − if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */
+ − { /* create a new free buffer and link it in the appropriate list*/
+ −
+ − T_RVF_INTERNAL_BUF * new_buf;
+ − UINT8 new_idx;
+ −
+ − new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF));
+ − new_buf->buf_size = GETSIZE( p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF);
+ − ENDSIZE(new_buf) = new_buf->buf_size;
+ −
+ − /* remove the used buffer from the list */
+ − lists[idx] = p_hdr->p_next;
+ − if( p_hdr->p_next != NULL)
+ − { (p_hdr->p_next)->header.p_prev = NULL;
+ − }
+ − p_hdr->p_next = NULL;
+ −
+ − SETSIZE(p_hdr, size);
+ − ENDSIZE(p_hdr) = size;
+ −
+ − /* insert the new buffer in the appropriate list */
+ − new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size);
+ − new_buf->p_next = lists[new_idx];
+ − lists[new_idx] = new_buf;
+ − new_buf->header.p_prev = NULL;
+ − if( new_buf->p_next != NULL)
+ − { (new_buf->p_next)->header.p_prev = new_buf;
+ − }
+ − RVF_SET_PREV_IN_USE(new_buf);
+ −
+ − last_remainder = new_buf; /* set this new buffer as the last remainder */
+ −
+ − rvf_enable(); /* exit critical section */
+ − return p_hdr;
+ −
+ − }
+ − else /* return the entire buffer */
+ − { lists[idx] = p_hdr->p_next;
+ − if( p_hdr->p_next != NULL)
+ − { (p_hdr->p_next)->header.p_prev = NULL;
+ − }
+ − p_hdr->p_next = NULL;
+ − RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) );
+ −
+ − if( last_remainder == p_hdr) /* if it was the last_remainder, clear it. */
+ − {
+ − last_remainder = NULL;
+ − }
+ −
+ − rvf_enable(); /* exit critical section */
+ − return p_hdr;
+ − }
+ − }
+ − }
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − idx++; /* search in the next list */
+ − }
+ −
+ − return NULL;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _release_buf
+ − **
+ − ** Description Internal function called to release a buffer after use.
+ − ** The parameter points to the beginning of the header.
+ − **
+ − ** Returns BOOLEAN: TRUE if successful, else FALSE
+ − **
+ − *******************************************************************************/
+ − INLINE BOOLEAN _release_buf (T_RVF_INTERNAL_BUF *p_hdr)
+ − { UINT8 idx;
+ −
+ − #if RVF_ENABLE_BUF_CORRUPTION_CHECK /* check for buffer corruption:i.e. if user wrote data after the end of the buffer */
+ − if ( _rvf_chk_buf_damage( MEM2USER(p_hdr) ) )
+ − { rvf_send_trace( "RVF: _release_buf(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return FALSE;
+ − }
+ −
+ − /* check if the buffer has been already freed */
+ − if ( RVF_IS_PREV_FREE( NEXTCHUNK(p_hdr) ) ) /* check buffer status */
+ − { rvf_send_trace( "RVF: _release_buf(): buffer already freed", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return FALSE;
+ − }
+ −
+ − #endif
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK /* check for buffer linkage */
+ − if ( RVF_BUF_IS_LINKED(p_hdr) ) /* check buffer status */
+ − { rvf_send_trace( "RVF: _release_buf(): free buf buffer linked", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return FALSE;
+ − }
+ − #endif
+ −
+ −
+ − rvf_disable(6); /* enter critical section */
+ −
+ − /* try to coalesce the buffer with its neighbors (left and right) */
+ −
+ − if( RVF_IS_PREV_FREE(p_hdr) )
+ − { /* merge the buffer with its left neighbor */
+ − UINT32 left_buf_size = *((UINT32*)((UINT8*)p_hdr - sizeof(UINT32) ) );
+ − T_RVF_INTERNAL_BUF * left_buf = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_hdr - left_buf_size - sizeof(T_RVF_INTERNAL_BUF) );
+ −
+ − /* remove the left buffer from its list */
+ − if( left_buf->header.p_prev == NULL)
+ − { lists[ RVF_BUF_LIST_INDEX(left_buf_size)] = left_buf->p_next;
+ − }
+ − else
+ − { (left_buf->header.p_prev)->p_next = left_buf->p_next;
+ − }
+ − if( left_buf->p_next != NULL)
+ − {
+ − (left_buf->p_next)->header.p_prev = left_buf->header.p_prev;
+ − }
+ − /* set the size of the newly created buffer */
+ − SETSIZE(left_buf, (left_buf_size + GETSIZE(p_hdr) + sizeof(T_RVF_INTERNAL_BUF) ) );
+ − /* set the current buffer as free to allow check for double free */
+ − RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) );
+ −
+ − p_hdr = left_buf;
+ − }
+ −
+ − /* check for pool limits */
+ − if( GETSIZE( NEXTCHUNK(p_hdr) ) != 0)
+ − { T_RVF_INTERNAL_BUF * right_buf = NEXTCHUNK(p_hdr);
+ − /* merge the buffer with its right neighbor */
+ −
+ − if( RVF_IS_PREV_FREE( NEXTCHUNK(right_buf) ) )
+ − { /* remove the right buffer from its list */
+ − UINT32 right_buf_size = GETSIZE( right_buf);
+ −
+ − if( right_buf->header.p_prev == NULL)
+ − { lists[ RVF_BUF_LIST_INDEX(right_buf_size)] = right_buf->p_next;
+ − }
+ − else
+ − { (right_buf->header.p_prev)->p_next = right_buf->p_next;
+ − }
+ − if( right_buf->p_next != NULL)
+ − { (right_buf->p_next)->header.p_prev = right_buf->header.p_prev;
+ − }
+ −
+ − right_buf_size += GETSIZE(p_hdr);
+ − SETSIZE(p_hdr, (right_buf_size + sizeof(T_RVF_INTERNAL_BUF) ) );
+ −
+ − if( last_remainder == right_buf) /* keep as last_remainder */
+ − { last_remainder = p_hdr;
+ − }
+ − }
+ − }
+ −
+ − /* enqueue the free buffer in the appropriate list */
+ − idx = RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) );
+ − p_hdr->header.p_prev = NULL;
+ − p_hdr->p_next = lists[idx];
+ − lists[idx] = p_hdr;
+ − if( p_hdr->p_next != NULL)
+ − { (p_hdr->p_next)->header.p_prev = p_hdr;
+ − }
+ −
+ − ENDSIZE(p_hdr) = GETSIZE(p_hdr);
+ − RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) );
+ −
+ − rvf_enable(); /* exit critical section */
+ − return TRUE;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − ** Function _str_cmp
+ − **
+ − ** Description Internal function which compares two null-terminated string.
+ − ** Returns TRUE if they are equal, else FALSE.
+ − *******************************************************************************/
+ − BOOLEAN _str_cmp( char *str1, char * str2)
+ − { UINT8 i;
+ − for ( i = 0; (str1[i] == str2[i]) && (str1[i] != 0) && (str2[i] != 0) && (i < RVF_MAX_MB_LEN); i++ );
+ − if ( i == RVF_MAX_MB_LEN)
+ − { return TRUE;
+ − }
+ −
+ − if ( (str1[i] == 0) && (str2[i] == 0) )
+ − { return TRUE;
+ − }
+ − return FALSE;
+ − }
+ −
+ − /******************************************************************************
+ − **
+ − ** MEMORY BANK RELATED FUNCTIONS
+ − **
+ − ******************************************************************************/
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _remove_from_list
+ − **
+ − ** Description Internal function called to remove a buffer from the list of
+ − ** buffer waiting to be counted on the memory bank.
+ − ** The parameter points to the beginning of the header.
+ − **
+ − ** Returns BOOLEAN: TRUE if successful, else FALSE
+ − **
+ − *******************************************************************************/
+ − BOOLEAN _remove_from_list (void *bptr, T_RVF_MB * mb)
+ − { UINT16 * index;
+ − UINT16 free_elem, prec;
+ −
+ − /* check all elements of the list */
+ − index = &(mb->first_buffer_index);
+ − prec = RVF_INVALID_INDEX;
+ −
+ − while ( (*index != RVF_INVALID_INDEX) && (waiting_buffers[*index]!=bptr) )
+ − { prec = *index;
+ − index = &(next_buffer[*index]);
+ − }
+ −
+ − if (waiting_buffers[*index] == bptr)
+ − { free_elem = *index;
+ − *index = next_buffer[free_elem]; /* link preceding element to the next one */
+ −
+ − if (next_buffer[free_elem] == RVF_INVALID_INDEX ) /* last element in the list */
+ − { mb->last_buffer_index = prec;
+ − }
+ −
+ − waiting_buffers[free_elem] = NULL;
+ − next_buffer[free_elem] = first_free_element; /* link free elements */
+ − first_free_element = free_elem;
+ − return TRUE;
+ − }
+ − return FALSE; /* buffer not found */
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function _add_to_list
+ − **
+ − ** Description Internal function called to add a buffer to the list of
+ − ** buffer waiting to be counted on the memory bank.
+ − ** The parameter points to the beginning of the header.
+ − **
+ − ** Returns BOOLEAN: TRUE if successful, else FALSE
+ − **
+ − *******************************************************************************/
+ − BOOLEAN _add_to_list (void *bptr, T_RVF_MB * mb)
+ − { UINT16 index = first_free_element;
+ −
+ − first_free_element = next_buffer[index];
+ −
+ − waiting_buffers[index] = bptr;
+ − next_buffer[index] = RVF_INVALID_INDEX;
+ −
+ − if ( mb->last_buffer_index == RVF_INVALID_INDEX) /* empty list */
+ − { mb->first_buffer_index = index;
+ − mb->last_buffer_index = index;
+ − }
+ − else
+ − { next_buffer[mb->last_buffer_index] = index;
+ − mb->last_buffer_index = index;
+ − }
+ −
+ − return TRUE;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_create_mb
+ − **
+ − ** Description Called by an application to create a memory bank
+ − **
+ − ** Parameters: memory bank name, memory bank param
+ − ** (return) memory bank id
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if success
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_create_mb(T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM mb_param, T_RVF_MB_ID *mb_id)
+ − { UINT8 num_mb;
+ − T_RVF_MB * mb;
+ − UINT32 available_mem = 0;
+ − UINT32 required_mem = 0;
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ −
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */
+ − {
+ − /* DLC added for dynamic memory bank creation*/
+ −
+ − /* search the first available place in the array */
+ − T_RVF_MB_ID first_available_mb_id = 0;
+ − BOOLEAN mb_id_found = FALSE;
+ −
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) ; num_mb++)
+ − { if( rvf_name_id[num_mb].mb_id == first_available_mb_id)
+ − { first_available_mb_id ++;
+ − }
+ − }
+ −
+ − while( (first_available_mb_id < RVF_MAX_REAL_MB) && (mb_id_found == FALSE) )
+ − {
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) && (rvf_name_id[num_mb].mb_id != first_available_mb_id) ; num_mb++);
+ − if ( rvf_name_id[num_mb].mb_id != first_available_mb_id)
+ − { /* available mb id found */
+ − mb_id_found = TRUE;
+ − }
+ − else
+ − { /* try the next one */
+ − first_available_mb_id++;
+ − }
+ − }
+ −
+ − if ( (num_mb == RVF_MAX_TOTAL_MB) || (first_available_mb_id + 1 >= RVF_MAX_REAL_MB ) ) /* no available space in the array */
+ −
+ − { *mb_id = RVF_INVALID_MB_ID;
+ − return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */
+ −
+ − /* create the new mb name and id */
+ − strcpy( rvf_name_id[num_mb].mb_name, mb_name);
+ − rvf_name_id[num_mb].mb_id = first_available_mb_id;
+ −
+ − /* initialize the next one */
+ − rvf_name_id[num_mb+1].mb_name[0] = 0;
+ − rvf_name_id[num_mb+1].mb_id = 0;
+ −
+ − if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */
+ − }
+ −
+ − /* check if the memory bank has been already created */
+ − if ( rvf_name_id[ num_mb].mb_params.size != 0)
+ − { *mb_id = RVF_INVALID_MB_ID;
+ − return RVF_INTERNAL_ERR;
+ − }
+ −
+ − rvf_get_available_mem( &available_mem, &required_mem);
+ −
+ − if ( ( (required_mem + mb_param.size)*100) > ( available_mem * _rvf_get_mem_usage_ratio()) ) /* if there is not enough available memory to create this mb */
+ − { *mb_id = RVF_INVALID_MB_ID; /* In a next version: try to create a dynamic pool */
+ − return RVF_MEMORY_ERR;
+ − }
+ −
+ − rvf_disable(20); /* enter critical section */
+ −
+ − /* save the mb parameters for deletion */
+ − rvf_name_id[num_mb].mb_params.size = mb_param.size;
+ − rvf_name_id[num_mb].mb_params.watermark = mb_param.watermark;
+ −
+ − * mb_id = rvf_name_id[num_mb].mb_id;
+ − mb = &rvf_banks[ *mb_id ];
+ − /* initialize the memory bank structure */
+ − mb->watermark += mb_param.watermark;
+ − mb->max += mb_param.size;
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_mb_id
+ − **
+ − ** Description Called by an application to get the memory bank id from its name
+ − **
+ − ** Parameters: memory bank name
+ − ** (return) memory bank id
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if success
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_get_mb_id(T_RVF_MB_NAME mb_name, T_RVF_MB_ID *mb_id)
+ − { UINT8 num_mb;
+ −
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */
+ − { *mb_id = RVF_INVALID_MB_ID;
+ − return RVF_INVALID_PARAMETER;
+ − }
+ − if ( rvf_banks[ rvf_name_id[num_mb].mb_id ].max == 0 )
+ − { /* the memory bank has not been created */
+ − *mb_id = RVF_INVALID_MB_ID;
+ − return RVF_NOT_READY;
+ − }
+ − *mb_id = rvf_name_id[num_mb].mb_id;
+ − return RVF_OK;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_delete_mb
+ − **
+ − ** Description Called by an application to delete a memory bank
+ − **
+ − ** Parameters: memory bank name
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if success
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_delete_mb(T_RVF_MB_NAME mb_name)
+ − { UINT8 num_mb;
+ − T_RVF_MB * mb;
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */
+ − { return RVF_INVALID_PARAMETER;
+ − }
+ − mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ];
+ −
+ − /* check if the mb is used more than once or not */
+ − if ( mb->max == rvf_name_id[num_mb].mb_params.size )
+ − { /* mb is used only once, check if cur_memory_used > 0 */
+ − if ( mb->cur_memory_used > 0)
+ − { rvf_send_trace( "RVF: rvf_delete_mb(): not all buffers have been freed", 53, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return RVF_MEMORY_ERR;
+ − /* free all buffers ????? -> NOT POSSIBLE */
+ − }
+ − /* initialize mb params */
+ − mb->max = 0;
+ − mb->first_buffer_index = RVF_INVALID_INDEX;
+ − mb->last_buffer_index = RVF_INVALID_INDEX;
+ − mb->watermark = 0;
+ − mb->returned_red = FALSE;
+ − mb->func = 0;
+ − #if RVF_ENABLE_STATS
+ − mb->max_reached = 0;
+ − mb->required_size = 0;
+ − mb->num_buf = 0;
+ − #endif
+ −
+ − }
+ − else /* mb is still used by another entity */
+ − { /* change mb params */
+ − mb->max -= rvf_name_id[num_mb].mb_params.size;
+ − mb->watermark -= rvf_name_id[num_mb].mb_params.watermark;
+ − }
+ −
+ − rvf_name_id[num_mb].mb_params.size = 0;
+ − rvf_name_id[num_mb].mb_params.watermark = 0;
+ −
+ − return RVF_OK;
+ − }
+ −
+ − T_RVF_RET rvf_mb_is_used(T_RVF_MB_NAME mb_name, UINT8* isUsed) {
+ − UINT8 num_mb;
+ − T_RVF_MB * mb;
+ −
+ − *isUsed=0;
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) {/* mb name not found */
+ − return RVF_INVALID_PARAMETER;
+ − }
+ − mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ];
+ −
+ − /* check if the mb is used more than once or not */
+ − if ( mb->max == rvf_name_id[num_mb].mb_params.size ) {
+ − /* mb is used only once, check if cur_memory_used > 0 */
+ − if ( mb->cur_memory_used > 0) *isUsed=1;
+ − }
+ − return RVF_OK;
+ − }
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_mb_status
+ − **
+ − ** Description Called by an application to get the status of a memory bank
+ − **
+ − ** Parameters: memory bank id
+ − **
+ − ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok,
+ − ** RVF_YELLOW if watermark limit has been reached,
+ − ** RVF_RED if max size has been reached
+ − **
+ − *******************************************************************************/
+ − T_RVF_MB_STATUS rvf_get_mb_status(T_RVF_MB_ID mb_id)
+ − { T_RVF_MB * mb;
+ −
+ − /* checking for invalid memory bank IDs */
+ − if (mb_id >= RVF_MAX_REAL_MB)
+ − {
+ − #ifdef RVM_DAR_SWE
+ − dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR,
+ − DAR_ASCII_FORMAT,
+ − RVM_USE_ID);
+ − #else
+ − rvf_send_trace (RVF_INVALID_MD_ID_ERRROR,
+ − sizeof (RVF_INVALID_MD_ID_ERRROR) - 1,
+ − NULL_PARAM,
+ − RV_TRACE_LEVEL_ERROR,
+ − RVM_USE_ID);
+ − #endif
+ − return RVF_RED;
+ − }
+ − mb = &rvf_banks[mb_id];
+ −
+ − if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */
+ − { return RVF_RED;
+ − }
+ −
+ − if ( mb->cur_memory_used < mb->watermark )
+ − { return RVF_GREEN;
+ − }
+ − else
+ − { if ( mb->cur_memory_used < mb->max )
+ − { return RVF_YELLOW;
+ − }
+ − else
+ − { return RVF_RED; /* since max and cur_memory_used are set to 0 for not-created mb, it will return RED*/
+ − }
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_mb_unused_mem
+ − **
+ − ** Description Called by an application to get the number of bytes available
+ − ** until the memory bank size.
+ − **
+ − ** Parameters: memory bank id
+ − **
+ − ** Returns UINT32: number of bytes available
+ − ** returns 0 if the memory bank has not been created.
+ − **
+ − *******************************************************************************/
+ − UINT32 rvf_get_mb_unused_mem(T_RVF_MB_ID mb_id)
+ − { T_RVF_MB * mb;
+ − mb = &rvf_banks[mb_id];
+ −
+ − if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */
+ − { return 0;
+ − }
+ −
+ − return( mb->max - mb->cur_memory_used);
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_mb_unused_green_mem
+ − **
+ − ** Description Called by an application to get the number of bytes available
+ − ** until the memory bank watermark.
+ − **
+ − ** Parameters: memory bank id
+ − **
+ − ** Returns UINT32: number of bytes available
+ − ** returns 0 if the memory bank has not been created.
+ − **
+ − *******************************************************************************/
+ − UINT32 rvf_get_mb_unused_green_mem(T_RVF_MB_ID mb_id)
+ − { T_RVF_MB * mb;
+ − mb = &rvf_banks[mb_id];
+ −
+ − if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */
+ − { return 0;
+ − }
+ −
+ − if( mb->cur_memory_used > mb->watermark)
+ − { return 0;
+ − }
+ −
+ − return( mb->watermark - mb->cur_memory_used);
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_buf
+ − **
+ − ** Description Called by an application to get a buffer from a memory bank
+ − **
+ − ** Parameters: memory bank id, buffer size
+ − ** (return) buffer pointer to the allocated buffer or null if
+ − ** mb status is RVF_RED
+ − **
+ − ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok,
+ − ** RVF_YELLOW if watermark limit has been reached,
+ − ** RVF_RED if max size has been reached (does not return a buffer)
+ − **
+ − *******************************************************************************/
+ − T_RVF_MB_STATUS rvf_get_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer)
+ − { T_RVF_MB * mb;
+ −
+ − /* checking for invalid memory bank IDs */
+ − if (mb_id >= RVF_MAX_REAL_MB)
+ − {
+ − #ifdef RVM_DAR_SWE
+ − dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR,
+ − DAR_ASCII_FORMAT,
+ − RVM_USE_ID);
+ − #else
+ − rvf_send_trace (RVF_INVALID_MD_ID_ERRROR,
+ − sizeof (RVF_INVALID_MD_ID_ERRROR) - 1,
+ − NULL_PARAM,
+ − RV_TRACE_LEVEL_ERROR,
+ − RVM_USE_ID);
+ − #endif
+ − return RVF_RED;
+ − }
+ − mb = &rvf_banks[ mb_id ];
+ −
+ − /* check memory usage */
+ − if ( ( mb->cur_memory_used + buffer_size) > mb->max )
+ − { /* over the limits, return RED and do not allocate a buffer */
+ − mb->returned_red = TRUE;
+ − *p_buffer = NULL;
+ − return RVF_RED;
+ − }
+ −
+ − /* find a buffer of the requested size */
+ − *p_buffer = _find_buf( buffer_size );
+ − if ( *p_buffer == NULL ) /* error during allocation, not enough memory */
+ − { //rvf_send_trace( "RVF: rvf_get_buf(): not enough available physical memory", 56, NULL_PARAM, RV_TRACE_LEVEL_ERROR, TRACE_RVF_BUFFER );
+ − mb->returned_red = TRUE;
+ − return RVF_RED;
+ − }
+ −
+ − #if RVF_ENABLE_STATS
+ − required_size += buffer_size;
+ − obtained_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF));
+ − used_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD;
+ − mem_in_use += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD;
+ − #endif
+ −
+ − if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − /* set as unlinked */
+ − RVF_SET_BUF_UNLINKED((T_RVF_INTERNAL_BUF*)(*p_buffer));
+ − #endif
+ −
+ − /* increase memory use counter */
+ − mb->cur_memory_used += rvf_get_buf_size( (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF) );
+ − ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_id = mb_id;
+ − ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_expected = RVF_INVALID_MB_ID;
+ −
+ − *p_buffer = (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF);
+ −
+ − #if RVF_ENABLE_STATS
+ − if ( mb->cur_memory_used > mb->max_reached )
+ − { mb->max_reached = mb->cur_memory_used;
+ − }
+ − mb->required_size += buffer_size;
+ − mb->num_buf++;
+ − #endif
+ −
+ − if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */
+ −
+ − /* return the correct flag */
+ − if ( mb->cur_memory_used > mb->watermark )
+ − { return RVF_YELLOW;
+ − }
+ − else
+ − { return RVF_GREEN;
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_count_buf
+ − **
+ − ** Description Called by an application to change the memory bank on which a buffer is counted
+ − **
+ − ** Parameters: new memory bank id,
+ − ** pointer to the buffer.
+ − **
+ − ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok,
+ − ** RVF_YELLOW if watermark limit has been reached,
+ − ** RVF_RED if max size has been reached
+ − **
+ − *******************************************************************************/
+ − T_RVF_MB_STATUS rvf_count_buf(T_RVF_MB_ID mb_id, T_RVF_BUFFER * p_buffer)
+ − { T_RVF_INTERNAL_BUF * buf;
+ − UINT32 buf_size;
+ − T_RVF_MB * new_mb;
+ − T_RVF_MB * old_mb;
+ −
+ − /* checking for invalid memory bank IDs */
+ − if (mb_id >= RVF_MAX_REAL_MB)
+ − {
+ − #ifdef RVM_DAR_SWE
+ − dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR,
+ − DAR_ASCII_FORMAT,
+ − RVM_USE_ID);
+ − #else
+ − rvf_send_trace (RVF_INVALID_MD_ID_ERRROR,
+ − sizeof (RVF_INVALID_MD_ID_ERRROR) - 1,
+ − NULL_PARAM,
+ − RV_TRACE_LEVEL_ERROR,
+ − RVM_USE_ID);
+ − #endif
+ − return RVF_RED;
+ − }
+ − buf = (T_RVF_INTERNAL_BUF *) ( (UINT8 *) p_buffer - sizeof(T_RVF_INTERNAL_BUF) );
+ − new_mb = &rvf_banks[mb_id];
+ − old_mb = &rvf_banks[buf->header.external.mb_id];
+ −
+ − /* get the size of the buffer and try to count it on the new mb */
+ − buf_size = rvf_get_buf_size( p_buffer );
+ −
+ − if ( ( new_mb->cur_memory_used + buf_size ) < new_mb->max )
+ − { /* there is enough memory in the new mb */
+ −
+ − if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID )
+ − { /* remove the buffer from the list of waiting buffers in mb expected */
+ − _remove_from_list( buf, &rvf_banks[buf->header.external.mb_expected] );
+ − buf->header.external.mb_expected = RVF_INVALID_MB_ID;
+ − }
+ −
+ − rvf_disable(20); /* enter critical section */
+ −
+ − /* decrease the memory used in the old mb */
+ − old_mb->cur_memory_used -= buf_size;
+ −
+ − /* increase memory used in the new mb */
+ − new_mb->cur_memory_used += buf_size;
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − /* call the callback function if state of the old mb switches to RVF_GREEN and there is no buffer waiting */
+ − if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) )
+ − { old_mb->returned_red = FALSE;
+ − old_mb->func( buf->header.external.mb_id);
+ − }
+ − else
+ − { /* count as many waiting buffers as possible on the old mb */
+ − while( (old_mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( buf->header.external.mb_id, (UINT8 *) (waiting_buffers[old_mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) );
+ − if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) )
+ − { old_mb->returned_red = FALSE;
+ − old_mb->func( buf->header.external.mb_id);
+ − }
+ − }
+ − /* change mb_id of the buffer */
+ − buf->header.external.mb_id = mb_id;
+ −
+ −
+ −
+ − #if RVF_ENABLE_STATS
+ − if ( new_mb->cur_memory_used > new_mb->max_reached )
+ − { new_mb->max_reached = new_mb->cur_memory_used;
+ − }
+ − #endif
+ −
+ − if ( new_mb->cur_memory_used > new_mb->watermark )
+ − { return RVF_YELLOW;
+ − }
+ − else
+ − { return RVF_GREEN;
+ − }
+ − }
+ − else
+ − { /* there is not enough memory in the new mb_id */
+ − if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID) /* remove the buffer from old expected mb */
+ − { _remove_from_list( buf, &rvf_banks[ buf->header.external.mb_expected] );
+ − }
+ − /* enqueue the buffer in the list of waiting buffer */
+ − buf->header.external.mb_expected = mb_id;
+ − _add_to_list( buf, new_mb );
+ − new_mb->returned_red = TRUE;
+ − return RVF_RED;
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_free_buf
+ − **
+ − ** Description Called by an application to free a buffer
+ − **
+ − ** Parameters: buffer pointer
+ − **
+ − ** Returns T_RVF_RET: T_RVF_OK if succesful,
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_free_buf( T_RVF_BUFFER * p_buffer)
+ − { T_RVF_INTERNAL_BUF * buf;
+ − T_RVF_MB * mb;
+ − T_RVF_MB_ID mb_id;
+ − UINT32 buf_size;
+ −
+ −
+ − buf = USER2MEM(p_buffer);
+ −
+ − mb_id = buf->header.external.mb_id;
+ − mb = &rvf_banks[mb_id];
+ − buf_size = rvf_get_buf_size(p_buffer);
+ −
+ − /* do not need to change the mb id of the buffer, since it will be overwritten by p_prev */
+ −
+ − /* free the buffer */
+ − if ( !_release_buf(buf) )
+ − { return RVF_MEMORY_ERR;
+ − }
+ −
+ − #if RVF_ENABLE_STATS
+ − mem_in_use -= buf_size + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD;
+ − #endif
+ −
+ − rvf_disable(20); /* enter critical section */
+ −
+ − /* decrease mb memory use */
+ − mb->cur_memory_used -= buf_size;
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ −
+ − /* call the callback function if state of the mb switches to RVF_GREEN and there is no buffer waiting */
+ − if ( (mb->returned_red == TRUE) && (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && ( mb->func != NULL) )
+ − { mb->returned_red = FALSE;
+ − mb->func( mb_id);
+ − }
+ − else
+ − { /* count as many waiting buffers as possible on the mb */
+ − while( (mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( mb_id, (UINT8 *) (waiting_buffers[mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) );
+ − if ( (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && (mb->returned_red == TRUE) && ( mb->func != NULL) )
+ − { mb->returned_red = FALSE;
+ − mb->func( mb_id);
+ − }
+ − }
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_set_callback_func
+ − **
+ − ** Description Called the first time an application wants to set the callback
+ − ** function associated to a memory bank.
+ − **
+ − ** Parameters: memory bank id, pointer to the callback function.
+ − **
+ − ** Returns T_RVF_RET: T_RVF_OK if succesful,
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_set_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func)
+ − { T_RVF_MB * mb;
+ −
+ − /* checking for invalid memory bank IDs */
+ − if (mb_id >= RVF_MAX_REAL_MB)
+ − return RVF_INVALID_PARAMETER;
+ − mb = &rvf_banks[mb_id];
+ − if ( (mb->max != 0) && (mb->func == NULL) ) /* if the mb has been created and the callback func has never been set */
+ − { mb->func = func;
+ − return RVF_OK;
+ − }
+ − return RVF_INVALID_PARAMETER;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_change_callback_func
+ − **
+ − ** Description Called by an application to change the callback
+ − ** function associated to a memory bank.
+ − ** It means the callback function has to be set before.
+ − **
+ − ** Parameters: memory bank id, pointer to the callback function.
+ − **
+ − ** Returns T_RVF_RET: T_RVF_OK if succesful,
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_change_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func)
+ − { T_RVF_MB * mb;
+ −
+ − /* checking for invalid memory bank IDs */
+ − if (mb_id >= RVF_MAX_REAL_MB)
+ − return RVF_INVALID_PARAMETER;
+ − mb = &rvf_banks[mb_id];
+ − if ( (mb->max != 0) && (mb->func != NULL) ) /* if the mb has been created and the callback func has already been set */
+ − { mb->func = func;
+ − return RVF_OK;
+ − }
+ − return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − #ifdef _WINDOWS_
+ − /*******************************************************************************
+ − **
+ − ** Function _rvf_window_dump_mem
+ − **
+ − ** Description Called by a C++ object to update the graphical display of
+ − ** memory
+ − **
+ − ** Parameters: Opaque pointer to C++ object
+ − **
+ − ** Returns void
+ − **
+ − ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE
+ − ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY
+ − ** STATUS
+ − **
+ − *******************************************************************************/
+ − void _rvf_window_dump_mem(void *m)
+ − {
+ −
+ −
+ − #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */
+ − char mb_info[100];
+ − UINT16 num_mb, num_buf, index;
+ − UINT32 total_mem_size = 0;
+ − UINT32 total_max_used = 0;
+ − UINT32 total_cur_used = 0;
+ − T_RVF_MB * mb;
+ −
+ −
+ − for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ )
+ − {
+ − /* trace the mb if it has been created*/
+ − if ( rvf_name_id[num_mb].mb_params.size > 0 )
+ − { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ];
+ − num_buf = 0;
+ − index = mb->first_buffer_index;
+ − while ( index != RVF_INVALID_INDEX)
+ − { num_buf++;
+ − index = next_buffer[index];
+ − }
+ − strcpy(mb_info,rvf_name_id[num_mb].mb_name);
+ − mb_info[10]='\0';
+ − AddNewState(m,mb_info,
+ − mb->cur_memory_used,mb->max_reached,mb->watermark,mb->max);
+ −
+ −
+ − total_mem_size += mb->max;
+ − total_max_used += mb->max_reached;
+ − total_cur_used += mb->cur_memory_used;
+ − }
+ − }
+ −
+ − #endif /* RVF_ENABLE_STATS */
+ − }
+ −
+ − #endif
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_dump_mem
+ − **
+ − ** Description Called by an application to dump mb state and display statistics
+ − **
+ − ** Parameters: None
+ − **
+ − ** Returns void
+ − **
+ − ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE
+ − ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY
+ − ** STATUS
+ − **
+ − *******************************************************************************/
+ − void rvf_dump_mem()
+ − {
+ − #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */
+ − char mb_info[100];
+ − UINT16 num_mb, num_buf, index;
+ − UINT32 total_mem_size = 0;
+ − UINT32 total_max_used = 0;
+ − UINT32 total_cur_used = 0;
+ − T_RVF_MB * mb;
+ −
+ −
+ − /* display memory required, obtained and ratio */
+ − rvf_send_trace("MEM STAT: Total memory required", 31, required_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ − rvf_send_trace("MEM STAT: Total memory obtained", 31, obtained_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ − rvf_send_trace("MEM STAT: Total memory used ", 31, used_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ − sprintf( mb_info,"MEM STAT: Mem usage ratio : %010f%%", ( (double)(required_size) / (double)(obtained_size) ) *100 );
+ − rvf_send_trace(mb_info, 44, NULL_PARAM , RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − rvf_send_trace("*** START DUMPING MEMORY BANK ***", 33, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ − /* for each mb, display its name, its id, its cur_size, its watermark, its limit, its max reached, the number of callback functions enqueued,
+ − (the requested size, the number of allocated buffer), the average buffer size for this mb */
+ − rvf_send_trace("**MB_NAME* Id Used_mem Watermark Limit Peak Nb_buff Avg_buf_size", 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ )
+ − {
+ − /* trace the mb if it has been created*/
+ − if ( rvf_name_id[num_mb].mb_params.size > 0 )
+ − { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ];
+ − num_buf = 0;
+ − index = mb->first_buffer_index;
+ − while ( index != RVF_INVALID_INDEX)
+ − { num_buf++;
+ − index = next_buffer[index];
+ − }
+ − sprintf( mb_info, "%10.10s %2d %6d %6d %6d %6d %2d %6d",
+ − rvf_name_id[num_mb].mb_name, rvf_name_id[num_mb].mb_id,
+ − mb->cur_memory_used, mb->watermark, mb->max, mb->max_reached, num_buf,
+ − mb->num_buf == 0? 0:mb->required_size / mb->num_buf);
+ −
+ − rvf_send_trace( mb_info, 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − total_mem_size += mb->max;
+ − total_max_used += mb->max_reached;
+ − total_cur_used += mb->cur_memory_used;
+ − }
+ − }
+ − sprintf( mb_info, "TOTAL: ******** %6d********** %6d %6d",
+ − total_cur_used, total_mem_size, total_max_used );
+ −
+ − rvf_send_trace( mb_info, 46, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − #endif /* RVF_ENABLE_STATS */
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_available_mem
+ − **
+ − ** Description Called to get the total size of the memory and the used size.
+ − **
+ − ** Parameters: (return) UINT32 * total_size: contains the number of bytes in the memory.
+ − ** (return) UINT32 * used_size: contains the number of used bytes in the memory.
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if successful, else a negative value.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_get_available_mem( UINT32 * total_size, UINT32 * used_size )
+ − {
+ − UINT16 count;
+ − *total_size = 0;
+ − *used_size = 0;
+ −
+ − /* check if there is enough available physical memory (static or dynamic): if Sum(mb size) <= Sum(pool size)*/
+ − for ( count = 0; count < _rvf_get_number_of_pool(); count ++ ) /* sum the memory in pools */
+ − { *total_size += _rvf_pools[count].pool_size;
+ − }
+ − /* sum the memory required by existing mb */
+ − for ( count = 0; count < RVF_MAX_REAL_MB; count ++ )
+ − { *used_size += rvf_banks[count].max;
+ − }
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_get_mb_param
+ − **
+ − ** Description return the parameters of a specific memory bank
+ − **
+ − ** Parameters: T_RVF_MB_NAME: name of the memory bank
+ − ** (return) T_RVF_MB_PARAM*: parameter of the memory bank.
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if successful, else a negative value.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_get_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param)
+ − { UINT8 num_mb;
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */
+ − { return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − /* copy the parameters of the memory bank */
+ − *param = rvf_name_id[num_mb].mb_params;
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_set_mb_param
+ − **
+ − ** Description change the parameters of a specific memory bank
+ − **
+ − ** Parameters: T_RVF_MB_NAME: name of the memory bank
+ − ** T_RVF_MB_PARAM*: parameter of the memory bank.
+ − **
+ − ** Returns T_RVF_RET: RVF_OK if successful, else a negative value.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_set_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param)
+ − { UINT8 num_mb;
+ − T_RVF_MB_ID mb_id;
+ − T_RVF_MB * mb;
+ −
+ − /* find the mb name in the array */
+ − for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++);
+ − if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */
+ − { return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − mb_id = rvf_name_id[num_mb].mb_id;
+ − mb = &rvf_banks[ mb_id ];
+ −
+ − rvf_disable(20); /* enter critical section */
+ −
+ − /* decrease the mb param by the old parameters */
+ − mb->watermark -= rvf_name_id[num_mb].mb_params.watermark;
+ − mb->max -= rvf_name_id[num_mb].mb_params.size;
+ −
+ − /* save the mb parameters */
+ − rvf_name_id[num_mb].mb_params.size = param->size;
+ − rvf_name_id[num_mb].mb_params.watermark = param->watermark;
+ −
+ − /* increase the mb param by the new parameters */
+ − mb->watermark += param->watermark;
+ − mb->max += param->size;
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − /* dequeue callback functions if state switches to RVF_GREEN */
+ −
+ − return RVF_OK;
+ − }
+ −
+ −
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_empty_mailboxes
+ − **
+ − ** Description Called by rvf_exit_task to empty a task's mailboxes before
+ − ** killing it
+ − **
+ − ** Parameters: task_id: task of wich the mailboxes have to be emptied
+ − **
+ − ** Returns RV_OK
+ − **
+ − *******************************************************************************/
+ − T_RV_RET _rvf_empty_mailboxes (T_RVF_G_ADDR_ID task_id)
+ − {
+ − void * p_buf = NULL;
+ − T_RVF_INTERNAL_BUF * p_hdr;
+ − UINT8 mbox_id = 0;
+ −
+ − if (task_id >= MAX_RVF_TASKS)
+ − {
+ − rvf_send_trace( "RVF: rvf_empty_mbox(): invalid taskid: ", 39, task_id, RV_TRACE_LEVEL_ERROR, RVM_USE_ID );
+ − return RVF_INVALID_PARAMETER;
+ − }
+ −
+ − for (mbox_id = 0; mbox_id< RVF_NUM_TASK_MBOX; mbox_id++)
+ − { /* while the chained list is not empty */
+ − /*while ( OSTaskQFirst[task_id][mbox_id] )
+ − {
+ − rvf_disable(9);
+ −
+ − p_hdr = OSTaskQFirst[task_id][mbox_id];
+ − OSTaskQFirst[task_id][mbox_id] = p_hdr->p_next;
+ − */
+ − while ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] )
+ − {
+ − rvf_disable(9);
+ −
+ − p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id];
+ − pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] = p_hdr->p_next;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − /* set as unlinked */
+ − RVF_SET_BUF_UNLINKED(p_hdr);
+ − #endif
+ −
+ − p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF);
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − rvf_free_buf(p_buf);
+ − }
+ − }
+ −
+ −
+ − return (RV_OK);
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_scan_next
+ − **
+ − ** Description return the next item in the queue if any.
+ − ** If the end of the queue is reached, returns NULL.
+ − ** If current item is NULL, returns the first item in the queue.
+ − **
+ − ** Returns NULL if the end of the queue is reached, else a pointer to the buffer.
+ − **
+ − *******************************************************************************/
+ − T_RVF_BUFFER * rvf_scan_next (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ −
+ − if (!p_q->count) /* if the queue is empty */
+ − return (NULL);
+ −
+ − if (p_buf == NULL) /* if current item == NULL, returns the first one */
+ − {
+ − return (T_RVF_BUFFER*)p_q->p_first;
+ − }
+ −
+ − rvf_disable(12); /* enter critical section */
+ −
+ − p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_buf - sizeof(T_RVF_INTERNAL_BUF));
+ − p_hdr = p_hdr->p_next;
+ − if (p_hdr != NULL)
+ − { p_hdr = (T_RVF_INTERNAL_BUF*) ((UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF));
+ − }
+ −
+ − rvf_enable();
+ −
+ − return (T_RVF_BUFFER*)p_hdr;
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_remove_from_queue
+ − **
+ − ** Description remove a specific item from a queue
+ − **
+ − ** Returns RVF_OK if the item is removed, RVF_INTERNAL_ERR else.
+ − **
+ − *******************************************************************************/
+ − T_RVF_RET rvf_remove_from_queue (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf)
+ − {
+ − T_RVF_INTERNAL_BUF *p_hdr;
+ − T_RVF_INTERNAL_BUF *p_target;
+ −
+ −
+ − if (!p_q->count) /* if the queue is empty */
+ − return (RVF_INTERNAL_ERR);
+ −
+ − rvf_disable(12); /* enter critical section */
+ −
+ − /* find the specific item in the queue */
+ − p_target = USER2MEM((UINT8*)p_buf);
+ − p_hdr = USER2MEM( (UINT8 *)p_q->p_first);
+ −
+ − if( p_hdr == p_target )
+ − { /* the specific item is the first one */
+ − rvf_dequeue( p_q);
+ − rvf_enable();
+ − return (RVF_OK);
+ − }
+ −
+ − while( (p_hdr->p_next != p_target) && (p_hdr->p_next != NULL) )
+ − { p_hdr = p_hdr->p_next;
+ − }
+ −
+ − if( p_hdr->p_next == NULL) /* item not found */
+ − { rvf_enable();
+ − return (RVF_INTERNAL_ERR);
+ − }
+ −
+ −
+ − p_hdr->p_next = p_target->p_next;
+ − p_q->count--;
+ −
+ − /* if we removed the last buffer */
+ − if (p_q->p_last == p_buf)
+ − { p_q->p_last = p_hdr + sizeof(T_RVF_INTERNAL_BUF);
+ − }
+ −
+ − p_target->p_next = NULL;
+ −
+ − #if RVF_ENABLE_BUF_LINKAGE_CHECK
+ − /* set as unlinked */
+ − RVF_SET_BUF_UNLINKED(p_target);
+ − #endif
+ −
+ − rvf_enable(); /* exit critical section */
+ −
+ − return (RVF_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − **
+ − ** Function rvf_dump_pool
+ − **
+ − ** Description Called by an application to dump memory pool usage
+ − **
+ − ** Parameters: None
+ − **
+ − ** Returns void
+ − **
+ − *******************************************************************************/
+ − void rvf_dump_pool()
+ − {
+ − #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */
+ −
+ − UINT16 num_pool;
+ − UINT32 total_mem = 0;
+ −
+ − /* display memory stats */
+ − rvf_send_trace("*** START DUMPING MEMORY ***", 28, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − /* display the total amount of memory available in the system */
+ − /* and the total amount of memory currently in use */
+ − for( num_pool = 0; num_pool < _rvf_get_number_of_pool(); num_pool++)
+ − { total_mem += _rvf_pools[num_pool].pool_size;
+ − }
+ −
+ − rvf_send_trace( "Total memory available ", 23, total_mem, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ − rvf_send_trace( "Memory currently in use", 23, mem_in_use, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID);
+ −
+ − #endif /* RVF_ENABLE_STATS */
+ − }
+ −
+ − static void rvf_free_protected_buf(void *buf)
+ − {
+ − rvf_free_buf(buf);
+ − }
+ −
+ − void rvf_get_protected_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer)
+ − {
+ − T_RVF_MB_STATUS err;
+ − err=rvf_get_buf(mb_id,buffer_size,p_buffer);
+ − if (err==RVF_GREEN)
+ − {
+ − struct _protectedPtr_ *ptr;
+ − struct _exceptionContext_ *context;
+ −
+ − context=_currentExceptionContext_[rvf_get_taskid()];
+ − err=rvf_get_buf(mb_id,sizeof(struct _protectedPtr_),(void*)&ptr);
+ − ptr->next=NULL;
+ − ptr->previous=NULL;
+ − ptr->ptr=*p_buffer;
+ − ptr->func=rvf_free_protected_buf;
+ −
+ − if (err==RVF_GREEN)
+ − {
+ − if (context->stack==NULL)
+ − {
+ − context->stack=ptr;
+ − }
+ − else
+ − {
+ − ptr->previous=context->stack;
+ − context->stack->next=ptr;
+ − context->stack=ptr;
+ − }
+ − }
+ − else
+ − {
+ − rvf_free_buf(*p_buffer);
+ − }
+ − }
+ − if (err!=RVF_GREEN)
+ − throw(E_not_enough_memory);
+ − }
+ −
+ − //TISHMMS Project
+ − /* add by xmzhou_trace_string to trace debug trace message */
+ − void xmzhou_trace_string(char * string2trace)
+ − {
+ − rvf_send_trace(string2trace,strlen(string2trace),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID);
+ − }
+ −
+ − void xmzhou_trace_string_value(char * string2trace,UINT32 value)
+ − {
+ − rvf_send_trace(string2trace,strlen(string2trace),value, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID);
+ − }
+ −
+ − static void mychar2hex(char ch, char *str)
+ − {
+ − unsigned char h_nibble = (ch >> 4) & 0x0F;
+ − unsigned char l_nibble = ch & 0x0F;
+ −
+ − if (h_nibble < 10)
+ − str[0] = 48 + h_nibble;
+ − else
+ − str[0] = 55 + h_nibble;
+ −
+ − if (l_nibble < 10)
+ − str[1] = 48 + l_nibble;
+ − else
+ − str[1] = 55 + l_nibble;
+ − }
+ −
+ − void xmzhou_trace_n_bytes(char * buffer0, UINT32 len)
+ − {
+ − int i;
+ − int traced_len=0;
+ − char mybuffer[40];
+ − char *tracebuffer;
+ −
+ − if(buffer0==NULL) return;
+ −
+ − xmzhou_trace_string_value("xmzhou dumping data length=",len);
+ − xmzhou_trace_string("-------");
+ −
+ −
+ − while(traced_len<len){
+ −
+ − if((len-traced_len)>=16){
+ − tracebuffer=mybuffer;
+ − for (i = 0; i < 16; i++) {
+ − mychar2hex (buffer0[traced_len+i], tracebuffer);
+ − tracebuffer += 2;
+ − }
+ − traced_len+=16;
+ − *tracebuffer = '\0';
+ − rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID);
+ − rvf_delay(20);
+ − }else{
+ − tracebuffer=mybuffer;
+ − for(i=0;i<(len-traced_len);i++)
+ − {
+ − mychar2hex (buffer0[traced_len+i], tracebuffer);
+ − tracebuffer += 2;
+ − }
+ − *tracebuffer = '\0';
+ − rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID);
+ − rvf_delay(20);
+ − break;
+ − }
+ −
+ − }
+ − }