1 /* 2 * Copyright (c) 2002, Intel Corporation. All rights reserved. 3 * This file is licensed under the GPL license. For the full content 4 * of this license, see the COPYING file at the top level of this 5 * source tree. 6 * 7 * The process-shared attribute shall be set to PTHREAD_PROCESS_SHARED 8 * to permit a read-write lock to be operated upon by any thread 9 * that has access to the memory where the read-write lock is allocated, 10 * even if the read-write lock is allocated in memory that is shared by 11 * multiple processes. 12 * 13 * steps: 14 * 1. Create a piece of shared memory object, create a read write lock 'rwlock' and 15 * set the PTHREAD_PROCESS_SHARED attribute. 16 * 2. Parent map the shared memory to its memory space, put 'rwlock' into it; 17 * 3. Parent get read lock; 18 * 4. Fork to create child, parent wait until child call pthread_rwlock_wrlock() 19 * 5. Child map the shared memory to its memory space; 20 * 6. Child call pthread_rwlock_trywrlock(), should fail with EBUSY; 21 * 7. Child call pthread_rwlock_wrlock(), should block; 22 * 8. Parent unlock 'rwlock' 23 * 9. Child should get the write lock. 24 */ 25 26 #define _XOPEN_SOURCE 600 27 #include <sys/mman.h> 28 #include <sys/stat.h> 29 #include <sys/wait.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <pthread.h> 33 #include <stdio.h> 34 #include <unistd.h> 35 #include "posixtest.h" 36 37 struct shmstruct { 38 pthread_rwlock_t rwl; 39 int data; 40 } *rwlock_data; 41 42 int main(void) 43 { 44 45 /* Make sure there is process-shared capability. */ 46 #ifndef PTHREAD_PROCESS_SHARED 47 fprintf(stderr, 48 "process-shared attribute is not available for testing\n"); 49 return PTS_UNSUPPORTED; 50 #endif 51 52 pthread_rwlockattr_t rwla; 53 int pshared = PTHREAD_PROCESS_SHARED; 54 55 char shm_name[] = "tmp_pthread_rwlock_getpshared"; 56 int shm_fd; 57 int pid; 58 59 /* Initialize a rwlock attributes object */ 60 if (pthread_rwlockattr_init(&rwla) != 0) { 61 printf("Error at pthread_rwlockattr_init()\n"); 62 return PTS_UNRESOLVED; 63 } 64 65 if (pthread_rwlockattr_setpshared(&rwla, pshared) != 0) { 66 printf("Error at pthread_rwlockattr_setpshared()\n"); 67 return PTS_UNRESOLVED; 68 } 69 70 if (pthread_rwlockattr_getpshared(&rwla, &pshared) != 0) { 71 printf 72 ("Test FAILED: Error at pthread_rwlockattr_getpshared()\n"); 73 return PTS_FAIL; 74 } 75 76 if (pshared != PTHREAD_PROCESS_SHARED) { 77 printf("Test FAILED: Got error shared attribute value %d\n", 78 pshared); 79 return PTS_FAIL; 80 } 81 82 /* Create shared object */ 83 shm_unlink(shm_name); 84 shm_fd = 85 shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 86 if (shm_fd == -1) { 87 perror("Error at shm_open()"); 88 return PTS_UNRESOLVED; 89 } 90 91 if (ftruncate(shm_fd, sizeof(struct shmstruct)) != 0) { 92 perror("Error at ftruncate()"); 93 shm_unlink(shm_name); 94 return PTS_UNRESOLVED; 95 } 96 97 /* Map the shared memory object to my memory */ 98 rwlock_data = 99 mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 100 MAP_SHARED, shm_fd, 0); 101 102 if (rwlock_data == MAP_FAILED) { 103 perror("Error at first mmap()"); 104 shm_unlink(shm_name); 105 return PTS_UNRESOLVED; 106 } 107 108 if ((pthread_rwlock_init(&(rwlock_data->rwl), &rwla)) != 0) { 109 printf("Error at pthread_rwlock_init()\n"); 110 return PTS_UNRESOLVED; 111 } 112 113 if ((pthread_rwlockattr_destroy(&rwla)) != 0) { 114 printf("Error at pthread_rwlockattr_destroy()\n"); 115 return PTS_UNRESOLVED; 116 } 117 118 printf("Parent getting read lock.\n"); 119 if ((pthread_rwlock_rdlock(&(rwlock_data->rwl))) != 0) { 120 printf("Error at pthread_rwlock_rdlock()\n"); 121 return PTS_UNRESOLVED; 122 } 123 printf("Parent got read lock.\n"); 124 rwlock_data->data = 0; 125 126 pid = fork(); 127 if (pid == -1) { 128 perror("Error at fork()"); 129 return PTS_UNRESOLVED; 130 } else if (pid > 0) { 131 /* Parent */ 132 /* wait until child do wrlock */ 133 while (rwlock_data->data == 0) { 134 sleep(1); 135 } 136 137 printf("Parent unlocking.\n"); 138 if (pthread_rwlock_unlock(&(rwlock_data->rwl)) != 0) { 139 printf("Parent: error at pthread_rwlock_unlock()\n"); 140 return PTS_FAIL; 141 } 142 printf("Parent unlocked.\n"); 143 144 /* Wait for child to end */ 145 wait(NULL); 146 147 if ((shm_unlink(shm_name)) != 0) { 148 perror("Error at shm_unlink()"); 149 return PTS_UNRESOLVED; 150 } 151 152 if (rwlock_data->data == -1) { 153 printf 154 ("Test FAILED: child did not block on write lock\n"); 155 return PTS_FAIL; 156 } 157 158 printf("Test PASSED\n"); 159 return PTS_PASS; 160 } else { 161 /* Child */ 162 /* Map the shared object to child's memory */ 163 rwlock_data = 164 mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 165 MAP_SHARED, shm_fd, 0); 166 167 if (rwlock_data == MAP_FAILED) { 168 perror("Error at first mmap()"); 169 return PTS_UNRESOLVED; 170 } 171 172 printf("Child tries to get write lock, should get EBUSY.\n"); 173 if ((pthread_rwlock_trywrlock(&(rwlock_data->rwl))) != EBUSY) { 174 printf("Test FAILED: Child expects EBUSY\n"); 175 return PTS_FAIL; 176 } 177 printf("Child got EBUSY.\n"); 178 179 printf("Child do wrlock.\n"); 180 181 /* Tell parent it can unlock now */ 182 rwlock_data->data = 1; 183 184 /* Should block until parent unlock */ 185 if ((pthread_rwlock_wrlock(&(rwlock_data->rwl))) != 0) { 186 printf("Child:pthread_rwlock_wrlock() error\n"); 187 printf 188 ("Test FAILED: Error while write lock the shared rwlock\n"); 189 rwlock_data->data = -1; 190 return PTS_FAIL; 191 } 192 printf("Child got wrlock.\n"); 193 if ((pthread_rwlock_unlock(&(rwlock_data->rwl))) != 0) { 194 printf("Child:pthread_rwlock_unlock() error\n"); 195 printf("Error while write unlock the shared rwlock\n"); 196 rwlock_data->data = -1; 197 return PTS_FAIL; 198 } 199 } 200 } 201