Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | /* * Copyright (c) 2011-2016 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr.h> #include <ztest.h> #include <debug/object_tracing.h> extern void test_obj_tracing(void); #define STSIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE) #define N_PHILOSOPHERS 5 #define TOTAL_TEST_NUMBER 2 #define ZTEST_THREADS_CREATED 1 #define TOTAL_THREADS (N_PHILOSOPHERS + 3 + IPM_THREAD + ZTEST_THREADS_CREATED) #define TOTAL_OBJECTS (N_PHILOSOPHERS) #define OBJ_LIST_NAME k_sem #define OBJ_LIST_TYPE struct k_sem #define FORK(x) (&forks[x]) #define TAKE(x) k_sem_take(x, K_FOREVER) #define GIVE(x) k_sem_give(x) #define RANDDELAY(x) k_sleep(10 * (x) + 1) /* 1 IPM console thread if enabled */ #if defined(CONFIG_IPM_CONSOLE_RECEIVER) && defined(CONFIG_PRINTK) #define IPM_THREAD 1 #else #define IPM_THREAD 0 #endif /* CONFIG_IPM_CONSOLE_RECEIVER && CONFIG_PRINTK*/ /* Must account for: * N Philosopher threads * 1 Object monitor thread * 1 System idle thread * 1 System workqueue thread * 1 IPM console thread */ void *force_sys_work_q_in = (void *)&k_sys_work_q; K_THREAD_STACK_ARRAY_DEFINE(phil_stack, N_PHILOSOPHERS, STSIZE); static struct k_thread phil_data[N_PHILOSOPHERS]; K_THREAD_STACK_DEFINE(mon_stack, STSIZE); static struct k_thread mon_data; struct k_sem forks[N_PHILOSOPHERS]; K_SEM_DEFINE(f3, -5, 1); /** * @brief Object Tracing Tests * @defgroup kernel_objtracing_tests Object Tracing Tests * @ingroup all_tests * @{ * @} */ static inline int test_thread_monitor(void) { int obj_counter = 0; struct k_thread *thread_list = NULL; /* wait a bit to allow any initialization-only threads to terminate */ thread_list = (struct k_thread *)SYS_THREAD_MONITOR_HEAD; while (thread_list != NULL) { if (thread_list->base.prio == -1) { TC_PRINT("PREMPT: %p OPTIONS: 0x%02x, STATE: 0x%02x\n", thread_list, thread_list->base.user_options, thread_list->base.thread_state); } else { TC_PRINT("COOP: %p OPTIONS: 0x%02x, STATE: 0x%02x\n", thread_list, thread_list->base.user_options, thread_list->base.thread_state); } thread_list = (struct k_thread *)SYS_THREAD_MONITOR_NEXT(thread_list); obj_counter++; } TC_PRINT("THREAD QUANTITY: %d\n", obj_counter); return obj_counter; } static void object_monitor(void) { int obj_counter = 0; int thread_counter = 0, sem = 0; void *obj_list = NULL; k_sem_take(&f3, 0); /* ztest use one semaphore so use one count less than expected to pass * test */ obj_list = SYS_TRACING_HEAD(OBJ_LIST_TYPE, OBJ_LIST_NAME); while (obj_list != NULL) { TC_PRINT("SEMAPHORE REF: %p\n", obj_list); obj_list = SYS_TRACING_NEXT(OBJ_LIST_TYPE, OBJ_LIST_NAME, obj_list); for (sem = 0; sem < N_PHILOSOPHERS; sem++) { if (obj_list == &forks[sem] || obj_list == &f3) { obj_counter++; break; } } } TC_PRINT("SEMAPHORE QUANTITY: %d\n", obj_counter); thread_counter += test_thread_monitor(); zassert_true(((thread_counter == TOTAL_THREADS) && (obj_counter == TOTAL_OBJECTS)), "test failed"); } static void phil_entry(void) { int counter; struct k_sem *f1; /* fork #1 */ struct k_sem *f2; /* fork #2 */ static int myId; /* next philosopher ID */ unsigned int pri = irq_lock(); /* interrupt lock level */ int id = myId++; /* current philosopher ID */ irq_unlock(pri); /* always take the lowest fork first */ if ((id + 1) != N_PHILOSOPHERS) { f1 = FORK(id); f2 = FORK(id + 1); } else { f1 = FORK(0); f2 = FORK(id); } for (counter = 0; counter < 5; counter++) { TAKE(f1); TAKE(f2); RANDDELAY(id); GIVE(f2); GIVE(f1); RANDDELAY(id); } GIVE(&f3); } /** * @brief Trace the number of objects created * * @ingroup kernel_objtracing_tests * * @details The test uses dining philsophers problem as * an application that implements multiple threads that * are synchronized with semaphores. */ void test_philosophers_tracing(void) { int i; for (i = 0; i < N_PHILOSOPHERS; i++) { k_sem_init(&forks[i], 1, 1); } /* create philosopher threads */ for (i = 0; i < N_PHILOSOPHERS; i++) { k_thread_create(&phil_data[i], &phil_stack[i][0], STSIZE, (k_thread_entry_t)phil_entry, NULL, NULL, NULL, K_PRIO_COOP(6), 0, K_NO_WAIT); } /* create object counter monitor thread */ k_thread_create(&mon_data, mon_stack, STSIZE, (k_thread_entry_t)object_monitor, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); } void test_main(void) { ztest_test_suite(obj_tracing, ztest_unit_test(test_philosophers_tracing), ztest_unit_test(test_obj_tracing)); ztest_run_test_suite(obj_tracing); } |