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

📄 sem.c

📁 介绍ROCK OS操作系统.一般用于汽车电子,类似OCVX.里面是个DEMO文档,内附说明.
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
    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 *)&params[0]);
            OS_ENTER_CRITICAL();
            trigger = getCoreEvent(selfTask);
            if (trigger == OS_EVENT_DELAY_TMO)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -