git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@505 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2008-11-09 11:12:11 +00:00
parent 87d83b1b7e
commit 6776d06927
8 changed files with 317 additions and 9 deletions

View File

@ -55,6 +55,16 @@
* the kernel.*/ * the kernel.*/
#define CH_USE_MUTEXES #define CH_USE_MUTEXES
/** Configuration option: if specified then the Conditional Variables APIs are
* included in the kernel.
* @note requires \p CH_USE_MUTEXES.*/
#define CH_USE_CONDVARS
/** Configuration option: if specified then the Conditional Variables APIs are
* included in the kernel.
* @note requires \p CH_USE_CONDVARS and \p CH_USE_MUTEXES.*/
#define CH_USE_CONDVARS_TIMEOUT
/** Configuration option: if specified then the Events APIs are included in /** Configuration option: if specified then the Events APIs are included in
* the kernel.*/ * the kernel.*/
#define CH_USE_EVENTS #define CH_USE_EVENTS

View File

@ -74,6 +74,7 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
***************************************************************************** *****************************************************************************
*** 0.8.0 *** *** 0.8.0 ***
- NEW: Added condvars mechanism on top of the mutexes subsystem.
- NEW: Improved events subsystems, now it is also possible to use it just as - NEW: Improved events subsystems, now it is also possible to use it just as
"event flags" without have to use event handler callbacks. "event flags" without have to use event handler callbacks.
Some new APIs were introduced: Some new APIs were introduced:
@ -90,6 +91,7 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
CH_USE_DEBUG is disabled, it produces no code but allows to check the CH_USE_DEBUG is disabled, it produces no code but allows to check the
optional code without have to compile twice. optional code without have to compile twice.
- FIX: Fixed a warning generated by the chEvtIsListening() macro. - FIX: Fixed a warning generated by the chEvtIsListening() macro.
- Added new test cases to the test suite about the new events APIs.
- Added a new benchmark to the test suite (timers set/reset performance). - Added a new benchmark to the test suite (timers set/reset performance).
- Renamed the macro fifo_init() to queue_init() because it is used to init - Renamed the macro fifo_init() to queue_init() because it is used to init
both FIFO queues and priority queues. both FIFO queues and priority queues.

216
src/chcond.c Normal file
View File

