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;
+}