source: rtems-libbsd/testsuite/condvar01/test_main.c @ b5cdb95

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since b5cdb95 was b5cdb95, checked in by Sebastian Huber <sebastian.huber@…>, on 06/23/15 at 07:13:55

condvar01: Initialize mutex

  • Property mode set to 100644
File size: 8.5 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 <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/mutex.h>
39#include <sys/condvar.h>
40
41#include <assert.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#include <rtems/libcsupport.h>
47#include <rtems.h>
48
49#define TEST_NAME "LIBBSD CONDVAR 1"
50
51#define PRIO_MASTER 3
52
53#define EVENT_LOCK RTEMS_EVENT_0
54
55#define EVENT_UNLOCK RTEMS_EVENT_1
56
57#define EVENT_WAIT RTEMS_EVENT_2
58
59#define EVENT_WAIT_SIG RTEMS_EVENT_3
60
61#define EVENT_WAIT_UNLOCK RTEMS_EVENT_4
62
63#define EVENT_TIMEDWAIT RTEMS_EVENT_5
64
65#define EVENT_TIMEDWAIT_SIG RTEMS_EVENT_6
66
67#define WORKER_COUNT 2
68
69typedef struct {
70        struct mtx mtx;
71        struct cv cv;
72        int rv;
73        int timo;
74        rtems_id worker_task[WORKER_COUNT];
75        bool done[WORKER_COUNT];
76} test_context;
77
78static test_context test_instance;
79
80static const rtems_task_priority prio_worker[2] = { 2, 1 };
81
82static void
83set_self_prio(rtems_task_priority prio)
84{
85        rtems_status_code sc;
86
87        sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
88        assert(sc == RTEMS_SUCCESSFUL);
89}
90
91static void
92worker_task(rtems_task_argument index)
93{
94        test_context *ctx = &test_instance;
95        struct mtx *mtx = &ctx->mtx;
96        struct cv *cv = &ctx->cv;
97
98        while (true) {
99                rtems_status_code sc;
100                rtems_event_set events;
101
102                sc = rtems_event_receive(
103                        RTEMS_ALL_EVENTS,
104                        RTEMS_EVENT_ANY | RTEMS_WAIT,
105                        RTEMS_NO_TIMEOUT,
106                        &events
107                );
108                assert(sc == RTEMS_SUCCESSFUL);
109
110                if ((events & EVENT_LOCK) != 0) {
111                        mtx_lock(mtx);
112                        ctx->done[index] = true;
113                }
114
115                if ((events & EVENT_UNLOCK) != 0) {
116                        mtx_unlock(mtx);
117                        ctx->done[index] = true;
118                }
119
120                if ((events & EVENT_WAIT) != 0) {
121                        cv_wait(cv, mtx);
122                        ctx->done[index] = true;
123                }
124
125                if ((events & EVENT_WAIT_SIG) != 0) {
126                        int rv = cv_wait_sig(cv, mtx);
127                        assert(rv == 0);
128                        ctx->done[index] = true;
129                }
130
131                if ((events & EVENT_WAIT_UNLOCK) != 0) {
132                        cv_wait_unlock(cv, mtx);
133                        ctx->done[index] = true;
134                }
135
136                if ((events & EVENT_TIMEDWAIT) != 0) {
137                        ctx->rv = cv_timedwait(cv, mtx, ctx->timo);
138                        ctx->done[index] = true;
139                }
140
141                if ((events & EVENT_TIMEDWAIT_SIG) != 0) {
142                        ctx->rv = cv_timedwait_sig(cv, mtx, ctx->timo);
143                        ctx->done[index] = true;
144                }
145        }
146}
147
148static void
149send_events(test_context *ctx, rtems_event_set events, size_t index)
150{
151        rtems_status_code sc;
152
153        sc = rtems_event_send(ctx->worker_task[index], events);
154        assert(sc == RTEMS_SUCCESSFUL);
155}
156
157static void
158start_worker(test_context *ctx)
159{
160        size_t i;
161
162        for (i = 0; i < WORKER_COUNT; ++i) {
163                rtems_status_code sc;
164
165                sc = rtems_task_create(
166                        rtems_build_name('W', 'O', 'R', 'K'),
167                        prio_worker[i],
168                        RTEMS_MINIMUM_STACK_SIZE,
169                        RTEMS_DEFAULT_MODES,
170                        RTEMS_FLOATING_POINT,
171                        &ctx->worker_task[i]
172                );
173                assert(sc == RTEMS_SUCCESSFUL);
174
175                sc = rtems_task_start(
176                        ctx->worker_task[i],
177                        worker_task,
178                        i
179                );
180                assert(sc == RTEMS_SUCCESSFUL);
181        }
182}
183
184static void
185delete_worker(test_context *ctx)
186{
187        size_t i;
188
189        for (i = 0; i < WORKER_COUNT; ++i) {
190                rtems_status_code sc;
191
192                sc = rtems_task_delete(ctx->worker_task[i]);
193                assert(sc == RTEMS_SUCCESSFUL);
194        }
195}
196
197static void
198test_cv_wait_signal(test_context *ctx, rtems_event_set event, const char *name)
199{
200        struct mtx *mtx = &ctx->mtx;
201        struct cv *cv = &ctx->cv;
202        size_t low = 0;
203        size_t high = 1;
204
205        printf("test cv %s signal\n", name);
206
207        mtx_lock(mtx);
208        mtx_unlock(mtx);
209
210        ctx->timo = 0;
211
212        ctx->done[low] = false;
213        send_events(ctx, EVENT_LOCK, low);
214        assert(ctx->done[low]);
215
216        ctx->done[high] = false;
217        send_events(ctx, EVENT_LOCK, high);
218        assert(!ctx->done[high]);
219
220        ctx->done[low] = false;
221        send_events(ctx, event, low);
222        assert(!ctx->done[low]);
223        assert(ctx->done[high]);
224
225        ctx->done[low] = false;
226        ctx->done[high] = false;
227        send_events(ctx, event, high);
228        assert(!ctx->done[low]);
229        assert(!ctx->done[high]);
230
231        cv_signal(cv);
232        assert(!ctx->done[low]);
233        assert(ctx->done[high]);
234
235        if (event != EVENT_WAIT_UNLOCK) {
236                cv_signal(cv);
237                assert(!ctx->done[low]);
238
239                ctx->done[high] = false;
240                send_events(ctx, EVENT_UNLOCK, high);
241                assert(ctx->done[high]);
242                assert(ctx->done[low]);
243
244                ctx->done[low] = false;
245                send_events(ctx, EVENT_UNLOCK, low);
246                assert(ctx->done[low]);
247        } else {
248                cv_signal(cv);
249                assert(ctx->done[low]);
250        }
251
252        mtx_lock(mtx);
253        mtx_unlock(mtx);
254}
255
256static void
257test_cv_wait_broadcast(test_context *ctx, rtems_event_set event, const char *name)
258{
259        struct mtx *mtx = &ctx->mtx;
260        struct cv *cv = &ctx->cv;
261        size_t low = 0;
262        size_t high = 1;
263
264        printf("test cv %s broadcast\n", name);
265
266        mtx_lock(mtx);
267        mtx_unlock(mtx);
268
269        ctx->timo = 0;
270
271        ctx->done[low] = false;
272        send_events(ctx, EVENT_LOCK, low);
273        assert(ctx->done[low]);
274
275        ctx->done[high] = false;
276        send_events(ctx, EVENT_LOCK, high);
277        assert(!ctx->done[high]);
278
279        ctx->done[low] = false;
280        send_events(ctx, event, low);
281        assert(!ctx->done[low]);
282        assert(ctx->done[high]);
283
284        ctx->done[low] = false;
285        ctx->done[high] = false;
286        send_events(ctx, event, high);
287        assert(!ctx->done[low]);
288        assert(!ctx->done[high]);
289
290        if (event != EVENT_WAIT_UNLOCK) {
291                cv_broadcast(cv);
292                assert(!ctx->done[low]);
293
294                ctx->done[high] = false;
295                send_events(ctx, EVENT_UNLOCK, high);
296                assert(ctx->done[high]);
297                assert(ctx->done[low]);
298
299                ctx->done[low] = false;
300                send_events(ctx, EVENT_UNLOCK, low);
301                assert(ctx->done[low]);
302        } else {
303                cv_broadcast(cv);
304                assert(ctx->done[low]);
305                assert(ctx->done[high]);
306        }
307
308        mtx_lock(mtx);
309        mtx_unlock(mtx);
310}
311
312static void
313test_cv_wait(test_context *ctx, rtems_event_set event, const char *name)
314{
315        test_cv_wait_signal(ctx, event, name);
316        test_cv_wait_broadcast(ctx, event, name);
317}
318
319static void
320test_cv_wait_timeout(test_context *ctx)
321{
322        size_t index = 0;
323        rtems_status_code sc;
324
325        puts("test cv wait timeout");
326
327        ctx->timo = 2;
328
329        ctx->done[index] = false;
330        send_events(ctx, EVENT_LOCK, index);
331        assert(ctx->done[index]);
332
333        ctx->done[index] = false;
334        ctx->rv = 0;
335        send_events(ctx, EVENT_TIMEDWAIT, index);
336        assert(!ctx->done[index]);
337
338        sc = rtems_task_wake_after(ctx->timo);
339        assert(sc == RTEMS_SUCCESSFUL);
340        assert(ctx->done[index]);
341        assert(ctx->rv == EWOULDBLOCK);
342
343        ctx->done[index] = false;
344        ctx->rv = 0;
345        send_events(ctx, EVENT_TIMEDWAIT_SIG, index);
346        assert(!ctx->done[index]);
347
348        sc = rtems_task_wake_after(ctx->timo);
349        assert(sc == RTEMS_SUCCESSFUL);
350        assert(ctx->done[index]);
351        assert(ctx->rv == EWOULDBLOCK);
352
353        ctx->done[index] = false;
354        send_events(ctx, EVENT_UNLOCK, index);
355        assert(ctx->done[index]);
356}
357
358static void
359alloc_basic_resources(void)
360{
361        curthread;
362}
363
364static void
365test_main(void)
366{
367        test_context *ctx = &test_instance;
368        rtems_resource_snapshot snapshot;
369
370        alloc_basic_resources();
371
372        rtems_resource_snapshot_take(&snapshot);
373
374        mtx_init(&ctx->mtx, "test", NULL, MTX_DEF);
375        cv_init(&ctx->cv, "test");
376        assert(strcmp(cv_wmesg(&ctx->cv), "test") == 0);
377
378        set_self_prio(PRIO_MASTER);
379        start_worker(ctx);
380
381        test_cv_wait(ctx, EVENT_WAIT, "wait");
382        test_cv_wait(ctx, EVENT_WAIT_SIG, "wait sig");
383        test_cv_wait(ctx, EVENT_WAIT_UNLOCK, "wait unlock");
384        test_cv_wait(ctx, EVENT_TIMEDWAIT, "timed wait");
385        test_cv_wait(ctx, EVENT_TIMEDWAIT_SIG, "timed wait sig");
386
387        test_cv_wait_timeout(ctx);
388
389        delete_worker(ctx);
390        cv_destroy(&ctx->cv);
391
392        assert(rtems_resource_snapshot_check(&snapshot));
393
394        exit(0);
395}
396
397#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.