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