]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <stdint.h> | |
36 | ||
37 | #include <rte_common.h> | |
38 | #include <rte_cycles.h> | |
39 | #include <rte_interrupts.h> | |
40 | #include <rte_common.h> | |
41 | #include <rte_atomic.h> | |
42 | #include <rte_alarm.h> | |
43 | ||
44 | #include "test.h" | |
45 | ||
46 | #define US_PER_MS 1000 | |
47 | ||
48 | #define RTE_TEST_ALARM_TIMEOUT 10 /* ms */ | |
49 | #define RTE_TEST_CHECK_PERIOD 3 /* ms */ | |
50 | ||
51 | static volatile int flag; | |
52 | ||
53 | static void | |
54 | test_alarm_callback(void *cb_arg) | |
55 | { | |
56 | flag = 1; | |
57 | printf("Callback setting flag - OK. [cb_arg = %p]\n", cb_arg); | |
58 | } | |
59 | ||
60 | static rte_atomic32_t cb_count; | |
61 | ||
62 | static void | |
63 | test_multi_cb(void *arg) | |
64 | { | |
65 | rte_atomic32_inc(&cb_count); | |
66 | printf("In %s - arg = %p\n", __func__, arg); | |
67 | } | |
68 | ||
69 | static volatile int recursive_error = 0; | |
70 | ||
71 | static void | |
72 | test_remove_in_callback(void *arg) | |
73 | { | |
74 | printf("In %s - arg = %p\n", __func__, arg); | |
75 | if (rte_eal_alarm_cancel(test_remove_in_callback, arg) || | |
76 | rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1)) { | |
77 | printf("Error - cancelling callback from within function succeeded!\n"); | |
78 | recursive_error = 1; | |
79 | } | |
80 | flag = (int)((uintptr_t)arg); | |
81 | } | |
82 | ||
83 | static volatile int flag_2; | |
84 | ||
85 | static void | |
86 | test_remove_in_callback_2(void *arg) | |
87 | { | |
88 | if (rte_eal_alarm_cancel(test_remove_in_callback_2, arg) || rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1)) { | |
89 | printf("Error - cancelling callback of test_remove_in_callback_2\n"); | |
90 | return; | |
91 | } | |
92 | flag_2 = 1; | |
93 | } | |
94 | ||
95 | static int | |
96 | test_multi_alarms(void) | |
97 | { | |
98 | int rm_count = 0; | |
99 | cb_count.cnt = 0; | |
100 | ||
101 | printf("Expect 6 callbacks in order...\n"); | |
102 | /* add two alarms in order */ | |
103 | rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1); | |
104 | rte_eal_alarm_set(20 * US_PER_MS, test_multi_cb, (void *)2); | |
105 | ||
106 | /* now add in reverse order */ | |
107 | rte_eal_alarm_set(60 * US_PER_MS, test_multi_cb, (void *)6); | |
108 | rte_eal_alarm_set(50 * US_PER_MS, test_multi_cb, (void *)5); | |
109 | rte_eal_alarm_set(40 * US_PER_MS, test_multi_cb, (void *)4); | |
110 | rte_eal_alarm_set(30 * US_PER_MS, test_multi_cb, (void *)3); | |
111 | ||
112 | /* wait for expiry */ | |
113 | rte_delay_ms(65); | |
114 | if (cb_count.cnt != 6) { | |
115 | printf("Missing callbacks\n"); | |
116 | /* remove any callbacks that might remain */ | |
117 | rte_eal_alarm_cancel(test_multi_cb, (void *)-1); | |
118 | return -1; | |
119 | } | |
120 | ||
121 | cb_count.cnt = 0; | |
122 | printf("Expect only callbacks with args 1 and 3...\n"); | |
123 | /* Add 3 flags, then delete one */ | |
124 | rte_eal_alarm_set(30 * US_PER_MS, test_multi_cb, (void *)3); | |
125 | rte_eal_alarm_set(20 * US_PER_MS, test_multi_cb, (void *)2); | |
126 | rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1); | |
127 | rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *)2); | |
128 | ||
129 | rte_delay_ms(35); | |
130 | if (cb_count.cnt != 2 || rm_count != 1) { | |
131 | printf("Error: invalid flags count or alarm removal failure" | |
132 | " - flags value = %d, expected = %d\n", | |
133 | (int)cb_count.cnt, 2); | |
134 | /* remove any callbacks that might remain */ | |
135 | rte_eal_alarm_cancel(test_multi_cb, (void *)-1); | |
136 | return -1; | |
137 | } | |
138 | ||
139 | printf("Testing adding and then removing multiple alarms\n"); | |
140 | /* finally test that no callbacks are called if we delete them all*/ | |
141 | rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1); | |
142 | rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)2); | |
143 | rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)3); | |
144 | rm_count = rte_eal_alarm_cancel(test_alarm_callback, (void *)-1); | |
145 | if (rm_count != 0) { | |
146 | printf("Error removing non-existant alarm succeeded\n"); | |
147 | rte_eal_alarm_cancel(test_multi_cb, (void *) -1); | |
148 | return -1; | |
149 | } | |
150 | rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *) -1); | |
151 | if (rm_count != 3) { | |
152 | printf("Error removing all pending alarm callbacks\n"); | |
153 | return -1; | |
154 | } | |
155 | ||
156 | /* Test that we cannot cancel an alarm from within the callback itself | |
157 | * Also test that we can cancel head-of-line callbacks ok.*/ | |
158 | flag = 0; | |
159 | recursive_error = 0; | |
160 | rte_eal_alarm_set(10 * US_PER_MS, test_remove_in_callback, (void *)1); | |
161 | rte_eal_alarm_set(20 * US_PER_MS, test_remove_in_callback, (void *)2); | |
162 | rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)1); | |
163 | if (rm_count != 1) { | |
164 | printf("Error cancelling head-of-list callback\n"); | |
165 | return -1; | |
166 | } | |
167 | rte_delay_ms(15); | |
168 | if (flag != 0) { | |
169 | printf("Error, cancelling head-of-list leads to premature callback\n"); | |
170 | return -1; | |
171 | } | |
172 | rte_delay_ms(10); | |
173 | if (flag != 2) { | |
174 | printf("Error - expected callback not called\n"); | |
175 | rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1); | |
176 | return -1; | |
177 | } | |
178 | if (recursive_error == 1) | |
179 | return -1; | |
180 | ||
181 | /* Check if it can cancel all for the same callback */ | |
182 | printf("Testing canceling all for the same callback\n"); | |
183 | flag_2 = 0; | |
184 | rte_eal_alarm_set(10 * US_PER_MS, test_remove_in_callback, (void *)1); | |
185 | rte_eal_alarm_set(20 * US_PER_MS, test_remove_in_callback_2, (void *)2); | |
186 | rte_eal_alarm_set(30 * US_PER_MS, test_remove_in_callback_2, (void *)3); | |
187 | rte_eal_alarm_set(40 * US_PER_MS, test_remove_in_callback, (void *)4); | |
188 | rm_count = rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1); | |
189 | if (rm_count != 2) { | |
190 | printf("Error, cannot cancel all for the same callback\n"); | |
191 | return -1; | |
192 | } | |
193 | rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1); | |
194 | if (rm_count != 2) { | |
195 | printf("Error, cannot cancel all for the same callback\n"); | |
196 | return -1; | |
197 | } | |
198 | ||
199 | return 0; | |
200 | } | |
201 | ||
202 | static int | |
203 | test_alarm(void) | |
204 | { | |
205 | int count = 0; | |
206 | ||
207 | /* check if the callback will be called */ | |
208 | printf("check if the callback will be called\n"); | |
209 | flag = 0; | |
210 | if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT * US_PER_MS, | |
211 | test_alarm_callback, NULL) < 0) { | |
212 | printf("fail to set alarm callback\n"); | |
213 | return -1; | |
214 | } | |
215 | while (flag == 0 && count ++ < 6) | |
216 | rte_delay_ms(RTE_TEST_CHECK_PERIOD); | |
217 | ||
218 | if (flag == 0){ | |
219 | printf("Callback not called\n"); | |
220 | return -1; | |
221 | } | |
222 | ||
223 | /* check if it will fail to set alarm with wrong us value */ | |
224 | printf("check if it will fail to set alarm with wrong ms values\n"); | |
225 | if (rte_eal_alarm_set(0, test_alarm_callback, | |
226 | NULL) >= 0) { | |
227 | printf("should not be successful with 0 us value\n"); | |
228 | return -1; | |
229 | } | |
230 | if (rte_eal_alarm_set(UINT64_MAX - 1, test_alarm_callback, | |
231 | NULL) >= 0) { | |
232 | printf("should not be successful with (UINT64_MAX-1) us value\n"); | |
233 | return -1; | |
234 | } | |
235 | ||
236 | /* check if it will fail to set alarm with null callback parameter */ | |
237 | printf("check if it will fail to set alarm with null callback parameter\n"); | |
238 | if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT, NULL, NULL) >= 0) { | |
239 | printf("should not be successful to set alarm with null callback parameter\n"); | |
240 | return -1; | |
241 | } | |
242 | ||
243 | /* check if it will fail to remove alarm with null callback parameter */ | |
244 | printf("check if it will fail to remove alarm with null callback parameter\n"); | |
245 | if (rte_eal_alarm_cancel(NULL, NULL) == 0) { | |
246 | printf("should not be successful to remove alarm with null callback parameter"); | |
247 | return -1; | |
248 | } | |
249 | ||
250 | if (test_multi_alarms() != 0) | |
251 | return -1; | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | REGISTER_TEST_COMMAND(alarm_autotest, test_alarm); |