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 31#define _XOPEN_SOURCE 600 32#include <pthread.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <unistd.h> 36#include <errno.h> 37#include <string.h> 38#include <sys/mman.h> 39#include <fcntl.h> 40#include <sys/wait.h> 41#include "posixtest.h" 42 43struct shmstruct{ 44 pthread_spinlock_t spinlock; 45 int data; 46} *spinlock_data; 47 48int main() 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 = shm_open(shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); 68 if(shm_fd == -1) 69 { 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 = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, 82 MAP_SHARED, shm_fd, 0); 83 84 if(spinlock_data == MAP_FAILED) 85 { 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 { 93 printf("Test FAILED: Error at pthread_rwlock_init()\n"); 94 return PTS_FAIL; 95 } 96 97 printf("main: attempt spin lock\n"); 98 if((pthread_spin_lock(&(spinlock_data->spinlock))) != 0) 99 { 100 printf("Error at pthread_spin_lock()\n"); 101 return PTS_UNRESOLVED; 102 } 103 printf("main: acquired spin lock\n"); 104 105 /* Initialized spinlock data */ 106 spinlock_data->data = 0; 107 108 pid = fork(); 109 if(pid == -1) 110 { 111 perror("Error at fork()"); 112 return PTS_UNRESOLVED; 113 } 114 else if(pid > 0) 115 { 116 /* Parent */ 117 /* wait until child writes to spinlock data */ 118 while(spinlock_data->data != 1) 119 sleep(1); 120 121 printf("main: unlock spin lock\n"); 122 if(pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) 123 { 124 printf("main: error at pthread_spin_unlock()\n"); 125 return PTS_UNRESOLVED; 126 } 127 128 /* Tell child that parent unlocked the spin lock */ 129 spinlock_data->data = 2; 130 131 /* Wait until child ends */ 132 wait(NULL); 133 134 if((shm_unlink(shm_name)) != 0) 135 { 136 perror("Error at shm_unlink()"); 137 return PTS_UNRESOLVED; 138 } 139 140 printf("Test PASSED\n"); 141 return PTS_PASS; 142 } 143 else 144 { 145 /* Child */ 146 /* Map the shared object to child's memory */ 147 spinlock_data = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, 148 MAP_SHARED, shm_fd, 0); 149 150 if(spinlock_data == MAP_FAILED) 151 { 152 perror("child : Error at mmap()"); 153 return PTS_UNRESOLVED; 154 } 155 156 printf("child: attempt spin lock\n"); 157 rc = pthread_spin_trylock(&(spinlock_data->spinlock)); 158 if( rc != EBUSY) 159 printf("child: get return code %d, %s\n", rc, strerror(rc)); 160 else 161 printf("child: correctly got EBUSY\n"); 162 163 /* Tell parent it can unlock now */ 164 spinlock_data->data = 1; 165 166 while(spinlock_data->data != 2) 167 sleep(1); 168 169 printf("child: attempt spin lock\n"); 170 rc = pthread_spin_trylock(&(spinlock_data->spinlock)); 171 if(rc == 0) 172 printf("child: acquired spin lock\n"); 173 else 174 printf("child: get return code %d, %s\n", rc, strerror(rc)); 175 176 printf("child: unlock spin lock\n"); 177 if(pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) 178 { 179 printf("Child: error at pthread_spin_unlock()\n"); 180 return PTS_UNRESOLVED; 181 } 182 183 if(pthread_spin_destroy(&(spinlock_data->spinlock)) != 0) 184 { 185 printf("Child: error at pthread_spin_destroy()\n"); 186 return PTS_UNRESOLVED; 187 } 188 } 189} 190