@ -0,0 +1,216 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Concepts and parts of this file are contributed by and Copyright (C) 2008
of Leon Woestenberg
*/
/**
* @addtogroup CondVars
* @{
*/
#include <ch.h>
#if defined(CH_USE_CONDVARS) && defined(CH_USE_MUTEXES)
/**
* Initializes s \p CondVar structure.
* @param cp pointer to a \p CondVar structure
*/
void chCondInit(CondVar *cp) {
queue_init(&cp->c_queue);
}
/**
* Signals one thread that is waiting on the condition variable.
*
* @param mp pointer to the \p CondVar structure
*/
void chCondSignal(CondVar *cp) {
chSysLock();
if (notempty(&cp->c_queue)) /* any thread ? */
chSchWakeupS(fifo_remove(&cp->c_queue), RDY_OK);
chSysUnlock();
}
/**
* Signals one thread that is waiting on the condition variable.
*
* @param cp pointer to the \p CondVar structure
* @note This function must be called within a \p chSysLock() / \p chSysUnlock()
* block.
*/
void chCondSignalI(CondVar *cp) {
if (notempty(&cp->c_queue)) /* any thread ? */
chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_OK;
}
/**
* Signal all threads that are waiting on the condition variable.
*
* @param mp pointer to the \p CondVar structure
*/
void chCondBroadcast(CondVar *cp) {
chSysLock();
chCondBroadcastI(cp);
chSchRescheduleS();
chSysUnlock();
}
/**
* Signal all threads that are waiting on the condition variable.
*
* @param cp pointer to the \p CondVar structure
* @note This function must be called within a \p chSysLock() / \p chSysUnlock()
*/
void chCondBroadcastI(CondVar *cp) {
/* empties the condition variable queue and inserts all the Threads into the
* ready list in FIFO order. The wakeup message is set to \p RDY_RESET in
* order to make a chCondBroadcast() detectable from a chCondSignal(). */
while (cp->c_queue.p_next != (void *)&cp->c_queue)
chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_RESET;
}
/**
* Wait on the condition variable releasing the mutex lock.
*
* Releases the mutex, waits on the condition variable, and finally acquires
* the mutex again. This is done atomically.
*
* The thread MUST already have locked the mutex when calling chCondWait().
*
* @param cp pointer to the \p CondVar structure
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
*/
msg_t chCondWait(CondVar *cp) {
msg_t msg;
chSysLock();
msg = chCondWaitS(cp);
chSysUnlock();
return msg;
}
/**
* Wait on the condition variable releasing the mutex lock.
*
* Releases the mutex, waits on the condition variable, and finally acquires
* the mutex again. This is done atomically.
*
* The thread MUST already have locked the mutex when calling chCondWait().
*
* @param cp pointer to the \p CondVar structure
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @note This function must be called within a \p chSysLock() / \p chSysUnlock()
*/
msg_t chCondWaitS(CondVar *cp) {
Mutex *mp;
msg_t msg;
chDbgAssert(currp->p_mtxlist != NULL, "chcond.c, chCondWaitS()");
mp = chMtxUnlockS(); /* unlocks the condvar mutex */
prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
currp->p_wtcondp = cp; /* needed by the tracer */
chSchGoSleepS(PRWTCOND); /* waits on the condvar */
msg = currp->p_rdymsg; /* fetches the wakeup message */
chMtxLockS(mp); /* atomically relocks the mutex */
return msg; /* returns the wakeup message */
}
#ifdef CH_USE_CONDVARS_TIMEOUT
/**
* Wait on the condition variable releasing the mutex lock.
*
* Releases the mutex, waits on the condition variable, and finally acquires
* the mutex again. This is done atomically.
*
* The thread MUST already have locked the mutex when calling chCondWait().
*
* @param cp pointer to the \p CondVar structure
* @param time the number of ticks before the operation fails
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @retval RDY_TIMEOUT if the condvar was not signaled within the specified
* timeout.
*/
msg_t chCondWaitTimeout(CondVar *cp, systime_t time) {
msg_t msg;
chSysLock();
msg = chCondWaitTimeoutS(cp, time);
chSysUnlock();
return msg;
}
/**
* Wait on the condition variable releasing the mutex lock.
*
* Releases the mutex, waits on the condition variable, and finally acquires
* the mutex again. This is done atomically.
*
* The thread MUST already have locked the mutex when calling chCondWait().
*
* @param cp pointer to the \p CondVar structure
* @param time the number of ticks before the operation fails
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @retval RDY_TIMEOUT if the condvar was not signaled within the specified
* timeout.
* @note This function must be called within a \p chSysLock() / \p chSysUnlock()
*/
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
Mutex *mp;
msg_t msg;
chDbgAssert(currp->p_mtxlist != NULL, "chcond.c, chCondWaitS()");
mp = chMtxUnlockS(); /* unlocks the condvar mutex */
prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
currp->p_wtcondp = cp; /* needed by the tracer */
chSchGoSleepTimeoutS(PRWTCOND, time); /* waits on the condvar */
msg = currp->p_rdymsg; /* fetches the wakeup message */
chMtxLockS(mp); /* atomically relocks the mutex */
return msg; /* returns the wakeup message */
}
#endif /* CH_USE_CONDVARS_TIMEOUT */
#endif /* defined(CH_USE_CONDVARS) && defined(CH_USE_MUTEXES) */
/** @} */

View File

@ -35,6 +35,7 @@
#include "scheduler.h" #include "scheduler.h"
#include "semaphores.h" #include "semaphores.h"
#include "mutexes.h" #include "mutexes.h"
#include "condvars.h"
#include "events.h" #include "events.h"
#include "messages.h" #include "messages.h"
#include "heap.h" #include "heap.h"

63
src/include/condvars.h Normal file
View File

