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 * Test pthread_spin_init(pthread_spinlock_t *lock, int pshared) 8 * 9 * If the Thread Process-Shared Synchronization option is supported 10 * and the value of pshared is PTHREAD_PROCESS_PRIVATE, or if the option 11 * is not supported, the spin lock shall only be operated upon by threads created 12 * within the same process as the thread that initialized the spin lock. 13 * If threads of different processed attempt to operation on such a spin 14 * lock, the behavior is undefined. 15 * 16 * NOTE: This case will always PASS 17 * 18 * steps: 19 * 1. Create a piece of shared memory object, create a spin lock 'spinlock' and 20 * set the PTHREAD_PROCESS_PRIVATE attribute. 21 * 2. Parent map the shared memory to its memory space, put 'spinlock' into it; 22 * 3. Parent get the spin lock; 23 * 4. Fork to create child 24 * 5. Child map the shared memory to its memory space; 25 * 6. Child call pthread_spin_trylock() 26 * 7. Main unlock 27 * 8. Child call pthread_spin_trylock() 28 */ 29 30 #define _XOPEN_SOURCE 600 31 #include <sys/mman.h> 32 #include <sys/stat.h> 33 #include <sys/wait.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <pthread.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include "posixtest.h" 42 43 struct shmstruct { 44 pthread_spinlock_t spinlock; 45 int data; 46 } *spinlock_data; 47 48 int main(void) 49 { 50 51 int pshared; 52 53 /* Make sure there is process-shared capability. */ 54 #ifdef PTHREAD_PROCESS_PRIVATE 55 pshared = PTHREAD_PROCESS_PRIVATE; 56 #else 57 pshared = -1; 58 #endif 59 60 char shm_name[] = "tmp_pthread_spinlock_init"; 61 int shm_fd; 62 int pid; 63 int rc; 64 65 /* Create shared object */ 66 shm_unlink(shm_name); 67 shm_fd = 68 shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 69 if (shm_fd == -1) { 70 perror("Error at shm_open()"); 71 return PTS_UNRESOLVED; 72 } 73 74 if (ftruncate(shm_fd, sizeof(struct shmstruct)) != 0) { 75 perror("Error at ftruncate()"); 76 shm_unlink(shm_name); 77 return PTS_UNRESOLVED; 78 } 79 80 /* Map the shared memory object to parent's memory */ 81 spinlock_data = 82 mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 83 MAP_SHARED, shm_fd, 0); 84 85 if (spinlock_data == MAP_FAILED) { 86 perror("Error at first mmap()"); 87 shm_unlink(shm_name); 88 return PTS_UNRESOLVED; 89 } 90 91 if ((pthread_spin_init(&(spinlock_data->spinlock), pshared)) != 0) { 92 printf("Test FAILED: Error at pthread_rwlock_init()\n"); 93 return PTS_FAIL; 94 } 95 96 printf("main: attempt spin lock\n"); 97 if ((pthread_spin_lock(&(spinlock_data->spinlock))) != 0) { 98 printf("Error at pthread_spin_lock()\n"); 99 return PTS_UNRESOLVED; 100 } 101 printf("main: acquired spin lock\n"); 102 103 /* Initialized spinlock data */ 104 spinlock_data->data = 0; 105 106 pid = fork(); 107 if (pid == -1) { 108 perror("Error at fork()"); 109 return PTS_UNRESOLVED; 110 } else if (pid > 0) { 111 /* Parent */ 112 /* wait until child writes to spinlock data */ 113 while (spinlock_data->data != 1) 114 sleep(1); 115 116 printf("main: unlock spin lock\n"); 117 if (pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) { 118 printf("main: error at pthread_spin_unlock()\n"); 119 return PTS_UNRESOLVED; 120 } 121 122 /* Tell child that parent unlocked the spin lock */ 123 spinlock_data->data = 2; 124 125 /* Wait until child ends */ 126 wait(NULL); 127 128 if ((shm_unlink(shm_name)) != 0) { 129 perror("Error at shm_unlink()"); 130 return PTS_UNRESOLVED; 131 } 132 133 printf("Test PASSED\n"); 134 return PTS_PASS; 135 } else { 136 /* Child */ 137 /* Map the shared object to child's memory */ 138 spinlock_data = 139 mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE, 140 MAP_SHARED, shm_fd, 0); 141 142 if (spinlock_data == MAP_FAILED) { 143 perror("child : Error at mmap()"); 144 return PTS_UNRESOLVED; 145 } 146 147 printf("child: attempt spin lock\n"); 148 rc = pthread_spin_trylock(&(spinlock_data->spinlock)); 149 if (rc != EBUSY) 150 printf("child: get return code %d, %s\n", rc, 151 strerror(rc)); 152 else 153 printf("child: correctly got EBUSY\n"); 154 155 /* Tell parent it can unlock now */ 156 spinlock_data->data = 1; 157 158 while (spinlock_data->data != 2) 159 sleep(1); 160 161 printf("child: attempt spin lock\n"); 162 rc = pthread_spin_trylock(&(spinlock_data->spinlock)); 163 if (rc == 0) 164 printf("child: acquired spin lock\n"); 165 else 166 printf("child: get return code %d, %s\n", rc, 167 strerror(rc)); 168 169 printf("child: unlock spin lock\n"); 170 if (pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) { 171 printf("Child: error at pthread_spin_unlock()\n"); 172 return PTS_UNRESOLVED; 173 } 174 175 if (pthread_spin_destroy(&(spinlock_data->spinlock)) != 0) { 176 printf("Child: error at pthread_spin_destroy()\n"); 177 return PTS_UNRESOLVED; 178 } 179 } 180 } 181