亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? buffer.c

?? 從大量的wince源代碼中剝離出的fat文件系統源代碼.移植性非常高. 里面帶有source i.rar
?? C
?? 第 1 頁 / 共 4 頁
字號:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    buffer.c

Abstract:

    This file contains routines for managing disk data buffers.  A
    buffer is one or more contiguous blocks.  Blocks are a fixed
    (compile-time) size, independent of sector size.  Buffer size is
    dynamic however; it is calculated as the LARGER of the sector size
    and the block size, and there MUST be an integral number of both
    blocks AND sectors per buffer (and normally it's the SAME integral
    number, because our fixed block size is normally the same as
    the sector size of most media -- 512 bytes).

    All read/write access to a volume is through the buffers managed
    by this module.  Every buffer has a variety of states:  it may be
    VALID or INVALID, HELD or UNHELD, DIRTY or CLEAN, and ASSIGNED or
    UNASSIGNED.

    VALID means the buffer contains data for some block on some volume;
    INVALID means it doesn't contain anything yet (or anymore, if a
    dirty buffer couldn't be committed due to some disk error).  A buffer
    is valid if its pvol points to a VOLUME structure and is invalid if
    null.

    HELD means the buffer is currently being examined and/or modified
    by one or more threads; UNHELD means it isn't.  Unless a buffer
    size was chosen that spans multiple sectors (and therefore multiple
    streams), it will be rare for a buffer to be held by more than one
    thread, because buffers are normally accessed only on behalf of streams,
    and streams are normally accessed only while their critical section
    is owned.

    DIRTY means a buffer contains changes that need to be written to
    a volume;  CLEAN means it matches the volume.  There is no lazy-write
    mechanism currently, so when a function is done modifying buffers, it
    needs to commit those dirty buffers synchronously.  CommitBuffer does
    this by clearing a buffer's DIRTY bit and then writing the buffer's
    data to disk;  thus, if another thread dirties the same buffer before
    the write completes, the buffer remains dirty.  Because a DIRTY buffer
    is not necessarily a HELD buffer, CommitBuffer also holds a buffer
    across the entire "cleaning" operation to insure that FindBuffer
    doesn't steal the buffer until it's fully committed.  In summary, a
    buffer must always be HELD while its DIRTY/CLEAN state is being changed.

    ASSIGNED means a buffer is assigned to some stream.  We assign
    buffers to streams so that when CommitStreamBuffers is called, we
    can readily find all the buffers containing data for that stream.
    Note that since the buffer size could be such that multiple streams
    could share the same buffers, we force AssignStreamBuffer to commit
    a buffer before giving it to a different stream.  This may or may
    not result in an extra write, but at least it preserves the notion
    that once CommitStreamBuffers has completed, the stream is fully
    committed.

    Streams also have the notion of a CURRENT buffer.  When they call
    ReadStreamBuffer, whatever buffer supplies the data is HELD and then
    recorded in the stream as the stream's current buffer (s_pbufCur).
    If a subsequent ReadStreamBuffer returns the same buffer, it remains
    the current buffer;  if it returns a different buffer, the previous
    current buffer is unheld and no longer current.

    A stream's current buffer state is protected by the stream's
    critical section;  ie, another thread cannot seek to another part of
    some stream, thereby forcing another buffer to become current, while
    an earlier thread was still examining data in an earlier current
    buffer.  A problem, however, can arise on the SAME thread.  MoveFile
    is a good example:  if MoveFile tries to open two streams at once
    (one for the source filename and one for destination) and both
    source and destination happen to be the same directory (ie, the same
    stream), MoveFile will simply get two pointers to the SAME stream
    data structure;  thus, every time it seeks and reads something using
    one stream, it could be modifying the stream's current buffer and
    thereby invalidating any pointer(s) it obtained via the other stream.

    So MoveFile, and any other code that juggles multiple streams, needs
    to be sure that its streams are unique, or take care to explicitly
    hold a stream's current buffer before operating on a second, potentially
    identical stream.

    Furthermore, every function that juggles multiple streams probably
    also uses multiple buffers.  Even if we had N buffers in the buffer
    pool (where N is a large number), we could have N threads all arrive
    in MoveFile at the same time, all obtain their first buffer, and then
    all block trying to get a second buffer.  Ouch.

    The easiest way to solve that problem is to count buffer-consuming
    threads in FATFS, and when the number of threads * MIN_BUFFERS exceeds
    the number of available buffers, block until available buffers increases
    sufficiently.

