www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > sem.c
/*
===============================================================================
| Copyright (C) 2004 RuanHaiShen, All rights reserved.
| SUMMARY:
| Counting 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_SEM_EN > 0
err_t sem_init(sem_t* sem, cnt_t value)
{
__ASSERT(sem != NULL);
sem->count = value;
__queue_init(sem->tasks);
return EOK;
}
err_t sem_wait(sem_t* sem)
{
__ASSERT(sem != NULL);
#if CFG_ARG_CHK > 0
if (_sched_lock > 0) {
return ELOCK;
}
#else
__ASSERT(_sched_lock == 0);
#endif
CRITICAL_ENTER;
if (sem->count > 0) {
sem->count--;
CRITICAL_EXIT;
return EOK;
}
__ipc_block(&sem->tasks, 0);
CRITICAL_EXIT;
__schedule();
return EOK;
}
#if CFG_IPC_TIMEOUT_EN > 0
err_t sem_timewait(sem_t* sem, tick_t ticks)
{
__ASSERT(sem != NULL);
#if CFG_ARG_CHK > 0
if (_sched_lock > 0) {
return ELOCK;
}
#else
__ASSERT(_sched_lock == 0);
#endif
CRITICAL_ENTER;
if (sem->count > 0) {
sem->count--;
CRITICAL_EXIT;
return EOK;
}
__ipc_block(&sem->tasks, ticks);
CRITICAL_EXIT;
__schedule();
CRITICAL_ENTER;
if (_tasks[_current_prio].state & STATE_BLOCKED) {
__ipc_timeout(&sem->tasks);
CRITICAL_EXIT;
return ETIMEOUT;
}
_tasks[_current_prio].delay = 0;
CRITICAL_EXIT;
return EOK;
}
#endif
void sem_post(sem_t* sem)
{
__ASSERT(sem != NULL);
CRITICAL_ENTER;
if (__ipc_resume(&sem->tasks) != NULL_PRIO) {
CRITICAL_EXIT;
__schedule();
} else if (sem->count < (cnt_t)-1) {
sem->count++;
CRITICAL_EXIT;
} else {
CRITICAL_EXIT;
}
}
err_t sem_trywait(sem_t* sem)
{
__ASSERT(sem != NULL);
CRITICAL_ENTER;
if (sem->count > 0) {
sem->count--;
CRITICAL_EXIT;
return EOK;
}
CRITICAL_EXIT;
return ENAVAIL;
}
cnt_t sem_getvalue(sem_t* sem)
{
register cnt_t val;
__ASSERT(sem != NULL);
CRITICAL_ENTER;
val = sem->count;
CRITICAL_EXIT;
return val;
}
err_t sem_destroy(sem_t* sem)
{
__ASSERT(sem != NULL);
while (true) {
CRITICAL_ENTER;
if (__ipc_resume(&sem->tasks) == NULL_PRIO) {
CRITICAL_EXIT;
break;
}
CRITICAL_EXIT;
}
return EOK;
}
#endif
/*===========================================================================*/