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

📄 fdi_bkgd.c

📁 FDI Intel开发的FLASH文件系统,功能很强大
💻 C
📖 第 1 页 / 共 5 页
字号:
 *### 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 = NULL;           /* 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) &&
          (TEST_LOOKUP_TABLE_DELETE_PENDING( cmd_ptr->type,
                                             cmd_ptr->identifier ) ||
           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 */
         if (cmd_ptr->sub_command != WRITE_TRUNCATE)
         {
         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 )
             && ( cmd_ptr->sub_command != WRITE_TRUNCATE )
            )
         {
#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 */
               }
#endif  /* PACKET_DATA */
               SEM_POST(RECL_Enable);     /* enable reclaim to begin */
#ifdef TEST_MSGS
               logMsg("Reclaim ENABLED before, needed %d, free %d, "
                      "spare %d\n", needed_space, (int) total_free,
                      FDI_SpareBlock, 0, 0, 0);
#endif

               /* Check if free space enough to hold all
                * objects of this queue item
                */
               if ( status == HW_ERR_FLASH_FULL )
               {
                  prev_free = 0;
                  /*
                   * simulate write sub functions to
                   * make sure there is enough free space
                   */
                  status=BKGD_CheckFreeSpace(cmd_ptr);

                  /* Reclaim untill there is enought free space to write */
                  while ( status != HW_ERR_NONE )
                  {
                     SEM_WAIT(RECL_Done);
                     total_free = BKGD_GetTotalSpace(FREE_UNITS);
                     total_dirty = BKGD_GetTotalSpace(DIRTY_UNITS);

                     /* Check again thereis enough free space */
                     status=BKGD_CheckFreeSpace(cmd_ptr);
                     if ( status == HW_ERR_NONE )
                     {
                        break;
                     }

                     /*
                      * If the total_dirty is zero and nothing
                      * to be reclaimed, return  flash full error.
                      */
/* E.5.1.776 Begin */
                     if ((total_free == prev_free) &&
                         (total_dirty == 0))
/* E.5.1.776 End */
                     {
                        FDI_HandleError(HW_ERR_FLASH_FULL);
                        BKGD_TaskId = 0;
                        return;
                     }
                     prev_free = total_free;
#if (PACKET_DATA == TRUE)              /* PACKET_DATA */
                     if ( FDI_Pckt.ID != WORDMAX )
                     {
                        FDI_RESET_RECLMSTATE;      /* for reclaim solution */
                     }
#endif  /* PACKET_DATA */
                     SEM_POST(RECL_Enable);     /* enable reclaim to begin */
                  }
               } /* End of status == ERR_FLASH_FULL */
            }                             /* ENDIF total_free < SYSTEM_THRESH */
            else
            {
               prev_free = 0;
               while ((total_free < SYSTEM_THRESHOLD) ||
                      (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 */
                  }
#endif /* PACKET_DATA */
                  SEM_POST(RECL_Enable);     /* enable reclaim to begin */
#ifdef TEST_MSGS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -