int main(){ size_t i; struct sembuf sem_start_array, sem_start_register, sem_wait_foo_end; for (i = 0; i<SYMBOLS_COUNT; i++){ symbols[i] = (char)i+'a'; } symbols[SYMBOLS_COUNT] = '\0'; create_semaphores(); sem_wait_foo_end.sem_num = SEM_FOO_END; sem_start_array.sem_num = SEM_ARRAY; sem_start_register.sem_num = SEM_REGISTER; sem_wait_foo_end.sem_flg = SEM_UNDO; sem_start_array.sem_flg = SEM_UNDO; sem_start_register.sem_flg = SEM_UNDO; sem_wait_foo_end.sem_op = -1; sem_start_array.sem_op = 1; sem_start_register.sem_op = 1; if (pthread_create(®_thr, NULL, &invert_register, NULL) != 0) print_error("Can't create a thread", 2, errno); if (pthread_create(&arr_inv_thr, NULL, &invert_array, NULL) != 0) print_error("Can't create a thread", 2, errno); signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); while (1){ if(semop(sem_id, &sem_start_array, 1)<0) print_error("Can't set a semaphore", 7, errno); if(semop(sem_id, &sem_wait_foo_end, 1)<0) print_error("Can't set a semaphore", 7, errno); sleep(SLEEP_TIME); printf("%s\n", symbols); if(semop(sem_id, &sem_start_register, 1)<0) print_error("Can't set a semaphore", 7, errno); if(semop(sem_id, &sem_wait_foo_end, 1)<0) print_error("Can't set a semaphore", 7, errno); sleep(SLEEP_TIME); printf("%s\n", symbols); } }
/*---------------------------------------------------------------------+ | main | | ==================================================================== | | | | Function: Main program (see prolog for more details) | | | | Returns: (0) Successful completion | | (-1) Error occurred | | | +---------------------------------------------------------------------*/ int main(int argc, char **argv) { int fd; /* Misc file descriptor */ int i; /* Misc loop index */ int shmem_size; /* Size (in bytes) of shared memory segment */ int status; /* Child processes exit status */ unsigned char *ptr; /* Misc pointer */ unsigned char data = 0; /* Value written into shared memory segment */ unsigned char *shmptr; /* Shared memory segment address */ unsigned long cksum; /* Shared memory segment checksum */ /* * Parse command line arguments and print out program header */ parse_args(argc, argv); printf("%s: IPC Shared Memory TestSuite program\n", *argv); /* * Setup the signal handlers (in case user aborts program). * * Create the semaphores to insure exclusive writes to the * shared memory segment. * * Save the parent process id and initialize the array of child * process ids. */ setup_signal_handlers(); create_semaphores(); parent_pid = getpid(); for (i = 0; i < num_children; i++) pid[i] = (pid_t) 0; /* * Create a shared memory segment for storing the read count * (number of child processes reading shared data) * After creating the shared memory segment, initialize it. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); if ((read_count = (int *) mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); *read_count = 0; /* * Create a shared memory segment for storing the child * processes checksums by memory mapping /dev/zero. * After creating the shared memory segment, initialize it. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); shmem_size = sizeof(unsigned long) * num_children; if ((checksum = (unsigned long *) mmap(0, shmem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); for (i = 0; i < num_children; i++) *(checksum + (sizeof(unsigned long) * i)) = 0; /* * Create the "scratch" shared memory segment for storing * a series of values by memory mapping /dev/zero. */ if ((fd = open("/dev/zero", O_RDWR)) < 0) sys_error("open failed", __LINE__); printf("\n\tGet shared memory segment (%d bytes)\n", buffer_size); if ((shmptr = mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) < 0) sys_error("mmap failed", __LINE__); close(fd); /* * Obtain an exclusive "write" lock on the shared memory data * segment -- get lock now to insure the parent process gets * first access to the segment. */ lock_resource(WRITE); /* * Spawn all N child processes. Each child process will compute * the checksum of the shared memory segment and will store * the results in the other shared memory segment accessible * by the parent. */ printf("\n\tSpawning %d child processes ... \n", num_children); for (i = 0; i < num_children; i++) { if ((pid[i] = fork()) == (pid_t) 0) { child(i, shmptr); exit(0); } else if (pid[i] < (pid_t) 0) sys_error("fork failed", __LINE__); } /* * Fill the "scratch" shared memory segment up with data and * compute the segments checksum. Release "write" lock after * completing so that the child processes may begin to read the * data. */ printf("\n\tParent: calculate shared memory segment checksum\n"); cksum = data = 0; for (ptr = shmptr; ptr < (shmptr + buffer_size); ptr++) { *ptr = (data++) % (UCHAR_MAX + 1); cksum += *ptr; } printf("\t shared memory checksum %08lx\n", cksum); unlock_resource(WRITE); /* * Wait for the child processes to compute the checksums and complete. * After the processes complete, check their exit status to insure * that they ran to completion and then verify the corresponding * checksum. */ for (i = 0; i < num_children; i++) { waitpid(pid[i], &status, 0); if (!WIFEXITED(status)) sys_error("child process terminated abnormally", __LINE__); if (cksum != *(checksum + (sizeof(unsigned long) * i))) { printf("checksum [%d] = %08lx\n", i, checksum[i]); error("checksums do not match", __LINE__); } } printf("\n\tParent: children calculated segment successfully\n"); /* * Program completed successfully, cleanup semaphores and exit. */ delete_semaphores(); printf("\nsuccessful!\n"); return (0); }
/** * Create a new bus * * @param file The pathname of the bus, `NULL` to create a random one * @param flags `BUS_EXCL` (if `file` is not `NULL`) to fail if the file * already exists, otherwise if the file exists, nothing * will happen; * `BUS_INTR` to fail if interrupted * @param out_file Output parameter for the pathname of the bus * @return 0 on success, -1 on error */ int bus_create(const char *file, int flags, char **out_file) { int fd = -1, saved_errno; bus_t bus; char buf[1 + 2 * (3 * sizeof(ssize_t) + 2)]; size_t ptr, len; ssize_t wrote; char *genfile = NULL; const char *env; if (out_file) *out_file = NULL; bus.sem_id = -1; bus.key_sem = -1; bus.key_shm = -1; bus.message = NULL; bus.first_poll = 0; srand((unsigned int)time(NULL) + (unsigned int)rand()); if (file) { fd = open(file, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_MODE); if (fd == -1) { if ((errno != EEXIST) || (flags & BUS_EXCL)) return -1; goto done; } } else { env = getenv("XDG_RUNTIME_DIR"); if (!env || !*env) env = "/run"; genfile = malloc((strlen(env) + 6 + 7 + 30) * sizeof(char)); if (!genfile) goto fail; if (out_file) *out_file = genfile; sprintf(genfile, "%s/bus", env); t(mkdirs(genfile, 0755)); sprintf(genfile, "%s/bus/random.", env); len = strlen(genfile); genfile[len + 30] = '\0'; retry: for (ptr = 0; ptr < 30; ptr++) genfile[len + ptr] = randomchar(); fd = open(genfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_MODE); if (fd == -1) { if (errno == EEXIST) goto retry; return -1; } } t(create_semaphores(&bus)); t(create_shared_memory(&bus)); sprintf(buf, "%zi\n%zi\n", (ssize_t)(bus.key_sem), (ssize_t)(bus.key_shm)); for (len = strlen(buf), ptr = 0; ptr < len;) { wrote = write(fd, buf + ptr, len - ptr); if (wrote < 0) { if ((errno != EINTR) || (flags & BUS_INTR)) goto fail; } else { ptr += (size_t)wrote; } } close(fd); done: if (out_file && !*out_file) { len = strlen(file) + 1; *out_file = malloc(len * sizeof(char)); memcpy(*out_file, file, len * sizeof(char)); } else if (!out_file) { free(genfile); } return 0; fail: saved_errno = errno; if (bus.key_sem) remove_semaphores(&bus); if (bus.key_shm) remove_shared_memory(&bus); if (fd == -1) close(fd); if (out_file) *out_file = NULL; free(genfile); unlink(file); errno = saved_errno; return -1; }