📄 fdi_bkgd.c
字号:
*###*/
HW_ERROR
BKGD_Terminate(void)
{
#ifdef TESTING
/* Make task safe during plr testing to ensure TID is updated
prior to preemption during power loss emulation. */
taskSafe();
#endif
#if(TASK_CREATE_DESTROY == TRUE)
/* destroy the background task. Only do this if the task still exists */
if (BKGD_TaskId != 0)
{
TASK_DESTROY(BKGD_TaskId);
}
#endif /* TASK_CREATE_DESTROY */
#if(SEM_CREATE_DESTROY == TRUE)
/* destroy mutex semaphore for the global data lookup table */
if (SEM_LookupTable != SEM_NULL)
{
SEM_MTX_DESTROY(SEM_LookupTable);
}
/* destroy mutex semaphore for the global logical block table */
if (SEM_BlockTable != SEM_NULL)
{
SEM_MTX_DESTROY(SEM_BlockTable);
}
/* destroy mutex semaphore for writing during the reclaim block copy */
if (SEM_WriteInProg != SEM_NULL)
{
SEM_MTX_DESTROY(SEM_WriteInProg);
}
if (SEM_AccumSize_Mutex != SEM_NULL)
{
SEM_MTX_DESTROY(SEM_AccumSize_Mutex);
}
#if (PACKET_DATA == TRUE) /* PACKET_DATA */
#if (OPTIMAL_TASKDELAY == TRUE) /* OPTIMAL_TASKDELAY */
if (SEM_QueueEmpty != SEM_NULL)
{
SEM_DESTROY(SEM_QueueEmpty);
}
#endif /* OPTIMAL_TASKDELAY */
#endif /* PACKET_DATA */
#if (PERF_TEST == TRUE)
if (PERF_SEM_Bkgd != SEM_NULL)
{
SEM_DESTROY(PERF_SEM_Bkgd);
}
#endif /* PERF_TEST */
#endif /* SEM_CREATE_DESTROY */
#ifdef TESTING
taskUnsafe();
#endif
return HW_ERR_NONE;
} /* END BKGD_Terminate */
/*############################################################################
*### BKGD_GetTotalSpace
*###
*### DESCRIPTION:
*### Scans the FDI_LogicalBlockTable and adds up the total free space or
*### dirty space in bytes depending on the input parameter.
*###
*### USAGE:
*### total_free = BKGD_GetTotalSpace(FREE_UNITS);
*### total_dirty = BKGD_GetTotalSpace(DIRTY_UNITS);
*###
*### PARAMETERS:
*### IN: field - free_space (FREE_UNITS) or dirty_space (DIRTY_UNITS)
*### enumeration
*### OUT:
*###
*### RETURNS:
*### total space free or dirty in bytes
*###
*###*/
DWORD
BKGD_GetTotalSpace(FDI_SPACE field)
{
int i;
DWORD total = 0;
SEM_MTX_WAIT(SEM_BlockTable);
/*
* DO FOR each data block: add up the dirty or free space in the
* FDI_LogicalBlockTable fields
*/
for (i = 0; i < MAX_DATA_BLOCKS; i++)
{
/*
* IF we want the free space available THEN select the free_space field
* in FDI_LogicalBlockTable[]
*/
/*
* IF the input parameter field is FREE_UNITS THEN add up the free_space
* values
*/
if (field == FREE_UNITS)
{
total += FDI_LogicalBlockTable[i].free_space;
}
/* ELSE select the dirty_space field in FDI_LogicalBlockTable[] */
else
{
total += FDI_LogicalBlockTable[i].dirty_space;
}
} /* ENDDO FOR each data block */
SEM_MTX_POST(SEM_BlockTable);
return (total * sizeof(DWORD));
} /* END BKGD_GetTotalSpace */
/*############################################################################
*### BKGD_Task
*###
*### DESCRIPTION:
*### Runs in the background as a task getting pointers to items in the queue
*### to write or delete from flash. It calculates the needed space and
*### requests or enables dirty space reclamation if needed. The task calls
*### WriteData or DeleteData depending on the command extracted from the queue
*### data. Once the command is completed successfully the item is deleted
*### from the queue.
*###
*### USAGE: *** NOTICE: THIS IS A SPAWNED TASK, NOT CALLED DIRECTLY ***
*### BKGD_TaskId = SPAWN("Background", BKGD_PRIORITY, VX_FP_TASK,
*### BKGD_STACK_SIZE, BKGD_Task);
*###
*###
*### PARAMETERS:
*### IN:
*### OUT:
*### GLOBALS USED:
*### FDI_QueueIdentifier
*###
*### RETURNS:
*###*/
void
BKGD_Task(void)
{
BYTE_PTR data_ptr; /* pointer to the raw data */
COMMAND_PTR cmd_ptr = NULL; /* pointer to the command structure */
DWORD total_free; /* total free space available */
DWORD prev_free;
DWORD total_dirty; /* total dirty space available */
WORD data_size; /* size of data item in queue */
#ifdef TEST_MSGS
WORD needed_space; /* data_size + size of unit header */
#endif
WORD initial_gran = 0; /* granularity before new data added */
WORD new_gran; /* granularity with new data added */
BYTE append_to_replace_flag; /* flag indicates the append does not
* change the number of units used */
#if (DATA_STREAM == TRUE)
BYTE data_streaming;
BYTE index; /*added as a counter through FDI_OpenParam*/
#endif
HW_ERROR status = HW_ERR_NONE;
Q_ERROR q_status;
DataBlocks = 0; /* initialize global tracking current
* logical block in use */
for(;;) /* DO FOREVER */
{
/* Wait for a data item to appear in queue, then get a pointer to it. */
q_status = Q_Peek(FDI_QueueIdentifier, (void **) &cmd_ptr, &data_size,
GET_FIRST_ITEM);
#ifdef TIMING
/* Get timestamp for start of update */
COMM_getTimestamp(&BKGD_Start);
#endif
if (q_status == Q_ERR_INVALID_HANDLE)
{
FDI_HandleError(HW_ERR_PARAM);/* */
#ifdef TEST_MSGS
logMsg("BKGD:ERROR Q_Peek() INVALID HANDLE\n", 0, 0, 0, 0, 0, 0);
#endif
break;
}
/*
* if this is not a new data parameter and we are doing an append, but
* the size is not changing, we are effectively doing a replace which
* will dirty as much as it uses. This means we don't need to account
* for threshold
*/
append_to_replace_flag = FALSE;
if (((cmd_ptr->sub_command == WRITE_APPEND) ||
(cmd_ptr->sub_command == WRITE_RESERVED)) &&
(cmd_ptr->data_offset != 0))
{
initial_gran = TO_GRAN(cmd_ptr->data_offset);
new_gran = TO_GRAN(cmd_ptr->data_offset + \
(data_size - sizeof(COMMAND)));
if (new_gran <= initial_gran)
{
append_to_replace_flag = TRUE;
}
}
SEM_MTX_WAIT(SEM_LookupTable);
/*
* If the parameter to write has been deleted by the foreground, then
* ignore the write
*/
if ((cmd_ptr->sub_command != WRITE_DELETE) &&
(EMPTY_LOOKUP_TABLE(cmd_ptr->type,cmd_ptr->identifier) ||
(NO_LOOKUP_TABLE_BLOCK(cmd_ptr->type,cmd_ptr->identifier) &&
((cmd_ptr->data_offset != 0) ||
(cmd_ptr->sub_command == WRITE_MODIFY) ||
(cmd_ptr->sub_command == WRITE_REPLACE)))))
{
/* Remove from queue */
Q_Remove(FDI_QueueIdentifier, cmd_ptr, append_to_replace_flag);
SEM_MTX_POST(SEM_LookupTable);
continue;
}
SEM_MTX_POST(SEM_LookupTable);
/*
* IF the access sub_command is NOT a DELETE command THEN do the
* following
*/
if (cmd_ptr->sub_command != WRITE_DELETE)
{
/* get a pointer to the beginning of the data item and the size */
data_ptr = (BYTE_PTR) cmd_ptr + sizeof(COMMAND);
/* assign data_size to be size of the data information */
data_size = data_size - sizeof(COMMAND);
/* get the total_free space available in flash */
total_free = BKGD_GetTotalSpace(FREE_UNITS);
total_dirty = BKGD_GetTotalSpace(DIRTY_UNITS);
if( cmd_ptr->sub_command != WRITE_MODIFY )
{
#if (FREE_SPACE_FUNCTIONS == TRUE)
status = BKGD_CheckForSpace(cmd_ptr,
data_size,
FALSE,
NORMAL_CALCCHK);
#else /* !FREE_SPACE_FUNCTIONS */
status = BKGD_CheckForSpace(cmd_ptr,
data_size,
FALSE);
#endif /* FREE_SPACE_FUNCTIONS */
#ifdef TEST_MSGS
/* size of data in terms of UNIT_GRANULARITY */
needed_space = TO_BYTES(TOTALGRAN(cmd_ptr->gran_needed));
#endif
#if (DATA_STREAM == TRUE)
/* can not take the SEM_OpenStream semaphore without effecting
* data streaming throughput */
/* if any? FDI_OpenParam entry is in use
* set the flag true, else false
*/
data_streaming = FALSE;
for(index = 0; index < OPEN_ARRAY_SIZE; index++)
{
/* check to see if this ID is open */
if(FDI_OpenParam[index].identifier == cmd_ptr->identifier)
{
/* check to see if this ID is open for streaming */
if(FDI_OpenParam[index].data_streaming == FALSE)
{
/* check to see if granularity operations are
* being done other than replace
*/
if(((cmd_ptr->data_offset%UNIT_GRANULARITY) == 0) &&
(cmd_ptr->sub_command != WRITE_REPLACE) &&
((data_size% UNIT_GRANULARITY) == 0))
{
data_streaming = TRUE;
}
/* Check if this ID is open for streaming and
granularity operations are not being done */
/* aux field was set to true, in other words, if data
* streaming was not being done, but the open stream
* structure says it is being done, update the open
* streaming structure to mean data streaming
* is not being done.
*/
/* REMEMBER::::::::::::::::::::::::::::::::::::::
* FDI_OpenParam.data_streaming field follows negative
* logic, while local varialble data_streaming follows
* positive logic.
*/
if(data_streaming == FALSE)
{
SEM_MTX_WAIT(SEM_OpenStream);
FDI_OpenParam[index].data_streaming = TRUE;
SEM_MTX_POST(SEM_OpenStream);
}
}
break;
}
}
#endif /* DATA_STREAM */
/*
* IF the total_space is less than the system threshold THEN start or
* request reclaim to be started
*/
#if (DATA_STREAM == TRUE)
if ((data_streaming == TRUE) &&
((total_free < FDI_OVERHEAD_PER_BLOCK) ||
(status == HW_ERR_FLASH_FULL)))
{
#if (PACKET_DATA == TRUE) /* PACKET_DATA */
if( FDI_Pckt.ID != WORDMAX )
{
FDI_WAIT_FORRECLM_DONE; /* for reclaim solution */
}
#endif /* PACKET_DATA */
SEM_TRY_WAIT(RECL_Done); /* reset RECL_Done semaphore */
#if (PACKET_DATA == TRUE) /* PACKET_DATA */
if( FDI_Pckt.ID != WORDMAX )
{
FDI_RESET_RECLMSTATE; /* for reclaim solution */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -