+#define WORKER_STACK_SIZE KERN_MINSTACKSIZE * 2
+
+#if CONFIG_KERN_HEAP
+#define WORKER_STACK(id) NULL
+#else /* !CONFIG_KERN_HEAP */
+static cpu_stack_t worker_stack[TASKS][(WORKER_STACK_SIZE +
+ sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)];
+#define WORKER_STACK(id) (&worker_stack[id][0])
+#endif /* CONFIG_KERN_HEAP */
+
+static int prime_numbers[] =
+{
+ 1, 3, 5, 7, 11, 13, 17, 19,
+ 23, 29, 31, 37, 41, 43, 47, 53,
+};
+STATIC_ASSERT(TASKS <= countof(prime_numbers));
+
+#if CONFIG_KERN_PREEMPT
+/* Time to run each preemptible thread (in seconds) */
+#define TIME 10
+
+static unsigned int preempt_counter[TASKS];
+static unsigned int preempt_done[TASKS];
+#endif
+
+static void cleanup(void)
+{
+#if CONFIG_KERN_PREEMPT
+ // Clear shared data (this is needed when this testcase is embedded in
+ // the demo application).
+ memset(preempt_counter, 0, sizeof(preempt_counter));
+ memset(preempt_done, 0, sizeof(preempt_done));
+#endif /* CONFIG_KERN_PREEMPT */
+ memset(done, 0, sizeof(done));
+ memset(barrier, 0, sizeof(barrier));
+ main_barrier = 0;
+}
+
+static void worker(void)
+{
+ ssize_t pid = (ssize_t)proc_currentUserData();
+ long tot = prime_numbers[pid - 1];
+ unsigned int my_count = 0;
+ int i;
+
+ barrier[pid - 1] = 1;
+ /* Synchronize on the main barrier */
+ while (!main_barrier)
+ proc_yield();
+ for (i = 0; i < tot; i++)
+ {
+ my_count++;
+ PROC_ATOMIC(kprintf("> %s[%zd] running\n", __func__, pid));
+ timer_delay(tot * DELAY);
+ }
+ done[pid - 1] = 1;
+ PROC_ATOMIC(kprintf("> %s[%zd] completed\n", __func__, pid));
+}
+
+static int worker_test(void)
+{
+ ssize_t i;
+
+ // Init the test processes
+ cleanup();
+ kputs("Run Proc test..\n");
+ for (i = 0; i < TASKS; i++)
+ {
+ name[i][0] = '\0';
+ snprintf(&name[i][0], sizeof(name[i]), "worker_%zd", i + 1);
+ name[i][sizeof(name[i]) - 1] = '\0';
+ proc_new_with_name(name[i], worker, (iptr_t)(i + 1),
+ WORKER_STACK_SIZE, WORKER_STACK(i));
+ }
+ /* Synchronize on start */
+ while (1)
+ {
+ for (i = 0; i < TASKS; i++)
+ if (!barrier[i])
+ break;
+ if (i == TASKS)
+ break;
+ proc_yield();
+ }
+ main_barrier = 1;
+ MEMORY_BARRIER;
+ kputs("> Main: Processes started\n");
+ while (1)
+ {
+ for (i = 0; i < TASKS; i++)
+ {
+ if (!done[i])
+ break;
+ }
+ if (i == TASKS)
+ break;
+ monitor_report();
+ timer_delay(93);
+ }
+ kputs("> Main: process test finished..ok!\n");
+ return 0;
+}
+
+#if CONFIG_KERN_PREEMPT
+static void preempt_worker(void)
+{
+ ssize_t pid = (ssize_t)proc_currentUserData();
+ unsigned int *my_count = &preempt_counter[pid - 1];
+ ticks_t start, stop;
+ int i;
+
+ barrier[pid - 1] = 1;
+ /* Synchronize on the main barrier */
+ while (!main_barrier)
+ proc_yield();
+ PROC_ATOMIC(kprintf("> %s[%zd] running\n", __func__, pid));
+ start = timer_clock();
+ stop = ms_to_ticks(TIME * 1000);
+ while (timer_clock() - start < stop)
+ {
+ IRQ_ASSERT_ENABLED();
+ (*my_count)++;
+ /* be sure to wrap to a value different than 0 */
+ if (UNLIKELY(*my_count == (unsigned int)~0))
+ *my_count = 1;
+ }
+ PROC_ATOMIC(kprintf("> %s[%zd] completed: (counter = %d)\n",
+ __func__, pid, *my_count));
+ for (i = 0; i < TASKS; i++)
+ if (!preempt_counter[i])
+ {
+ preempt_done[pid - 1] = TEST_FAIL;
+ return;
+ }
+ preempt_done[pid - 1] = TEST_OK;
+}
+
+static int preempt_worker_test(void)
+{
+ unsigned long score = 0;
+ ssize_t i;
+
+ // Init the test processes
+ cleanup();
+ kputs("Run Preemption test..\n");
+ for (i = 0; i < TASKS; i++)
+ {
+ name[i][0] = '\0';
+ snprintf(&name[i][0], sizeof(name[i]),
+ "preempt_worker_%zd", i + 1);
+ name[i][sizeof(name[i]) - 1] = '\0';
+ proc_new_with_name(name[i], preempt_worker, (iptr_t)(i + 1),
+ WORKER_STACK_SIZE, WORKER_STACK(i));
+ }
+ kputs("> Main: Processes created\n");
+ /* Synchronize on start */
+ while (1)
+ {
+ for (i = 0; i < TASKS; i++)
+ if (!barrier[i])
+ break;
+ if (i == TASKS)
+ break;
+ proc_yield();
+ }
+ /* Now all threads have been created, start them all */
+ main_barrier = 1;
+ MEMORY_BARRIER;
+ kputs("> Main: Processes started\n");
+ while (1)
+ {
+ for (i = 0; i < TASKS; i++)
+ {
+ if (!preempt_done[i])
+ break;
+ else if (preempt_done[i] == TEST_FAIL)
+ {
+ kputs("> Main: process test finished..fail!\n");
+ return -1;
+ }
+ }
+ if (i == TASKS)
+ break;
+ monitor_report();
+ timer_delay(1000);
+ }
+ for (i = 0; i < TASKS; i++)
+ score += preempt_counter[i];
+ kputs("> Main: process test finished..ok!\n");
+ kprintf("> Score: %lu\n", score);
+ return 0;
+}
+#endif /* CONFIG_KERN_PREEMPT */
+
+#if CONFIG_KERN_SIGNALS & CONFIG_KERN_PRI