Home | History | Annotate | Download | only in pthread_spin_trylock
      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