📄 sem.c
字号:
/******************************************************************************
Copyright (c) 2006 by RockOS.
All rights reserved.
This software is supported by the Rock Software Workroom only.
Any bugs please contact the author with e-mail or QQ:
E-mail : baobaoba520@yahoo.com.cn
QQ : 59681888
*******************************************************************************
File name : sema.c
Description : semaphore management for RockOS.
:
:
Auther : sunxinqiu
History :
2006-3-15 first release.
******************************************************************************/
#include "os.h"
/******************************************************************************
Global var : SEMACB g_semaCB[MAX_SYS_SEMA];
Description : control blocks for semaphore.
:
******************************************************************************/
SEMACB g_semaCB[MAX_SYS_SEMA];
/******************************************************************************
Function : STATUS sem_init(void)
Params : N/A
:
:
:
Return : OS_SUCCESS or OS_FAIL
Description : initialize all semaphore CB during system starting up.
:
******************************************************************************/
STATUS sem_init()
{
HSEMA handle;
if (g_OSRunning != OS_PHASE_INIT)
{
OS_error("sem_init(): this function can't be called after system in scheduling!!!\n");
return OS_FAIL;
}
for (handle = 0; handle < MAX_SYS_SEMA; handle++)
{
memset (&g_semaCB[handle], 0, sizeof(SEMACB));
g_semaCB[handle].state = OS_SEMA_FREE;
g_semaCB[handle].ownerTask = NULL_TASK;
}
return OS_SUCCESS;
}
/******************************************************************************
Function : HSEMA semCreate(U16 type, U32 value, const char * name)
Params : type - binary semaphore or counter semaphore.
: value - the initial value for this sema.
: name - the semaphore's name.
:
Return : the semaphore handle.
Description : create a semaphore before using it.
:
******************************************************************************/
HSEMA semCreate(U16 type, U32 value, const char * name)
{
HANDLE handle;
HSEMA hsema;
char qName[MAX_NAME_LEN+1];
switch(type)
{
case OS_SEMA_MUTEX:
/* find a free semaphore first. */
hsema = NULL_SEMA;
OS_ENTER_CRITICAL();
for (handle = 0; handle < MAX_SYS_SEMA; handle++)
{
if (g_semaCB[handle].state == OS_SEMA_FREE)
{
hsema = (HSEMA)handle;
g_semaCB[hsema].state = OS_SEMA_MUTEX;
break;
}
}
OS_LEAVE_CRITICAL();
g_semaCB[hsema].semaphore = 1;
strncpy(&g_semaCB[hsema].name[0], name, MAX_NAME_LEN);
g_semaCB[hsema].tobefree = OS_FALSE;
g_semaCB[hsema].ownerTask = NULL_TASK;
break;
case OS_SEMA_SYNC:
/* find a free semaphore first. */
hsema = NULL_SEMA;
OS_ENTER_CRITICAL();
for (handle = 0; handle < MAX_SYS_SEMA; handle++)
{
if (g_semaCB[handle].state == OS_SEMA_FREE)
{
hsema = (HSEMA)handle;
g_semaCB[hsema].state = OS_SEMA_SYNC;
break;
}
}
OS_LEAVE_CRITICAL();
g_semaCB[hsema].semaphore = value;
strncpy(&g_semaCB[hsema].name[0], name, MAX_NAME_LEN);
g_semaCB[hsema].tobefree = OS_FALSE;
g_semaCB[hsema].ownerTask = NULL_TASK;
memset (&qName[0], 0, sizeof(qName));
break;
default:
OS_error("semCreate(): semaphore type [%d] is invalid!!!\n", type);
return NULL_SEMA;
}
if (hsema != NULL_SEMA)
{
/* create pend task queue. */
sprintf(&qName[0], "sema [%d] penders", hsema);
g_semaCB[hsema].pendTaskQ = q_create(OS_QUEUE_PRIO, MAX_SYS_TASK, NULL_TASK, &qName[0]);
if (g_semaCB[hsema].pendTaskQ == NULL_QUEUE)
{
OS_error("semCreate(): create pend task queue failure, priority base queue not enouth!!!\n");
OS_ENTER_CRITICAL();
memset (&g_semaCB[hsema], 0, sizeof(SEMACB));
g_semaCB[hsema].state = OS_SEMA_FREE;
OS_LEAVE_CRITICAL();
hsema = NULL_SEMA;
}
}
return hsema;
}
/******************************************************************************
Function : STATUS semDestroy(HSEMA hsema)
Params : hsema - the semaphore.
:
:
:
Return : OS_SUCCESS or OS_FAIL.
Description : destroy the semaphore.
:
******************************************************************************/
STATUS semDestroy(HSEMA hSema)
{
/* param check. */
if (hSema >= MAX_SYS_SEMA)
{
OS_error("semDestroy(): semapore [%d] is invlaid!!!\n", hSema);
return OS_FAIL;
}
if (g_semaCB[hSema].state == OS_SEMA_FREE)
{
OS_error("semDestroy(): semapore [%d] is free!!!\n", hSema);
return OS_SUCCESS;
}
if (g_semaCB[hSema].tobefree == OS_TRUE)
{
OS_error("semDestroy(): semapore [%d] has been free!!!\n", hSema);
return OS_SUCCESS;
}
/* here, the semaphore's state is change to OS_SEMA_TOBEFREE, it will be
* changed to OS_SEMA_FREE when there is no task taking or pending on it,
* see function semGive() for more. */
OS_ENTER_CRITICAL();
g_semaCB[hSema].tobefree = OS_TRUE;
OS_LEAVE_CRITICAL();
return OS_SUCCESS;
}
/******************************************************************************
Function : STATUS semTake(HSEMA hSema, U32 timeout)
Params : hSema - the semaphore.
: timeout - the wait ticks if the task is pending on this semaphore.
:
:
Return : OS_SUCCESS or OS_FAIL
Description : take the semaphore to use.
:
******************************************************************************/
STATUS semTake(HSEMA hSema, U32 timeout)
{
U16 selfPriority;
HTASK selfTask;
STATUS nret;
U16 trigger;
U32 params[2];
/* param check. */
if (hSema >= MAX_SYS_SEMA)
{
OS_error("semTake(): semapore [%d] is invlaid!!!\n", hSema);
return OS_FAIL;
}
if (g_semaCB[hSema].state == OS_SEMA_FREE)
{
OS_error("semTake(): semapore [%d] is free!!!\n", hSema);
return OS_FAIL;
}
if (g_semaCB[hSema].tobefree == OS_TRUE)
{
OS_error("semTake(): semapore [%d] is to be free and can't be take again!!!\n", hSema);
return OS_FAIL;
}
selfTask = taskIdSelf();
selfPriority = taskPrioritySelf();
switch(g_semaCB[hSema].state)
{
case OS_SEMA_MUTEX:
OS_ENTER_CRITICAL();
if (g_semaCB[hSema].semaphore != 0)
{
/* running task owns this semaphore. */
g_semaCB[hSema].semaphore = 0;
g_semaCB[hSema].ownerTask = selfTask;
OS_LEAVE_CRITICAL();
taskSetTrigger(selfTask, T_TRIG_TAKE_SEMA_DONE, (void *)hSema);
nret = OS_SUCCESS;
}
else
{
if (selfTask == g_semaCB[hSema].ownerTask)
{
/* this samphore is taken by the same task twicely or more. */
OS_error("semTake(): task [%d] takes semaphore [%d] twicely or more!!!\n",
selfTask, hSema);
}
/* add this task to pend task queue. */
q_add(g_semaCB[hSema].pendTaskQ, (HANDLE)selfTask, selfPriority);
/* change the semaphore's owner task's priority if necessary. */
taskSetPriorityAuto(g_semaCB[hSema].ownerTask);
OS_LEAVE_CRITICAL();
/* now current task is pending on the semaphore. */
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 == OS_EVENT_DELAY_TMO)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -