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