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 | /* critical.c - test the offload workqueue API */ /* * Copyright (c) 2013-2014 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /* * DESCRIPTION * This module tests the offload workqueue. */ #include <zephyr.h> #include <linker/sections.h> #include <ztest.h> #define NUM_MILLISECONDS 5000 #define TEST_TIMEOUT 20000 static u32_t critical_var; static u32_t alt_task_iterations; static struct k_work_q offload_work_q; static K_THREAD_STACK_DEFINE(offload_work_q_stack, CONFIG_OFFLOAD_WORKQUEUE_STACK_SIZE); #define STACK_SIZE 1024 static K_THREAD_STACK_DEFINE(stack1, STACK_SIZE); static K_THREAD_STACK_DEFINE(stack2, STACK_SIZE); static struct k_thread thread1; static struct k_thread thread2; K_SEM_DEFINE(ALT_SEM, 0, UINT_MAX); K_SEM_DEFINE(REGRESS_SEM, 0, UINT_MAX); K_SEM_DEFINE(TEST_SEM, 0, UINT_MAX); /** * * @brief Routine to be called from a workqueue * * This routine increments the global variable <critical_var>. * * @return 0 */ void critical_rtn(struct k_work *unused) { volatile u32_t x; ARG_UNUSED(unused); x = critical_var; critical_var = x + 1; } /** * * @brief Common code for invoking offload work * * @param count number of critical section calls made thus far * * @return number of critical section calls made by task */ u32_t critical_loop(u32_t count) { s64_t mseconds; mseconds = k_uptime_get(); while (k_uptime_get() < mseconds + NUM_MILLISECONDS) { struct k_work work_item; k_work_init(&work_item, critical_rtn); k_work_submit_to_queue(&offload_work_q, &work_item); count++; } return count; } /** * * @brief Alternate task * * This routine invokes the workqueue many times. * * @return N/A */ void alternate_task(void *arg1, void *arg2, void *arg3) { ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); k_sem_take(&ALT_SEM, K_FOREVER); /* Wait to be activated */ alt_task_iterations = critical_loop(alt_task_iterations); k_sem_give(®RESS_SEM); k_sem_take(&ALT_SEM, K_FOREVER); /* Wait to be re-activated */ alt_task_iterations = critical_loop(alt_task_iterations); k_sem_give(®RESS_SEM); } /** * * @brief Regression task * * This routine calls invokes the workqueue many times. It also checks to * ensure that the number of times it is called matches the global variable * <criticalVar>. * * @return N/A */ void regression_task(void *arg1, void *arg2, void *arg3) { u32_t ncalls = 0; ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); k_sem_give(&ALT_SEM); /* Activate AlternateTask() */ ncalls = critical_loop(ncalls); /* Wait for AlternateTask() to complete */ zassert_true(k_sem_take(®RESS_SEM, TEST_TIMEOUT) == 0, "Timed out waiting for REGRESS_SEM"); zassert_equal(critical_var, ncalls + alt_task_iterations, "Unexpected value for <criticalVar>"); k_sched_time_slice_set(10, 10); k_sem_give(&ALT_SEM); /* Re-activate AlternateTask() */ ncalls = critical_loop(ncalls); /* Wait for AlternateTask() to finish */ zassert_true(k_sem_take(®RESS_SEM, TEST_TIMEOUT) == 0, "Timed out waiting for REGRESS_SEM"); zassert_equal(critical_var, ncalls + alt_task_iterations, "Unexpected value for <criticalVar>"); k_sem_give(&TEST_SEM); } static void init_objects(void) { critical_var = 0; alt_task_iterations = 0; k_work_q_start(&offload_work_q, offload_work_q_stack, K_THREAD_STACK_SIZEOF(offload_work_q_stack), CONFIG_OFFLOAD_WORKQUEUE_PRIORITY); } static void start_threads(void) { k_thread_create(&thread1, stack1, STACK_SIZE, alternate_task, NULL, NULL, NULL, K_PRIO_PREEMPT(12), 0, 0); k_thread_create(&thread2, stack2, STACK_SIZE, regression_task, NULL, NULL, NULL, K_PRIO_PREEMPT(12), 0, 0); } void test_critical(void) { init_objects(); start_threads(); zassert_true(k_sem_take(&TEST_SEM, TEST_TIMEOUT * 2) == 0, "Timed out waiting for TEST_SEM"); } |