Home | History | Annotate | Download | only in pthread_rwlockattr_getpshared
      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  *	The process-shared attribute shall be set to PTHREAD_PROCESS_SHARED
      8  *	to permit a read-write lock to be operated upon by any thread
      9  *	that has access to the memory where the read-write lock is allocated,
     10  *	even if the read-write lock is allocated in memory that is shared by
     11  *	multiple processes.
     12  *
     13  * steps:
     14  *	1. Create a piece of shared memory object, create a read write lock 'rwlock' and
     15  *	   set the PTHREAD_PROCESS_SHARED attribute.
     16  *	2. Parent map the shared memory to its memory space, put 'rwlock' into it;
     17  *	3. Parent get read lock;
     18  *	4. Fork to create child, parent wait until child call pthread_rwlock_wrlock()
     19  *	5. Child map the shared memory to its memory space;
     20  *	6. Child call pthread_rwlock_trywrlock(), should fail with EBUSY;
     21  *	7. Child call pthread_rwlock_wrlock(), should block;
     22  *	8. Parent unlock 'rwlock'
     23  *	9. Child should get the write lock.
     24  */
     25 
     26 #define _XOPEN_SOURCE 600
     27 #include <sys/mman.h>
     28 #include <sys/stat.h>
     29 #include <sys/wait.h>
     30 #include <errno.h>
     31 #include <fcntl.h>
     32 #include <pthread.h>
     33 #include <stdio.h>
     34 #include <unistd.h>
     35 #include "posixtest.h"
     36 
     37 struct shmstruct {
     38 	pthread_rwlock_t rwl;
     39 	int data;
     40 } *rwlock_data;
     41 
     42 int main(void)
     43 {
     44 
     45 	/* Make sure there is process-shared capability. */
     46 #ifndef PTHREAD_PROCESS_SHARED
     47 	fprintf(stderr,
     48 		"process-shared attribute is not available for testing\n");
     49 	return PTS_UNSUPPORTED;
     50 #endif
     51 
     52 	pthread_rwlockattr_t rwla;
     53 	int pshared = PTHREAD_PROCESS_SHARED;
     54 
     55 	char shm_name[] = "tmp_pthread_rwlock_getpshared";
     56 	int shm_fd;
     57 	int pid;
     58 
     59 	/* Initialize a rwlock attributes object */
     60 	if (pthread_rwlockattr_init(&rwla) != 0) {
     61 		printf("Error at pthread_rwlockattr_init()\n");
     62 		return PTS_UNRESOLVED;
     63 	}
     64 
     65 	if (pthread_rwlockattr_setpshared(&rwla, pshared) != 0) {
     66 		printf("Error at pthread_rwlockattr_setpshared()\n");
     67 		return PTS_UNRESOLVED;
     68 	}
     69 
     70 	if (pthread_rwlockattr_getpshared(&rwla, &pshared) != 0) {
     71 		printf
     72 		    ("Test FAILED: Error at pthread_rwlockattr_getpshared()\n");
     73 		return PTS_FAIL;
     74 	}
     75 
     76 	if (pshared != PTHREAD_PROCESS_SHARED) {
     77 		printf("Test FAILED: Got error shared attribute value %d\n",
     78 		       pshared);
     79 		return PTS_FAIL;
     80 	}
     81 
     82 	/* Create shared object */
     83 	shm_unlink(shm_name);
     84 	shm_fd =
     85 	    shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     86 	if (shm_fd == -1) {
     87 		perror("Error at shm_open()");
     88 		return PTS_UNRESOLVED;
     89 	}
     90 
     91 	if (ftruncate(shm_fd, sizeof(struct shmstruct)) != 0) {
     92 		perror("Error at ftruncate()");
     93 		shm_unlink(shm_name);
     94 		return PTS_UNRESOLVED;
     95 	}
     96 
     97 	/* Map the shared memory object to my memory */
     98 	rwlock_data =
     99 	    mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
    100 		 MAP_SHARED, shm_fd, 0);
    101 
    102 	if (rwlock_data == MAP_FAILED) {
    103 		perror("Error at first mmap()");
    104 		shm_unlink(shm_name);
    105 		return PTS_UNRESOLVED;
    106 	}
    107 
    108 	if ((pthread_rwlock_init(&(rwlock_data->rwl), &rwla)) != 0) {
    109 		printf("Error at pthread_rwlock_init()\n");
    110 		return PTS_UNRESOLVED;
    111 	}
    112 
    113 	if ((pthread_rwlockattr_destroy(&rwla)) != 0) {
    114 		printf("Error at pthread_rwlockattr_destroy()\n");
    115 		return PTS_UNRESOLVED;
    116 	}
    117 
    118 	printf("Parent getting read lock.\n");
    119 	if ((pthread_rwlock_rdlock(&(rwlock_data->rwl))) != 0) {
    120 		printf("Error at pthread_rwlock_rdlock()\n");
    121 		return PTS_UNRESOLVED;
    122 	}
    123 	printf("Parent got read lock.\n");
    124 	rwlock_data->data = 0;
    125 
    126 	pid = fork();
    127 	if (pid == -1) {
    128 		perror("Error at fork()");
    129 		return PTS_UNRESOLVED;
    130 	} else if (pid > 0) {
    131 		/* Parent */
    132 		/* wait until child do wrlock */
    133 		while (rwlock_data->data == 0) {
    134 			sleep(1);
    135 		}
    136 
    137 		printf("Parent unlocking.\n");
    138 		if (pthread_rwlock_unlock(&(rwlock_data->rwl)) != 0) {
    139 			printf("Parent: error at pthread_rwlock_unlock()\n");
    140 			return PTS_FAIL;
    141 		}
    142 		printf("Parent unlocked.\n");
    143 
    144 		/* Wait for child to end */
    145 		wait(NULL);
    146 
    147 		if ((shm_unlink(shm_name)) != 0) {
    148 			perror("Error at shm_unlink()");
    149 			return PTS_UNRESOLVED;
    150 		}
    151 
    152 		if (rwlock_data->data == -1) {
    153 			printf
    154 			    ("Test FAILED: child did not block on write lock\n");
    155 			return PTS_FAIL;
    156 		}
    157 
    158 		printf("Test PASSED\n");
    159 		return PTS_PASS;
    160 	} else {
    161 		/* Child */
    162 		/* Map the shared object to child's memory */
    163 		rwlock_data =
    164 		    mmap(NULL, sizeof(struct shmstruct), PROT_READ | PROT_WRITE,
    165 			 MAP_SHARED, shm_fd, 0);
    166 
    167 		if (rwlock_data == MAP_FAILED) {
    168 			perror("Error at first mmap()");
    169 			return PTS_UNRESOLVED;
    170 		}
    171 
    172 		printf("Child tries to get write lock, should get EBUSY.\n");
    173 		if ((pthread_rwlock_trywrlock(&(rwlock_data->rwl))) != EBUSY) {
    174 			printf("Test FAILED: Child expects EBUSY\n");
    175 			return PTS_FAIL;
    176 		}
    177 		printf("Child got EBUSY.\n");
    178 
    179 		printf("Child do wrlock.\n");
    180 
    181 		/* Tell parent it can unlock now */
    182 		rwlock_data->data = 1;
    183 
    184 		/* Should block until parent unlock */
    185 		if ((pthread_rwlock_wrlock(&(rwlock_data->rwl))) != 0) {
    186 			printf("Child:pthread_rwlock_wrlock() error\n");
    187 			printf
    188 			    ("Test FAILED: Error while write lock the shared rwlock\n");
    189 			rwlock_data->data = -1;
    190 			return PTS_FAIL;
    191 		}
    192 		printf("Child got wrlock.\n");
    193 		if ((pthread_rwlock_unlock(&(rwlock_data->rwl))) != 0) {
    194 			printf("Child:pthread_rwlock_unlock() error\n");
    195 			printf("Error while write unlock the shared rwlock\n");
    196 			rwlock_data->data = -1;
    197 			return PTS_FAIL;
    198 		}
    199 	}
    200 }
    201