📄 sem.c
字号:
{
q_del(g_semaCB[hSema].pendTaskQ, (HANDLE)selfTask);
g_sysTcb[selfTask].bWaitTimeout = OS_FALSE;
OS_LEAVE_CRITICAL();
nret = OS_FAIL;
}
else
{
g_semaCB[hSema].ownerTask = selfTask;
OS_LEAVE_CRITICAL();
nret = OS_SUCCESS;
}
}
break;
case OS_SEMA_SYNC:
OS_ENTER_CRITICAL();
if (g_semaCB[hSema].semaphore != 0)
{
g_semaCB[hSema].semaphore --;
OS_LEAVE_CRITICAL();
taskSetTrigger(selfTask, T_TRIG_TAKE_SEMA_DONE, (void *)hSema);
nret = OS_SUCCESS;
}
else
{
/* add this task to pend task queue. */
q_add(g_semaCB[hSema].pendTaskQ, (HANDLE)selfTask, selfPriority);
/* synchronization semaphore doesn't support auto priority inverse,
* because I can't know which task's priority should be inverse. */
OS_LEAVE_CRITICAL();
/* pend task here. */
params[0] = (U32)hSema;
params[1] = (U32)timeout;
taskSetTrigger(selfTask, T_TRIG_TAKE_SEMA_PEND, (void *)¶ms[0]);
OS_ENTER_CRITICAL();
trigger = getCoreEvent(selfTask);
if (trigger == T_TRIG_DELAY_TMO)
{
q_del(g_semaCB[hSema].pendTaskQ, (HANDLE)selfTask);
OS_LEAVE_CRITICAL();
nret = OS_FAIL;
}
else
{
/* the task has been added to the semaphore's owner queue already (in semGive).*/
OS_LEAVE_CRITICAL();
nret = OS_SUCCESS;
}
}
break;
default:
OS_error("semTake(): semapore [%d] state is [%d]!!!\n", hSema, g_semaCB[hSema].state);
nret = OS_FAIL;
break;
}
return nret;
}
/******************************************************************************
Function : STATUS semGive(HSEMA hSema)
Params : hSema - the semaphore.
:
:
:
Return : OS_FAIL or OS_SUCCESS
Description : give up the semaphore.
:
******************************************************************************/
STATUS semGive(HSEMA hSema)
{
HTASK nextTask;
U16 selfPriority;
HTASK selfTask;
STATUS nret;
/* param check. */
if (hSema >= MAX_SYS_SEMA)
{
OS_error("semGive(): semapore [%d] is invlaid!!!\n", hSema);
return OS_FAIL;
}
if (g_semaCB[hSema].state == OS_SEMA_FREE)
{
OS_error("semGive(): semapore [%d] is free!!!\n", hSema);
return OS_FAIL;
}
selfTask = taskIdSelf();
selfPriority = taskPrioritySelf();
switch(g_semaCB[hSema].state)
{
case OS_SEMA_MUTEX:
/* task fsm event. */
taskSetTrigger(selfTask, T_TRIG_SEMA_GIVE, (void *)&hSema);
OS_ENTER_CRITICAL();
/* clear the semaphore owner task. */
g_semaCB[hSema].ownerTask = NULL_TASK;
/* free the next pending task from the samaphore's pending task queue. */
if (q_head(g_semaCB[hSema].pendTaskQ, (HANDLE *)&nextTask) == OS_FAIL)
{
g_semaCB[hSema].ownerTask = NULL_TASK;
g_semaCB[hSema].semaphore = 1;
OS_LEAVE_CRITICAL();
nret = OS_SUCCESS;
}
else
{
q_enum(g_semaCB[hSema].pendTaskQ, (HANDLE *)&nextTask);
/* restore the owner task's priority. */
taskSetPriorityAuto(selfTask);
if ((getTaskState(nextTask) == OS_TASK_PEND_ON_SEMA)
&&(getTaskPendObj(nextTask) == (HANDLE)hSema))
{
g_semaCB[hSema].ownerTask = nextTask;
OS_LEAVE_CRITICAL();
/* the nextTask can now continue. */
taskSetTrigger(nextTask, T_TRIG_TAKE_SEMA_DONE, (void *)hSema);
}
nret = OS_SUCCESS;
}
break;
case OS_SEMA_SYNC:
/* task fsm event. */
taskSetTrigger(selfTask, T_TRIG_SEMA_GIVE, (void *)&hSema);
OS_ENTER_CRITICAL();
/* free the next pending task from the samaphore's pending task queue. */
if (q_head(g_semaCB[hSema].pendTaskQ, (HANDLE *)&nextTask) == OS_FAIL)
{
g_semaCB[hSema].semaphore++;
OS_LEAVE_CRITICAL();
nret = OS_SUCCESS;
}
else
{
q_enum(g_semaCB[hSema].pendTaskQ, (HANDLE *)&nextTask);
if ((getTaskState(nextTask) == OS_TASK_PEND_ON_SEMA)
&&(getTaskPendObj(nextTask) == (HANDLE)hSema))
{
OS_LEAVE_CRITICAL();
/* the nextTask can now continue. */
taskSetTrigger(nextTask, T_TRIG_TAKE_SEMA_DONE, (void *)hSema);
}
}
break;
default:
OS_error("semGive(): semapore [%d] state is [%d]!!!\n", hSema, g_semaCB[hSema].state);
nret = OS_FAIL;
break;
}
return nret;
}
/******************************************************************************
Function : void getSemType(HSEMA hsema)
Params : hsema - the semaphore
:
:
:
Return : N/A
Description : get the semaphore's type, a mutex or a synchronization semaphore.
:
******************************************************************************/
U16 getSemType(HSEMA hsema)
{
if (hsema >= MAX_SYS_SEMA)
{
OS_error("getSemType(): semaphore [%d] out of range!!!\n", hsema);
return OS_SEMA_FREE;
}
return g_semaCB[hsema].state;
}
/******************************************************************************
Function : void semCheck(void)
Params : N/A
:
:
:
Return : N/A
Description : check the semaphore periodly, if a semphore is ready for free,
: then free it.
******************************************************************************/
void semCheck ()
{
HSEMA hsema;
for (hsema = 0; hsema < MAX_SYS_SEMA; hsema++)
{
if (g_semaCB[hsema].state == OS_SEMA_FREE)
{
continue;
}
else if (g_semaCB[hsema].tobefree == OS_TRUE)
{
switch(g_semaCB[hsema].state)
{
case OS_SEMA_MUTEX:
if ((g_semaCB[hsema].ownerTask == NULL_TASK)
&&(q_count(g_semaCB[hsema].pendTaskQ)==0))
{
OS_ENTER_CRITICAL();
q_destroy(g_semaCB[hsema].pendTaskQ);
memset (&g_semaCB[hsema], 0, sizeof(SEMACB));
g_semaCB[hsema].state = OS_SEMA_FREE;
OS_LEAVE_CRITICAL();
}
break;
case OS_SEMA_SYNC:
if (q_count(g_semaCB[hsema].pendTaskQ)==0)
{
OS_ENTER_CRITICAL();
q_destroy(g_semaCB[hsema].pendTaskQ);
memset (&g_semaCB[hsema], 0, sizeof(SEMACB));
g_semaCB[hsema].state = OS_SEMA_FREE;
OS_LEAVE_CRITICAL();
}
break;
default:
OS_error("semCheck(): semaphore [%d] is in error state [%d], recycle now!!!\n",
hsema, g_semaCB[hsema].state);
OS_ENTER_CRITICAL();
q_destroy(g_semaCB[hsema].pendTaskQ);
memset (&g_semaCB[hsema], 0, sizeof(SEMACB));
g_semaCB[hsema].state = OS_SEMA_FREE;
OS_LEAVE_CRITICAL();
break;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -