📄 os_pend_multi.c
字号:
/*
************************************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
* (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* PEND ON MULTIPLE OBJECTS
*
* File : OS_PEND_MULTI.C
* By : JJL
* Version : V3.02.00
*
* LICENSING TERMS:
* ---------------
* uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
* application/product. We provide ALL the source code for your convenience and to help you
* experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
* it commercially without paying a licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
************************************************************************************************************************
*/
#include <os.h>
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const CPU_CHAR *os_pend_multi__c = "$Id: $";
#endif
#if (((OS_CFG_Q_EN > 0u) || (OS_CFG_SEM_EN > 0u)) && (OS_CFG_PEND_MULTI_EN > 0u))
/*
************************************************************************************************************************
* PEND ON MULTIPLE OBJECTS
*
* Description: This function pends on multiple objects. The objects pended on MUST be either semaphores or message
* queues. If multiple objects are ready at the start of the pend call, then all available objects that
* are ready will be indicated to the caller. If the task must pend on the multiple events then, as soon
* as one of the object is either posted, aborted or deleted, the task will be readied.
*
* This function only allows you to pend on semaphores and/or message queues.
*
* Arguments : p_pend_data_tbl is a pointer to an array of type OS_PEND_DATA which contains a list of all the
* objects we will be waiting on. The caller must declare an array of OS_PEND_DATA
* and initialize the .PendObjPtr (see below) with a pointer to the object (semaphore or
* message queue) to pend on.
*
* OS_PEND_DATA MyPendArray[?];
*
* The OS_PEND_DATA field are as follows:
*
* OS_PEND_DATA *PrevPtr; Used to link OS_PEND_DATA objects
* OS_PEND_DATA *NextPtr; Used to link OS_PEND_DATA objects
* OS_TCB *TCBPtr; Pointer to the TCB that is pending on multiple objects
* > OS_PEND_OBJ *PendObjPtr; USER supplied field which is a pointer to the
* semaphore or message queue you want to pend on. When
* you call OSPendMulti() you MUST fill this field for
* each of the objects you want to pend on.
* OS_PEND_OBJ *RdyObjPtr; OSPendMulti() will return the object that was posted,
* aborted or deleted in this field.
* void *RdyMsgPtr; OSPendMulti() will fill in this field if the object
* posted was a message queue. This corresponds to the
* message posted.
* OS_MSG_SIZE RdyMsgSize; OSPendMulti() will fill in this field if the object
* posted was a message queue. This corresponds to the
* size of the message posted.
* CPU_TS RdyTS; OSPendMulti() will fill in this field if the object
* was a message queue. This corresponds to the time
* stamp when the message was posted. However, if the
* object is a semaphore and the object is already ready
* the this field will be set to (CPU_TS)0 because it's
* not possible to know when the semaphore was posted.
*
* tbl_size is the size (in number of elements) of the OS_PEND_DATA array passed to this function. In
* other words, if the called needs to pend on 4 separate objects (semaphores and/or queues)
* then you would pass 4 to this call.
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait any of
* the objects up to the amount of time specified by this argument. If you specify 0, however,
* your task will wait forever for the specified objects or, until an object is posted,
* aborted or deleted.
*
* opt determines whether the user wants to block if none of the objects are available.
*
* OS_OPT_PEND_BLOCKING
* OS_OPT_PEND_NON_BLOCKING
*
* p_err is a pointer to where an error message will be deposited. Possible error messages are:
*
* OS_ERR_NONE The call was successful and your task owns the resources or,
* the objects you are waiting for occurred. Check the .RdyObjPtr
* fields to know which objects have been posted.
* OS_ERR_OBJ_TYPE If any of the .PendPtr is NOT a semaphore or a message queue
* OS_ERR_OPT_INVALID If you specified an invalid option for 'opt'
* OS_ERR_PEND_ABORT The wait on the events was aborted; check the .RdyObjPtr fields
* for which objects were aborted.
* OS_ERR_PEND_DEL The wait on the events was aborted; check the .RdyObjPtr fields
* for which objects were aborted.
* OS_ERR_PEND_ISR If you called this function from an ISR
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked.
* OS_ERR_PEND_WOULD_BLOCK If the caller didn't want to block and no object ready
* OS_ERR_STATUS_INVALID Invalid pend status
* OS_ERR_PTR_INVALID If you passes a NULL pointer of 'p_pend_data_tbl'
* OS_ERR_TIMEOUT The objects were not posted within the specified 'timeout'.
*
* Returns : > 0 the number of objects returned as ready, aborted or deleted
* == 0 if no events are returned as ready because of timeout or upon error.
************************************************************************************************************************
*/
/*$PAGE*/
OS_OBJ_QTY OSPendMulti (OS_PEND_DATA *p_pend_data_tbl,
OS_OBJ_QTY tbl_size,
OS_TICK timeout,
OS_OPT opt,
OS_ERR *p_err)
{
CPU_BOOLEAN valid;
OS_OBJ_QTY nbr_obj_rdy;
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_OBJ_QTY)0);
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend from an ISR */
*p_err = OS_ERR_PEND_ISR;
return ((OS_OBJ_QTY)0);
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u
if (p_pend_data_tbl == (OS_PEND_DATA *)0) { /* Validate 'p_pend_data_tbl' */
*p_err = OS_ERR_PTR_INVALID;
return ((OS_OBJ_QTY)0);
}
if (tbl_size == (OS_OBJ_QTY)0) { /* Array size must be > 0 */
*p_err = OS_ERR_PTR_INVALID;
return ((OS_OBJ_QTY)0);
}
switch (opt) {
case OS_OPT_PEND_BLOCKING:
case OS_OPT_PEND_NON_BLOCKING:
break;
default:
*p_err = OS_ERR_OPT_INVALID;
return ((OS_OBJ_QTY)0);
}
#endif
valid = OS_PendMultiValidate(p_pend_data_tbl, /* -------- Validate objects to be OS_SEM or OS_Q ------- */
tbl_size);
if (valid == DEF_FALSE) {
*p_err = OS_ERR_OBJ_TYPE; /* Invalid, not OS_SEM or OS_Q */
return ((OS_OBJ_QTY)0);
}
/*$PAGE*/
CPU_CRITICAL_ENTER();
nbr_obj_rdy = OS_PendMultiGetRdy(p_pend_data_tbl, /* --------- SEE IF OBJECT(s) HAVE BEEN POSTED ---------- */
tbl_size);
if (nbr_obj_rdy > (OS_OBJ_QTY)0) {
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_NONE;
return ((OS_OBJ_QTY)nbr_obj_rdy);
}
if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
return ((OS_OBJ_QTY)0);
} else {
if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
CPU_CRITICAL_EXIT();
*p_err = OS_ERR_SCHED_LOCKED;
return ((OS_OBJ_QTY)0);
}
}
OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
/* ------ NO OBJECT READY, PEND ON MULTIPLE OBJECTS ----- */
OS_PendMultiWait(p_pend_data_tbl, /* Suspend task until object posted or timeout occurs */
tbl_size,
timeout);
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); /* Find next highest priority task ready */
CPU_CRITICAL_ENTER();
switch (OSTCBCurPtr->PendStatus) {
case OS_STATUS_PEND_OK: /* We got one of the objects posted to */
*p_err = OS_ERR_NONE;
break;
case OS_STATUS_PEND_ABORT: /* Indicate that the multi-pend was aborted */
*p_err = OS_ERR_PEND_ABORT;
break;
case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
*p_err = OS_ERR_TIMEOUT;
break;
case OS_STATUS_PEND_DEL: /* Indicate that an object pended on has been deleted */
*p_err = OS_ERR_OBJ_DEL;
break;
default:
*p_err = OS_ERR_STATUS_INVALID;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -