source: rtems-libbsd/testsuite/rwlock01/test_main.c @ 4b8bc5c

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 4b8bc5c was 4b8bc5c, checked in by Sebastian Huber <sebastian.huber@…>, on 12/05/13 at 12:58:42

Use floating-point tasks for tests

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/*
2 * Copyright (c) 2013 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 <rtems/bsd/sys/param.h>
35#include <rtems/bsd/sys/types.h>
36#include <sys/systm.h>
37#include <rtems/bsd/sys/lock.h>
38#include <sys/rwlock.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 RWLOCK 1"
49
50#define PRIO_MASTER 2
51
52#define PRIO_WORKER 1
53
54#define EVENT_RLOCK RTEMS_EVENT_0
55
56#define EVENT_WLOCK RTEMS_EVENT_1
57
58#define EVENT_TRY_RLOCK RTEMS_EVENT_2
59
60#define EVENT_TRY_WLOCK RTEMS_EVENT_3
61
62#define EVENT_UNLOCK RTEMS_EVENT_4
63
64#define EVENT_SLEEP RTEMS_EVENT_5
65
66typedef struct {
67        struct rwlock rw;
68        bool done;
69        int rv;
70        int timo;
71        rtems_id worker_task;
72} test_context;
73
74static test_context test_instance;
75
76static void
77set_self_prio(rtems_task_priority prio)
78{
79        rtems_status_code sc;
80
81        sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
82        assert(sc == RTEMS_SUCCESSFUL);
83}
84
85static void
86worker_task(rtems_task_argument arg)
87{
88        test_context *ctx = (test_context *) arg;
89        struct rwlock *rw = &ctx->rw;
90
91        while (true) {
92                rtems_status_code sc;
93                rtems_event_set events;
94
95                sc = rtems_event_receive(
96                        RTEMS_ALL_EVENTS,
97                        RTEMS_EVENT_ANY | RTEMS_WAIT,
98                        RTEMS_NO_TIMEOUT,
99                        &events
100                );
101                assert(sc == RTEMS_SUCCESSFUL);
102
103                if ((events & EVENT_RLOCK) != 0) {
104                        rw_rlock(rw);
105                        ctx->done = true;
106                }
107
108                if ((events & EVENT_WLOCK) != 0) {
109                        rw_wlock(rw);
110                        ctx->done = true;
111                }
112
113                if ((events & EVENT_TRY_RLOCK) != 0) {
114                        ctx->rv = rw_try_rlock(rw);
115                        ctx->done = true;
116                }
117
118                if ((events & EVENT_TRY_WLOCK) != 0) {
119                        ctx->rv = rw_try_wlock(rw);
120                        ctx->done = true;
121                }
122
123                if ((events & EVENT_UNLOCK) != 0) {
124                        rw_unlock(rw);
125                        ctx->done = true;
126                }
127
128                if ((events & EVENT_SLEEP) != 0) {
129                        ctx->rv = rw_sleep(ctx, rw, 0, "worker", ctx->timo);
130                        ctx->done = true;
131                }
132        }
133}
134
135static void
136send_events(test_context *ctx, rtems_event_set events)
137{
138        rtems_status_code sc;
139
140        sc = rtems_event_send(ctx->worker_task, events);
141        assert(sc == RTEMS_SUCCESSFUL);
142}
143
144static void
145start_worker(test_context *ctx)
146{
147        rtems_status_code sc;
148
149        sc = rtems_task_create(
150                rtems_build_name('W', 'O', 'R', 'K'),
151                PRIO_WORKER,
152                RTEMS_MINIMUM_STACK_SIZE,
153                RTEMS_DEFAULT_MODES,
154                RTEMS_FLOATING_POINT,
155                &ctx->worker_task
156        );
157        assert(sc == RTEMS_SUCCESSFUL);
158
159        sc = rtems_task_start(
160                ctx->worker_task,
161                worker_task,
162                (rtems_task_argument) ctx
163        );
164        assert(sc == RTEMS_SUCCESSFUL);
165}
166
167static void
168delete_worker(test_context *ctx)
169{
170        rtems_status_code sc;
171
172        sc = rtems_task_delete(ctx->worker_task);
173        assert(sc == RTEMS_SUCCESSFUL);
174}
175
176static void
177test_rw_non_recursive(test_context *ctx)
178{
179        struct rwlock *rw = &ctx->rw;
180        int ok;
181
182        puts("test rw non-recursive");
183
184        assert(!rw_initialized(rw));
185        rw_init(rw, "test");
186        assert(rw_initialized(rw));
187
188        rw_rlock(rw);
189        /* FIXME: We use a mutex implementation */
190        assert(rw_wowned(rw));
191        /* FIXME: We always allow recursion */
192        rw_rlock(rw);
193        rw_runlock(rw);
194        rw_runlock(rw);
195
196        rw_rlock(rw);
197        rw_unlock(rw);
198
199        rw_rlock(rw);
200        ok = rw_try_upgrade(rw);
201        assert(ok != 0);
202        assert(rw_wowned(rw));
203        rw_wunlock(rw);
204
205        rw_rlock(rw);
206        ok = rw_try_upgrade(rw);
207        assert(ok != 0);
208        assert(rw_wowned(rw));
209        rw_unlock(rw);
210
211        rw_rlock(rw);
212        ok = rw_try_upgrade(rw);
213        assert(ok != 0);
214        assert(rw_wowned(rw));
215        rw_downgrade(rw);
216        /* FIXME: We use a mutex implementation */
217        assert(rw_wowned(rw));
218        rw_runlock(rw);
219
220        rw_rlock(rw);
221        ok = rw_try_upgrade(rw);
222        assert(ok != 0);
223        assert(rw_wowned(rw));
224        rw_downgrade(rw);
225        /* FIXME: We use a mutex implementation */
226        assert(rw_wowned(rw));
227        rw_unlock(rw);
228
229        rw_wlock(rw);
230        assert(rw_wowned(rw));
231        /* FIXME: We always allow recursion */
232        rw_wlock(rw);
233        rw_wunlock(rw);
234        rw_wunlock(rw);
235
236        rw_wlock(rw);
237        rw_unlock(rw);
238
239        ok = rw_try_rlock(rw);
240        assert(ok != 0);
241        rw_unlock(rw);
242
243        ok = rw_try_wlock(rw);
244        assert(ok != 0);
245        rw_unlock(rw);
246
247        rw_destroy(rw);
248}
249
250static void
251test_rw_recursive(test_context *ctx)
252{
253        struct rwlock *rw = &ctx->rw;
254
255        puts("test rw recursive");
256
257        assert(!rw_initialized(rw));
258        rw_init_flags(rw, "test", RW_RECURSE);
259        assert(rw_initialized(rw));
260
261        rw_rlock(rw);
262        rw_rlock(rw);
263        rw_runlock(rw);
264        rw_runlock(rw);
265
266        rw_wlock(rw);
267        rw_wlock(rw);
268        rw_wunlock(rw);
269        rw_wunlock(rw);
270
271        rw_destroy(rw);
272}
273
274static void
275test_rw_try_rlock(test_context *ctx)
276{
277        struct rwlock *rw = &ctx->rw;
278
279        puts("test rw try rlock");
280
281        rw_init(rw, "test");
282
283        rw_rlock(rw);
284        /* FIXME: We use a mutex implementation */
285        ctx->done = false;
286        ctx->rv = 1;
287        send_events(ctx, EVENT_TRY_RLOCK);
288        assert(ctx->done);
289        assert(ctx->rv == 0);
290        rw_unlock(rw);
291
292        rw_wlock(rw);
293        ctx->done = false;
294        ctx->rv = 1;
295        send_events(ctx, EVENT_TRY_RLOCK);
296        assert(ctx->done);
297        assert(ctx->rv == 0);
298        rw_unlock(rw);
299
300        rw_destroy(rw);
301}
302
303static void
304test_rw_try_wlock(test_context *ctx)
305{
306        struct rwlock *rw = &ctx->rw;
307
308        puts("test rw try wlock");
309
310        rw_init(rw, "test");
311
312        rw_rlock(rw);
313        ctx->done = false;
314        ctx->rv = 1;
315        send_events(ctx, EVENT_TRY_WLOCK);
316        assert(ctx->done);
317        assert(ctx->rv == 0);
318        rw_unlock(rw);
319
320        rw_wlock(rw);
321        ctx->done = false;
322        ctx->rv = 1;
323        send_events(ctx, EVENT_TRY_WLOCK);
324        assert(ctx->done);
325        assert(ctx->rv == 0);
326        rw_unlock(rw);
327
328        rw_destroy(rw);
329}
330
331static void
332test_rw_rlock(test_context *ctx)
333{
334        struct rwlock *rw = &ctx->rw;
335
336        puts("test rw rlock");
337
338        rw_init(rw, "test");
339
340        rw_rlock(rw);
341        /* FIXME: We use a mutex implementation */
342        ctx->done = false;
343        send_events(ctx, EVENT_RLOCK);
344        assert(!ctx->done);
345        rw_unlock(rw);
346        assert(ctx->done);
347        ctx->done = false;
348        send_events(ctx, EVENT_UNLOCK);
349        assert(ctx->done);
350
351        rw_wlock(rw);
352        ctx->done = false;
353        send_events(ctx, EVENT_RLOCK);
354        assert(!ctx->done);
355        rw_unlock(rw);
356        assert(ctx->done);
357        ctx->done = false;
358        send_events(ctx, EVENT_UNLOCK);
359        assert(ctx->done);
360
361        rw_destroy(rw);
362}
363
364static void
365test_rw_wlock(test_context *ctx)
366{
367        struct rwlock *rw = &ctx->rw;
368
369        puts("test rw rlock");
370
371        rw_init(rw, "test");
372
373        rw_rlock(rw);
374        ctx->done = false;
375        send_events(ctx, EVENT_WLOCK);
376        assert(!ctx->done);
377        rw_unlock(rw);
378        assert(ctx->done);
379        ctx->done = false;
380        send_events(ctx, EVENT_UNLOCK);
381        assert(ctx->done);
382
383        rw_wlock(rw);
384        ctx->done = false;
385        send_events(ctx, EVENT_WLOCK);
386        assert(!ctx->done);
387        rw_unlock(rw);
388        assert(ctx->done);
389        ctx->done = false;
390        send_events(ctx, EVENT_UNLOCK);
391        assert(ctx->done);
392
393        rw_destroy(rw);
394}
395
396static void
397test_rw_sleep_with_rlock(test_context *ctx)
398{
399        struct rwlock *rw = &ctx->rw;
400
401        puts("test rw sleep with rlock");
402
403        rw_init(rw, "test");
404
405        ctx->done = false;
406        send_events(ctx, EVENT_RLOCK);
407        assert(ctx->done);
408
409        ctx->done = false;
410        ctx->timo = 0;
411        send_events(ctx, EVENT_SLEEP);
412        assert(!ctx->done);
413
414        rw_rlock(rw);
415        wakeup(ctx);
416        /* FIXME: We use a mutex implementation */
417        assert(!ctx->done);
418        rw_unlock(rw);
419        /* FIXME: We use a mutex implementation */
420        assert(ctx->done);
421
422        ctx->done = false;
423        send_events(ctx, EVENT_UNLOCK);
424        assert(ctx->done);
425
426        rw_destroy(rw);
427}
428
429static void
430test_rw_sleep_with_wlock(test_context *ctx)
431{
432        struct rwlock *rw = &ctx->rw;
433
434        puts("test rw sleep with wlock");
435
436        rw_init(rw, "test");
437
438        ctx->done = false;
439        send_events(ctx, EVENT_WLOCK);
440        assert(ctx->done);
441
442        ctx->done = false;
443        ctx->timo = 0;
444        send_events(ctx, EVENT_SLEEP);
445        assert(!ctx->done);
446
447        rw_rlock(rw);
448        wakeup(ctx);
449        assert(!ctx->done);
450        rw_unlock(rw);
451        assert(ctx->done);
452
453        ctx->done = false;
454        send_events(ctx, EVENT_UNLOCK);
455        assert(ctx->done);
456
457        rw_destroy(rw);
458}
459
460static void
461test_rw_sleep_timeout(test_context *ctx)
462{
463        struct rwlock *rw = &ctx->rw;
464        rtems_status_code sc;
465
466        puts("test rw sleep timeout");
467
468        rw_init(rw, "test");
469
470        ctx->done = false;
471        send_events(ctx, EVENT_RLOCK);
472        assert(ctx->done);
473
474        ctx->done = false;
475        ctx->timo = 2;
476        send_events(ctx, EVENT_SLEEP);
477        assert(!ctx->done);
478
479        sc = rtems_task_wake_after(ctx->timo);
480        assert(sc == RTEMS_SUCCESSFUL);
481
482        assert(ctx->done);
483
484        ctx->done = false;
485        send_events(ctx, EVENT_UNLOCK);
486        assert(ctx->done);
487
488        rw_destroy(rw);
489}
490
491static void
492alloc_basic_resources(void)
493{
494        curthread;
495}
496
497static void
498test_main(void)
499{
500        rtems_resource_snapshot snapshot_0;
501        rtems_resource_snapshot snapshot_1;
502
503        test_context *ctx = &test_instance;
504
505        alloc_basic_resources();
506
507        rtems_resource_snapshot_take(&snapshot_0);
508
509        set_self_prio(PRIO_MASTER);
510        start_worker(ctx);
511
512        rtems_resource_snapshot_take(&snapshot_1);
513
514        test_rw_non_recursive(ctx);
515        test_rw_recursive(ctx);
516        test_rw_try_rlock(ctx);
517        test_rw_try_wlock(ctx);
518        test_rw_rlock(ctx);
519        test_rw_wlock(ctx);
520
521        assert(rtems_resource_snapshot_check(&snapshot_1));
522
523        test_rw_sleep_with_rlock(ctx);
524        test_rw_sleep_with_wlock(ctx);
525        test_rw_sleep_timeout(ctx);
526
527        delete_worker(ctx);
528
529        assert(rtems_resource_snapshot_check(&snapshot_0));
530
531        exit(0);
532}
533
534#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.