aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/LPC214x-GCC/chconf.h4
-rw-r--r--demos/Win32-MSVS/ch.vcproj7
-rw-r--r--demos/Win32-MSVS/chconf.h8
-rw-r--r--demos/Win32-MSVS/demo.c21
-rw-r--r--demos/Win32-MinGW/Makefile2
-rw-r--r--demos/Win32-MinGW/chconf.h8
-rw-r--r--demos/Win32-MinGW/chcore.c2
-rw-r--r--demos/Win32-MinGW/chcore2.s2
-rw-r--r--demos/Win32-MinGW/demo.c17
-rw-r--r--docs/Doxyfile3
-rw-r--r--readme.txt21
-rw-r--r--src/chsem.c21
-rw-r--r--src/include/delta.h3
-rw-r--r--src/include/semaphores.h2
-rw-r--r--src/templates/chconf.h4
-rw-r--r--test/test.c273
16 files changed, 364 insertions, 34 deletions
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">
</File>
</Filter>
+ <Filter
+ Name="test"
+ Filter="">
+ <File
+ RelativePath="..\..\test\test.c">
+ </File>
+ </Filter>
</Filter>
<Filter
Name="Header Files"
diff --git a/demos/Win32-MSVS/chconf.h b/demos/Win32-MSVS/chconf.h
index 59a13d224..da7fcd266 100644
--- a/demos/Win32-MSVS/chconf.h
+++ b/demos/Win32-MSVS/chconf.h
@@ -68,6 +68,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.
@@ -134,11 +138,11 @@
/** Configuration option: Frequency of the system timer that drives the system
* ticks. This also defines the system time unit.*/
-#define CH_FREQUENCY 100
+#define CH_FREQUENCY 1000
/** Configuration option: This constant is the number of ticks allowed for the
* threads before preemption occurs.*/
-#define CH_TIME_QUANTUM 10
+#define CH_TIME_QUANTUM 20
/** Configuration option: Defines a CPU register to be used as storage for the
* global \p currp variable. Caching this variable in a register can greatly
diff --git a/demos/Win32-MSVS/demo.c b/demos/Win32-MSVS/demo.c
index d068ca730..077877f8e 100644
--- a/demos/Win32-MSVS/demo.c
+++ b/demos/Win32-MSVS/demo.c
@@ -31,11 +31,13 @@ static BYTE8 iarea[UserStackSize(2048)];
static ULONG32 cdguard;
static BYTE8 cdarea[UserStackSize(2048)];
static Thread *cdtp;
-
+
static t_msg WatchdogThread(void *arg);
static t_msg ConsoleThread(void *arg);
static t_msg InitThread(void *arg);
+t_msg TestThread(void *p);
+
void InitCore(void);
extern FullDuplexDriver COM1, COM2;
@@ -73,7 +75,7 @@ static t_msg WatchdogThread(void *arg) {
printf("Halted by watchdog");
chSysHalt();
}
- chThdSleep(5);
+ chThdSleep(50);
}
return 0;
}
@@ -144,7 +146,7 @@ static t_msg HelloWorldThread(void *arg) {
for (i = 0; i < 100; i++) {
PrintLineFDD(sd, "Hello World\r\n");
- c = chFDDGetTimeout(sd, 33);
+ c = chFDDGetTimeout(sd, 333);
switch (c) {
case -1:
continue;
@@ -154,7 +156,7 @@ static t_msg HelloWorldThread(void *arg) {
PrintLineFDD(sd, "^C\r\n");
return 0;
default:
- chThdSleep(33);
+ chThdSleep(333);
}
}
return 0;
@@ -202,6 +204,7 @@ static t_msg ShellThread(void *arg) {
PrintLineFDD(sd, " exit - Logout from ChibiOS/RT\r\n");
PrintLineFDD(sd, " time - Prints the system timer value\r\n");
PrintLineFDD(sd, " hello - Runs the Hello World demo thread\r\n");
+ PrintLineFDD(sd, " test - Runs the System Test thread\r\n");
}
else if (stricmp(lp, "exit") == 0) {
if (checkend(sd))
@@ -223,6 +226,14 @@ static t_msg ShellThread(void *arg) {
if (chThdWait(tp))
break; // Lost connection while executing the hello thread.
}
+ else if (stricmp(lp, "test") == 0) {
+ if (checkend(sd))
+ continue;
+ tp = chThdCreate(NORMALPRIO, 0, tarea, sizeof(tarea),
+ TestThread, arg);
+ if (chThdWait(tp))
+ break; // Lost connection while executing the hello thread.
+ }
else {
PrintLineFDD(sd, lp);
PrintLineFDD(sd, " ?\r\n");
@@ -281,7 +292,7 @@ static void COM2Handler(t_eventid id) {
static t_evhandler fhandlers[2] = {
COM1Handler,
COM2Handler
-};
+};
/*
* Init-like thread, it starts the shells and handles their termination.
diff --git a/demos/Win32-MinGW/Makefile b/demos/Win32-MinGW/Makefile
index 4ab603d8e..9ee9dfb77 100644
--- a/demos/Win32-MinGW/Makefile
+++ b/demos/Win32-MinGW/Makefile
@@ -57,7 +57,7 @@ UADEFS =
# List C source files here
SRC = chcore.c demo.c \
- ../../ports/win32/simcom.c \
+ ../../test/test.c ../../ports/win32/simcom.c \
../../src/chinit.c ../../src/chlists.c ../../src/chdelta.c ../../src/chschd.c \
../../src/chthreads.c ../../src/chsem.c ../../src/chevents.c ../../src/chmsg.c \
../../src/chsleep.c ../../src/chqueues.c ../../src/chserial.c
diff --git a/demos/Win32-MinGW/chconf.h b/demos/Win32-MinGW/chconf.h
index 13de9f457..5582ae80a 100644
--- a/demos/Win32-MinGW/chconf.h
+++ b/demos/Win32-MinGW/chconf.h
@@ -68,6 +68,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.
@@ -134,11 +138,11 @@
/** Configuration option: Frequency of the system timer that drives the system
* ticks. This also defines the system time unit.*/
-#define CH_FREQUENCY 100
+#define CH_FREQUENCY 1000
/** Configuration option: This constant is the number of ticks allowed for the
* threads before preemption occurs.*/
-#define CH_TIME_QUANTUM 10
+#define CH_TIME_QUANTUM 20
/** Configuration option: Defines a CPU register to be used as storage for the
* global \p currp variable. Caching this variable in a register can greatly
diff --git a/demos/Win32-MinGW/chcore.c b/demos/Win32-MinGW/chcore.c
index d48188b49..77195c44c 100644
--- a/demos/Win32-MinGW/chcore.c
+++ b/demos/Win32-MinGW/chcore.c
@@ -52,7 +52,7 @@ void InitCore(void) {
exit(1);
}
- printf("Win32 ChobiOS/RT simulator\n\n");
+ printf("Win32 ChibiOS/RT simulator\n\n");
printf("Thread structure %d bytes\n", sizeof(Thread));
if (!QueryPerformanceFrequency(&slice)) {
printf("QueryPerformanceFrequency() error");
diff --git a/demos/Win32-MinGW/chcore2.s b/demos/Win32-MinGW/chcore2.s
index 80985e3f7..c8260e3e6 100644
--- a/demos/Win32-MinGW/chcore2.s
+++ b/demos/Win32-MinGW/chcore2.s
@@ -39,5 +39,5 @@
.p2align 4,,15
.globl @threadstart@0
@threadstart@0:
- push %ecx
+ push %eax
call _chThdExit
diff --git a/demos/Win32-MinGW/demo.c b/demos/Win32-MinGW/demo.c
index 166923d2c..077877f8e 100644
--- a/demos/Win32-MinGW/demo.c
+++ b/demos/Win32-MinGW/demo.c
@@ -36,6 +36,8 @@ static t_msg WatchdogThread(void *arg);
static t_msg ConsoleThread(void *arg);
static t_msg InitThread(void *arg);
+t_msg TestThread(void *p);
+
void InitCore(void);
extern FullDuplexDriver COM1, COM2;
@@ -73,7 +75,7 @@ static t_msg WatchdogThread(void *arg) {
printf("Halted by watchdog");
chSysHalt();
}
- chThdSleep(5);
+ chThdSleep(50);
}
return 0;
}
@@ -144,7 +146,7 @@ static t_msg HelloWorldThread(void *arg) {
for (i = 0; i < 100; i++) {
PrintLineFDD(sd, "Hello World\r\n");
- c = chFDDGetTimeout(sd, 33);
+ c = chFDDGetTimeout(sd, 333);
switch (c) {
case -1:
continue;
@@ -154,7 +156,7 @@ static t_msg HelloWorldThread(void *arg) {
PrintLineFDD(sd, "^C\r\n");
return 0;
default:
- chThdSleep(33);
+ chThdSleep(333);
}
}
return 0;
@@ -202,6 +204,7 @@ static t_msg ShellThread(void *arg) {
PrintLineFDD(sd, " exit - Logout from ChibiOS/RT\r\n");
PrintLineFDD(sd, " time - Prints the system timer value\r\n");
PrintLineFDD(sd, " hello - Runs the Hello World demo thread\r\n");
+ PrintLineFDD(sd, " test - Runs the System Test thread\r\n");
}
else if (stricmp(lp, "exit") == 0) {
if (checkend(sd))
@@ -223,6 +226,14 @@ static t_msg ShellThread(void *arg) {
if (chThdWait(tp))
break; // Lost connection while executing the hello thread.
}
+ else if (stricmp(lp, "test") == 0) {
+ if (checkend(sd))
+ continue;
+ tp = chThdCreate(NORMALPRIO, 0, tarea, sizeof(tarea),
+ TestThread, arg);
+ if (chThdWait(tp))
+ break; // Lost connection while executing the hello thread.
+ }
else {
PrintLineFDD(sd, lp);
PrintLineFDD(sd, " ?\r\n");
diff --git a/docs/Doxyfile b/docs/Doxyfile
index 0bcdbdbf2..2129c1de5 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -241,7 +241,8 @@ PREDEFINED = __JUST_STUBS__ \
CH_USE_SERIAL_HALFDUPLEX \
CH_USE_MESSAGES \
CH_USE_MESSAGES_TIMEOUT \
- CH_USE_MESSAGES_EVENT
+ CH_USE_MESSAGES_EVENT \
+ CH_USE_SEMSW
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
diff --git a/readme.txt b/readme.txt
index 6261bb2da..e76cbe524 100644
--- a/readme.txt
+++ b/readme.txt
@@ -33,23 +33,36 @@ LPC214x-GCC - ChibiOS/RT port for ARM7 LPC2148, the demo targets the
*****************************************************************************
*** 0.3.1 ***
+- Test program added to the MinGW and MSVS demos. Telnet the demo and type
+ "test" at the "ch>" 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.h>
+
+#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;
+}