source: rtems/testsuites/psxtests/psxcleanup/psxcleanup.c @ 9a4eca5

5
Last change on this file since 9a4eca5 was 698c2e50, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 07:06:16

tests/psxtests: Use <rtems/test.h>

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 *
3 *  This is a simple real-time applications XXX.
4 *
5 *  Other POSIX facilities such as XXX, condition, .. is also used
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#define CONFIGURE_INIT
17#include "system.h"
18#include <pthread.h>  /* thread facilities */
19#include <signal.h>   /* signal facilities */
20#include <unistd.h>   /* sleep facilities */
21#include <sched.h>    /* schedule facilities */
22#include <time.h>     /* time facilities */
23#include <stdio.h>    /* console facilities */
24#include "tmacros.h"
25
26const char rtems_test_name[] = "PSXCLEANUP";
27
28#define NUMBER_THREADS 2
29pthread_t ThreadIds[NUMBER_THREADS];
30
31typedef struct {
32  pthread_mutex_t lock;
33  pthread_cond_t rcond;
34  pthread_cond_t wcond;
35  int lock_count; /* < 0 .. Held by writer. */
36                  /* > 0 .. Held by lock_count readers. */
37                  /* = 0 .. Held by nobody. */
38  int waiting_writers; /* Count of waiting writers. */
39} lock_t;
40
41volatile bool reader_cleanup_ran;
42volatile bool release_read_lock_ran;
43volatile bool writer_cleanup_ran;
44
45void waiting_reader_cleanup(void *arg);
46void lock_for_read(void *arg);
47void release_read_lock(void *arg);
48void waiting_writer_cleanup(void *arg);
49void lock_for_write(lock_t *l);
50void release_write_lock(void *arg);
51void initialize_lock_t(lock_t *l);
52void *ReaderThread(void *arg);
53void *WriterThread(void *arg);
54
55void waiting_reader_cleanup(void *arg)
56{
57  lock_t *l;
58
59  reader_cleanup_ran = TRUE;
60
61  l = (lock_t *) arg;
62  pthread_mutex_unlock(&l->lock);
63}
64
65void lock_for_read(void *arg)
66{
67  lock_t *l = arg;
68
69  pthread_mutex_lock(&l->lock);
70  pthread_cleanup_push(waiting_reader_cleanup, l);
71  while ((l->lock_count < 0) && (l->waiting_writers != 0))
72    pthread_cond_wait(&l->rcond, &l->lock);
73  l->lock_count++;
74  reader_cleanup_ran = FALSE;
75
76  /*
77   * Note the pthread_cleanup_pop executes
78   * waiting_reader_cleanup.
79   */
80  pthread_cleanup_pop(1);
81
82  if ( reader_cleanup_ran == FALSE ) {
83    puts( "reader cleanup did not run" );
84    rtems_test_exit(0);
85  }
86}
87
88void release_read_lock(void *arg)
89{
90  lock_t *l = arg;
91
92  release_read_lock_ran = TRUE;
93  pthread_mutex_lock(&l->lock);
94  if (--l->lock_count == 0)
95    pthread_cond_signal(&l->wcond);
96  pthread_mutex_unlock(&l->lock);
97}
98
99void waiting_writer_cleanup(void *arg)
100{
101  lock_t *l = arg;
102
103  writer_cleanup_ran = TRUE;
104
105  if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) {
106    /*
107     * This only happens if we have been canceled.
108     */
109    pthread_cond_broadcast(&l->wcond);
110  }
111    pthread_mutex_unlock(&l->lock);
112}
113
114void lock_for_write(lock_t *l)
115{
116  pthread_mutex_lock(&l->lock);
117  l->waiting_writers++;
118  l->lock_count = -1;
119
120  pthread_cleanup_push(waiting_writer_cleanup, l);
121
122  while (l->lock_count != 0)
123      pthread_cond_wait(&l->wcond, &l->lock);
124  l->lock_count = -1;
125
126  /*
127   * Note the pthread_cleanup_pop executes
128   * waiting_writer_cleanup.
129   */
130  writer_cleanup_ran = FALSE;
131  pthread_cleanup_pop(1);
132
133  if ( writer_cleanup_ran == FALSE ) {
134    puts( "writer cleanup did not run" );
135    rtems_test_exit(0);
136  }
137}
138
139void release_write_lock(void *arg)
140{
141  lock_t *l = arg;
142
143  writer_cleanup_ran = TRUE;
144
145  /* pthread_mutex_lock(&l->lock); */
146  l->lock_count = 0;
147  if (l->waiting_writers == 0)
148      pthread_cond_broadcast(&l->rcond);
149  else
150      pthread_cond_signal(&l->wcond);
151  /* pthread_mutex_unlock(&l->lock); */
152}
153
154
155/*
156 * This function is called to initialize the read/write lock.
157 */
158void initialize_lock_t(lock_t *l)
159{
160  pthread_mutexattr_t mutexattr;    /* mutex attributes */
161  pthread_condattr_t  condattr;     /* condition attributes */
162
163  if (pthread_mutexattr_init (&mutexattr) != 0) {
164    perror ("Error in mutex attribute init\n");
165  }
166  if (pthread_mutex_init (&l->lock,&mutexattr) != 0) {
167    perror ("Error in mutex init");
168  }
169
170  if (pthread_condattr_init (&condattr) != 0) {
171     perror ("Error in condition attribute init\n");
172  }
173  if (pthread_cond_init (&l->wcond,&condattr) != 0) {
174    perror ("Error in write condition init");
175  }
176  if (pthread_cond_init (&l->rcond,&condattr) != 0) {
177    perror ("Error in read condition init");
178  }
179
180  l->lock_count = 0;
181  l->waiting_writers = 0;
182}
183
184void *ReaderThread(void *arg)
185{
186  lock_t *l = arg;
187
188  puts("Lock for read");
189  lock_for_read(l);
190  puts("cleanup push for read");
191  pthread_cleanup_push(release_read_lock, &l->lock);
192
193  /* Thread has read lock. */
194  release_read_lock_ran = FALSE;
195  puts("cleanup pop for read");
196  pthread_cleanup_pop(1);
197
198  if ( release_read_lock_ran == FALSE ) {
199    puts( "release read lock did not run" );
200    rtems_test_exit(0);
201  }
202  return NULL;
203}
204
205void *WriterThread(void *arg)
206{
207  lock_t *l = arg;
208
209  puts("Lock for write");
210  lock_for_write(l);
211  puts("cleanup push for write");
212  pthread_cleanup_push(release_write_lock, &l->lock);
213
214  /* Thread has write lock. */
215  release_write_lock(&l->lock);
216
217  /* do nothing */
218  puts("do nothing cleanup pop for write");
219  pthread_cleanup_pop(0);
220  return NULL;
221}
222
223/*
224 *  main entry point to the test
225 */
226
227void *POSIX_Init(
228  void *argument
229)
230{
231  pthread_attr_t attr;              /* task attributes */
232  int            status;
233  lock_t         l;
234
235  TEST_BEGIN();
236
237  /*************** INITIALIZE  ***************/
238  initialize_lock_t(&l);
239  if (pthread_attr_init(&attr) != 0) {
240    perror ("Error in attribute init\n");
241  }
242
243  /*************** CREATE THREADS  ***************/
244
245  status = pthread_create(&ThreadIds[0], NULL, ReaderThread, &l);
246  posix_service_failed( status, "pthread_create Reader" );
247
248  sleep(1);
249
250  status = pthread_create(&ThreadIds[1], NULL, WriterThread, &l);
251  posix_service_failed( status, "pthread_create Writer" );
252
253  sleep(1);
254
255  /*************** END OF TEST *****************/
256  TEST_END();
257  rtems_test_exit(0);
258}
259
Note: See TracBrowser for help on using the repository browser.