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_trylock(pthread_spinlock_t *lock) 8 * 9 * The function shall lock the spin lock referenced by 'lock' if it is not 10 * held by any thread. Otherwise, the function shall fail. 11 * 12 * Steps: 13 * 1. Initialize a pthread_spinlock_t object 'spinlock' with 14 * pthread_spin_init() 15 * 2. Main thread lock 'spinlock', using pthread_spin_trylock(), 16 * should get the lock successfully. 17 * 3. Create a child thread. The thread lock 'spinlock', 18 * using pthread_spin_trylock(), shall fail with EBUSY. 19 * 4. If the child spins on the lock, after 2 seconds, send SIGALRM to it. 20 * 5. Child thread check its state 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 <errno.h> 30 #include "posixtest.h" 31 32 static pthread_spinlock_t spinlock; 33 static volatile int thread_state; 34 static int rc; 35 36 #define NOT_CREATED_THREAD 1 37 #define ENTERED_THREAD 2 38 #define EXITING_THREAD 3 39 40 static void sig_handler() 41 { 42 if (thread_state == ENTERED_THREAD) { 43 printf("Test FAILED: thread incorrectly spins on trylock\n"); 44 exit(PTS_FAIL); 45 } else { 46 printf("UNRESOLVED: Unexpected child thread state %d\n", 47 thread_state); 48 exit(PTS_UNRESOLVED); 49 } 50 } 51 52 static void *fn_chld(void *arg) 53 { 54 rc = 0; 55 56 struct sigaction act; 57 thread_state = ENTERED_THREAD; 58 59 (void) arg; 60 61 /* Set up child thread to handle SIGALRM */ 62 act.sa_flags = 0; 63 act.sa_handler = sig_handler; 64 sigfillset(&act.sa_mask); 65 sigaction(SIGALRM, &act, 0); 66 67 /* thread: send SIGALRM to me after 2 seconds in case in spins on trylock */ 68 alarm(2); 69 70 printf("thread: attempt trylock\n"); 71 rc = pthread_spin_trylock(&spinlock); 72 73 pthread_exit(0); 74 return NULL; 75 } 76 77 int main(void) 78 { 79 pthread_t child_thread; 80 81 if (pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE) != 0) { 82 printf("main: Error at pthread_spin_init()\n"); 83 return PTS_UNRESOLVED; 84 } 85 86 printf("main: attempt to trylock\n"); 87 88 /* We should get the lock */ 89 if (pthread_spin_trylock(&spinlock) != 0) { 90 printf 91 ("Test FAILED: main cannot get spin lock when no one owns the lock\n"); 92 return PTS_FAIL; 93 } 94 printf("main: acquired spin lock\n"); 95 96 thread_state = NOT_CREATED_THREAD; 97 printf("main: create thread\n"); 98 if (pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) { 99 printf("main: Error creating child thread\n"); 100 return PTS_UNRESOLVED; 101 } 102 103 /* Wait for thread to end execution */ 104 pthread_join(child_thread, NULL); 105 106 /* Check the return code of pthread_spin_trylock */ 107 if (rc != EBUSY) { 108 printf 109 ("Test FAILED: pthread_spin_trylock should return EBUSY, instead got error code:%d\n", 110 rc); 111 return PTS_FAIL; 112 } 113 114 printf("thread: correctly returned EBUSY on trylock\n"); 115 printf("Test PASSED\n"); 116 return PTS_PASS; 117 118 } 119