blob: 81ce258c6d886e3d9e80d89432f5cd3536b8c70e [file] [log] [blame]
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Test that the check for the existence of the shared memory object and the
* creation of the object if it does not exist is atomic with respect to other
* processes executing shm_open() naming the same shared memory object with
* O_EXCL and O_CREAT set.
*
* This test launch NPROCESS processes which all try to open NLOOP shared
* memory objects. If an unexpected error occurs or if the number of created
* objects is not NLOOP, the test failed. In other case the test is unresolved.
*/
/* adam.li: 2004-04-30: Rewrite the test case. The idea is that with
O_CREAT and O_EXCL specified, to shm_open() a object can only success
once, although multiple processes might open with the same name at the
same time.
*/
#include <errno.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "posixtest.h"
#define NAME_SIZE 20
#define SHM_NAME "/posixtest_23-1_%d"
/* The processes communicate by a shared memory object */
#define SHM_RESULT_NAME "/result_23-1"
#define NPROCESS 1000 /* Number of concurrent processes */
#define NLOOP 1000 /* Number of shared memory object */
char name[NAME_SIZE];
int *create_cnt;
sem_t *sem;
int child_func(void)
{
int i, fd;
struct timespec ts = {.tv_sec = 0,.tv_nsec = 0 };
int msec = 0;
sleep(1);
srand(time(NULL));
for (i = 0; i < NLOOP; i++) {
sprintf(name, SHM_NAME, i);
fd = shm_open(name, O_RDONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR);
if (fd != -1) {
sem_wait(sem);
//fprintf(stderr, "%d: %d\n", getpid(), *create_cnt);
(*create_cnt)++;
sem_post(sem);
}
/* get a random number [0, 20] */
msec = (int)(20.0 * rand() / RAND_MAX);
ts.tv_nsec = msec * 1000000;
nanosleep(&ts, NULL);
}
return 0;
}
int main(void)
{
int i, pid, result_fd;
char semname[20];
snprintf(semname, 20, "/sem23-1_%d", getpid());
sem = sem_open(semname, O_CREAT, 0777, 1);
if (sem == SEM_FAILED || sem == NULL) {
perror("error at sem_open");
return PTS_UNRESOLVED;
}
sem_unlink(semname);
result_fd = shm_open(SHM_RESULT_NAME,
O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (result_fd == -1) {
perror("An error occurs when calling shm_open()");
return PTS_UNRESOLVED;
}
shm_unlink(SHM_RESULT_NAME);
if (ftruncate(result_fd, sizeof(*create_cnt)) != 0) {
perror("An error occurs when calling ftruncate()");
shm_unlink(SHM_RESULT_NAME);
return PTS_UNRESOLVED;
}
create_cnt = mmap(NULL, sizeof(*create_cnt), PROT_WRITE | PROT_READ,
MAP_SHARED, result_fd, 0);
if (create_cnt == MAP_FAILED) {
perror("An error occurs when calling mmap()");
shm_unlink(SHM_RESULT_NAME);
return PTS_UNRESOLVED;
}
*create_cnt = 0;
for (i = 0; i < NPROCESS; i++) {
pid = fork();
if (pid == -1) {
perror("An error occurs when calling fork()");
return PTS_UNRESOLVED;
} else if (pid == 0) {
child_func();
exit(0);
}
}
while (wait(NULL) > 0) ;
for (i = 0; i < NLOOP; i++) {
sprintf(name, SHM_NAME, i);
shm_unlink(name);
}
fprintf(stderr, "create_cnt: %d\n", *create_cnt);
if (*create_cnt != NLOOP) {
printf("Test FAILED\n");
return PTS_FAIL;
}
return PTS_PASS;
}