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
/*===========================================================================*/