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

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? buffer.c

?? 從大量的wince源代碼中剝離出的fat文件系統(tǒng)源代碼。移植性非常高。 微軟的代碼
?? 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;

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
色综合一个色综合亚洲| 91久久香蕉国产日韩欧美9色| 国产精品成人在线观看| 欧美日韩一区不卡| 成人午夜激情片| 天使萌一区二区三区免费观看| 国产欧美精品一区二区三区四区| 欧美午夜一区二区三区| 国产suv一区二区三区88区| 日韩国产成人精品| 日韩一区中文字幕| 久久网这里都是精品| 在线观看欧美日本| 成人免费av网站| 激情五月激情综合网| 日欧美一区二区| 一区二区在线观看av| 国产日韩欧美一区二区三区乱码| 91精品国产综合久久久蜜臀粉嫩 | 寂寞少妇一区二区三区| 亚洲一区二区黄色| 国产精品国产三级国产普通话三级| 日韩欧美一级片| 欧美片在线播放| 91黄视频在线观看| 91尤物视频在线观看| 福利电影一区二区三区| 激情文学综合网| 日韩av网站免费在线| 天天综合天天综合色| 亚洲国产aⅴ成人精品无吗| 日韩久久一区二区| 国产精品久久久久精k8| 久久久精品日韩欧美| 欧美不卡一区二区| 欧美v日韩v国产v| 日韩女优制服丝袜电影| 欧美一区二区三区婷婷月色| 欧美美女直播网站| 欧美日韩国产欧美日美国产精品| 欧洲视频一区二区| 欧美性生活一区| 欧美伊人久久久久久午夜久久久久| 26uuu色噜噜精品一区二区| 777久久久精品| 在线观看91av| 日韩一级二级三级| 日韩欧美不卡在线观看视频| 精品国产成人系列| 国产偷国产偷精品高清尤物| 国产欧美一区二区三区沐欲 | 亚洲第一成年网| 日韩在线观看一区二区| 免费日韩伦理电影| 极品尤物av久久免费看| 国产乱人伦偷精品视频不卡| 国产91丝袜在线播放九色| 成人丝袜高跟foot| 91丨porny丨蝌蚪视频| 91久久国产最好的精华液| 欧美性感一区二区三区| 欧美一级一级性生活免费录像| 欧美一区二区三区喷汁尤物| 欧美大尺度电影在线| 国产午夜三级一区二区三| 中文字幕日本不卡| 亚洲午夜电影网| 老汉av免费一区二区三区| 国产精品资源在线| 972aa.com艺术欧美| 欧美日韩精品一区二区三区四区| 日韩欧美的一区二区| 国产欧美综合色| 亚洲国产综合色| 激情文学综合网| 色综合久久久久网| 日韩视频在线一区二区| 中文无字幕一区二区三区| 一区二区三区日韩在线观看| 美国毛片一区二区三区| 成人毛片老司机大片| 欧美剧在线免费观看网站| 亚洲精品一区二区三区在线观看 | 亚洲另类春色校园小说| 日韩二区三区在线观看| 成人深夜在线观看| 欧美午夜宅男影院| 国产偷国产偷亚洲高清人白洁 | 免费高清在线一区| 高清在线不卡av| 欧美巨大另类极品videosbest | 日韩欧美久久一区| 亚洲日穴在线视频| 精品综合久久久久久8888| 91麻豆123| 26uuu成人网一区二区三区| 亚洲嫩草精品久久| 国产中文一区二区三区| 欧美日韩精品专区| 国产精品二区一区二区aⅴ污介绍| 天堂av在线一区| 93久久精品日日躁夜夜躁欧美| 欧美一区欧美二区| 亚洲综合在线五月| 国产.欧美.日韩| 日韩欧美区一区二| 亚洲国产日韩综合久久精品| 成人免费观看视频| 久久亚洲精品小早川怜子| 丝袜美腿亚洲一区| 色天使色偷偷av一区二区| 久久精品视频免费观看| 日韩主播视频在线| 在线亚洲欧美专区二区| 国产嫩草影院久久久久| 久久 天天综合| 欧美蜜桃一区二区三区| 亚洲图片你懂的| 成人性生交大片免费看中文网站| 欧美一区二区三区婷婷月色| 亚欧色一区w666天堂| 91国产丝袜在线播放| 中文字幕亚洲成人| 成人国产亚洲欧美成人综合网| 久久久久国产精品麻豆ai换脸| 久久精品99国产精品| 在线播放/欧美激情| 亚洲18女电影在线观看| 欧美伊人精品成人久久综合97| 国产精品不卡一区二区三区| 成人毛片老司机大片| 亚洲国产经典视频| 大白屁股一区二区视频| 国产欧美在线观看一区| 欧美午夜一区二区三区免费大片| 亚洲免费av观看| caoporn国产精品| 国产精品灌醉下药二区| 99久久婷婷国产综合精品电影| 国产精品久久毛片av大全日韩| 国产成人精品一区二| 国产日产欧美一区二区三区 | 毛片一区二区三区| 日韩欧美亚洲一区二区| 久久99精品一区二区三区| 欧美本精品男人aⅴ天堂| 美国欧美日韩国产在线播放| 欧美岛国在线观看| 国产精品99久久久| 国产精品乱码人人做人人爱| 99国产麻豆精品| 亚洲激情男女视频| 欧美午夜精品久久久久久超碰| 亚洲狠狠爱一区二区三区| 在线电影院国产精品| 久久99国产精品久久| 中文字幕精品一区二区精品绿巨人 | 一卡二卡三卡日韩欧美| 欧美日韩国产影片| 蜜桃av一区二区| 久久久久久免费毛片精品| 国产69精品久久久久毛片| 国产精品的网站| 欧美三级资源在线| 蜜臀av一区二区在线观看| 欧美精品一区二区在线播放 | 67194成人在线观看| 日本vs亚洲vs韩国一区三区二区| 精品国产免费视频| 99久久免费视频.com| 午夜精彩视频在线观看不卡| 精品人在线二区三区| 白白色 亚洲乱淫| 亚洲成人资源在线| 26uuu国产电影一区二区| 色哟哟一区二区| 91猫先生在线| 奇米色一区二区| 国产精品久久影院| 日韩一区二区视频在线观看| 国产精品夜夜嗨| 一区二区日韩电影| 精品国产伦一区二区三区观看方式| kk眼镜猥琐国模调教系列一区二区| 亚洲在线免费播放| 久久久激情视频| 欧美日韩精品福利| 国产白丝网站精品污在线入口| 亚洲mv大片欧洲mv大片精品| 久久九九影视网| 欧美三电影在线| 成人网男人的天堂| 美女免费视频一区| 一区二区激情小说| 国产午夜亚洲精品羞羞网站| 91.麻豆视频| 一本久久精品一区二区| 国产一区二区免费在线| 亚洲成av人综合在线观看| 国产精品乱码妇女bbbb|