www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > semb.c


/* 
=============================================================================== 
| Copyright (C) 2004 RuanHaiShen, All rights reserved. 
| SUMMARY:  
|   Binary semaphore implementation. 
| 
| DESCRIPTION: 
|   See http://www.01s.org for documentation, latest information, license  
|   and contact details. 
|   email:ruanhaishen@01s.org 
=============================================================================*/ 
/*===========================================================================*/ 
#include "arch/arch.h" 
#include "inc/queue.h" 
#include "inc/kernel.h" 
#include "inc/memory.h" 
#include "inc/ipc.h" 
#include "inc/kapi.h" 
 
 
#if CFG_SEMB_EN > 0  
err_t semb_init(semb_t* semb, bool value) 
{ 
    __ASSERT(semb != NULL); 
 
    semb->avail = value; 
    __queue_init(semb->tasks); 
    return EOK; 
} 
 
err_t semb_wait(semb_t* semb) 
{ 
    __ASSERT(semb != NULL); 
 
#if CFG_ARG_CHK > 0 
    if (_sched_lock > 0) { 
        return ELOCK; 
    } 
#else 
    __ASSERT(_sched_lock == 0); 
#endif 
 
    CRITICAL_ENTER; 
    if (semb->avail) { 
        semb->avail = false; 
        CRITICAL_EXIT; 
        return EOK; 
    } 
    __ipc_block(&semb->tasks, 0); 
    CRITICAL_EXIT; 
 
    __schedule(); 
    return EOK; 
} 
 
#if CFG_IPC_TIMEOUT_EN > 0 
err_t semb_timewait(semb_t* semb, tick_t ticks) 
{ 
    __ASSERT(semb != NULL); 
 
#if CFG_ARG_CHK > 0 
    if (_sched_lock > 0) { 
        return ELOCK; 
    } 
#else 
    __ASSERT(_sched_lock == 0); 
#endif 
 
    CRITICAL_ENTER; 
    if (semb->avail) { 
        semb->avail = false; 
        CRITICAL_EXIT; 
        return EOK; 
    } 
    __ipc_block(&semb->tasks, ticks); 
    CRITICAL_EXIT; 
 
    __schedule(); 
 
    CRITICAL_ENTER; 
    if (_tasks[_current_prio].state & STATE_BLOCKED) { 
        __ipc_timeout(&semb->tasks); 
        CRITICAL_EXIT; 
        return ETIMEOUT; 
    } 
    _tasks[_current_prio].delay = 0; 
    CRITICAL_EXIT; 
    return EOK; 
} 
#endif 
 
void semb_post(semb_t* semb) 
{ 
    __ASSERT(semb != NULL); 
 
    CRITICAL_ENTER; 
    if (__ipc_resume(&semb->tasks) != NULL_PRIO) { 
        CRITICAL_EXIT; 
        __schedule(); 
    } else { 
        semb->avail = true; 
        CRITICAL_EXIT; 
    } 
} 
 
err_t semb_trywait(semb_t* semb) 
{ 
    __ASSERT(semb != NULL); 
 
    CRITICAL_ENTER; 
    if (semb->avail) { 
        semb->avail = false; 
        CRITICAL_EXIT; 
        return EOK; 
    } 
    CRITICAL_EXIT; 
    return ENAVAIL; 
} 
 
bool semb_getvalue(semb_t* semb) 
{ 
    register bool val; 
 
    __ASSERT(semb != NULL); 
 
    CRITICAL_ENTER; 
    val = semb->avail; 
    CRITICAL_EXIT; 
    return val; 
} 
 
err_t semb_destroy(semb_t* semb) 
{ 
    __ASSERT(semb != NULL); 
 
    while (true) { 
        CRITICAL_ENTER; 
        if (__ipc_resume(&semb->tasks) == NULL_PRIO) { 
            CRITICAL_EXIT; 
            break; 
        } 
        CRITICAL_EXIT; 
    } 
    return EOK; 
} 
#endif 
 
 
/*===========================================================================*/