Home | History | Annotate | Download | only in pthread_spin_init
      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 #include <sys/mman.h>
     26 #include <sys/stat.h>
     27 #include <sys/wait.h>
     28 #include <errno.h>
     29 #include <fcntl.h>
     30 #include <pthread.h>
     31 #include <stdio.h>
     32 #include <unistd.h>
     33 #include "posixtest.h"
     34 
     35 struct shmstruct {
     36 	pthread_spinlock_t spinlock;
     37 	int data;
     38 } *spinlock_data;
     39 
     40 int main(void)
     41 {
     42 
     43 	/* Make sure there is process-shared capability. */
     44 #ifndef PTHREAD_PROCESS_SHARED
     45 	fprintf(stderr,
     46 		"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 =
     59 	    shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     60 	if (shm_fd == -1) {
     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 =
     73 	    mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
     74 		 MAP_SHARED, shm_fd, 0);
     75 
     76 	if (spinlock_data == MAP_FAILED) {
     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 		printf("Test FAILED: Error at pthread_rwlock_init()\n");
     85 		return PTS_FAIL;
     86 	}
     87 
     88 	printf("main: attempt spin lock\n");
     89 	if ((pthread_spin_lock(&(spinlock_data->spinlock))) != 0) {
     90 		printf("Error at pthread_spin_lock()\n");
     91 		return PTS_UNRESOLVED;
     92 	}
     93 	printf("main: acquired spin lock\n");
     94 
     95 	/* Initialize spinlock data */
     96 	spinlock_data->data = 0;
     97 
     98 	/* Fork a child process */
     99 	pid = fork();
    100 	if (pid == -1) {
    101 		perror("Error at fork()");
    102 		return PTS_UNRESOLVED;
    103 	} else if (pid > 0) {
    104 		/* Parent */
    105 		/* wait until child writes to spinlock data */
    106 		while (spinlock_data->data != 1)
    107 			sleep(1);
    108 
    109 		printf("main: unlock spin lock\n");
    110 		if (pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) {
    111 			printf("Parent: error at pthread_spin_unlock()\n");
    112 			return PTS_UNRESOLVED;
    113 		}
    114 
    115 		/* Tell child that parent unlocked the spin lock */
    116 		spinlock_data->data = 2;
    117 
    118 		/* Wait until child ends */
    119 		wait(NULL);
    120 
    121 		if ((shm_unlink(shm_name)) != 0) {
    122 			perror("Error at shm_unlink()");
    123 			return PTS_UNRESOLVED;
    124 		}
    125 
    126 		printf("Test PASSED\n");
    127 		return PTS_PASS;
    128 	} else {
    129 		/* Child */
    130 		/* Map the shared object to child's memory */
    131 		spinlock_data =
    132 		    mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
    133 			 MAP_SHARED, shm_fd, 0);
    134 
    135 		if (spinlock_data == MAP_FAILED) {
    136 			perror("child : Error at mmap()");
    137 			return PTS_UNRESOLVED;
    138 		}
    139 
    140 		printf("child: attempt spin lock\n");
    141 		if ((pthread_spin_trylock(&(spinlock_data->spinlock))) != EBUSY) {
    142 			printf("Test FAILED: Child expects EBUSY\n");
    143 			return PTS_FAIL;
    144 		}
    145 		printf("child: correctly got EBUSY\n");
    146 
    147 		/* Tell parent it can unlock now */
    148 		spinlock_data->data = 1;
    149 
    150 		/* Wait for parent to unlock spinlock */
    151 		while (spinlock_data->data != 2)
    152 			sleep(1);
    153 
    154 		/* Child tries to get spin lock after parent unlock,
    155 		 * it should get the lock. */
    156 		printf("child: attempt spin lock\n");
    157 		if ((pthread_spin_trylock(&(spinlock_data->spinlock))) != 0) {
    158 			printf("Test FAILED: Child should get the lock\n");
    159 			return PTS_FAIL;
    160 		}
    161 		printf("child: acquired spin lock\n");
    162 
    163 		printf("child: unlock spin lock\n");
    164 		if (pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) {
    165 			printf("Child: error at pthread_spin_unlock()\n");
    166 			return PTS_UNRESOLVED;
    167 		}
    168 
    169 		if (pthread_spin_destroy(&(spinlock_data->spinlock)) != 0) {
    170 			printf("Child: error at pthread_spin_destroy()\n");
    171 			return PTS_UNRESOLVED;
    172 		}
    173 	}
    174 }
    175