@ -0,0 +1,63 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Concepts and parts of this file are contributed by and Copyright (C) 2008
of Leon Woestenberg
*/
/**
* @addtogroup Conditional Variables
* @{
*/
#ifndef _CONDVARS_H_
#define _CONDVARS_H_
#if defined(CH_USE_CONDVARS) && defined(CH_USE_MUTEXES)
/**
* CondVar structure.
*/
typedef struct {
ThreadsQueue c_queue;
} CondVar;
#ifdef __cplusplus
extern "C" {
#endif
void chCondInit(CondVar *cp);
void chCondSignal(CondVar *cp);
void chCondSignalI(CondVar *cp);
void chCondBroadcast(CondVar *cp);
void chCondBroadcastI(CondVar *cp);
msg_t chCondWait(CondVar *cp);
msg_t chCondWaitS(CondVar *cp);
#ifdef CH_USE_CONDVARS_TIMEOUT
msg_t chCondWaitTimeout(CondVar *cp, systime_t time);
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time);
#endif
#ifdef __cplusplus
}
#endif
#endif /* defined(CH_USE_CONDVARS) && defined(CH_USE_MUTEXES) */
#endif /* _CONDVARS_H_ */
/** @} */

View File

@ -68,12 +68,17 @@ struct Thread {
/** Mutex where the thread is waiting on (only in \p PRWTMTX state).*/ /** Mutex where the thread is waiting on (only in \p PRWTMTX state).*/
Mutex *p_wtmtxp; Mutex *p_wtmtxp;
#endif #endif
#ifdef CH_USE_CONDVARS
/** CondVar where the thread is waiting on (only in \p PRWTCOND state).*/
CondVar *p_wtcondp;
#endif
#ifdef CH_USE_MESSAGES #ifdef CH_USE_MESSAGES
/** Destination thread for message send (only in \p PRSNDMSG state).*/ /** Destination thread for message send (only in \p PRSNDMSG state).*/
Thread *p_wtthdp; Thread *p_wtthdp;
#endif #endif
#ifdef CH_USE_EVENTS #ifdef CH_USE_EVENTS
/** Enabled events mask (only while in \p PRWTEVENT state). */ /** Enabled events mask (only while in \p PRWTOREVT or \p PRWTANDEVT
states). */
eventmask_t p_ewmask; eventmask_t p_ewmask;
#endif #endif
#ifdef CH_USE_TRACE #ifdef CH_USE_TRACE

View File

@ -4,6 +4,7 @@ KERNSRC = ../../src/chinit.c ../../src/chdebug.c \
../../src/chlists.c ../../src/chvt.c \ ../../src/chlists.c ../../src/chvt.c \
../../src/chschd.c ../../src/chthreads.c \ ../../src/chschd.c ../../src/chthreads.c \
../../src/chsem.c ../../src/chmtx.c \ ../../src/chsem.c ../../src/chmtx.c \
../../src/chevents.c ../../src/chmsg.c \ ../../src/chcond.c ../../src/chevents.c \
../../src/chqueues.c ../../src/chserial.c \ ../../src/chmsg.c ../../src/chqueues.c \
../../src/chheap.c ../../src/chmempools.c ../../src/chheap.c ../../src/chmempools.c \
../../src/chserial.c

View File

@ -60,6 +60,16 @@
* the kernel.*/ * the kernel.*/
#define CH_USE_MUTEXES #define CH_USE_MUTEXES
/** Configuration option: if specified then the Conditional Variables APIs are
* included in the kernel.
* @note requires \p CH_USE_MUTEXES.*/
#define CH_USE_CONDVARS
/** Configuration option: if specified then the Conditional Variables APIs are
* included in the kernel.
* @note requires \p CH_USE_CONDVARS and \p CH_USE_MUTEXES.*/
#define CH_USE_CONDVARS_TIMEOUT
/** Configuration option: if specified then the Events APIs are included in /** Configuration option: if specified then the Events APIs are included in
* the kernel.*/ * the kernel.*/
#define CH_USE_EVENTS #define CH_USE_EVENTS