source: rtems/testsuites/sptests/spthreadq01/init.c @ 1fcac5ad

5
Last change on this file since 1fcac5ad was 1fcac5ad, checked in by Sebastian Huber <sebastian.huber@…>, on 07/25/16 at 14:35:37

score: Turn thread lock into thread wait lock

The _Thread_Lock_acquire() function had a potentially infinite run-time
due to the lack of fairness at atomic operations level.

Update #2412.
Update #2556.
Update #2765.

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2009.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  Copyright (c) 2016 embedded brains GmbH.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif
15
16#include <tmacros.h>
17
18#include <rtems.h>
19
20#include <rtems/score/threadimpl.h>
21
22#if defined(RTEMS_POSIX_API)
23  #include <fcntl.h>
24  #include <mqueue.h>
25  #include <semaphore.h>
26  #include <string.h>
27  #include <pthread.h>
28#endif
29
30const char rtems_test_name[] = "SPTHREADQ 1";
31
32static Thread_queue_Control queue = THREAD_QUEUE_INITIALIZER( "Queue" );
33
34typedef struct {
35  Thread_Control *master;
36  rtems_id master_id;
37  rtems_id worker_id;
38  rtems_id sem;
39  rtems_id mtx;
40  rtems_id mq;
41  rtems_id br;
42#if defined(RTEMS_POSIX_API)
43  sem_t psem;
44  pthread_mutex_t pmtx;
45  pthread_cond_t pcv;
46  pthread_rwlock_t prw;
47  mqd_t pmq;
48#endif
49} test_context;
50
51static test_context test_instance;
52
53static void wait_for_worker(test_context *ctx)
54{
55  rtems_status_code sc;
56
57  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
58  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
59}
60
61static void wake_up_master(test_context *ctx)
62{
63  rtems_status_code sc;
64
65  sc = rtems_event_transient_send(ctx->master_id);
66  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
67}
68
69static rtems_id get_wait_id(test_context *ctx)
70{
71  Thread_queue_Context queue_context;
72  rtems_id id;
73
74  _Thread_Wait_acquire(ctx->master, &queue_context);
75  id = _Thread_Wait_get_id(ctx->master);
76  _Thread_Wait_release(ctx->master, &queue_context);
77
78  return id;
79}
80
81static void classic_worker(test_context *ctx)
82{
83  rtems_status_code sc;
84  char buf[1];
85
86  wake_up_master(ctx);
87  rtems_test_assert(get_wait_id(ctx) == ctx->sem);
88
89  sc = rtems_semaphore_release(ctx->sem);
90  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
91
92  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
93  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
94
95  wake_up_master(ctx);
96  rtems_test_assert(get_wait_id(ctx) == ctx->mtx);
97
98  sc = rtems_semaphore_release(ctx->mtx);
99  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
100
101  wake_up_master(ctx);
102  rtems_test_assert(get_wait_id(ctx) == ctx->mq);
103
104  buf[0] = 'X';
105  sc = rtems_message_queue_send(ctx->mq, &buf[0], sizeof(buf));
106  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
107
108  wake_up_master(ctx);
109  rtems_test_assert(get_wait_id(ctx) == ctx->br);
110
111  sc = rtems_barrier_wait(ctx->br, RTEMS_NO_TIMEOUT);
112  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
113}
114
115static void posix_worker(test_context *ctx)
116{
117#if defined(RTEMS_POSIX_API)
118  int rv;
119  int eno;
120  char buf[1];
121
122  wake_up_master(ctx);
123  rtems_test_assert(get_wait_id(ctx) == ctx->psem);
124
125  rv = sem_post(&ctx->psem);
126  rtems_test_assert(rv == 0);
127
128  eno = pthread_mutex_lock(&ctx->pmtx);
129  rtems_test_assert(eno == 0);
130
131  wake_up_master(ctx);
132  rtems_test_assert(get_wait_id(ctx) == ctx->pmtx);
133
134  eno = pthread_mutex_unlock(&ctx->pmtx);
135  rtems_test_assert(eno == 0);
136
137  eno = pthread_mutex_lock(&ctx->pmtx);
138  rtems_test_assert(eno == 0);
139
140  rtems_test_assert(get_wait_id(ctx) == ctx->pcv);
141
142  eno = pthread_cond_signal(&ctx->pcv);
143  rtems_test_assert(eno == 0);
144
145  eno = pthread_mutex_unlock(&ctx->pmtx);
146  rtems_test_assert(eno == 0);
147
148  eno = pthread_rwlock_wrlock(&ctx->prw);
149  rtems_test_assert(eno == 0);
150
151  wake_up_master(ctx);
152  rtems_test_assert(get_wait_id(ctx) == ctx->prw);
153
154  eno = pthread_rwlock_unlock(&ctx->prw);
155  rtems_test_assert(eno == 0);
156
157  wake_up_master(ctx);
158  rtems_test_assert(get_wait_id(ctx) == ctx->pmq);
159
160  buf[0] = 'x';
161  rv = mq_send(ctx->pmq, &buf[0], sizeof(buf), 0);
162  rtems_test_assert(rv == 0);
163#endif
164}
165
166static rtems_task worker(rtems_task_argument arg)
167{
168  test_context *ctx = (test_context *) arg;
169
170  rtems_test_assert(get_wait_id(ctx) == 0);
171
172  classic_worker(ctx);
173  posix_worker(ctx);
174}
175
176static void test_classic_init(test_context *ctx)
177{
178  rtems_status_code sc;
179
180  sc = rtems_semaphore_create(
181    rtems_build_name('S', 'E', 'M', ' '),
182    0,
183    RTEMS_COUNTING_SEMAPHORE,
184    0,
185    &ctx->sem
186  );
187  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
188
189  sc = rtems_semaphore_create(
190    rtems_build_name('M', 'T', 'X', ' '),
191    1,
192    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
193    0,
194    &ctx->mtx
195  );
196  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
197
198  sc = rtems_message_queue_create(
199    rtems_build_name('M', 'Q', ' ', ' '),
200    1,
201    1,
202    RTEMS_DEFAULT_ATTRIBUTES,
203    &ctx->mq
204  );
205  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
206
207  sc = rtems_barrier_create(
208    rtems_build_name('B', 'R', ' ', ' '),
209    RTEMS_BARRIER_AUTOMATIC_RELEASE,
210    2,
211    &ctx->br
212  );
213  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
214}
215
216static void test_posix_init(test_context *ctx)
217{
218#if defined(RTEMS_POSIX_API)
219  int rv;
220  int eno;
221  struct mq_attr attr;
222
223  rv = sem_init(&ctx->psem, 0, 0);
224  rtems_test_assert(rv == 0);
225
226  eno = pthread_mutex_init(&ctx->pmtx, NULL);
227  rtems_test_assert(eno == 0);
228
229  eno = pthread_cond_init(&ctx->pcv, NULL);
230  rtems_test_assert(eno == 0);
231
232  eno = pthread_rwlock_init(&ctx->prw, NULL);
233  rtems_test_assert(eno == 0);
234
235  memset(&attr, 0, sizeof(attr));
236  attr.mq_maxmsg = 1;
237  attr.mq_msgsize = sizeof(char);
238
239  ctx->pmq = mq_open("mq", O_CREAT | O_RDWR, 0x777, &attr);
240  rtems_test_assert(ctx->mq != -1);
241#endif
242}
243
244static void test_context_init(test_context *ctx)
245{
246  rtems_status_code sc;
247
248  ctx->master = _Thread_Get_executing();
249  ctx->master_id = rtems_task_self();
250
251  test_classic_init(ctx);
252  test_posix_init(ctx);
253
254  sc = rtems_task_create(
255    rtems_build_name('W', 'O', 'R', 'K'),
256    2,
257    RTEMS_MINIMUM_STACK_SIZE,
258    RTEMS_DEFAULT_MODES,
259    RTEMS_DEFAULT_ATTRIBUTES,
260    &ctx->worker_id
261  );
262  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
263
264  sc = rtems_task_start(ctx->worker_id, worker, (rtems_task_argument) ctx);
265  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
266}
267
268static void test_classic_obj(test_context *ctx)
269{
270  rtems_status_code sc;
271  char buf[1];
272  size_t n;
273
274  wait_for_worker(ctx);
275
276  sc = rtems_semaphore_obtain(ctx->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
277  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
278
279  wait_for_worker(ctx);
280
281  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
282  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
283
284  wait_for_worker(ctx);
285
286  buf[0] = 'Y';
287  n = 123;
288  sc = rtems_message_queue_receive(
289    ctx->mq,
290    &buf[0],
291    &n,
292    RTEMS_WAIT,
293    RTEMS_NO_TIMEOUT
294  );
295  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
296  rtems_test_assert(buf[0] == 'X');
297  rtems_test_assert(n == sizeof(buf));
298
299  wait_for_worker(ctx);
300
301  sc = rtems_barrier_wait(ctx->br, RTEMS_NO_TIMEOUT);
302  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
303}
304
305static void test_posix_obj(test_context *ctx)
306{
307#if defined(RTEMS_POSIX_API)
308  int rv;
309  int eno;
310  char buf[1];
311  unsigned prio;
312  ssize_t n;
313
314  wait_for_worker(ctx);
315
316  rv = sem_wait(&ctx->psem);
317  rtems_test_assert(rv == 0);
318
319  wait_for_worker(ctx);
320
321  eno = pthread_mutex_lock(&ctx->pmtx);
322  rtems_test_assert(eno == 0);
323
324  eno = pthread_cond_wait(&ctx->pcv, &ctx->pmtx);
325  rtems_test_assert(eno == 0);
326
327  eno = pthread_mutex_unlock(&ctx->pmtx);
328  rtems_test_assert(eno == 0);
329
330  wait_for_worker(ctx);
331
332  eno = pthread_rwlock_wrlock(&ctx->prw);
333  rtems_test_assert(eno == 0);
334
335  wait_for_worker(ctx);
336
337  buf[0] = 'y';
338  prio = 1;
339  n = mq_receive(ctx->pmq, &buf[0], sizeof(buf), &prio);
340  rtems_test_assert(n == (ssize_t) sizeof(buf));
341  rtems_test_assert(buf[0] == 'x');
342  rtems_test_assert(prio == 0);
343#endif
344}
345
346static rtems_task Init(
347  rtems_task_argument ignored
348)
349{
350  test_context *ctx = &test_instance;
351
352  TEST_BEGIN();
353
354  puts( "Init - _Thread_queue_Extract - thread not blocked on a thread queue" );
355  _Thread_queue_Extract( _Thread_Get_executing() );
356  /* is there more to check? */
357
358  test_context_init(ctx);
359  test_classic_obj(ctx);
360  test_posix_obj(ctx);
361
362  rtems_test_assert( _Thread_queue_Is_empty( &queue.Queue ) );
363
364  TEST_END();
365  rtems_test_exit(0);
366}
367
368/* configuration information */
369
370#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
371#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
372
373#define CONFIGURE_MAXIMUM_TASKS  2
374#define CONFIGURE_MAXIMUM_SEMAPHORES  2
375#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES  1
376#define CONFIGURE_MAXIMUM_BARRIERS  1
377
378#if defined(RTEMS_POSIX_API)
379  #define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1
380  #define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1
381  #define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 1
382  #define CONFIGURE_MAXIMUM_POSIX_RWLOCKS 1
383  #define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1
384  #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
385    (2 * CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(1, 1))
386#else
387  #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
388    CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(1, 1)
389#endif
390
391#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
392
393#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
394
395#define CONFIGURE_INIT
396#include <rtems/confdefs.h>
397
398/* global variables */
Note: See TracBrowser for help on using the repository browser.