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

📄 cache.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

  /*-------------------------------------------------------------------*/
  /* Set the LRU head to first and LRU tail to last entry in pool.     */
  /*-------------------------------------------------------------------*/
  C->lru_head = &C->pool[0];
  C->lru_tail = &C->pool[C->pool_size - 1];
}

/***********************************************************************/
/* DestroyCache: Deallocate all the memory taken by cache C            */
/*                                                                     */
/*       Input: C = cache to be deleted                                */
/*                                                                     */
/***********************************************************************/
void DestroyCache(Cache *C)
{
  /*-------------------------------------------------------------------*/
  /* Write back all the dirty sectors.                                 */
  /*-------------------------------------------------------------------*/
  FlushSectors(C);

  /*-------------------------------------------------------------------*/
  /* Deallocate the memory for the pool and the hash table.            */
  /*-------------------------------------------------------------------*/
  free(C->pool[0].sector);
  free(C->pool);
  free(C->hash_tbl);

  /*-------------------------------------------------------------------*/
  /* Null out the LRU head and tail.                                   */
  /*-------------------------------------------------------------------*/
  C->lru_head = C->lru_tail = NULL;
}

/***********************************************************************/
/*   GetSector: Return pointer to cache entry containing the specified */
/*              sector number, bringing the sector into the cache if   */
/*              not already there.                                     */
/*                                                                     */
/*      Inputs: C = cache pointer                                      */
/*              sector_number = sector to return pointer to            */
/*              skip_read = if TRUE, don't read new sector from media  */
/*              file_ptr = pointer to file control information         */
/*              entry_ptr = cache entry with new sector                */
/*                                                                     */
/*     Returns: GET_OK on success, GET_WRITE_ERROR on write error,     */
/*              GET_READ_ERROR on read error                           */
/*                                                                     */
/***********************************************************************/
int GetSector(Cache *C, int sector_number, int skip_read, void *file_ptr,
              CacheEntry **entry_ptr)
{
  int index, r_val = GET_OK;
  CacheEntry *entry;

  /*-------------------------------------------------------------------*/
  /* Remember the current sector being chached and get the head of the */
  /* list in which the corresponding entry would be in the cache.      */
  /*-------------------------------------------------------------------*/
  C->sector_number = sector_number;
  entry = C->hash_tbl[hash(C->sector_number, C->pool_size)];

  /*-------------------------------------------------------------------*/
  /* Look first if sector is already in the cache.                     */
  /*-------------------------------------------------------------------*/
  for (; entry; entry = entry->next_hash)
    if (entry->sect_num == C->sector_number)
    {
      /*---------------------------------------------------------------*/
      /* If entry is on replacer list, take it out.                    */
      /*---------------------------------------------------------------*/
      if (entry->pin_cnt++ == 0)
        remove_from_replacer(entry, C);

      *entry_ptr = entry;
      return r_val;
    }

  /*-------------------------------------------------------------------*/
  /* The sector is not in the cache. Choose one to replace with LRU    */
  /* replacement policy.                                               */
  /*-------------------------------------------------------------------*/
  entry = C->lru_head;
  remove_from_replacer(C->lru_head, C);

  /*-------------------------------------------------------------------*/
  /* There should always be an available sector.                       */
  /*-------------------------------------------------------------------*/
  PfAssert(entry);

  /*-------------------------------------------------------------------*/
  /* If dirty sector, write it back to its medium.                     */
  /*-------------------------------------------------------------------*/
  if (entry->dirty != CLEAN && C->write(entry, FALSE))
  {
    entry->dirty = CLEAN;
    put_into_tail(entry, C);
    *entry_ptr = NULL;
    return GET_WRITE_ERROR;
  }

  /*-------------------------------------------------------------------*/
  /* If the entry is in the hash table, remove it from there.          */
  /*-------------------------------------------------------------------*/
  if (entry->hash_loc)
  {
    /*-----------------------------------------------------------------*/
    /* If entry is not first, update previous one, else update head.   */
    /*-----------------------------------------------------------------*/
    if (entry->prev_hash)
      entry->prev_hash->next_hash = entry->next_hash;
    else
      *(entry->hash_loc) = entry->next_hash;

    /*-----------------------------------------------------------------*/
    /* If next entry needs to be updated, update it.                   */
    /*-----------------------------------------------------------------*/
    if (entry->next_hash)
      entry->next_hash->prev_hash = entry->prev_hash;
  }

  /*-------------------------------------------------------------------*/
  /* Read new sector into the cache if skip_read is not set.           */
  /*-------------------------------------------------------------------*/
  if (skip_read == FALSE &&
      C->read(entry->sector, (ui32)C->sector_number))
  {
    set_errno(EIO);
    r_val = GET_READ_ERROR;
  }

  /*-------------------------------------------------------------------*/
  /* Set entry for new sector.                                         */
  /*-------------------------------------------------------------------*/
  entry->sect_num = C->sector_number;
  entry->dirty = CLEAN;
  entry->pin_cnt = 1;
  entry->file_ptr = file_ptr;

  /*-------------------------------------------------------------------*/
  /* Add new entry into the hash table.                                */
  /*-------------------------------------------------------------------*/
  index = hash(C->sector_number, C->pool_size);
  entry->prev_hash = NULL;

  if (C->hash_tbl[index])
  {
    entry->next_hash = C->hash_tbl[index];
    C->hash_tbl[index]->prev_hash = entry;
  }
  else
    entry->next_hash = NULL;

  C->hash_tbl[index] = entry;
  entry->hash_loc = &C->hash_tbl[index];

  /*-------------------------------------------------------------------*/
  /* No need to remember the sector being cached any longer.           */
  /*-------------------------------------------------------------------*/
  C->sector_number = -1;

  *entry_ptr = entry;
  return r_val;
}