Revision History:

    Lazy Writer Thread (added post v2.0 -JTP)

    Initial design goals for lazy writing include:

        1. Simplicity.  Create a dedicated lazy-writer thread when FATFS.DLL
        is loaded and initialized for the first time.  The natural place
        to manage creation/destruction of the thread is entirely within the
        BufInit and BufDeinit functions.

        Although it might be nice to have "lazy lazy-writer thread creation"
        (ie, to defer thread creation until we get to a point where something
        has actually been written), I think that for now WE will be the
        lazy ones, and defer that feature to a later date.  Besides, we reduce
        the risk of running into some architectural problem with that approach
        downstream.

        2. Minimum lazy-writer wake-ups (ie, it shouldn't wake up if there's
        no work to do), balanced by a maximum age for dirty data.  Age will be
        tracked by timestamps in the buffer headers, updating those timestamps
        every time DirtyBuffer is called.

        3. Maximum transparency (ie, existing FATFS code shouldn't change too
        much).  However, we do need to more carefully differentiate between
        those places where we really need to COMMIT as opposed to simply WRITE.
        Thus, we now have WriteStreamBuffers and WriteAndReleaseStreamBuffers to
        complement CommitStreamBuffers and CommitAndReleaseStreamBuffers.
--*/

#include "fatfs.h"


/*  The minimum number of buffers is the number of buffers that may be
 *  simultaneously held during any one operation.  For example, when
 *  CreateName is creating an entry for a new subdirectory, it can have
 *  holds on 1 FAT buffer and up to 2 directory buffers (in the case of
 *  zeroing a growing directory), all simultaneously.  We round the minimum
 *  up to 4, (a) to be safe, and (b) to evenly divide the default number of
 *  buffers.
 */

#define MIN_BUFFERS     4
#define DEF_BUFFERS     32      
#if (DEF_BUFFERS < MIN_BUFFERS)
#error  Default buffer pool size too small
#endif

#if (DEF_BUFFERS % MIN_BUFFERS)
#error  Default buffer pool size should be multiple of minimum
#endif

#if ((DEF_BUFFERS*512) & (4096-1))
#error  Default buffer pool memory allocation should be multiple of typical page size
#endif




//#define BIG_BUFFERS

DWORD       cbBuf;              // buffer size (computed at run-time)
DWORD       cbufTotal;          // total number of buffers
DWORD       cbufError;          // total buffers with outstanding write errors


DWORD       flBuf;              // see GBUF_*
#define GBUF_LOCALALLOC         0x00000001

DWORD       cblkBuf;            // blocks per buffer (computed at run-time)
DWORD       maskBufBlock;       // to convert blocks to buffer-granular blocks
PBYTE       pbBufCarve;         // address of carved buffer memory, if any
BUF_DLINK   dlBufMRU;           // MRU list of buffers
DWORD       cBufVolumes;        // number of volumes using buffer pool
DWORD       cBufThreads;        // number of threads buffer pool can handle
DWORD       cBufThreadsOrig;    // number of threads buffer pool can handle
HANDLE      hevBufThreads;      // auto-reset event signalled when another thread can be handled
CRITICAL_SECTION csBuffers;     // buffer pool critical section




BOOL BufInit(void)
{
    InitializeCriticalSection(&csBuffers);
    DEBUGALLOC(DEBUGALLOC_CS);
    hevBufThreads = CreateEvent(NULL, FALSE, FALSE, NULL);      // auto-reset, not initially signalled
    if (hevBufThreads) {
        DEBUGALLOC(DEBUGALLOC_EVENT);
        return TRUE;
    }
    return FALSE;
}


