📄 os_mutex.c
字号:
/*
************************************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* MUTEX MANAGEMENT
*
* File : OS_MUTEX.C
* By : JJL
* Version : V3.03.01
*
* 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.
************************************************************************************************************************
*/
#define MICRIUM_SOURCE
#include <os.h>
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const CPU_CHAR *os_mutex__c = "$Id: $";
#endif
#if OS_CFG_MUTEX_EN > 0u
/*
************************************************************************************************************************
* CREATE A MUTEX
*
* Description: This function creates a mutex.
*
* Arguments : p_mutex is a pointer to the mutex to initialize. Your application is responsible for allocating
* storage for the mutex.
*
* p_name is a pointer to the name you would like to give the mutex.
*
* p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE if the call was successful
* OS_ERR_CREATE_ISR if you called this function from an ISR
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the Mutex after you called
* OSSafetyCriticalStart().
* OS_ERR_NAME if 'p_name' is a NULL pointer
* OS_ERR_OBJ_CREATED if the mutex has already been created
* OS_ERR_OBJ_PTR_NULL if 'p_mutex' is a NULL pointer
*
* Returns : none
************************************************************************************************************************
*/
void OSMutexCreate (OS_MUTEX *p_mutex,
CPU_CHAR *p_name,
OS_ERR *p_err)
{
CPU_SR_ALLOC();
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
return;
}
#endif
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
*p_err = OS_ERR_CREATE_ISR;
return;
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
*p_err = OS_ERR_OBJ_PTR_NULL;
return;
}
#endif
OS_CRITICAL_ENTER();
p_mutex->Type = OS_OBJ_TYPE_MUTEX; /* Mark the data structure as a mutex */
p_mutex->NamePtr = p_name;
p_mutex->OwnerTCBPtr = (OS_TCB *)0;
p_mutex->OwnerNestingCtr = (OS_NESTING_CTR)0; /* Mutex is available */
p_mutex->TS = (CPU_TS )0;
p_mutex->OwnerOriginalPrio = OS_CFG_PRIO_MAX;
OS_PendListInit(&p_mutex->PendList); /* Initialize the waiting list */
#if OS_CFG_DBG_EN > 0u
OS_MutexDbgListAdd(p_mutex);
#endif
OSMutexQty++;
OS_CRITICAL_EXIT_NO_SCHED();
*p_err = OS_ERR_NONE;
}
/*$PAGE*/
/*
************************************************************************************************************************
* DELETE A MUTEX
*
* Description: This function deletes a mutex and readies all tasks pending on the mutex.
*
* Arguments : p_mutex is a pointer to the mutex to delete
*
* opt determines delete options as follows:
*
* OS_OPT_DEL_NO_PEND Delete mutex ONLY if no task pending
* OS_OPT_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE The call was successful and the mutex was deleted
* OS_ERR_DEL_ISR If you attempted to delete the mutex from an ISR
* OS_ERR_OBJ_PTR_NULL If 'p_mutex' is a NULL pointer.
* OS_ERR_OBJ_TYPE If 'p_mutex' is not pointing to a mutex
* OS_ERR_OPT_INVALID An invalid option was specified
* OS_ERR_STATE_INVALID Task is in an invalid state
* OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
*
* Returns : == 0 if no tasks were waiting on the mutex, or upon error.
* > 0 if one or more tasks waiting on the mutex are now readied and informed.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of the mutex MUST
* check the return code of OSMutexPend().
*
* 2) OSMutexAccept() callers will not know that the intended mutex has been deleted.
*
* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful in applications where the
* mutex is used for mutual exclusion because the resource(s) will no longer be guarded by the mutex.
************************************************************************************************************************
*/
#if OS_CFG_MUTEX_DEL_EN > 0u
OS_OBJ_QTY OSMutexDel (OS_MUTEX *p_mutex,
OS_OPT opt,
OS_ERR *p_err)
{
OS_OBJ_QTY cnt;
OS_OBJ_QTY nbr_tasks;
OS_PEND_DATA *p_pend_data;
OS_PEND_LIST *p_pend_list;
OS_TCB *p_tcb;
OS_TCB *p_tcb_owner;
CPU_TS ts;
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) { /* Not allowed to delete a mutex from an ISR */
*p_err = OS_ERR_DEL_ISR;
return ((OS_OBJ_QTY)0);
}
#endif
#if OS_CFG_ARG_CHK_EN > 0u
if (p_mutex == (OS_MUTEX *)0) { /* Validate 'p_mutex' */
*p_err = OS_ERR_OBJ_PTR_NULL;
return ((OS_OBJ_QTY)0);
}
switch (opt) { /* Validate 'opt' */
case OS_OPT_DEL_NO_PEND:
case OS_OPT_DEL_ALWAYS:
break;
default:
*p_err = OS_ERR_OPT_INVALID;
return ((OS_OBJ_QTY)0);
}
#endif
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_mutex->Type != OS_OBJ_TYPE_MUTEX) { /* Make sure mutex was created */
*p_err = OS_ERR_OBJ_TYPE;
return ((OS_OBJ_QTY)0);
}
#endif
OS_CRITICAL_ENTER();
p_pend_list = &p_mutex->PendList;
cnt = p_pend_list->NbrEntries;
nbr_tasks = cnt;
switch (opt) {
case OS_OPT_DEL_NO_PEND: /* Delete mutex only if no task waiting */
if (nbr_tasks == (OS_OBJ_QTY)0) {
#if OS_CFG_DBG_EN > 0u
OS_MutexDbgListRemove(p_mutex);
#endif
OSMutexQty--;
OS_MutexClr(p_mutex);
OS_CRITICAL_EXIT();
*p_err = OS_ERR_NONE;
} else {
OS_CRITICAL_EXIT();
*p_err = OS_ERR_TASK_WAITING;
}
break;
case OS_OPT_DEL_ALWAYS: /* Always delete the mutex */
p_tcb_owner = p_mutex->OwnerTCBPtr; /* Did we had to change the prio of owner? */
if ((p_tcb_owner != (OS_TCB *)0) &&
(p_tcb_owner->Prio != p_mutex->OwnerOriginalPrio)) {
switch (p_tcb_owner->TaskState) { /* yes */
case OS_TASK_STATE_RDY:
OS_RdyListRemove(p_tcb_owner);
p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Lower owner's prio back */
OS_PrioInsert(p_tcb_owner->Prio);
OS_RdyListInsertTail(p_tcb_owner); /* Insert owner in ready list at new prio */
break;
case OS_TASK_STATE_DLY:
case OS_TASK_STATE_SUSPENDED:
case OS_TASK_STATE_DLY_SUSPENDED:
p_tcb_owner->Prio = p_mutex->OwnerOriginalPrio; /* Not in any pend list, change the prio */
break;
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_PEND_TIMEOUT:
case OS_TASK_STATE_PEND_SUSPENDED:
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
OS_PendListChangePrio(p_tcb_owner, /* Owner is pending on another object */
p_mutex->OwnerOriginalPrio);
break;
default:
OS_CRITICAL_EXIT();
*p_err = OS_ERR_STATE_INVALID;
return ((OS_OBJ_QTY)0);
}
}
ts = OS_TS_GET(); /* Get timestamp */
while (cnt > 0u) { /* Remove all tasks from the pend list */
p_pend_data = p_pend_list->HeadPtr;
p_tcb = p_pend_data->TCBPtr;
OS_PendObjDel((OS_PEND_OBJ *)((void *)p_mutex),
p_tcb,
ts);
cnt--;
}
#if OS_CFG_DBG_EN > 0u
OS_MutexDbgListRemove(p_mutex);
#endif
OSMutexQty--;
OS_MutexClr(p_mutex);
OS_CRITICAL_EXIT_NO_SCHED();
OSSched(); /* Find highest priority task ready to run */
*p_err = OS_ERR_NONE;
break;
default:
OS_CRITICAL_EXIT();
*p_err = OS_ERR_OPT_INVALID;
break;
}
return (nbr_tasks);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -