Home | History | Annotate | Download | only in shm_open
      1 /*
      2  *  This program is free software; you can redistribute it and/or modify
      3  *  it under the terms of the GNU General Public License version 2.
      4  *
      5  *  This program is distributed in the hope that it will be useful,
      6  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      7  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      8  *  GNU General Public License for more details.
      9  *
     10  * Test that the check for the existence of the shared memory object and the
     11  * creation of the object if it does not exist is atomic with respect to other
     12  * processes executing shm_open() naming the same shared memory object with
     13  * O_EXCL and O_CREAT set.
     14  *
     15  * This test launch NPROCESS processes which all try to open NLOOP shared
     16  * memory objects. If an unexpected error occurs or if the number of created
     17  * objects is not NLOOP, the test failed. In other case the test is unresolved.
     18  */
     19 
     20 /* ftruncate was formerly an XOPEN extension. We define _XOPEN_SOURCE here to
     21    avoid warning if the implementation does not program ftruncate as a base
     22    interface */
     23 
     24 /* adam.li: 2004-04-30: Rewrite the test case. The idea is that with
     25    O_CREAT and O_EXCL specified, to shm_open() a object can only success
     26    once, although multiple processes might open with the same name at the
     27    same time.
     28  */
     29 #define _XOPEN_SOURCE 600
     30 
     31 #include <errno.h>
     32 #include <fcntl.h>
     33 #include <semaphore.h>
     34 #include <stdlib.h>
     35 #include <stdio.h>
     36 #include <sys/mman.h>
     37 #include <sys/stat.h>
     38 #include <sys/wait.h>
     39 #include <time.h>
     40 #include <unistd.h>
     41 #include "posixtest.h"
     42 
     43 #define NAME_SIZE 20
     44 #define SHM_NAME "/posixtest_23-1_%d"
     45 
     46 /* The processes communicate by a shared memory object */
     47 #define SHM_RESULT_NAME "/result_23-1"
     48 
     49 #define NPROCESS 1000		/* Number of concurrent processes */
     50 #define NLOOP 1000		/* Number of shared memory object */
     51 
     52 char name[NAME_SIZE];
     53 int *create_cnt;
     54 sem_t *sem;
     55 
     56 int child_func(void)
     57 {
     58 	int i, fd;
     59 	struct timespec ts = {.tv_sec = 0,.tv_nsec = 0 };
     60 	int msec = 0;
     61 
     62 	sleep(1);
     63 	srand(time(NULL));
     64 	for (i = 0; i < NLOOP; i++) {
     65 		sprintf(name, SHM_NAME, i);
     66 		fd = shm_open(name, O_RDONLY | O_CREAT | O_EXCL,
     67 			      S_IRUSR | S_IWUSR);
     68 		if (fd != -1) {
     69 			sem_wait(sem);
     70 			//fprintf(stderr, "%d: %d\n", getpid(), *create_cnt);
     71 			(*create_cnt)++;
     72 			sem_post(sem);
     73 		}
     74 		/* get a random number [0, 20] */
     75 		msec = (int)(20.0 * rand() / RAND_MAX);
     76 		ts.tv_nsec = msec * 1000000;
     77 		nanosleep(&ts, NULL);
     78 	}
     79 	return 0;
     80 }
     81 
     82 int main(void)
     83 {
     84 	int i, pid, result_fd;
     85 	char semname[20];
     86 
     87 	snprintf(semname, 20, "/sem23-1_%d", getpid());
     88 	sem = sem_open(semname, O_CREAT, 0777, 1);
     89 	if (sem == SEM_FAILED || sem == NULL) {
     90 		perror("error at sem_open");
     91 		return PTS_UNRESOLVED;
     92 	}
     93 	sem_unlink(semname);
     94 
     95 	result_fd = shm_open(SHM_RESULT_NAME,
     96 			     O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
     97 	if (result_fd == -1) {
     98 		perror("An error occurs when calling shm_open()");
     99 		return PTS_UNRESOLVED;
    100 	}
    101 	shm_unlink(SHM_RESULT_NAME);
    102 	if (ftruncate(result_fd, sizeof(*create_cnt)) != 0) {
    103 		perror("An error occurs when calling ftruncate()");
    104 		shm_unlink(SHM_RESULT_NAME);
    105 		return PTS_UNRESOLVED;
    106 	}
    107 
    108 	create_cnt = mmap(NULL, sizeof(*create_cnt), PROT_WRITE | PROT_READ,
    109 			  MAP_SHARED, result_fd, 0);
    110 	if (create_cnt == MAP_FAILED) {
    111 		perror("An error occurs when calling mmap()");
    112 		shm_unlink(SHM_RESULT_NAME);
    113 		return PTS_UNRESOLVED;
    114 	}
    115 
    116 	*create_cnt = 0;
    117 
    118 	for (i = 0; i < NPROCESS; i++) {
    119 		pid = fork();
    120 		if (pid == -1) {
    121 			perror("An error occurs when calling fork()");
    122 			return PTS_UNRESOLVED;
    123 		} else if (pid == 0) {
    124 			child_func();
    125 			exit(0);
    126 		}
    127 	}
    128 
    129 	while (wait(NULL) > 0) ;
    130 
    131 	for (i = 0; i < NLOOP; i++) {
    132 		sprintf(name, SHM_NAME, i);
    133 		shm_unlink(name);
    134 	}
    135 
    136 	fprintf(stderr, "create_cnt: %d\n", *create_cnt);
    137 	if (*create_cnt != NLOOP) {
    138 		printf("Test FAILED\n");
    139 		return PTS_FAIL;
    140 	}
    141 
    142 	return PTS_PASS;
    143 }
    144