📄 qm.c
字号:
if (QCB_ptr -> qm_queue_front == QCB_ptr -> qm_queue_back)
{
/* Mark this queue as full. */
QCB_ptr -> qm_queue_full = NU_TRUE;
}
}
else
{
/* Return an appropriate status. */
status = NU_QUEUE_FULL;
}
/* Return the status to the caller. */
return(status);
} /* end of QM_Place_Item */
/************************************************************************/
/* */
/* FUNCTION "QM_Force_Item_In_Front" */
/* */
/* */
/* DESCRIPTION */
/* */
/* This function forces an item into the front position of the */
/* specified queue. If the queue is full, the last item in the */
/* queue is slicked. */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Accelerated Technology */
/* */
/* CALLED FROM */
/* */
/* Service routines that request forced queue items */
/* */
/* ROUTINES CALLED */
/* */
/* QM_Remove_From_List Remove from queue empty list*/
/* SKP_Ready_Task Place the task on ready lst */
/* SKD_Leave_Task Leave the task if necessary */
/* */
/* INPUTS */
/* */
/* queue_id Queue_identification */
/* source_ptr Pointer to source item */
/* */
/* OUTPUTS */
/* */
/* return(status) */
/* */
/************************************************************************/
signed int QM_Force_Item_In_Front(signed int queue_id,
unsigned int *source_ptr)
{
struct QM_QUEUE_CONTROL_STRUCT
*QCB_ptr; /* Pointer to QCB entry */
struct QM_SUSPENSION_STRUCT
*suspend_ptr; /* Suspension pointer */
unsigned int i; /* Working variable */
signed int task_id; /* Task id */
signed int status; /* Status of request */
unsigned int *destination_ptr; /* Pointer to destination */
/* Build a pointer to the queue control block. */
QCB_ptr = &QM_QCB_List[queue_id];
/* Yes there is room in the queue. Place the item before the current
front. */
status = NU_SUCCESS;
/* Check for task(s) suspended on an empty queue. */
if (QCB_ptr -> qm_empty_wait_head != NU_NULL)
{
/* Point to the queue suspend block. */
suspend_ptr = QCB_ptr -> qm_empty_wait_head;
/* Return the queue id. */
*(suspend_ptr -> qm_return_addr) = queue_id;
/* Copy the item from the source buffer into the waiting task's
buffer. */
for (i = 0; i < QCB_ptr -> qm_item_size; i++)
{
*(suspend_ptr -> qm_item_ptr++) = *(source_ptr++);
}
/* Get the task ID to wake up later. */
task_id = suspend_ptr -> qm_task_id;
/* Determine if the suspend is one of many or just one. */
if (suspend_ptr -> qm_susp_type == QM_SINGLE)
{
/* Single QCB. Remove it from the list. */
QM_Remove_From_List( &(QCB_ptr -> qm_empty_wait_head),
&(QCB_ptr -> qm_empty_wait_tail),
suspend_ptr);
}
else
{
/* Remove the suspend pointers from the suspend list. The
loop is necessary to remove suspend blocks in multiple
suspension on empty queues. Adjust the suspend pointer to
the first element of the suspend array for this task, which
was allocated off of this task's stack. */
suspend_ptr = suspend_ptr - suspend_ptr -> qm_susp_id;
for (i = 0; i < MAX_Q_SUSPENSIONS; i++)
{
/* Remove the suspend block, if it was associated with a
valid queue id. */
if (suspend_ptr -> qm_QCB_ptr != NU_NULL)
{
/* Remove it from the list. */
QM_Remove_From_List(
&((suspend_ptr -> qm_QCB_ptr) -> qm_empty_wait_head),
&((suspend_ptr -> qm_QCB_ptr) -> qm_empty_wait_tail),
suspend_ptr);
}
/* Position to the next suspend block. */
suspend_ptr++;
}
}
/* Lift the suspension on the task that was waiting to
for an item on the queue and context switch if necessary. */
if (SKP_Ready_Task(task_id))
{
/* Leave this task temporarily. */
SKD_Leave_Task();
}
}
else
{
/* Figure out where to place the forced item in the queue. */
/* Adjust the front of the queue and then add the item. */
if (QCB_ptr -> qm_queue_front > QCB_ptr -> qm_queue_start)
{
/* Decrement the front pointer. */
destination_ptr = QCB_ptr -> qm_queue_front -
QCB_ptr -> qm_item_size;
}
else
{
/* Put the front item to the back of the queue to handle
the wrap condition. */
destination_ptr = QCB_ptr -> qm_queue_end -
QCB_ptr -> qm_item_size;
}
/* Update the front of the queue pointer. */
QCB_ptr -> qm_queue_front = destination_ptr;
/* Check if we are under a queue full condition. */
if (QCB_ptr -> qm_queue_full)
{
/* Adjust the back of the queue to follow the front. */
QCB_ptr -> qm_queue_back = QCB_ptr -> qm_queue_front;
}
else
{
/* Increment the number of items queued. */
QCB_ptr -> qm_queued++;
}
/* Copy the item from the source buffer. */
for (i = 0; i < QCB_ptr -> qm_item_size; i++)
{
*(destination_ptr++) = *source_ptr++;
}
/* Check for a queue full condition. */
if (QCB_ptr -> qm_queue_items == QCB_ptr -> qm_queued)
{
/* Mark this queue as full. */
QCB_ptr -> qm_queue_full = NU_TRUE;
}
}
/* Return the status to the caller. */
return(status);
} /* end QM_Force_Item_In_Front */
/************************************************************************/
/* */
/* FUNCTION "QM_Wait_To_Place" */
/* */
/* */
/* DESCRIPTION */
/* */
/* This function suspends the task on the queue full list for */
/* the specified queue. */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Accelerated Technology */
/* */
/* CALLED FROM */
/* */
/* Service routines that wait to queue items */
/* */
/* ROUTINES CALLED */
/* */
/* QM_Place_On_List Place a suspend block on lst*/
/* QM_Remove_From_List Remove suspend block */
/* SKP_Suspend_Task Suspend the task */
/* */
/* INPUTS */
/* */
/* task_id Task identification */
/* queue_id Queue identification */
/* source_ptr Pointer to source item */
/* */
/* OUTPUTS */
/* */
/* return(status) */
/* */
/************************************************************************/
signed int QM_Wait_To_Place(signed int task_id, signed int queue_id,
unsigned int *source_ptr)
{
struct QM_QUEUE_CONTROL_STRUCT
*QCB_ptr; /* Pointer to QCB entry */
struct QM_SUSPENSION_STRUCT
suspend_block; /* Suspension control block */
signed int status; /* Status of request */
/* Build a pointer to the queue control block. */
QCB_ptr = &QM_QCB_List[queue_id];
/* Initialize the status variable as NU_QUEUE_TIMEOUT. */
status = NU_QUEUE_TIMEOUT;
/* Build the suspension block. */
suspend_block.qm_task_id = task_id;
suspend_block.qm_QCB_ptr = QCB_ptr;
suspend_block.qm_susp_id = 0;
suspend_block.qm_return_addr = &status;
suspend_block.qm_item_ptr = source_ptr;
suspend_block.qm_next_susp = NU_NULL;
suspend_block.qm_prev_susp = NU_NULL;
/* Place the suspend block on the queue full suspension for associated
queue. */
QM_Place_On_List(&(QCB_ptr -> qm_full_wait_head),
&(QCB_ptr -> qm_full_wait_tail),
&suspend_block);
/* Suspend the task. */
SKP_Suspend_Task(task_id, NU_QUEUE_SUSPEND);
/* Check to see if a timeout occurred. In this case the suspend block
is still part of the list, remove it! */
if (status == NU_QUEUE_TIMEOUT)
{
/* Remove the suspend block from the list. */
QM_Remove_From_List(&(QCB_ptr -> qm_full_wait_head),
&(QCB_ptr -> qm_full_wait_tail),
&suspend_block);
}
/* Return the status to the caller. */
return(status);
} /* end of QM_Wait_To_Place */
/************************************************************************/
/* */
/* FUNCTION "QM_Wait_To_Retrieve" */
/* */
/* */
/* DESCRIPTION */
/* */
/* This function suspends the task on the queue empty list for */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -