source: rtems-libbsd/testsuite/rwlock01/test_main.c @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

  • Property mode set to 100644
File size: 9.8 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 <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        rw_runlock(rw);
192
193        rw_rlock(rw);
194        rw_unlock(rw);
195
196        rw_rlock(rw);
197        ok = rw_try_upgrade(rw);
198        assert(ok != 0);
199        assert(rw_wowned(rw));
200        rw_wunlock(rw);
201
202        rw_rlock(rw);
203        ok = rw_try_upgrade(rw);
204        assert(ok != 0);
205        assert(rw_wowned(rw));
206        rw_unlock(rw);
207
208        rw_rlock(rw);
209        ok = rw_try_upgrade(rw);
210        assert(ok != 0);
211        assert(rw_wowned(rw));
212        rw_downgrade(rw);
213        /* FIXME: We use a mutex implementation */
214        assert(rw_wowned(rw));
215        rw_runlock(rw);
216
217        rw_rlock(rw);
218        ok = rw_try_upgrade(rw);
219        assert(ok != 0);
220        assert(rw_wowned(rw));
221        rw_downgrade(rw);
222        /* FIXME: We use a mutex implementation */
223        assert(rw_wowned(rw));
224        rw_unlock(rw);
225
226        rw_wlock(rw);
227        assert(rw_wowned(rw));
228        rw_wunlock(rw);
229
230        rw_wlock(rw);
231        rw_unlock(rw);
232
233        ok = rw_try_rlock(rw);
234        assert(ok != 0);
235        rw_unlock(rw);
236
237        ok = rw_try_wlock(rw);
238        assert(ok != 0);
239        rw_unlock(rw);
240
241        rw_destroy(rw);
242}
243
244static void
245test_rw_recursive(test_context *ctx)
246{
247        struct rwlock *rw = &ctx->rw;
248
249        puts("test rw recursive");
250
251        assert(!rw_initialized(rw));
252        rw_init_flags(rw, "test", RW_RECURSE);
253        assert(rw_initialized(rw));
254
255        rw_rlock(rw);
256        rw_rlock(rw);
257        rw_runlock(rw);
258        rw_runlock(rw);
259
260        rw_wlock(rw);
261        rw_wlock(rw);
262        rw_wunlock(rw);
263        rw_wunlock(rw);
264
265        rw_destroy(rw);
266}
267
268static void
269test_rw_try_rlock(test_context *ctx)
270{
271        struct rwlock *rw = &ctx->rw;
272
273        puts("test rw try rlock");
274
275        rw_init(rw, "test");
276
277        rw_rlock(rw);
278        /* FIXME: We use a mutex implementation */
279        ctx->done = false;
280        ctx->rv = 1;
281        send_events(ctx, EVENT_TRY_RLOCK);
282        assert(ctx->done);
283        assert(ctx->rv == 0);
284        rw_unlock(rw);
285
286        rw_wlock(rw);
287        ctx->done = false;
288        ctx->rv = 1;
289        send_events(ctx, EVENT_TRY_RLOCK);
290        assert(ctx->done);
291        assert(ctx->rv == 0);
292        rw_unlock(rw);
293
294        rw_destroy(rw);
295}
296
297static void
298test_rw_try_wlock(test_context *ctx)
299{
300        struct rwlock *rw = &ctx->rw;
301
302        puts("test rw try wlock");
303
304        rw_init(rw, "test");
305
306        rw_rlock(rw);
307        ctx->done = false;
308        ctx->rv = 1;
309        send_events(ctx, EVENT_TRY_WLOCK);
310        assert(ctx->done);
311        assert(ctx->rv == 0);
312        rw_unlock(rw);
313
314        rw_wlock(rw);
315        ctx->done = false;
316        ctx->rv = 1;
317        send_events(ctx, EVENT_TRY_WLOCK);
318        assert(ctx->done);
319        assert(ctx->rv == 0);
320        rw_unlock(rw);
321
322        rw_destroy(rw);
323}
324
325static void
326test_rw_rlock(test_context *ctx)
327{
328        struct rwlock *rw = &ctx->rw;
329
330        puts("test rw rlock");
331
332        rw_init(rw, "test");
333
334        rw_rlock(rw);
335        /* FIXME: We use a mutex implementation */
336        ctx->done = false;
337        send_events(ctx, EVENT_RLOCK);
338        assert(!ctx->done);
339        rw_unlock(rw);
340        assert(ctx->done);
341        ctx->done = false;
342        send_events(ctx, EVENT_UNLOCK);
343        assert(ctx->done);
344
345        rw_wlock(rw);
346        ctx->done = false;
347        send_events(ctx, EVENT_RLOCK);
348        assert(!ctx->done);
349        rw_unlock(rw);
350        assert(ctx->done);
351        ctx->done = false;
352        send_events(ctx, EVENT_UNLOCK);
353        assert(ctx->done);
354
355        rw_destroy(rw);
356}
357
358static void
359test_rw_wlock(test_context *ctx)
360{
361        struct rwlock *rw = &ctx->rw;
362
363        puts("test rw rlock");
364
365        rw_init(rw, "test");
366
367        rw_rlock(rw);
368        ctx->done = false;
369        send_events(ctx, EVENT_WLOCK);
370        assert(!ctx->done);
371        rw_unlock(rw);
372        assert(ctx->done);
373        ctx->done = false;
374        send_events(ctx, EVENT_UNLOCK);
375        assert(ctx->done);
376
377        rw_wlock(rw);
378        ctx->done = false;
379        send_events(ctx, EVENT_WLOCK);
380        assert(!ctx->done);
381        rw_unlock(rw);
382        assert(ctx->done);
383        ctx->done = false;
384        send_events(ctx, EVENT_UNLOCK);
385        assert(ctx->done);
386
387        rw_destroy(rw);
388}
389
390static void
391test_rw_sleep_with_rlock(test_context *ctx)
392{
393        struct rwlock *rw = &ctx->rw;
394
395        puts("test rw sleep with rlock");
396
397        rw_init(rw, "test");
398
399        ctx->done = false;
400        send_events(ctx, EVENT_RLOCK);
401        assert(ctx->done);
402
403        ctx->done = false;
404        ctx->timo = 0;
405        send_events(ctx, EVENT_SLEEP);
406        assert(!ctx->done);
407
408        rw_rlock(rw);
409        wakeup(ctx);
410        /* FIXME: We use a mutex implementation */
411        assert(!ctx->done);
412        rw_unlock(rw);
413        /* FIXME: We use a mutex implementation */
414        assert(ctx->done);
415
416        ctx->done = false;
417        send_events(ctx, EVENT_UNLOCK);
418        assert(ctx->done);
419
420        rw_destroy(rw);
421}
422
423static void
424test_rw_sleep_with_wlock(test_context *ctx)
425{
426        struct rwlock *rw = &ctx->rw;
427
428        puts("test rw sleep with wlock");
429
430        rw_init(rw, "test");
431
432        ctx->done = false;
433        send_events(ctx, EVENT_WLOCK);
434        assert(ctx->done);
435
436        ctx->done = false;
437        ctx->timo = 0;
438        send_events(ctx, EVENT_SLEEP);
439        assert(!ctx->done);
440
441        rw_rlock(rw);
442        wakeup(ctx);
443        assert(!ctx->done);
444        rw_unlock(rw);
445        assert(ctx->done);
446
447        ctx->done = false;
448        send_events(ctx, EVENT_UNLOCK);
449        assert(ctx->done);
450
451        rw_destroy(rw);
452}
453
454static void
455test_rw_sleep_timeout(test_context *ctx)
456{
457        struct rwlock *rw = &ctx->rw;
458        rtems_status_code sc;
459
460        puts("test rw sleep timeout");
461
462        rw_init(rw, "test");
463
464        ctx->done = false;
465        send_events(ctx, EVENT_RLOCK);
466        assert(ctx->done);
467
468        ctx->done = false;
469        ctx->timo = 2;
470        send_events(ctx, EVENT_SLEEP);
471        assert(!ctx->done);
472
473        sc = rtems_task_wake_after(ctx->timo);
474        assert(sc == RTEMS_SUCCESSFUL);
475
476        assert(ctx->done);
477
478        ctx->done = false;
479        send_events(ctx, EVENT_UNLOCK);
480        assert(ctx->done);
481
482        rw_destroy(rw);
483}
484
485static void
486alloc_basic_resources(void)
487{
488        curthread;
489}
490
491static void
492test_main(void)
493{
494        rtems_resource_snapshot snapshot_0;
495        rtems_resource_snapshot snapshot_1;
496
497        test_context *ctx = &test_instance;
498
499        alloc_basic_resources();
500
501        rtems_resource_snapshot_take(&snapshot_0);
502
503        set_self_prio(PRIO_MASTER);
504        start_worker(ctx);
505
506        rtems_resource_snapshot_take(&snapshot_1);
507
508        test_rw_non_recursive(ctx);
509        test_rw_recursive(ctx);
510        test_rw_try_rlock(ctx);
511        test_rw_try_wlock(ctx);
512        test_rw_rlock(ctx);
513        test_rw_wlock(ctx);
514
515        assert(rtems_resource_snapshot_check(&snapshot_1));
516
517        test_rw_sleep_with_rlock(ctx);
518        test_rw_sleep_with_wlock(ctx);
519        test_rw_sleep_timeout(ctx);
520
521        delete_worker(ctx);
522
523        assert(rtems_resource_snapshot_check(&snapshot_0));
524
525        exit(0);
526}
527
528#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.