⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdi_bkgd.c

📁 Flash file system
💻 C
📖 第 1 页 / 共 5 页
字号:
 *###*/
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 + -