void BufDeinit(void)
{
    if (hevBufThreads) {
        CloseHandle(hevBufThreads);
        DEBUGFREE(DEBUGALLOC_EVENT);
    }
    DEBUGFREE(DEBUGALLOC_CS);
    DeleteCriticalSection(&csBuffers);
}


/*  BufEnter - Gates threads using the buffer pool
 *
 *  Originally, this function was very simple.  If cBufThreads dropped
 *  below zero, it waited for the supportable thread count to rise again
 *  before letting another thread enter.
 *
 *  Unfortunately, because we retain dirty data indefinitely, in the hopes
 *  that it can eventually be committed, dirty buffers may not actually be
 *  usable if the data cannot actually be committed at this time (eg, card
 *  is bad, card has been removed, etc).  So, now we charge uncommitable
 *  buffers against cBufThreads as well.
 *
 *  ENTRY
 *      fForce - TRUE to force entry, FALSE if not
 *
 *  EXIT
 *      TRUE if successful, FALSE if not (SetLastError is already set)
 *
 *  NOTES
 *      Called at the start of *all* FATFS API entry points, either directly
 *      or via FATEnter.
 */

BOOL BufEnter(BOOL fForce)
{
    if (fForce) {
        // Keep the buffer thread count balanced, but don't tarry
        InterlockedDecrement(&cBufThreads);
        return TRUE;
    }

    if (cLoads == 0) {
        // Any non-forced request during unloading is promptly failed
        SetLastError(ERROR_NOT_READY);
        return FALSE;
    }

    if (InterlockedDecrement(&cBufThreads) < 0) {

        // We have exceeded the number of threads that the buffer pool
        // can handle simultaneously.  We shall wait on an event that will
        // be set as soon as someone increments cBufThreads from within
        // negative territory.

        WaitForSingleObject(hevBufThreads, INFINITE);
    }
    return TRUE;
}


/*  BufExit - Gates threads finished with the buffer pool
 *
 *  ENTRY
 *      None
 *
 *  EXIT
 *      None
 *
 *  NOTES
 *      Called at the end of *all* FATFS API entry points, either directly
 *      or via FATExit.
 */

void BufExit()
{
    if (InterlockedIncrement(&cBufThreads) <= 0) {
        SetEvent(hevBufThreads);
    }
}


/*  NewBuffer - allocate a new buffer
 *
 *  ENTRY
 *      cb - size of buffer, in bytes
 *      ppbCarve - pointer to address of buffer memory to carve up;
 *      if either the pointer or the address it points is NULL, then
 *      we will allocate memory for the buffer internally.
 *
 *  EXIT
 *      pointer to buffer, NULL if error.  Note that this allocates
 *      both a BUF structure and the block of memory referenced by the
 *      BUF structure that is actually used to cache the disk data.
 */

__inline PBUF NewBuffer(DWORD cb, PBYTE *ppbCarve)
{
    PBUF pbuf;

    pbuf = (PBUF)LocalAlloc(LPTR, sizeof(BUF));

    if (pbuf) {

        DEBUGALLOC(sizeof(BUF));

        if (ppbCarve && *ppbCarve) {
            pbuf->b_pdata = *ppbCarve;
            pbuf->b_flags |= BUF_CARVED;
            *ppbCarve += cb;
        }
        else {
            if (flBuf & GBUF_LOCALALLOC) {
                pbuf->b_pdata = (PVOID)LocalAlloc(LMEM_FIXED, cb);
            }
            else {
                pbuf->b_pdata = VirtualAlloc(0,
                                             cb,
                                             MEM_RESERVE|MEM_COMMIT,
                                           //MEM_RESERVE|MEM_MAPPED,
                                             PAGE_READWRITE
                                           //PAGE_NOACCESS
                                            );
            }
            if (!pbuf->b_pdata) {
                DEBUGFREE(sizeof(BUF));
                VERIFYNULL(LocalFree((HLOCAL)pbuf));
                return NULL;
            }
            DEBUGALLOC(cb);
        }
    }
    return pbuf;
}


