📄 fsmqueue.c
字号:
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;
}
/***************************************************************************************************
*
*
File Data: 0 Offset Offset+Length End of File
| ! ! Length ! |
| +-------------------------|--------------------------|----------------------------+ |
+---> | | Append/Modify | | <---+
| | Operation in the | |
| | Write Queue | |
+-------------------------|--------------------------|----------------------------+
| |
CMD_MODIFY Off | |
+-----------+ | |
Case 1 -----> | Len | | |
+-----------+ | |
| |
Off | |
+-----------------+----------------+ |
Case 2 -----> | Length | |
+-----------------+----------------+ |
| |
Off | |
+-----------------+--------------------------+--------+
Case 3 -----> | Length |
+-----------------+--------------------------+--------+
| |
| Off |
| +---------------+ |
Case 4 -------------------------> | | Length | |
| +---------------+ |
| |
| Off |
| +---------------------+----------+
Case 5 -------------------------> | | Length |
| +---------------------+----------+
| |
| | Off
| | +-----------+
Case 6 ---------------------------+--------------------------+---> | Len |
| | +-----------+
****************************************************************************************************/
/* UPDATE DATA TO EXISTED APPEND ITEMS */
CurP = FsmWriteQueue.FirstP->NextP;
tempDataP = DataP;
CopyDataCnt = 0;
for ( ; ((CurP != NULL) && (length > 0)); CurP = CurP->NextP)
{
if ((CurP->type != type) || (CurP->ItemFd.fd != fd))
continue;
if (CurP->cmd != CMD_APPEND)
continue;
if ((offset + length) <= CurP->offset)
{
/* It is the Case 1 as shown above. */
break;
}
else if ((offset < CurP->offset)) /* MUST NOT use <=, the following should be executed only once. */
{
#if 0
if (NewP->offset == offset) /* To ensure it is the first time of running. */
NewP->length = CurP->offset - offset;
#endif
if ((offset + length) <= (CurP->offset + CurP->length))
{
/* It is the Case 2 as shown above. */
uint32 copy_len;
copy_len = offset + length - CurP->offset;
FsmMemoryMove((uint8 *)(CurP + 1), tempDataP + CurP->offset - offset, copy_len);
length -= copy_len;
CopyDataCnt += copy_len;
break;
}
else /* ((offset + length) > (CurP->offset + CurP->length)) */
{
/* It is the Case 3 as shown above. */
FsmMemoryMove((uint8 *)(CurP + 1), tempDataP + CurP->offset - offset, CurP->length);
tempDataP += CurP->offset + CurP->length - offset;
length = (offset + length) - (CurP->offset + CurP->length);
offset = CurP->offset + CurP->length; /* Now offset will be equal to offset of the next Append operation. */
CopyDataCnt += CurP->length;
continue; /* There must be another Append operations in the write queue. */
}
}
else if (offset < (CurP->offset + CurP->length))
{
#if 0
if (NewP->offset == offset) /* To ensure it is not from Case 3. */
NewP->length = 0;
#endif
if ((offset + length) <= (CurP->offset + CurP->length))
{
/* It is the Case 4 as shown above. */
FsmMemoryMove(((uint8 *)(CurP + 1)) + (offset - CurP->offset), tempDataP, length);
CopyDataCnt += length;
length = 0;
break;
}
else
{
/* It is the Case 5 as shown above. */
uint32 copy_len;
copy_len = CurP->offset + CurP->length - offset;
FsmMemoryMove(((uint8 *)(CurP + 1)) + (offset - CurP->offset), tempDataP, copy_len);
tempDataP += copy_len;
offset += copy_len;
length -= copy_len;
CopyDataCnt += copy_len;
continue; /* There must be another Append operations in the write queue. */
}
}
else
{
/* It is the Case 6 as shown above. */
}
}
#if 1
NewP->length -= CopyDataCnt;
#endif
length = NewP->length;
offset = NewP->offset;
/* update data to existed modify items. */
PrevP = FsmWriteQueue.FirstP;
CurP = PrevP->NextP;
for ( ; ((CurP != NULL) && (length > 0)); PrevP = CurP, CurP = CurP->NextP)
{
if (CurP->type != type || CurP->ItemFd.fd != fd)
continue;
if (CurP->cmd != CMD_MODIFY)
continue;
if ((CurP->offset <= offset) &&
((CurP->offset + CurP->length) >= (offset + length)))
{
/* It is the Case 4 as shown above. */
FsmMemoryMove(((uint8 *)(CurP + 1)) + (offset - CurP->offset), DataP, length);
length = 0;
break;
}
else if (CurP->offset >= offset &&
(CurP->offset + CurP->length) <= (offset + length))
{
/* It is the Case 3 as shown above. */
/* Free current item from queue. */
#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;
FsmWriteQueue.AccumCnt -= ACCUM_CNT_MODIFY;
continue;
}
else if (CurP->offset > offset &&
CurP->offset < (offset + length) &&
(CurP->offset + CurP->length) > (offset + length))
{
/* It is the Case 2 as shown above. */
FsmMemoryMove((uint8 *)(CurP + 1),
DataP + (CurP->offset - offset),
offset + length - CurP->offset);
length = CurP->offset - offset;
}
else if (CurP->offset < offset &&
offset < (CurP->offset + CurP->length) &&
(CurP->offset + CurP->length) < (offset + length))
{
/* It is the Case 5 as shown above. */
uint32 copy_len;
copy_len = CurP->offset + CurP->length - offset;
FsmMemoryMove(((uint8 *)(CurP + 1)) + (offset - CurP->offset),
DataP,
copy_len);
length -= copy_len;
DataP += copy_len;
offset += copy_len;
}
else
{
/* Here are Case 1 and Case 6 as shown above. */
}
}
if (length > 0)
{
/* if (NewP->length > length) */
if (NewP->offset != offset)
{
FsmMemoryMove((uint8 *)(NewP + 1), DataP, length);
}
NewP->length = length;
NewP->offset = 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 */
FsmWriteQueue.LastP->NextP = NewP;
FsmWriteQueue.LastP = NewP;
}
else
{
FsmFree((void *)NewP);
FsmWriteQueue.AccumCnt -= ACCUM_CNT_MODIFY;
}
break;
}
/* UNLOCK QUEUE */
FsmReleaseMtxSem(FsmWriteQueue.QueueMtxLock);
return ERR_NONE;
}
/*#############################################################################
### QueueAddFileDir
###
### DESCRIPTION:
### This function inserts a queue item whose type is file or dir
### into the queue. This function allocates memory for queue
### item structure and data object.
### PARAMETERS:
### IN:
### cmd Operation command.
### It may be the following value:
### CMD_CREATE : Create a file
### CMD_MKDIR : Make a directory
### CMD_MODIFY : Modify a file
### CMD_APPEND : Append a file
### CMD_TRUNCATE : Truncate a file
### CMD_DELETE : Delete a file
### CMD_RMDIR : Remove a directory
### CMD_RENAME : Rename a file or a directory
### fd File descriptor.
### offset the number of offset bytes
### from the beginning of file contents
### to current operation position.
### DataP Points to data object to store data.
### length Byte size of data object.
###
### OUT:
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
### ERR_MEMORY
### ERR_PARAM
###
*/
uint32 QueueAddFileDir(
uint8 cmd,
uint32 fd,
uint32 offset,
uint8 * DataP,
uint32 length
)
{
uint32 SectorSize;
FsmDfsFileDescriptorT * FdP;
if ((cmd != CMD_CREATE)
&& (cmd != CMD_MKDIR)
&& (cmd != CMD_APPEND)
&& (cmd != CMD_DELETE)
&& (cmd != CMD_RMDIR)
&& (cmd != CMD_RENAME)
&& (cmd != CMD_MODIFY)
&& (cmd != CMD_TRUNCATE))
{
return ERR_PARAM;
}
FdP = &FsmDfsFds[fd];
SectorSize = ((FsmFlashMediaT*)FdP->FdHdr.DevObjP->MediaObjP)->SectorSize;
return QueueAdd(
QUEUE_FILE_DIR,
cmd,
fd,
offset,
DataP,
length,
SectorSize);
}
/*#############################################################################
### QueueAddDataItem
###
### DESCRIPTION:
### This function inserts a queue item whose type is data item
### into the queue. This function allocates memory for queue
### item structure and data object.
###
### PARAMETERS:
### IN:
### cmd Operation command.
### It may be the following value:
### CMD_CREATE : Create a data item
### CMD_MODIFY : Modify a data item
### CMD_APPEND : Append a data item
### CMD_DELETE : Delete a data item
### ItemType data item type;
### ItemId data item id;
### offset the number of offset bytes
### from the beginning of data item contents
### to current operation position.
### DataP Points to data object to store data.
### length Byte size of data object.
###
### OUT:
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
### ERR_MEMORY
### ERR_PARAM
###
*/
uint32 QueueAddDataItem(
uint8 cmd,
uint16 ItemType,
uint16 ItemId,
uint32 offset,
uint8 * DataP,
uint32 length
)
{
uint32 SectorSize;
FsmItemFdT itemfd;
itemfd.Item.ItemType = ItemType;
itemfd.Item.ItemId = ItemId;
if ((cmd != CMD_CREATE)
&& (cmd != CMD_APPEND)
&& (cmd != CMD_DELETE)
&& (cmd != CMD_MODIFY))
{
return ERR_PARAM;
}
SectorSize = ((FsmFlashMediaT*)(FsmDataItemDevObjP->MediaObjP))->SectorSize;
return QueueAdd(
QUEUE_DATA_ITEM,
cmd,
itemfd.fd,
offset,
DataP,
length,
SectorSize);
}
/*#############################################################################
### QueuePeek
###
### DESCRIPTION:
### Gets address of the first queue item.
###
### PARAMETERS:
### IN:
### QueueItemPP Points to address of the first queue item.
###
### OUT:
### QueueItemPP Points to address of the first queue item.
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
###
*/
uint32 QueuePeek(FsmQueueItemT ** QueueItemPP)
{
uint32 ret;
if (QueueCreated == 0)
return ERR_INIT;
ret = FsmGetBinSem(FsmWriteQueue.SyncLock);
if (ret != ERR_NONE)
{
return ret;
}
ret = FsmGetMtxSem(FsmWriteQueue.QueueMtxLock);
if (ret != ERR_NONE)
{
return ret;
}
*QueueItemPP = FsmWriteQueue.FirstP;
FsmReleaseMtxSem(FsmWriteQueue.QueueMtxLock);
FsmReleaseBinSem(FsmWriteQueue.SyncLock);
if (*QueueItemPP == NULL)
{
return ERR_SYSTEM;
}
return ERR_NONE;
}
/*#############################################################################
### QueueDel
###
### DESCRIPTION:
### Delete the first item of the queue.
###
### PARAMETERS:
### IN:
###
### OUT:
###
### RETURNS:
### Returns the following errors codes:
### ERR_NONE
### ERR_SYSTEM
###
*/
uint32 QueueDel()
{
uint32 ret;
uint32 SectorSize;
FsmQueueItemT * CurP;
FsmDevObjHdrT * DevP;
FsmDfsFileDescriptorT * FdP;
if (QueueCreated == 0)
return ERR_INIT;
ret = FsmGetMtxSem(FsmWriteQueue.QueueMtxLock);
if (ret != ERR_NONE)
{
return ret;
}
if (FsmWriteQueue.FirstP != NULL)
{
/* Dequeue the first Item. */
CurP = FsmWriteQueue.FirstP;
FsmWriteQueue.FirstP = CurP->NextP;
CurP->NextP = NULL;
if (FsmWriteQueue.FirstP == NULL)
{
#ifdef DEBUG_FSM
/* If the tail item has already been dequeued, fails this function. */
if ((FsmWriteQueue.LastP == NULL) || (FsmWriteQueue.LastP != CurP))
{
if (CurP->SemEvent != NULL)
{
FsmReleaseBinSem(CurP->SemEvent);
}
FsmFree((void *)CurP);
MonPrintf("\nOops, there is a bug in Queue module!");
return ERR_SYSTEM; /* ERROR */
}
#endif /* DEBUG_FSM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -