diff options
-rw-r--r-- | os/kernel/include/scheduler.h | 24 | ||||
-rw-r--r-- | os/kernel/include/threads.h | 3 | ||||
-rw-r--r-- | os/kernel/src/chschd.c | 2 | ||||
-rw-r--r-- | os/kernel/src/chthreads.c | 15 | ||||
-rw-r--r-- | readme.txt | 2 | ||||
-rw-r--r-- | test/testbmk.c | 120 |
6 files changed, 131 insertions, 35 deletions
diff --git a/os/kernel/include/scheduler.h b/os/kernel/include/scheduler.h index 235761216..00294e190 100644 --- a/os/kernel/include/scheduler.h +++ b/os/kernel/include/scheduler.h @@ -78,6 +78,12 @@ typedef struct { extern ReadyList rlist; +#ifdef CH_CURRP_REGISTER_CACHE +register Thread *currp asm(CH_CURRP_REGISTER_CACHE); +#else +#define currp rlist.r_current +#endif + /* * Scheduler APIs. */ @@ -96,11 +102,19 @@ extern "C" { } #endif -#ifdef CH_CURRP_REGISTER_CACHE -register Thread *currp asm(CH_CURRP_REGISTER_CACHE); -#else -#define currp rlist.r_current -#endif +/** + * @brief Determines if yielding is possible. + * @details This function returns @p TRUE if there is a ready thread with + * equal or higher priority. + */ +#define chSchCanYieldS() (firstprio(&rlist.r_queue) >= currp->p_prio) + +/** + * @brief Determines if the current thread must reschedule. + * @details This function returns @p TRUE if there is a ready thread with + * higher priority. + */ +#define chSchMustRescheduleS() (firstprio(&rlist.r_queue) >= currp->p_prio) #endif /* _SCHEDULER_H_ */ diff --git a/os/kernel/include/threads.h b/os/kernel/include/threads.h index 7155e9b32..da7dfc152 100644 --- a/os/kernel/include/threads.h +++ b/os/kernel/include/threads.h @@ -183,6 +183,9 @@ extern "C" { #if CH_USE_WAITEXIT msg_t chThdWait(Thread *tp); #endif +#if CH_USE_ROUNDROBIN + void chThdYield(void); +#endif #ifdef __cplusplus } #endif diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index af24f5cf4..6183180bc 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -211,7 +211,7 @@ void chSchDoRescheduleI(void) { void chSchRescheduleS(void) { /* first thread in the runnable queue has higher priority than the running * thread? */ - if (firstprio(&rlist.r_queue) > currp->p_prio) + if (chSchMustRescheduleS()) chSchDoRescheduleI(); } diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c index 583bc7c04..c18a4f8cd 100644 --- a/os/kernel/src/chthreads.c +++ b/os/kernel/src/chthreads.c @@ -290,6 +290,21 @@ void chThdSleepUntil(systime_t time) { chSysUnlock(); } +#if CH_USE_ROUNDROBIN +/** + * @brief Yields the time slot. + * @details Yields the CPU control to the next thread in the ready list with + * equal priority, if any. + */ +void chThdYield(void) { + + chSysLock(); + if (chSchCanYieldS()) + chSchDoRescheduleI(); + chSysUnlock(); +} +#endif /* CH_USE_ROUNDROBIN */ + /** * @brief Terminates the current thread by specifying an exit status code. * diff --git a/readme.txt b/readme.txt index 8b0608363..8a90b6f15 100644 --- a/readme.txt +++ b/readme.txt @@ -12,6 +12,8 @@ - FIX: Fixed GCC 4.4.x related problems in CM3 port (bug 2846162).(backported
in stable branch)
- FIX: Fixed LPC214x UART problem (bug 2841088)(backported in stable branch).
+- NEW: Added new API chThdYield().
+- MEW: Added new benchmark about round robin rescheduling.
- NEW: Reorganized and rationalized the distribution tree and the
documentation.
- NEW: Enhanced serial driver. The driver now supports speed change at runtime
diff --git a/test/testbmk.c b/test/testbmk.c index 7a99c37af..f44ae0b8b 100644 --- a/test/testbmk.c +++ b/test/testbmk.c @@ -418,7 +418,66 @@ const struct testcase testbmk7 = { };
/**
- * @page test_benchmarks_008 I/O Queues throughput
+ * @page test_benchmarks_009 I/O Round-Robin voluntary rescedulation.
+ *
+ * <h2>Description</h2>
+ * Five threads are created at equal priority, each thread just increases a
+ * variable and yields.<br>
+ * The performance is calculated by measuring the number of iterations after
+ * a second of continuous operations.
+ */
+
+#if CH_USE_ROUNDROBIN
+static msg_t thread8(void *p) {
+
+ do {
+ chThdYield();
+ chThdYield();
+ chThdYield();
+ chThdYield();
+ (*(uint32_t *)p) += 4;
+ } while(!chThdShouldTerminate());
+ return 0;
+}
+
+static char *bmk8_gettest(void) {
+
+ return "Benchmark, round robin context switching";
+}
+
+static void bmk8_execute(void) {
+ uint32_t n;
+
+ n = 0;
+ test_wait_tick();
+
+ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
+ threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
+ threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
+ threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
+ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread8, (void *)&n);
+
+ chThdSleepSeconds(1);
+ test_terminate_threads();
+ test_wait_threads();
+
+ test_print("--- Score : ");
+ test_printn(n);
+ test_print(" reschedulations/S, ");
+ test_printn(n);
+ test_println(" ctxswc/S");
+}
+
+const struct testcase testbmk8 = {
+ bmk8_gettest,
+ NULL,
+ NULL,
+ bmk8_execute
+};
+#endif
+
+/**
+ * @page test_benchmarks_009 I/O Queues throughput
*
* <h2>Description</h2>
* Four bytes are written and then read from an @p InputQueue into a continuous
@@ -427,12 +486,12 @@ const struct testcase testbmk7 = { * a second of continuous operations.
*/
-static char *bmk8_gettest(void) {
+static char *bmk9_gettest(void) {
return "Benchmark, I/O Queues throughput";
}
-static void bmk8_execute(void) {
+static void bmk9_execute(void) {
static uint8_t ib[16];
static InputQueue iq;
@@ -459,15 +518,15 @@ static void bmk8_execute(void) { test_println(" bytes/S");
}
-const struct testcase testbmk8 = {
- bmk8_gettest,
+const struct testcase testbmk9 = {
+ bmk9_gettest,
NULL,
NULL,
- bmk8_execute
+ bmk9_execute
};
/**
- * @page test_benchmarks_009 Virtual Timers set/reset performance
+ * @page test_benchmarks_010 Virtual Timers set/reset performance
*
* <h2>Description</h2>
* A virtual timer is set and immediately reset into a continuous loop.<br>
@@ -475,14 +534,14 @@ const struct testcase testbmk8 = { * a second of continuous operations.
*/
-static char *bmk9_gettest(void) {
+static char *bmk10_gettest(void) {
return "Benchmark, virtual timers set/reset";
}
static void tmo(void *param) {}
-static void bmk9_execute(void) {
+static void bmk10_execute(void) {
static VirtualTimer vt1, vt2;
uint32_t n = 0;
@@ -505,15 +564,15 @@ static void bmk9_execute(void) { test_println(" timers/S");
}
-const struct testcase testbmk9 = {
- bmk9_gettest,
+const struct testcase testbmk10 = {
+ bmk10_gettest,
NULL,
NULL,
- bmk9_execute
+ bmk10_execute
};
/**
- * @page test_benchmarks_010 Semaphores wait/signal performance
+ * @page test_benchmarks_011 Semaphores wait/signal performance
*
* <h2>Description</h2>
* A counting semaphore is taken/released into a continuous loop, no Context
@@ -522,17 +581,17 @@ const struct testcase testbmk9 = { * a second of continuous operations.
*/
-static char *bmk10_gettest(void) {
+static char *bmk11_gettest(void) {
return "Benchmark, semaphores wait/signal";
}
-static void bmk10_setup(void) {
+static void bmk11_setup(void) {
chSemInit(&sem1, 1);
}
-static void bmk10_execute(void) {
+static void bmk11_execute(void) {
uint32_t n = 0;
test_wait_tick();
@@ -556,16 +615,16 @@ static void bmk10_execute(void) { test_println(" wait+signal/S");
}
-const struct testcase testbmk10 = {
- bmk10_gettest,
- bmk10_setup,
+const struct testcase testbmk11 = {
+ bmk11_gettest,
+ bmk11_setup,
NULL,
- bmk10_execute
+ bmk11_execute
};
#if CH_USE_MUTEXES
/**
- * @page test_benchmarks_011 Mutexes lock/unlock performance
+ * @page test_benchmarks_012 Mutexes lock/unlock performance
*
* <h2>Description</h2>
* A mutex is locked/unlocked into a continuous loop, no Context Switch happens
@@ -574,17 +633,17 @@ const struct testcase testbmk10 = { * a second of continuous operations.
*/
-static char *bmk11_gettest(void) {
+static char *bmk12_gettest(void) {
return "Benchmark, mutexes lock/unlock";
}
-static void bmk11_setup(void) {
+static void bmk12_setup(void) {
chMtxInit(&mtx1);
}
-static void bmk11_execute(void) {
+static void bmk12_execute(void) {
uint32_t n = 0;
test_wait_tick();
@@ -608,11 +667,11 @@ static void bmk11_execute(void) { test_println(" lock+unlock/S");
}
-const struct testcase testbmk11 = {
- bmk11_gettest,
- bmk11_setup,
+const struct testcase testbmk12 = {
+ bmk12_gettest,
+ bmk12_setup,
NULL,
- bmk11_execute
+ bmk12_execute
};
#endif
@@ -628,11 +687,14 @@ const struct testcase * const patternbmk[] = { &testbmk5,
&testbmk6,
&testbmk7,
+#if CH_USE_ROUNDROBIN
&testbmk8,
+#endif
&testbmk9,
&testbmk10,
-#if CH_USE_MUTEXES
&testbmk11,
+#if CH_USE_MUTEXES
+ &testbmk12,
#endif
#endif
NULL
|