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

📄 qm.c

📁 NecluesRTX RTOS的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -