| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /*
- * Copyright (c) 2008 Travis Geiselbrecht
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- #include <debug.h>
- #include <rand.h>
- #include <app/tests.h>
- #include <kernel/thread.h>
- #include <kernel/mutex.h>
- #include <kernel/event.h>
- static int sleep_thread(void *arg)
- {
- for(;;) {
- printf("sleeper %p\n", current_thread);
- thread_sleep(rand() % 500);
- }
- return 0;
- }
- int sleep_test(void)
- {
- int i;
- for(i=0; i < 16; i++)
- thread_resume(thread_create("sleeper", &sleep_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- return 0;
- }
- static volatile int shared = 0;
- static mutex_t m;
- static volatile int mutex_thread_count = 0;
- static int mutex_thread(void *arg)
- {
- int i;
- const int iterations = 10000;
- atomic_add(&mutex_thread_count, 1);
- printf("mutex tester thread %p starting up, will go for %d iterations\n", current_thread, iterations);
- for (i = 0; i < iterations; i++) {
- mutex_acquire(&m);
- if (shared != 0)
- panic("someone else has messed with the shared data\n");
- shared = (int)current_thread;
- thread_yield();
- shared = 0;
- mutex_release(&m);
- thread_yield();
- }
- atomic_add(&mutex_thread_count, -1);
- return 0;
- }
- static int mutex_timeout_thread(void *arg)
- {
- mutex_t *timeout_mutex = (mutex_t *)arg;
- status_t err;
- printf("mutex_timeout_thread acquiring mutex %p with 1 second timeout\n", timeout_mutex);
- err = mutex_acquire_timeout(timeout_mutex, 1000);
- printf("mutex_acquire_timeout returns %d\n", err);
- return err;
- }
- static int mutex_zerotimeout_thread(void *arg)
- {
- mutex_t *timeout_mutex = (mutex_t *)arg;
- status_t err;
- printf("mutex_zerotimeout_thread acquiring mutex %p with zero second timeout\n", timeout_mutex);
- err = mutex_acquire_timeout(timeout_mutex, 0);
- printf("mutex_acquire_timeout returns %d\n", err);
- return err;
- }
- int mutex_test(void)
- {
- mutex_init(&m);
- int i;
- for(i=0; i < 5; i++)
- thread_resume(thread_create("mutex tester", &mutex_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(1000);
- while (mutex_thread_count > 0)
- thread_yield();
- printf("done with simple mutex tests\n");
- printf("testing mutex timeout\n");
- mutex_t timeout_mutex;
- mutex_init(&timeout_mutex);
- mutex_acquire(&timeout_mutex);
- for (i=0; i < 2; i++)
- thread_resume(thread_create("mutex timeout tester", &mutex_timeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- for (i=0; i < 2; i++)
- thread_resume(thread_create("mutex timeout tester", &mutex_zerotimeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(5000);
- mutex_release(&timeout_mutex);
- printf("done with mutex tests\n");
- mutex_destroy(&timeout_mutex);
- return 0;
- }
- static event_t e;
- static int event_signaller(void *arg)
- {
- printf("event signaller pausing\n");
- thread_sleep(1000);
- // for (;;) {
- printf("signalling event\n");
- event_signal(&e, true);
- printf("done signalling event\n");
- thread_yield();
- // }
- return 0;
- }
- static int event_waiter(void *arg)
- {
- printf("event waiter starting\n");
- for (;;) {
- printf("%p: waiting on event...\n", current_thread);
- if (event_wait(&e) < 0) {
- printf("%p: event_wait() returned error\n", current_thread);
- return -1;
- }
- printf("%p: done waiting on event...\n", current_thread);
- thread_yield();
- }
- return 0;
- }
- void event_test(void)
- {
- /* make sure signalling the event wakes up all the threads */
- event_init(&e, false, 0);
- thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(2000);
- event_destroy(&e);
- /* make sure signalling the event wakes up precisely one thread */
- event_init(&e, false, EVENT_FLAG_AUTOUNSIGNAL);
- thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(2000);
- event_destroy(&e);
- }
- static int quantum_tester(void *arg)
- {
- for (;;) {
- printf("%p: in this thread. rq %d\n", current_thread, current_thread->remaining_quantum);
- }
- return 0;
- }
- void quantum_test(void)
- {
- thread_resume(thread_create("quantum tester 0", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("quantum tester 1", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("quantum tester 2", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("quantum tester 3", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- }
- static event_t context_switch_event;
- static event_t context_switch_done_event;
- static int context_switch_tester(void *arg)
- {
- int i;
- uint total_count = 0;
- const int iter = 100000;
- int thread_count = (int)arg;
- event_wait(&context_switch_event);
- uint count = arch_cycle_count();
- for (i = 0; i < iter; i++) {
- thread_yield();
- }
- total_count += arch_cycle_count() - count;
- thread_sleep(1000);
- printf("took %u cycles to yield %d times, %u per yield, %u per yield per thread\n",
- total_count, iter, total_count / iter, total_count / iter / thread_count);
- event_signal(&context_switch_done_event, true);
- return 0;
- }
- void context_switch_test(void)
- {
- event_init(&context_switch_event, false, 0);
- event_init(&context_switch_done_event, false, 0);
- thread_resume(thread_create("context switch idle", &context_switch_tester, (void *)1, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(100);
- event_signal(&context_switch_event, true);
- event_wait(&context_switch_done_event);
- thread_sleep(100);
- event_unsignal(&context_switch_event);
- event_unsignal(&context_switch_done_event);
- thread_resume(thread_create("context switch 2a", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("context switch 2b", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(100);
- event_signal(&context_switch_event, true);
- event_wait(&context_switch_done_event);
- thread_sleep(100);
- event_unsignal(&context_switch_event);
- event_unsignal(&context_switch_done_event);
- thread_resume(thread_create("context switch 4a", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("context switch 4b", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("context switch 4c", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("context switch 4d", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
- thread_sleep(100);
- event_signal(&context_switch_event, true);
- event_wait(&context_switch_done_event);
- thread_sleep(100);
- }
- static volatile int atomic;
- static volatile int atomic_count;
- static int atomic_tester(void *arg)
- {
- int add = (int)arg;
- int i;
- TRACEF("add %d\n", add);
- for (i=0; i < 1000000; i++) {
- atomic_add(&atomic, add);
- }
- int old = atomic_add(&atomic_count, -1);
- TRACEF("exiting, old count %d\n", old);
- return 0;
- }
- static void atomic_test(void)
- {
- atomic = 0;
- atomic_count = 8;
- thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
- while (atomic_count > 0) {
- thread_sleep(1);
- }
- printf("atomic count == %d (should be zero)\n", atomic);
- }
- int thread_tests(void)
- {
- mutex_test();
- event_test();
- thread_sleep(200);
- context_switch_test();
- atomic_test();
-
- return 0;
- }
|