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