source: rtems/testsuites/psxtests/psxcleanup/psxcleanup.c @ f7ad5b3

4.104.114.95
Last change on this file since f7ad5b3 was f7ad5b3, checked in by Jennifer Averett <Jennifer.Averett@…>, on 01/18/08 at 17:09:51

2008-01-18 Jennifer Averett <jennifer.averett@…>

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