File indexing completed on 2025-05-11 08:24:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifdef HAVE_CONFIG_H
0032 #include "config.h"
0033 #endif
0034
0035 #define CONFIGURE_INIT
0036 #include "system.h"
0037 #include <pthread.h> /* thread facilities */
0038 #include <signal.h> /* signal facilities */
0039 #include <unistd.h> /* sleep facilities */
0040 #include <sched.h> /* schedule facilities */
0041 #include <time.h> /* time facilities */
0042 #include <stdio.h> /* console facilities */
0043 #include "tmacros.h"
0044
0045 const char rtems_test_name[] = "PSXCLEANUP";
0046
0047 #define NUMBER_THREADS 2
0048 pthread_t ThreadIds[NUMBER_THREADS];
0049
0050 typedef struct {
0051 pthread_mutex_t lock;
0052 pthread_cond_t rcond;
0053 pthread_cond_t wcond;
0054 int lock_count;
0055
0056
0057 int waiting_writers;
0058 } lock_t;
0059
0060 volatile bool reader_cleanup_ran;
0061 volatile bool release_read_lock_ran;
0062 volatile bool writer_cleanup_ran;
0063
0064 void waiting_reader_cleanup(void *arg);
0065 void lock_for_read(void *arg);
0066 void release_read_lock(void *arg);
0067 void waiting_writer_cleanup(void *arg);
0068 void lock_for_write(lock_t *l);
0069 void release_write_lock(void *arg);
0070 void initialize_lock_t(lock_t *l);
0071 void *ReaderThread(void *arg);
0072 void *WriterThread(void *arg);
0073
0074 void waiting_reader_cleanup(void *arg)
0075 {
0076 lock_t *l;
0077
0078 reader_cleanup_ran = TRUE;
0079
0080 l = (lock_t *) arg;
0081 pthread_mutex_unlock(&l->lock);
0082 }
0083
0084 void lock_for_read(void *arg)
0085 {
0086 lock_t *l = arg;
0087
0088 pthread_mutex_lock(&l->lock);
0089 pthread_cleanup_push(waiting_reader_cleanup, l);
0090 while ((l->lock_count < 0) && (l->waiting_writers != 0))
0091 pthread_cond_wait(&l->rcond, &l->lock);
0092 l->lock_count++;
0093 reader_cleanup_ran = FALSE;
0094
0095
0096
0097
0098
0099 pthread_cleanup_pop(1);
0100
0101 if ( reader_cleanup_ran == FALSE ) {
0102 puts( "reader cleanup did not run" );
0103 rtems_test_exit(0);
0104 }
0105 }
0106
0107 void release_read_lock(void *arg)
0108 {
0109 lock_t *l = arg;
0110
0111 release_read_lock_ran = TRUE;
0112 pthread_mutex_lock(&l->lock);
0113 if (--l->lock_count == 0)
0114 pthread_cond_signal(&l->wcond);
0115 pthread_mutex_unlock(&l->lock);
0116 }
0117
0118 void waiting_writer_cleanup(void *arg)
0119 {
0120 lock_t *l = arg;
0121
0122 writer_cleanup_ran = TRUE;
0123
0124 if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) {
0125
0126
0127
0128 pthread_cond_broadcast(&l->wcond);
0129 }
0130 pthread_mutex_unlock(&l->lock);
0131 }
0132
0133 void lock_for_write(lock_t *l)
0134 {
0135 pthread_mutex_lock(&l->lock);
0136 l->waiting_writers++;
0137 l->lock_count = -1;
0138
0139 pthread_cleanup_push(waiting_writer_cleanup, l);
0140
0141 while (l->lock_count != 0)
0142 pthread_cond_wait(&l->wcond, &l->lock);
0143 l->lock_count = -1;
0144
0145
0146
0147
0148
0149 writer_cleanup_ran = FALSE;
0150 pthread_cleanup_pop(1);
0151
0152 if ( writer_cleanup_ran == FALSE ) {
0153 puts( "writer cleanup did not run" );
0154 rtems_test_exit(0);
0155 }
0156 }
0157
0158 void release_write_lock(void *arg)
0159 {
0160 lock_t *l = arg;
0161
0162 writer_cleanup_ran = TRUE;
0163
0164
0165 l->lock_count = 0;
0166 if (l->waiting_writers == 0)
0167 pthread_cond_broadcast(&l->rcond);
0168 else
0169 pthread_cond_signal(&l->wcond);
0170
0171 }
0172
0173
0174
0175
0176
0177 void initialize_lock_t(lock_t *l)
0178 {
0179 pthread_mutexattr_t mutexattr;
0180 pthread_condattr_t condattr;
0181
0182 if (pthread_mutexattr_init (&mutexattr) != 0) {
0183 perror ("Error in mutex attribute init\n");
0184 }
0185 if (pthread_mutex_init (&l->lock,&mutexattr) != 0) {
0186 perror ("Error in mutex init");
0187 }
0188
0189 if (pthread_condattr_init (&condattr) != 0) {
0190 perror ("Error in condition attribute init\n");
0191 }
0192 if (pthread_cond_init (&l->wcond,&condattr) != 0) {
0193 perror ("Error in write condition init");
0194 }
0195 if (pthread_cond_init (&l->rcond,&condattr) != 0) {
0196 perror ("Error in read condition init");
0197 }
0198
0199 l->lock_count = 0;
0200 l->waiting_writers = 0;
0201 }
0202
0203 void *ReaderThread(void *arg)
0204 {
0205 lock_t *l = arg;
0206
0207 puts("Lock for read");
0208 lock_for_read(l);
0209 puts("cleanup push for read");
0210 pthread_cleanup_push(release_read_lock, &l->lock);
0211
0212
0213 release_read_lock_ran = FALSE;
0214 puts("cleanup pop for read");
0215 pthread_cleanup_pop(1);
0216
0217 if ( release_read_lock_ran == FALSE ) {
0218 puts( "release read lock did not run" );
0219 rtems_test_exit(0);
0220 }
0221 return NULL;
0222 }
0223
0224 void *WriterThread(void *arg)
0225 {
0226 lock_t *l = arg;
0227
0228 puts("Lock for write");
0229 lock_for_write(l);
0230 puts("cleanup push for write");
0231 pthread_cleanup_push(release_write_lock, &l->lock);
0232
0233
0234 release_write_lock(&l->lock);
0235
0236
0237 puts("do nothing cleanup pop for write");
0238 pthread_cleanup_pop(0);
0239 return NULL;
0240 }
0241
0242
0243
0244
0245
0246 void *POSIX_Init(
0247 void *argument
0248 )
0249 {
0250 pthread_attr_t attr;
0251 int status;
0252 lock_t l;
0253
0254 TEST_BEGIN();
0255
0256
0257 initialize_lock_t(&l);
0258 if (pthread_attr_init(&attr) != 0) {
0259 perror ("Error in attribute init\n");
0260 }
0261
0262
0263
0264 status = pthread_create(&ThreadIds[0], NULL, ReaderThread, &l);
0265 posix_service_failed( status, "pthread_create Reader" );
0266
0267 sleep(1);
0268
0269 status = pthread_create(&ThreadIds[1], NULL, WriterThread, &l);
0270 posix_service_failed( status, "pthread_create Writer" );
0271
0272 sleep(1);
0273
0274
0275 TEST_END();
0276 rtems_test_exit(0);
0277 }
0278