/***********************************************************************/
/* FlushFileSectors: Flush all sectors belonging to a file             */
/*                                                                     */
/*      Inputs: C = cache for which flush is to be performed           */
/*              file_ptr = pointer to file                             */
/*                                                                     */
/*     Returns: NULL on success, (void)-1 on failure                   */
/*                                                                     */
/***********************************************************************/
void *FlushFileSectors(Cache *C, const void *file_ptr)
{
  int i;
  void *r_val = NULL;

  /*-------------------------------------------------------------------*/
  /* If no dirty sectors, return success.                              */
  /*-------------------------------------------------------------------*/
  if (!C->dirty_old && !C->dirty_new)
    return NULL;

  /*-------------------------------------------------------------------*/
  /* Loop over cache entries, flushing each one.                       */
  /*-------------------------------------------------------------------*/
  C->dirty_old = C->dirty_new = FALSE;
  for (i = 0; i < C->pool_size; ++i)
  {
    /*-----------------------------------------------------------------*/
    /* If sector is not clean, either it belongs to the file or have   */
    /* to set the dirty flag.                                          */
    /*-----------------------------------------------------------------*/
    if (C->pool[i].dirty != CLEAN)
    {
      /*---------------------------------------------------------------*/
      /* If it belongs to the file, write it and mark it clear.        */
      /*---------------------------------------------------------------*/
      if (C->pool[i].file_ptr == file_ptr)
      {
        if (C->write(&C->pool[i], TRUE))
          r_val = (void *)-1;
        C->pool[i].dirty = CLEAN;
      }

      /*---------------------------------------------------------------*/
      /* Else, mark the appropriate flag.                              */
      /*---------------------------------------------------------------*/
      else if (C->pool[i].dirty == DIRTY_NEW)
        C->dirty_new = TRUE;
      else
        C->dirty_old = TRUE;
    }
  }
  return r_val;
}

/***********************************************************************/
/* FlushSectors: Go through cache and flush all dirty sectors          */
/*                                                                     */
/*       Input: C = cache for which flush is to be performed           */
/*                                                                     */
/*     Returns: -1 on failure, 0 if no sectors written, 1 otherwise    */
/*                                                                     */
/***********************************************************************/
int FlushSectors(Cache *C)
{
  int i, r_val = 0, written;

  /*-------------------------------------------------------------------*/
  /* If no dirty sectors, return.                                      */
  /*-------------------------------------------------------------------*/
  if (!C->dirty_old && !C->dirty_new)
    return 0;

  /*-------------------------------------------------------------------*/
  /* Loop over cache entries, flushing each one.                       */
  /*-------------------------------------------------------------------*/
  for (i = 0, written = FALSE; i < C->pool_size; ++i)
  {
    /*-----------------------------------------------------------------*/
    /* If sector is not clean, write it and then mark it clean.        */
    /*-----------------------------------------------------------------*/
    if (C->pool[i].dirty != CLEAN)
    {
      written = TRUE;
      if (C->write(&C->pool[i], TRUE))

⌨️ 快捷键说明

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