From 7dfa36f86d896cdb824a9137a81f324c8243c4d9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 5 Sep 2009 15:31:27 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1148 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/include/scheduler.h | 24 +++++++-- os/kernel/include/threads.h | 3 ++ os/kernel/src/chschd.c | 2 +- os/kernel/src/chthreads.c | 15 ++++++ readme.txt | 2 + 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. + * + *

Description

+ * Five threads are created at equal priority, each thread just increases a + * variable and yields.
+ * 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 * *

Description

* 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 * *

Description

* A virtual timer is set and immediately reset into a continuous loop.
@@ -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 * *

Description

* 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 * *

Description

* 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 -- cgit v1.2.3