📄 fsmqueue.c
字号:
/*****************************************************************************
FILE NAME: FsmQueue.c
DESCRIPTION:
Implement write queue services for Data File System.
Copyright (c) 2002, VIA Technologies, Inc.
*****************************************************************************/
#include "fsmdefs.h"
#include "ostype.h"
#include "fsmdfs.h"
#include "FsmQueue.h"
/*******************************************
*
* The following structure is used for
* Write Queue.
*
*******************************************/
typedef /*PACKED*/ struct
{
HBSEM SyncLock; /* TRUE WHEN AN ITEM IS IN QUEUE */
HBSEM WaitQueueEmptyLock;
HMSEM QueueMtxLock; /* ACCESS QUEUE MUTUALLY EXCLUSIVELY */
uint32 AccumCnt;
/* these two fields are used to replace AccumCnt field in future. */
/* uint32 FreeCnt; */
/* uint32 DirtyCnt; */
FsmQueueItemT * FirstP;
FsmQueueItemT * LastP;
} FsmWriteQueueT;
/* Global Variable */
static FsmWriteQueueT FsmWriteQueue;
static uint8 QueueCreated = 0;
extern FsmDevObjHdrT * FsmDataItemDevObjP;
extern FsmDfsFileDescriptorT FsmDfsFds[];
/*#############################################################################
### GetAccumSize
###
### DESCRIPTION:
### Get the number of sectors that items in queue take up in flash.
###
### PARAMETERS:
### IN:
### CntP Points to the number of sectors
### that items in queue take up in flash.
###
### OUT:
### CntP Points to the number of sectors
### that items in queue take up in flash.
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
###
*/
uint32 GetAccumSize(uint32 * CntP)
{
uint32 ret;
if (QueueCreated == 0)
return ERR_INIT;
ret = FsmGetMtxSem(FsmWriteQueue.QueueMtxLock);
if (ret != ERR_NONE)
{
return ret;
}
*CntP = FsmWriteQueue.AccumCnt;
FsmReleaseMtxSem(FsmWriteQueue.QueueMtxLock);
return ERR_NONE;
}
/*#############################################################################
### QueueCreate
###
### DESCRIPTION:
### This function allocates all resource for the queue,
### and initializes the queue.
###
### PARAMETERS:
### IN:
###
### OUT:
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
###
*/
uint32 QueueCreate()
{
if (QueueCreated != 0)
return ERR_NONE;
FsmWriteQueue.SyncLock = FsmCreateBinSem(0);
if (FsmWriteQueue.SyncLock == NULL)
{
return ERR_SYSTEM;
}
FsmWriteQueue.QueueMtxLock = FsmCreateMtxSem(1);
if (FsmWriteQueue.QueueMtxLock == NULL)
{
FsmDeleteBinSem(FsmWriteQueue.SyncLock);
return ERR_SYSTEM;
}
FsmWriteQueue.WaitQueueEmptyLock = FsmCreateBinSem(1);
if (FsmWriteQueue.WaitQueueEmptyLock == NULL)
{
FsmDeleteBinSem(FsmWriteQueue.SyncLock);
FsmDeleteMtxSem(FsmWriteQueue.QueueMtxLock);
return ERR_SYSTEM;
}
FsmWriteQueue.AccumCnt = ACCUM_START_VALUE;
FsmWriteQueue.FirstP = NULL;
FsmWriteQueue.LastP = NULL;
QueueCreated = 1; /* It is OK to use FsmWriteQueue; */
return ERR_NONE;
}
/*#############################################################################
### QueueDestroy
###
### DESCRIPTION:
### This function frees any resource allocated by the queue code.
###
### PARAMETERS:
### IN:
###
### OUT:
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
###
*/
uint32 QueueDestroy()
{
uint32 ret;
FsmQueueItemT * CurP;
HMSEM QueueMtxLock;
if (QueueCreated == 0)
return ERR_NONE;
ret = FsmGetMtxSem(FsmWriteQueue.QueueMtxLock);
if (ret != ERR_NONE)
{
return ret;
}
QueueCreated = 0;
while (FsmWriteQueue.FirstP != NULL)
{
CurP = FsmWriteQueue.FirstP;
FsmWriteQueue.FirstP = CurP->NextP;
CurP->NextP = NULL;
if (CurP->SemEvent != NULL)
{
FsmReleaseBinSem(CurP->SemEvent);
}
FsmFree((void *)CurP);
}
FsmWriteQueue.AccumCnt = 0;
FsmWriteQueue.FirstP = NULL;
FsmWriteQueue.LastP = NULL;
FsmDeleteBinSem(FsmWriteQueue.SyncLock);
FsmDeleteBinSem(FsmWriteQueue.WaitQueueEmptyLock);
FsmWriteQueue.SyncLock = NULL;
FsmWriteQueue.WaitQueueEmptyLock = NULL;
QueueMtxLock = FsmWriteQueue.QueueMtxLock;
FsmWriteQueue.QueueMtxLock = NULL;
FsmReleaseMtxSem(QueueMtxLock); /* Is it necessary? */
FsmDeleteMtxSem(QueueMtxLock);
return ERR_NONE;
}
uint32 QueueAdd(
uint8 type,
uint8 cmd,
uint32 fd,
uint32 offset,
uint8 * DataP,
uint32 length,
uint32 SectorSize
)
{
uint32 ret;
uint8 * tempDataP;
uint32 Enqueue;
uint32 CopyDataCnt;
FsmQueueItemT * PrevP;
FsmQueueItemT * CurP;
FsmQueueItemT * NewP;
if (QueueCreated == 0)
return ERR_INIT;
if (cmd == CMD_APPEND || cmd == CMD_MODIFY)
{
if (length == 0)
{
return ERR_NONE;
}
}
/* ALLOCATE AND INITIALIZE AN ITEM */
NewP = (FsmQueueItemT *)FsmMalloc(sizeof(FsmQueueItemT) + length);
if (NewP == NULL)
{
return ERR_MEMORY;
}
NewP->NextP = NULL;
NewP->type = type;
NewP->cmd = cmd;
NewP->ItemFd.fd = fd;
NewP->offset = offset;
NewP->SemEvent = 0;
NewP->length = length;
/* LOCK QUEUE */
ret = FsmGetMtxSem(FsmWriteQueue.QueueMtxLock);
if (ret != ERR_NONE)
{
return ret;
}
/* increment accumulated count */
switch (cmd)
{
case CMD_CREATE:
NewP->length = 0;
FsmWriteQueue.AccumCnt += ACCUM_CNT_CREATE;
break;
case CMD_MKDIR:
NewP->length = 0;
FsmWriteQueue.AccumCnt += ACCUM_CNT_MKDIR;
break;
case CMD_APPEND:
FsmWriteQueue.AccumCnt += ACCUM_CNT_APPEND(offset, length, SectorSize);
break;
case CMD_DELETE:
NewP->length = 0;
FsmWriteQueue.AccumCnt += ACCUM_CNT_DELETE;
break;
case CMD_RMDIR:
NewP->length = 0;
FsmWriteQueue.AccumCnt += ACCUM_CNT_RMDIR;
break;
case CMD_RENAME:
FsmWriteQueue.AccumCnt += ACCUM_CNT_RENAME;
break;
case CMD_MODIFY:
FsmWriteQueue.AccumCnt += ACCUM_CNT_MODIFY;
break;
case CMD_TRUNCATE:
NewP->length = 0;
FsmWriteQueue.AccumCnt += ACCUM_CNT_TRUNCATE;
break;
}
if (NewP->length > 0)
{
FsmMemoryMove((uint8 *)(NewP + 1), DataP, NewP->length);
}
switch (cmd)
{
case CMD_APPEND:
case CMD_CREATE:
case CMD_MKDIR:
case CMD_DELETE:
case CMD_RMDIR:
case CMD_RENAME:
/* append an item */
if (FsmWriteQueue.FirstP != NULL)
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP == NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.LastP->NextP = NewP;
FsmWriteQueue.LastP = NewP;
}
else
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP != NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.FirstP = NewP;
FsmWriteQueue.LastP = NewP;
FsmReleaseBinSem(FsmWriteQueue.SyncLock);
}
break;
case CMD_TRUNCATE:
if (FsmWriteQueue.FirstP == NULL)
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP != NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.FirstP = NewP;
FsmWriteQueue.LastP = NewP;
FsmReleaseBinSem(FsmWriteQueue.SyncLock);
break;
}
if (FsmWriteQueue.FirstP->NextP == NULL)
{
#ifdef DEBUG_FSM
if ((FsmWriteQueue.LastP == NULL) || (FsmWriteQueue.FirstP != FsmWriteQueue.LastP))
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.FirstP->NextP = NewP;
FsmWriteQueue.LastP->NextP = NewP;
FsmWriteQueue.LastP = NewP;
break;
}
PrevP = FsmWriteQueue.FirstP;
CurP = PrevP->NextP;
for (Enqueue = 1; CurP != NULL; PrevP = CurP, CurP = CurP->NextP)
{
if ((CurP->type != type) || (CurP->ItemFd.fd != fd))
continue;
if (CurP->cmd == CMD_TRUNCATE)
{
if (offset < CurP->offset)
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP == NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
/* Dequeue current item. */
PrevP->NextP = CurP->NextP;
if (FsmWriteQueue.LastP == CurP)
{
FsmWriteQueue.LastP = PrevP;
}
/*
* This IF may be superfluous.
* Foreground API will forbid this
* NewP operation to enter queue.
*/
if (CurP->SemEvent != NULL)
{
FsmReleaseBinSem(CurP->SemEvent);
}
FsmFree((void *)CurP);
FsmWriteQueue.AccumCnt -= ACCUM_CNT_TRUNCATE;
CurP = PrevP;
}
continue;
}
if (CurP->cmd == CMD_APPEND && CurP->offset <= offset)
{
Enqueue = 0;
}
if (CurP->cmd == CMD_MODIFY || CurP->cmd == CMD_APPEND)
{
if (offset <= CurP->offset)
{
if (CurP->cmd == CMD_MODIFY)
FsmWriteQueue.AccumCnt -= ACCUM_CNT_MODIFY;
else
FsmWriteQueue.AccumCnt -= ACCUM_CNT_APPEND(CurP->offset, CurP->length, SectorSize);
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP == NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
/* Dequeue current item. */
PrevP->NextP = CurP->NextP;
if (FsmWriteQueue.LastP == CurP)
{
FsmWriteQueue.LastP = PrevP;
}
/*
* This IF may be superfluous.
* Foreground API will forbid this
* NewP operation to enter queue.
*/
if (CurP->SemEvent != NULL)
{
FsmReleaseBinSem(CurP->SemEvent);
}
FsmFree((void *)CurP);
CurP = PrevP;
continue;
}
else if (offset < (CurP->offset + CurP->length))
{
if (CurP->cmd == CMD_APPEND)
FsmWriteQueue.AccumCnt -= ACCUM_CNT_APPEND(CurP->offset, CurP->length, SectorSize);
CurP->length = offset - CurP->offset;
if (CurP->cmd == CMD_APPEND)
FsmWriteQueue.AccumCnt += ACCUM_CNT_APPEND(CurP->offset, CurP->length, SectorSize);
}
}
}
if (Enqueue)
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP == NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.LastP->NextP = NewP;
FsmWriteQueue.LastP = NewP;
}
else
{
FsmFree((void *)NewP);
FsmWriteQueue.AccumCnt -= ACCUM_CNT_TRUNCATE;
}
break;
case CMD_MODIFY:
if (FsmWriteQueue.FirstP == NULL)
{
#ifdef DEBUG_FSM
if (FsmWriteQueue.LastP != NULL)
{
FsmFree((void *)NewP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
FsmWriteQueue.FirstP = NewP;
FsmWriteQueue.LastP = NewP;
FsmReleaseBinSem(FsmWriteQueue.SyncLock);
break;
}
if (FsmWriteQueue.FirstP->NextP == NULL)
{
#ifdef DEBUG_FSM
if ((FsmWriteQueue.LastP == NULL) || (FsmWriteQueue.FirstP != FsmWriteQueue.LastP))
{
FsmFree((void *)NewP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -