source: rtems-libbsd/testsuite/mutex01/test_main.c @ c64806c

5-freebsd-12
Last change on this file since c64806c was c64806c, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 9, 2017 at 1:28:37 PM

tests/mutex01: Fix mtx_recursed() usage

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <machine/rtems-bsd-kernel-space.h>
33
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/systm.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39
40#include <assert.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#include <rtems/libcsupport.h>
46#include <rtems.h>
47
48#define TEST_NAME "LIBBSD MUTEX 1"
49
50#define PRIO_MASTER 3
51
52#define EVENT_LOCK RTEMS_EVENT_0
53
54#define EVENT_TRY_LOCK RTEMS_EVENT_1
55
56#define EVENT_UNLOCK RTEMS_EVENT_2
57
58#define EVENT_SLEEP RTEMS_EVENT_3
59
60#define WORKER_COUNT 2
61
62typedef struct {
63        struct mtx mtx;
64        struct mtx mtx2;
65        int rv;
66        int timo;
67        rtems_id worker_task[WORKER_COUNT];
68        bool done[WORKER_COUNT];
69} test_context;
70
71static test_context test_instance;
72
73static const rtems_task_priority prio_worker[2] = { 2, 1 };
74
75static void
76set_self_prio(rtems_task_priority prio)
77{
78        rtems_status_code sc;
79
80        sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
81        assert(sc == RTEMS_SUCCESSFUL);
82}
83
84static rtems_task_priority
85get_self_prio(void)
86{
87        rtems_status_code sc;
88        rtems_task_priority prio;
89
90        sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
91        assert(sc == RTEMS_SUCCESSFUL);
92
93        return prio;
94}
95
96static void
97worker_task(rtems_task_argument index)
98{
99        test_context *ctx = &test_instance;
100        struct mtx *mtx = &ctx->mtx;
101
102        while (true) {
103                rtems_status_code sc;
104                rtems_event_set events;
105
106                sc = rtems_event_receive(
107                        RTEMS_ALL_EVENTS,
108                        RTEMS_EVENT_ANY | RTEMS_WAIT,
109                        RTEMS_NO_TIMEOUT,
110                        &events
111                );
112                assert(sc == RTEMS_SUCCESSFUL);
113
114                if ((events & EVENT_LOCK) != 0) {
115                        mtx_lock(mtx);
116                        ctx->done[index] = true;
117                }
118
119                if ((events & EVENT_TRY_LOCK) != 0) {
120                        ctx->rv = mtx_trylock(mtx);
121                        ctx->done[index] = true;
122                }
123
124                if ((events & EVENT_UNLOCK) != 0) {
125                        mtx_unlock(mtx);
126                        ctx->done[index] = true;
127                }
128
129                if ((events & EVENT_SLEEP) != 0) {
130                        ctx->rv = mtx_sleep(ctx, mtx, 0, "worker", ctx->timo);
131                        ctx->done[index] = true;
132                }
133        }
134}
135
136static void
137send_events(test_context *ctx, rtems_event_set events, size_t index)
138{
139        rtems_status_code sc;
140
141        sc = rtems_event_send(ctx->worker_task[index], events);
142        assert(sc == RTEMS_SUCCESSFUL);
143}
144
145static void
146start_worker(test_context *ctx)
147{
148        size_t i;
149
150        for (i = 0; i < WORKER_COUNT; ++i) {
151                rtems_status_code sc;
152
153                sc = rtems_task_create(
154                        rtems_build_name('W', 'O', 'R', 'K'),
155                        prio_worker[i],
156                        RTEMS_MINIMUM_STACK_SIZE,
157                        RTEMS_DEFAULT_MODES,
158                        RTEMS_FLOATING_POINT,
159                        &ctx->worker_task[i]
160                );
161                assert(sc == RTEMS_SUCCESSFUL);
162
163                sc = rtems_task_start(
164                        ctx->worker_task[i],
165                        worker_task,
166                        i
167                );
168                assert(sc == RTEMS_SUCCESSFUL);
169        }
170}
171
172static void
173delete_worker(test_context *ctx)
174{
175        size_t i;
176
177        for (i = 0; i < WORKER_COUNT; ++i) {
178                rtems_status_code sc;
179
180                sc = rtems_task_delete(ctx->worker_task[i]);
181                assert(sc == RTEMS_SUCCESSFUL);
182        }
183}
184
185static void
186test_mtx_non_recursive(test_context *ctx)
187{
188        struct mtx *mtx = &ctx->mtx;
189
190        puts("test mtx non-recursive");
191
192        assert(!mtx_initialized(mtx));
193        mtx_init(mtx, "test", NULL, MTX_DEF);
194        assert(mtx_initialized(mtx));
195
196        assert(!mtx_owned(mtx));
197        assert(!mtx_recursed(mtx));
198        mtx_lock(mtx);
199
200        assert(mtx_owned(mtx));
201        assert(!mtx_recursed(mtx));
202
203        mtx_unlock(mtx);
204        assert(!mtx_owned(mtx));
205        assert(!mtx_recursed(mtx));
206
207        mtx_destroy(mtx);
208        assert(!mtx_initialized(mtx));
209}
210
211static void
212test_mtx_recursive(test_context *ctx)
213{
214        struct mtx *mtx = &ctx->mtx;
215
216        puts("test mtx recursive");
217
218        assert(!mtx_initialized(mtx));
219        mtx_init(mtx, "test", NULL, MTX_DEF | MTX_RECURSE);
220        assert(mtx_initialized(mtx));
221
222        assert(!mtx_owned(mtx));
223        assert(!mtx_recursed(mtx));
224        mtx_lock(mtx);
225
226        assert(mtx_owned(mtx));
227        assert(!mtx_recursed(mtx));
228        mtx_lock(mtx);
229
230        assert(mtx_owned(mtx));
231        assert(mtx_recursed(mtx));
232        mtx_lock(mtx);
233
234        assert(mtx_owned(mtx));
235        assert(mtx_recursed(mtx));
236
237        mtx_unlock(mtx);
238        assert(mtx_owned(mtx));
239        assert(mtx_recursed(mtx));
240
241        mtx_unlock(mtx);
242        assert(mtx_owned(mtx));
243        assert(!mtx_recursed(mtx));
244
245        mtx_unlock(mtx);
246        assert(!mtx_owned(mtx));
247        assert(!mtx_recursed(mtx));
248
249        mtx_destroy(mtx);
250        assert(!mtx_initialized(mtx));
251}
252
253static void
254test_mtx_trylock(test_context *ctx)
255{
256        size_t index = 0;
257        struct mtx *mtx = &ctx->mtx;
258        int ok;
259
260        puts("test mtx try lock");
261
262        assert(!mtx_initialized(mtx));
263        mtx_init(mtx, "test", NULL, MTX_DEF);
264        assert(mtx_initialized(mtx));
265
266        assert(!mtx_owned(mtx));
267        assert(!mtx_recursed(mtx));
268        ok = mtx_trylock(mtx);
269        assert(ok != 0);
270        assert(mtx_owned(mtx));
271        assert(!mtx_recursed(mtx));
272
273        mtx_unlock(mtx);
274        assert(!mtx_owned(mtx));
275        assert(!mtx_recursed(mtx));
276
277        assert(!mtx_owned(mtx));
278        assert(!mtx_recursed(mtx));
279        mtx_lock(mtx);
280        assert(mtx_owned(mtx));
281        assert(!mtx_recursed(mtx));
282
283        ctx->done[index] = false;
284        ctx->rv = 1;
285        send_events(ctx, EVENT_TRY_LOCK, index);
286        assert(ctx->done[index]);
287        assert(ctx->rv == 0);
288
289        assert(mtx_owned(mtx));
290        assert(!mtx_recursed(mtx));
291        mtx_unlock(mtx);
292        assert(!mtx_owned(mtx));
293        assert(!mtx_recursed(mtx));
294
295        mtx_destroy(mtx);
296        assert(!mtx_initialized(mtx));
297}
298
299static void
300test_mtx_lock(test_context *ctx)
301{
302        struct mtx *mtx = &ctx->mtx;
303        struct mtx *mtx2 = &ctx->mtx2;
304        size_t low = 0;
305        size_t high = 1;
306
307        puts("test mtx lock");
308
309        assert(!mtx_initialized(mtx));
310        mtx_init(mtx, "test", NULL, MTX_DEF);
311        assert(mtx_initialized(mtx));
312
313        assert(!mtx_initialized(mtx2));
314        mtx_init(mtx2, "test 2", NULL, MTX_DEF);
315        assert(mtx_initialized(mtx2));
316
317        /* Resource count one */
318
319        assert(!mtx_owned(mtx));
320        assert(!mtx_recursed(mtx));
321        mtx_lock(mtx);
322        assert(mtx_owned(mtx));
323        assert(!mtx_recursed(mtx));
324        assert(get_self_prio() == PRIO_MASTER);
325
326        ctx->done[low] = false;
327        ctx->done[high] = false;
328
329        send_events(ctx, EVENT_LOCK, low);
330        assert(!ctx->done[low]);
331        assert(!ctx->done[high]);
332        assert(mtx_owned(mtx));
333        assert(!mtx_recursed(mtx));
334        assert(get_self_prio() == prio_worker[low]);
335
336        send_events(ctx, EVENT_LOCK, high);
337        assert(!ctx->done[low]);
338        assert(!ctx->done[high]);
339        assert(mtx_owned(mtx));
340        assert(!mtx_recursed(mtx));
341        assert(get_self_prio() == prio_worker[high]);
342
343        mtx_unlock(mtx);
344        assert(!ctx->done[low]);
345        assert(ctx->done[high]);
346        assert(!mtx_owned(mtx));
347        assert(!mtx_recursed(mtx));
348        assert(get_self_prio() == PRIO_MASTER);
349
350        ctx->done[high] = false;
351        send_events(ctx, EVENT_UNLOCK, high);
352        assert(ctx->done[low]);
353        assert(ctx->done[high]);
354
355        ctx->done[low] = false;
356        send_events(ctx, EVENT_UNLOCK, low);
357        assert(ctx->done[low]);
358
359        /* Resource count two */
360
361        assert(!mtx_owned(mtx));
362        assert(!mtx_recursed(mtx));
363        mtx_lock(mtx);
364        assert(mtx_owned(mtx));
365        assert(!mtx_recursed(mtx));
366        assert(get_self_prio() == PRIO_MASTER);
367
368        assert(!mtx_owned(mtx2));
369        assert(!mtx_recursed(mtx2));
370        mtx_lock(mtx2);
371        assert(mtx_owned(mtx2));
372        assert(!mtx_recursed(mtx2));
373        assert(get_self_prio() == PRIO_MASTER);
374
375        ctx->done[low] = false;
376        send_events(ctx, EVENT_LOCK, low);
377        assert(!ctx->done[low]);
378        assert(mtx_owned(mtx));
379        assert(!mtx_recursed(mtx));
380        assert(get_self_prio() == prio_worker[low]);
381
382        mtx_unlock(mtx2);
383        assert(!mtx_owned(mtx2));
384        assert(!mtx_recursed(mtx2));
385        assert(get_self_prio() == prio_worker[low]);
386
387        mtx_unlock(mtx);
388        assert(ctx->done[low]);
389        assert(!mtx_owned(mtx));
390        assert(!mtx_recursed(mtx));
391        assert(get_self_prio() == PRIO_MASTER);
392
393        ctx->done[low] = false;
394        send_events(ctx, EVENT_UNLOCK, low);
395        assert(ctx->done[low]);
396
397        mtx_destroy(mtx2);
398        assert(!mtx_initialized(mtx2));
399
400        mtx_destroy(mtx);
401        assert(!mtx_initialized(mtx));
402}
403
404static void
405test_mtx_sleep_with_lock(test_context *ctx)
406{
407        size_t index = 0;
408        struct mtx *mtx = &ctx->mtx;
409
410        puts("test mtx sleep with lock");
411
412        assert(!mtx_initialized(mtx));
413        mtx_init(mtx, "test", NULL, MTX_DEF);
414        assert(mtx_initialized(mtx));
415
416        ctx->done[index] = false;
417        send_events(ctx, EVENT_LOCK, index);
418        assert(ctx->done[index]);
419
420        ctx->done[index] = false;
421        ctx->timo = 0;
422        send_events(ctx, EVENT_SLEEP, index);
423        assert(!ctx->done[index]);
424
425        assert(!mtx_owned(mtx));
426        assert(!mtx_recursed(mtx));
427        mtx_lock(mtx);
428        assert(mtx_owned(mtx));
429        assert(!mtx_recursed(mtx));
430
431        wakeup(ctx);
432        assert(!ctx->done[index]);
433
434        mtx_unlock(mtx);
435        assert(ctx->done[index]);
436        assert(!mtx_owned(mtx));
437        assert(!mtx_recursed(mtx));
438
439        ctx->done[index] = false;
440        send_events(ctx, EVENT_UNLOCK, index);
441        assert(ctx->done[index]);
442
443        mtx_destroy(mtx);
444        assert(!mtx_initialized(mtx));
445}
446
447static void
448test_mtx_sleep_timeout(test_context *ctx)
449{
450        size_t index = 0;
451        struct mtx *mtx = &ctx->mtx;
452        rtems_status_code sc;
453
454        puts("test mtx sleep timeout");
455
456        assert(!mtx_initialized(mtx));
457        mtx_init(mtx, "test", NULL, MTX_DEF);
458        assert(mtx_initialized(mtx));
459
460        ctx->done[index] = false;
461        send_events(ctx, EVENT_LOCK, index);
462        assert(ctx->done[index]);
463
464        ctx->done[index] = false;
465        ctx->timo = 2;
466        send_events(ctx, EVENT_SLEEP, index);
467        assert(!ctx->done[index]);
468
469        sc = rtems_task_wake_after(ctx->timo);
470        assert(sc == RTEMS_SUCCESSFUL);
471        assert(ctx->done[index]);
472
473        ctx->done[index] = false;
474        send_events(ctx, EVENT_UNLOCK, index);
475        assert(ctx->done[index]);
476
477        mtx_destroy(mtx);
478        assert(!mtx_initialized(mtx));
479}
480
481static void
482alloc_basic_resources(void)
483{
484        curthread;
485}
486
487static void
488test_main(void)
489{
490        test_context *ctx = &test_instance;
491        rtems_resource_snapshot snapshot_0;
492        rtems_resource_snapshot snapshot_1;
493
494        alloc_basic_resources();
495
496        rtems_resource_snapshot_take(&snapshot_0);
497
498        set_self_prio(PRIO_MASTER);
499        start_worker(ctx);
500
501        rtems_resource_snapshot_take(&snapshot_1);
502
503        test_mtx_non_recursive(ctx);
504        test_mtx_recursive(ctx);
505        test_mtx_trylock(ctx);
506        test_mtx_lock(ctx);
507
508        assert(rtems_resource_snapshot_check(&snapshot_1));
509
510        test_mtx_sleep_with_lock(ctx);
511        test_mtx_sleep_timeout(ctx);
512
513        delete_worker(ctx);
514
515        assert(rtems_resource_snapshot_check(&snapshot_0));
516
517        exit(0);
518}
519
520#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.