www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > mailbox.c
/*
===============================================================================
| Copyright (C) 2004 RuanHaiShen, All rights reserved.
| SUMMARY:
| Mailbox 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_MBOX_EN > 0
err_t mbox_init(mbox_t* mbox)
{
__ASSERT(mbox != NULL);
mbox->value = 0;
mbox->avail = false;
__queue_init(mbox->tasks);
return EOK;
}
err_t mbox_send(mbox_t* mbox, u32 value)
{
__ASSERT(mbox != NULL);
CRITICAL_ENTER;
if (!mbox->avail) {
mbox->avail = true;
mbox->value = value;
if (__ipc_resume(&mbox->tasks) != NULL_PRIO) {
CRITICAL_EXIT;
__schedule();
} else {
CRITICAL_EXIT;
}
return EOK;
} else {
CRITICAL_EXIT;
return EFULL;
}
}
err_t mbox_receive(mbox_t* mbox, u32* pvalue)
{
__ASSERT(mbox != NULL);
#if CFG_ARG_CHK > 0
if (_sched_lock > 0) {
return ELOCK;
}
#else
__ASSERT(_sched_lock == 0);
#endif
while (true) {
CRITICAL_ENTER;
if (mbox->avail) {
mbox->avail = false;
*pvalue = mbox->value;
CRITICAL_EXIT;
return EOK;
}
__ipc_block(&mbox->tasks, 0);
CRITICAL_EXIT;
__schedule();
}
}
#if CFG_IPC_TIMEOUT_EN > 0
err_t mbox_timereceive(mbox_t* mbox, u32* pvalue, tick_t ticks)
{
register u8 current;
__ASSERT(mbox != NULL);
#if CFG_ARG_CHK > 0
if (_sched_lock > 0) {
return ELOCK;
}
#else
__ASSERT(_sched_lock == 0);
#endif
while (true) {
CRITICAL_ENTER;
if (mbox->avail) {
mbox->avail = false;
*pvalue = mbox->value;
CRITICAL_EXIT;
return EOK;
}
__ipc_block(&mbox->tasks, ticks);
CRITICAL_EXIT;
__schedule();
CRITICAL_ENTER;
current = _current_prio;
if (_tasks[current].state & STATE_BLOCKED) {
__ipc_timeout(&mbox->tasks);
CRITICAL_EXIT;
return ETIMEOUT;
}
__adjust_delay(current, ticks);
CRITICAL_EXIT;
}
}
#endif
err_t mbox_flush(mbox_t* mbox)
{
__ASSERT(mbox != NULL);
CRITICAL_ENTER;
mbox->avail = false;
mbox->value = 0;
CRITICAL_EXIT;
return EOK;
}
err_t mbox_destroy(mbox_t* mbox)
{
__ASSERT(mbox != NULL);
CRITICAL_ENTER;
if (__ipc_resume(&mbox->tasks) != NULL_PRIO) {
CRITICAL_EXIT;
return EEXIST;
}
CRITICAL_EXIT;
return EOK;
}
#endif
/*===========================================================================*/