From 2310f80695b4051cb63ca14878dfc5e76acb94e6 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 3 Oct 2007 17:14:03 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@30 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/LPC214x-GCC/chconf.h | 4 + demos/Win32-MSVS/ch.vcproj | 7 + demos/Win32-MSVS/chconf.h | 8 +- demos/Win32-MSVS/demo.c | 21 ++- demos/Win32-MinGW/Makefile | 2 +- demos/Win32-MinGW/chconf.h | 8 +- demos/Win32-MinGW/chcore.c | 2 +- demos/Win32-MinGW/chcore2.s | 2 +- demos/Win32-MinGW/demo.c | 17 ++- docs/Doxyfile | 3 +- readme.txt | 21 ++- src/chsem.c | 21 ++- src/include/delta.h | 3 +- src/include/semaphores.h | 2 +- src/templates/chconf.h | 4 + test/test.c | 273 ++++++++++++++++++++++++++++++++++++ 16 files changed, 364 insertions(+), 34 deletions(-) create mode 100644 test/test.c diff --git a/demos/LPC214x-GCC/chconf.h b/demos/LPC214x-GCC/chconf.h index 30670c8fd..da8553399 100644 --- a/demos/LPC214x-GCC/chconf.h +++ b/demos/LPC214x-GCC/chconf.h @@ -63,6 +63,10 @@ * in the kernel.*/ #define CH_USE_SEMAPHORES +/** Configuration option: if specified then the Semaphores atomic Signal+Wait + * APIs are included in the kernel.*/ +#define CH_USE_SEMSW + /** Configuration option: if specified then the Semaphores with timeout APIs * are included in the kernel. * @note requires \p CH_USE_SEMAPHORES. diff --git a/demos/Win32-MSVS/ch.vcproj b/demos/Win32-MSVS/ch.vcproj index 185e65dc1..8764f059d 100644 --- a/demos/Win32-MSVS/ch.vcproj +++ b/demos/Win32-MSVS/ch.vcproj @@ -182,6 +182,13 @@ RelativePath="..\..\ports\Win32\simcom.c"> + + + + " prompt. The test performs integrity tests on the main + ChibiOS/RT functionalities. + The test code is also a good example of APIs usage and ChibiOS/RT behavior. +- Fixed bug in chEvtWaitTimeout(), the timeout code performed an useless + dequeue operation. +- Fixed a bug in chSemWaitTimeoutS() and chSemWaitTimeout(), the semaphore + counter was not atomically updated on a timeout condition. +- Fixed bug on RT semaphores, the priority queuing was broken. +- Fixed a bug in the MinGW demo, the chThdExit() code was not correctly + reported to the thread waiting in chThdWait(). +- Fixed a function declaration in semaphores.h. - Lists code moved into chlists.c from various other places optimized and reorganized. - The list of the threads waiting in chThdWait() is now a single link list, this saves some space. - Cleaned the template files code, the files contained some obsolete declarations. -- Code optimization in scSemSignalWait(). +- Code optimization in chSemWaitTimeoutS(), chSemWaitTimeout() and + chSemSignalWait(). - Code optimization in chEvtSend(). +- Code optimization in chVTDoTickI(). - Added a Semaphore pointer to the Thread structure, this allows to know on which semaphore a thread is waiting on. It takes no space because it is located in the union inside the Thread structure. This also allowed a minor optimization inside chSemWaitTimeout() and chSemWaitTimeoutS(). - Changed the priority type to unsigned in order to make it compatible with a byte value, this is very important for 8 bits architectures. -- Fixed bug in chEvtWaitTimeout(), the timeout code performed a useless - dequeue operation. -- Fixed bug on RT semaphores, the priority queuing was broken. +- Modified the MinGW and MSVS demos to use 1ms ticks instead of 10ms as + before. *** 0.3.0 *** - ChibiOS/RT goes beta. diff --git a/src/chsem.c b/src/chsem.c index 5c1ff0544..70741c4f0 100644 --- a/src/chsem.c +++ b/src/chsem.c @@ -138,13 +138,9 @@ t_msg chSemWaitTimeout(Semaphore *sp, t_time time) { fifo_insert(currp, &sp->s_queue); currp->p_semp = sp; chSchGoSleepI(PRWTSEM); - msg = currp->p_rdymsg; // Note, got value *before* invoking CH_LEAVE_SYSTEM(). - if (!vt.vt_func) { - - chSysUnlock(); - return msg; - } - chVTResetI(&vt); + msg = currp->p_rdymsg; + if (vt.vt_func) + chVTResetI(&vt); chSysUnlock(); return msg; @@ -173,9 +169,8 @@ t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time) { fifo_insert(currp, &sp->s_queue); currp->p_semp = sp; chSchGoSleepI(PRWTSEM); - if (!vt.vt_func) - return currp->p_rdymsg; - chVTResetI(&vt); + if (vt.vt_func) + chVTResetI(&vt); return currp->p_rdymsg; } return RDY_OK; @@ -211,6 +206,7 @@ void chSemSignalI(Semaphore *sp) { chSchReadyI(fifo_remove(&sp->s_queue)); } +#ifdef CH_USE_SEMSW /** * Performs atomic signal and wait operations on two semaphores. * @param sps pointer to a \p Semaphore structure to be signaled @@ -235,6 +231,7 @@ void chSemSignalWait(Semaphore *sps, Semaphore *spw) { chSysUnlock(); } +#endif /* CH_USE_SEMSW */ #ifdef CH_USE_RT_SEMAPHORES /* @@ -299,6 +296,7 @@ void chSemLowerPrioSignal(Semaphore *sp) { chSysUnlock(); } +#ifdef CH_USE_SEMSW /** * Performs atomic signal and wait operations on two semaphores with priority * boost. @@ -326,7 +324,7 @@ void chSemRaisePrioSignalWait(Semaphore *sps, Semaphore *spw) { if (!currp->p_rtcnt++) currp->p_prio += MEPRIO; - chSchRescheduleI(); + chSchRescheduleI(); // Really needed ? } chSysUnlock(); @@ -360,6 +358,7 @@ void chSemLowerPrioSignalWait(Semaphore *sps, Semaphore *spw) { chSysUnlock(); } +#endif /* CH_USE_SEMSW */ #endif /* CH_USE_RT_SEMAPHORES */ diff --git a/src/include/delta.h b/src/include/delta.h index 14f5b550e..7639301e1 100644 --- a/src/include/delta.h +++ b/src/include/delta.h @@ -77,8 +77,7 @@ extern DeltaList dlist; while (!(vtp = dlist.dl_next)->vt_dtime) { \ t_vtfunc fn = vtp->vt_func; \ vtp->vt_func = 0; \ - vtp->vt_prev->vt_next = vtp->vt_next; \ - vtp->vt_next->vt_prev = vtp->vt_prev; \ + (vtp->vt_next->vt_prev = (VirtualTimer *)&dlist)->vt_next = vtp->vt_next; \ fn(vtp->vt_par); \ } \ } diff --git a/src/include/semaphores.h b/src/include/semaphores.h index 8179627f4..c1f3f9db6 100644 --- a/src/include/semaphores.h +++ b/src/include/semaphores.h @@ -46,7 +46,7 @@ t_msg chSemWaitTimeout(Semaphore *sp, t_time time); t_msg chSemWaitTimeoutS(Semaphore *sp, t_time time); void chSemSignal(Semaphore *sp); void chSemSignalI(Semaphore *sp); -void chSignalWait(Semaphore *sps, Semaphore *spw); +void chSemSignalWait(Semaphore *sps, Semaphore *spw); #ifdef CH_USE_RT_SEMAPHORES void chSemRaisePrioWait(Semaphore *sp); diff --git a/src/templates/chconf.h b/src/templates/chconf.h index 87f9a18b6..478abd8f9 100644 --- a/src/templates/chconf.h +++ b/src/templates/chconf.h @@ -64,6 +64,10 @@ * in the kernel.*/ #define CH_USE_SEMAPHORES +/** Configuration option: if specified then the Semaphores atomic Signal+Wait + * APIs are included in the kernel.*/ +#define CH_USE_SEMSW + /** Configuration option: if specified then the Semaphores with timeout APIs * are included in the kernel. * @note requires \p CH_USE_SEMAPHORES. diff --git a/test/test.c b/test/test.c new file mode 100644 index 000000000..deed9a08c --- /dev/null +++ b/test/test.c @@ -0,0 +1,273 @@ +/* + 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 . +*/ + +#include + +#if defined(WIN32) && defined(_DEBUG) +static BYTE8 wsT1[UserStackSize(512)]; +static BYTE8 wsT2[UserStackSize(512)]; +static BYTE8 wsT3[UserStackSize(512)]; +static BYTE8 wsT4[UserStackSize(512)]; +static BYTE8 wsT5[UserStackSize(512)]; +#else +static BYTE8 wsT1[UserStackSize(64)]; +static BYTE8 wsT2[UserStackSize(64)]; +static BYTE8 wsT3[UserStackSize(64)]; +static BYTE8 wsT4[UserStackSize(64)]; +static BYTE8 wsT5[UserStackSize(64)]; +#endif +static Thread *t1, *t2, *t3, *t4, *t5; + +static FullDuplexDriver *comp; +static Semaphore sem1, sem2; + +static void wait(void) { + + chThdWait(t1); + chThdWait(t2); + chThdWait(t3); + chThdWait(t4); + chThdWait(t5); +} + +static void println(char *msgp) { + + while (*msgp) + chFDDPut(comp, *msgp++); + chFDDPut(comp, '\r'); + chFDDPut(comp, '\n'); +} + +t_msg Thread1(void *p) { + + chFDDPut(comp, *(BYTE8 *)p); + return 0; +} + +t_msg Thread2(void *p) { + + chSemWait(&sem1); + chFDDPut(comp, *(BYTE8 *)p); + return 0; +} + +t_msg Thread3(void *p) { + + chSemRaisePrioWait(&sem1); + chFDDPut(comp, *(BYTE8 *)p); + return 0; +} + +t_msg Thread4(void *p) { + + chSemWait(&sem1); + chFDDPut(comp, *(BYTE8 *)p); + /* + * NOTE: chSemSignalWait() is not the same of chSemSignal()+chSemWait(). + * The former is performed atomically, try it. + */ + chSemSignalWait(&sem1, &sem2); +// chSemSignal(&sem1); +// chSemWait(&sem2); + chFDDPut(comp, *(BYTE8 *)p); + chSemSignal(&sem2); + return 0; +} + +t_msg Thread5(void *p) { + + chSemWait(&sem1); + chFDDPut(comp, *(BYTE8 *)p); + chSemRaisePrioSignalWait(&sem1, &sem2); +// chSemSignal(&sem1); +// chSemRaisePrioWait(&sem2); + chFDDPut(comp, *(BYTE8 *)p); + chSemLowerPrioSignal(&sem2); + return 0; +} + +t_msg Thread6(void *p) { + t_msg msg; + int i; + + for (i = 0; i < 5; i++) { + msg = chMsgSend(p, 'A' + i); + chFDDPut(comp, msg); + } + chMsgSend(p, 0); + return 0; +} + +t_msg Thread7(void *p) { + + // NOTE, this thread does not serve messages this causes the client to + // timeout. + chThdSleep(3000); + return 0; +} + +/** + * Tester thread, this thread must be created with priority \p NORMALPRIO. + */ +t_msg TestThread(void *p) { + t_msg msg; + int i; + + comp = p; + + /* + * Ready list ordering test. + */ + println("*** Ready List, priority enqueuing test #1, you should read ABCDE:"); + t5 = chThdCreate(NORMALPRIO-5, 0, wsT5, sizeof(wsT5), Thread1, "E"); + t4 = chThdCreate(NORMALPRIO-4, 0, wsT4, sizeof(wsT4), Thread1, "D"); + t3 = chThdCreate(NORMALPRIO-3, 0, wsT3, sizeof(wsT3), Thread1, "C"); + t2 = chThdCreate(NORMALPRIO-2, 0, wsT2, sizeof(wsT2), Thread1, "B"); + t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread1, "A"); + wait(); + println(""); + println("*** Ready List, priority enqueuing test #2, you should read ABCDE:"); + t4 = chThdCreate(NORMALPRIO-4, 0, wsT4, sizeof(wsT4), Thread1, "D"); + t5 = chThdCreate(NORMALPRIO-5, 0, wsT5, sizeof(wsT5), Thread1, "E"); + t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread1, "A"); + t2 = chThdCreate(NORMALPRIO-2, 0, wsT2, sizeof(wsT2), Thread1, "B"); + t3 = chThdCreate(NORMALPRIO-3, 0, wsT3, sizeof(wsT3), Thread1, "C"); + wait(); + println(""); + + /* + * Semaphores test. + */ + chSemInit(&sem1, 0); + println("*** Semaphores, FIFO enqueuing test, you should read ABCDE:"); + t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread2, "A"); + t2 = chThdCreate(NORMALPRIO+1, 0, wsT2, sizeof(wsT2), Thread2, "B"); + t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread2, "C"); + t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread2, "D"); + t5 = chThdCreate(NORMALPRIO+2, 0, wsT5, sizeof(wsT5), Thread2, "E"); + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, priority enqueuing test #1, you should read ABCDE:"); + t5 = chThdCreate(NORMALPRIO+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); + t4 = chThdCreate(NORMALPRIO+2, 0, wsT4, sizeof(wsT4), Thread3, "D"); + t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread3, "C"); + t2 = chThdCreate(NORMALPRIO+4, 0, wsT2, sizeof(wsT2), Thread3, "B"); + t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread3, "A"); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, priority enqueuing test #2, you should read ABCDE:"); + t4 = chThdCreate(NORMALPRIO+2, 0, wsT4, sizeof(wsT4), Thread3, "D"); + t5 = chThdCreate(NORMALPRIO+1, 0, wsT5, sizeof(wsT5), Thread3, "E"); + t1 = chThdCreate(NORMALPRIO+5, 0, wsT1, sizeof(wsT1), Thread3, "A"); + t2 = chThdCreate(NORMALPRIO+4, 0, wsT2, sizeof(wsT2), Thread3, "B"); + t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread3, "C"); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + chSemLowerPrioSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, atomicity test #1, you should read ABCDEABCDE:"); + chSemInit(&sem1, 0); + chSemInit(&sem2, 1); + t1 = chThdCreate(NORMALPRIO+1, 0, wsT1, sizeof(wsT1), Thread4, "A"); + t2 = chThdCreate(NORMALPRIO+2, 0, wsT2, sizeof(wsT2), Thread4, "B"); + t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread4, "C"); + t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread4, "D"); + t5 = chThdCreate(NORMALPRIO+5, 0, wsT5, sizeof(wsT5), Thread4, "E"); + chSemSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, atomicity test #2, you should read ABCDEABCDE:"); + chSemInit(&sem1, 0); + chSemInit(&sem2, 1); + t1 = chThdCreate(NORMALPRIO+1, 0, wsT1, sizeof(wsT1), Thread4, "A"); + t2 = chThdCreate(NORMALPRIO+5, 0, wsT2, sizeof(wsT2), Thread4, "B"); + t3 = chThdCreate(NORMALPRIO+2, 0, wsT3, sizeof(wsT3), Thread4, "C"); + t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread4, "D"); + t5 = chThdCreate(NORMALPRIO+3, 0, wsT5, sizeof(wsT5), Thread4, "E"); + chSemSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, atomicity test #3, you should read AABBCCDDEE:"); + chSemInit(&sem1, 0); + chSemInit(&sem2, 1); + t1 = chThdCreate(NORMALPRIO+1, 0, wsT1, sizeof(wsT1), Thread5, "A"); + t2 = chThdCreate(NORMALPRIO+2, 0, wsT2, sizeof(wsT2), Thread5, "B"); + t3 = chThdCreate(NORMALPRIO+3, 0, wsT3, sizeof(wsT3), Thread5, "C"); + t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread5, "D"); + t5 = chThdCreate(NORMALPRIO+5, 0, wsT5, sizeof(wsT5), Thread5, "E"); + chSemSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, atomicity test #4, you should read AABBCCDDEE:"); + chSemInit(&sem1, 0); + chSemInit(&sem2, 1); + t1 = chThdCreate(NORMALPRIO+1, 0, wsT1, sizeof(wsT1), Thread5, "A"); + t2 = chThdCreate(NORMALPRIO+5, 0, wsT2, sizeof(wsT2), Thread5, "B"); + t3 = chThdCreate(NORMALPRIO+2, 0, wsT3, sizeof(wsT3), Thread5, "C"); + t4 = chThdCreate(NORMALPRIO+4, 0, wsT4, sizeof(wsT4), Thread5, "D"); + t5 = chThdCreate(NORMALPRIO+3, 0, wsT5, sizeof(wsT5), Thread5, "E"); + chSemSignal(&sem1); + wait(); + println(""); + println("*** Semaphores, timeout test, you should read ABCDE (slowly):"); + chSemInit(&sem1, 0); + for (i = 0; i < 5; i++) { + chFDDPut(comp, 'A'+i); + chSemWaitTimeout(&sem1, 500); + } + println(""); + + /* + * Messages test. + */ + println("*** Messages, dispatch test, you should read AABBCCDDEE:"); + t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread6, chThdSelf()); + do { + chMsgRelease(msg = chMsgWait()); + if (msg) + chFDDPut(comp, msg); + } while (msg); + chThdWait(t1); + println(""); + println("*** Messages, timeout test, you should read ABCDE (slowly):"); + t1 = chThdCreate(NORMALPRIO-1, 0, wsT1, sizeof(wsT1), Thread7, chThdSelf()); + for (i = 0; i < 5; i++) { + chFDDPut(comp, 'A'+i); + chMsgSendTimeout(t1, 'A'+i, 500); + } + chMsgSendTimeout(t1, 0, 500); + chThdWait(t1); + println(""); + + println("\r\nTest complete"); + return 0; +}