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_lock(pthread_spinlock_t *lock) 8 * 9 * The function shall lock the spin lock referenced by lock. The calling thread 10 * shall acquire the lock if it is not held by another thread. Otherwise, the 11 * thread shall spin (that is, shall not return from the pthread_spin_lock()) 12 * until the lock becomes available. 13 * 14 * Steps: 15 * 1. Initialize a pthread_spinlock_t object 'spinlock' with 16 * pthread_spin_init() 17 * 2. Main thread lock 'spinlock', should get the lock 18 * 3. Create a child thread. The thread lock 'spinlock', should spin. 19 * 4. After child thread spin for 2 seconds, send SIGALRM to it. 20 * 5. Child thread check its status in the signal handler. 21 */ 22 23#define _XOPEN_SOURCE 600 24#include <pthread.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <unistd.h> 28#include <signal.h> 29#include "posixtest.h" 30 31static pthread_spinlock_t spinlock; 32volatile static int thread_state; 33 34#define NOT_CREATED_THREAD 1 35#define ENTERED_THREAD 2 36#define EXITING_THREAD 3 37#define GET_SPIN_LOCK 4 38 39static void sig_handler() 40{ 41 /* Just return */ 42 pthread_exit(0); 43 return; 44} 45 46static void* fn_chld(void *arg) 47{ 48 int rc = 0; 49 50 struct sigaction act; 51 struct timespec ts; 52 thread_state = ENTERED_THREAD; 53 int cnt = 0; 54 55 /* Unblock the SIGALRM signal for the thread */ 56 sigemptyset (&act.sa_mask); 57 sigaddset(&act.sa_mask, SIGALRM); 58 if (pthread_sigmask (SIG_UNBLOCK, &act.sa_mask, NULL)) 59 { 60 perror("thread: could not unblock SIGALRM\n"); 61 return (void *)PTS_UNRESOLVED; 62 } 63 64 /* Set up child thread to handle SIGALRM */ 65 act.sa_flags = 0; 66 act.sa_handler = sig_handler; 67 sigfillset(&act.sa_mask); 68 sigaction(SIGALRM, &act, 0); 69 70 printf("thread: send SIGALRM to me after 2 secs\n"); 71 alarm(2); 72 73 printf("thread: attempt spin lock\n"); 74 rc = pthread_spin_lock(&spinlock); 75 if(rc != 0) 76 { 77 printf("Test FAILED: thread failed to get spin lock,error code:%d\n" , rc); 78 pthread_exit((void*)PTS_FAIL); 79 } 80 81 printf("thread: acquired spin lock\n"); 82 83 thread_state = GET_SPIN_LOCK; 84 /* Wait 10 seconds for SIGALRM to be sent */ 85 while( cnt++ < 10) 86 { 87 ts.tv_sec = 1; 88 ts.tv_nsec = 0; 89 nanosleep(&ts, NULL); 90 } 91 92 /* Shouldn't get here. If we do, it means that SIGALRM wasn't sent/received */ 93 printf("Error in thread: SIGALRM was not received/sent correctly, timedout after 10 secs of waiting.\n"); 94 pthread_exit((void*)PTS_UNRESOLVED); 95 return NULL; 96} 97 98int main() 99{ 100 pthread_t child_thread; 101 void *value_ptr; 102 struct sigaction sa; 103 104 /* Block the SIGALRM signal for main thread */ 105 sigemptyset (&sa.sa_mask); 106 sigaddset(&sa.sa_mask, SIGALRM); 107 if (pthread_sigmask (SIG_BLOCK, &sa.sa_mask, NULL)) 108 { 109 perror("main: could not block SIGALRM\n"); 110 return PTS_UNRESOLVED; 111 } 112 113 if(pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE) != 0) 114 { 115 perror("main: Error at pthread_spin_init()\n"); 116 return PTS_UNRESOLVED; 117 } 118 119 printf("main: attempt spin lock\n"); 120 121 /* We should get the lock */ 122 if(pthread_spin_lock(&spinlock) != 0) 123 { 124 printf("Test FAILED: main cannot get spin lock when no one owns the lock\n"); 125 return PTS_FAIL; 126 } 127 128 printf("main: acquired spin lock\n"); 129 130 thread_state = NOT_CREATED_THREAD; 131 132 printf("main: create thread\n"); 133 if(pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) 134 { 135 printf("main: Error creating child thread\n"); 136 return PTS_UNRESOLVED; 137 } 138 139 /* Wait for thread to end execution */ 140 if(pthread_join(child_thread, &value_ptr) != 0) 141 { 142 perror("Error in pthread_join()\n"); 143 return PTS_UNRESOLVED; 144 } 145 146 /* Check the return value of the thread */ 147 if(thread_state == GET_SPIN_LOCK) 148 { 149 printf("Test FAILED: Child thread did not spin on spin lock when other thread holds the lock\n"); 150 exit(PTS_FAIL); 151 } 152 else if(thread_state == ENTERED_THREAD) 153 { 154 printf("thread: spins on spin lock\n"); 155 printf("Test PASSED\n"); 156 exit(PTS_PASS); 157 } 158 else 159 { 160 printf("Unexpected child thread state: %d\n", thread_state); 161 exit(PTS_UNRESOLVED); 162 } 163} 164