/*  AllocBufferPool - pre-allocate all buffers in buffer pool
 *
 *  ENTRY
 *      pvol - pointer to VOLUME currently being mounted
 *
 *  EXIT
 *      TRUE if buffer pool successfully (or already) allocated.  Every
 *      successful call must ultimately be matched by a call to
 *      FreeBufferPool;  only when the last volume has called FreeBufferPool
 *      will the pool actually be deallocated.
 *
 *  NOTES
 *      This function can fail if (a) the minimum number of buffers
 *      could not be allocated, or (b) the buffer pool was already allocated
 *      but the size of the buffers cannot accomodate the sector size of
 *      this particular volume.
 */

BOOL AllocBufferPool(PVOLUME pvol)
{
    ASSERT(OWNCRITICALSECTION(&pvol->v_cs));

    if (cBufVolumes > 0) {

        
#ifdef BIG_BUFFERS
        if (cbBuf < pvol->v_pdsk->d_diActive.di_bytes_per_sect)
            return FALSE;
#else
        if (cbBuf != pvol->v_pdsk->d_diActive.di_bytes_per_sect)
            return FALSE;
#endif
    }

    // If the current volume is already using the buffer pool,
    // then we're done.  Otherwise, increment total buffer pool clients.

    EnterCriticalSection(&csBuffers);

    // If the volume is already buffered, then we can skip most of this
    // work, but we'll still need to perform the recycled check below, because
    // if the volume changed on us, we need to throw away all its buffers.

    if (!(pvol->v_flags & VOLF_BUFFERED)) {

        pvol->v_flags |= VOLF_BUFFERED;

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
激情丁香综合五月| 欧美巨大另类极品videosbest| 97久久人人超碰| 欧美高清视频www夜色资源网| 中文字幕精品—区二区四季| 日本在线不卡一区| 91丨porny丨首页| 久久久久九九视频| 五月天精品一区二区三区| 99久久国产综合精品女不卡| 日韩一级免费观看| 亚洲电影一区二区三区| av网站免费线看精品| 久久综合久久99| 奇米在线7777在线精品| 欧美在线观看一二区| 国产精品理伦片| 国产成人啪午夜精品网站男同| 欧美一区二区在线免费观看| 亚洲国产一二三| 在线中文字幕一区| 日韩久久一区二区| 成人白浆超碰人人人人| 久久久精品一品道一区| 久久福利视频一区二区| 欧美一级在线视频| 热久久免费视频| 欧美蜜桃一区二区三区| 亚洲成人动漫在线免费观看| 色婷婷亚洲综合| 亚洲精品五月天| 91麻豆福利精品推荐| 亚洲视频一区在线观看| 91视频免费播放| 亚洲日本中文字幕区| 99re这里只有精品首页| 中文字幕中文乱码欧美一区二区 | 欧美日韩不卡一区| 亚洲自拍偷拍图区| 91国产免费看| 午夜激情久久久| 欧美一区二区三区婷婷月色| 日韩精品高清不卡| 欧美刺激午夜性久久久久久久| 久久精品国产一区二区| 久久亚洲综合av| 成人高清视频在线| 亚洲欧美视频在线观看| 欧美日韩一区二区三区免费看| 无吗不卡中文字幕| 日韩精品一区二区三区在线观看| 激情图片小说一区| 国产精品视频线看| 在线亚洲+欧美+日本专区| 三级久久三级久久久| 精品国产一区二区三区不卡 | 精品久久久久av影院| 国产一区高清在线| 国产精品福利在线播放| 在线观看www91| 看电影不卡的网站| 欧美国产乱子伦 | 成人少妇影院yyyy| 亚洲一级在线观看| 精品av综合导航| 91视频你懂的| 麻豆精品一区二区三区| 国产精品久久久久aaaa樱花| 欧美日韩dvd在线观看| 国产麻豆视频一区二区| 一区二区三区不卡在线观看| 日韩精品一区二区在线| 91美女片黄在线观看91美女| 免费观看在线色综合| 国产精品免费久久| 欧美一级片在线| 一本一道久久a久久精品| 日韩av电影免费观看高清完整版在线观看 | 26uuu欧美| 欧美中文字幕亚洲一区二区va在线 | 亚洲色欲色欲www| 日韩欧美二区三区| aaa亚洲精品一二三区| 爽好多水快深点欧美视频| 国产精品视频在线看| 欧美一区二区三区成人| 99re66热这里只有精品3直播 | 91精品国产综合久久久久久漫画 | 一本久久a久久精品亚洲| 蜜桃视频在线观看一区| 亚洲精品老司机| 久久精品一区二区三区四区| 69久久夜色精品国产69蝌蚪网| 成人av影视在线观看| 久久99精品久久久| 无码av免费一区二区三区试看| 国产精品国产a| 国产天堂亚洲国产碰碰| 欧美一区二区三区精品| 欧美久久久久久久久| 99久久夜色精品国产网站| 国产精品资源在线| 麻豆精品精品国产自在97香蕉| 亚洲国产精品自拍| 夜夜操天天操亚洲| 亚洲色图制服丝袜| 国产精品超碰97尤物18| 国产精品免费久久| 国产精品丝袜91| 国产精品美女一区二区| 国产精品色在线观看| 国产人妖乱国产精品人妖| 久久婷婷久久一区二区三区| 精品欧美一区二区在线观看| 日韩一级免费一区| 精品国产不卡一区二区三区| 欧美大片在线观看| 精品日韩在线一区| 久久久久久久综合日本| 久久精品无码一区二区三区| 久久久99精品久久| 国产嫩草影院久久久久| 国产精品拍天天在线| 国产精品色一区二区三区| 国产精品美女久久久久久久网站| 国产精品三级在线观看| 综合色天天鬼久久鬼色| 一区二区在线观看视频在线观看| 亚洲六月丁香色婷婷综合久久 | 亚洲国产视频直播| 免费成人小视频| 精品一区二区国语对白| 国产成人av影院| 91麻豆高清视频| 欧美蜜桃一区二区三区| 欧美电视剧在线观看完整版| 国产三级精品视频| 中文字幕在线不卡一区| 亚洲一卡二卡三卡四卡无卡久久| 日韩av网站在线观看| 国产麻豆91精品| 91亚洲精品久久久蜜桃| 欧美日韩三级视频| 精品国产91乱码一区二区三区| 中文一区在线播放| 亚洲国产精品久久人人爱| 九九精品一区二区| 91在线小视频| 日韩视频在线你懂得| 国产精品久久国产精麻豆99网站| 一区二区三区不卡在线观看 | 亚洲成av人影院在线观看网| 久久不见久久见免费视频1| 丁香五精品蜜臀久久久久99网站| 91精品1区2区| 欧美mv日韩mv| 亚洲精品国产视频| 国产自产v一区二区三区c| 一本一本久久a久久精品综合麻豆| 欧美人妖巨大在线| 国产精品久久久久影院| 天堂午夜影视日韩欧美一区二区| 国产精品99久久久久| 欧美日韩另类一区| 国产精品久久一级| 麻豆成人av在线| 欧美在线综合视频| 国产精品区一区二区三| 久久综合综合久久综合| 欧美亚洲禁片免费| 国产精品久久久久婷婷二区次| 青青草视频一区| 欧美在线999| 亚洲欧洲日本在线| 国产主播一区二区| 日韩一卡二卡三卡四卡| 洋洋av久久久久久久一区| 成人性生交大合| 26uuu国产在线精品一区二区| 亚洲午夜国产一区99re久久| 不卡视频免费播放| 久久久久久免费毛片精品| 日本亚洲最大的色成网站www| 一本到一区二区三区| 国产精品久久久久久妇女6080| 国产伦理精品不卡| 欧美mv日韩mv| 久久99国产精品成人| 3751色影院一区二区三区| 亚洲免费视频中文字幕| 岛国av在线一区| 国产欧美一区二区精品仙草咪 | 成人美女在线视频| 久久精子c满五个校花| 精品一区二区在线看| 欧美精品三级日韩久久| 午夜久久久久久电影| 色爱区综合激月婷婷| 亚洲男女一区二区三区| 在线亚洲欧美专区二区|