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

📄 fsmqueue.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 
  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 + -