| | |
| | | #include "sem_util.h" |
| | | #include "logger_factory.h" |
| | | |
| | | static Logger logger = LoggerFactory::getLogger(); |
| | | |
| | | int SemUtil::get(key_t key, unsigned int value) { |
| | | int semid, perms; |
| | | |
| | | perms = S_IRUSR | S_IWUSR; |
| | | int semid, perms; |
| | | |
| | | semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms); |
| | | perms = S_IRUSR | S_IWUSR; |
| | | |
| | | if (semid != -1) { /* Successfully created the semaphore */ |
| | | union semun arg; |
| | | struct sembuf sop; |
| | | semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms); |
| | | |
| | | fprintf(stderr, "%ld: created semaphore\n", (long) getpid()); |
| | | if (semid != -1) { /* Successfully created the semaphore */ |
| | | union semun arg; |
| | | struct sembuf sop; |
| | | |
| | | arg.val = 0; /* So initialize it to 0 */ |
| | | if (semctl(semid, 0, SETVAL, arg) == -1) |
| | | err_exit(errno, "semctl 1"); |
| | | fprintf(stderr, "%ld: initialized semaphore\n", (long) getpid()); |
| | | logger.info("%ld: created semaphore\n", (long)getpid()); |
| | | |
| | | /* Perform a "no-op" semaphore operation - changes sem_otime |
| | | so other processes can see we've initialized the set. */ |
| | | arg.val = 0; /* So initialize it to 0 */ |
| | | if (semctl(semid, 0, SETVAL, arg) == -1) |
| | | err_exit(errno, "semctl 1"); |
| | | logger.info("%ld: initialized semaphore\n", (long)getpid()); |
| | | |
| | | sop.sem_num = 0; /* Operate on semaphore 0 */ |
| | | sop.sem_op = value; |
| | | sop.sem_flg = 0; |
| | | if (semop(semid, &sop, 1) == -1) |
| | | err_exit(errno, "semop"); |
| | | fprintf(stderr, "%ld: completed dummy semop()\n", (long) getpid()); |
| | | /* Perform a "no-op" semaphore operation - changes sem_otime |
| | | so other processes can see we've initialized the set. */ |
| | | |
| | | } else { /* We didn't create the semaphore set */ |
| | | sop.sem_num = 0; /* Operate on semaphore 0 */ |
| | | sop.sem_op = value; |
| | | sop.sem_flg = 0; |
| | | if (semop(semid, &sop, 1) == -1) |
| | | err_exit(errno, "semop"); |
| | | logger.info("%ld: completed dummy semop()\n", (long)getpid()); |
| | | |
| | | if (errno != EEXIST) { /* Unexpected error from semget() */ |
| | | err_exit(errno, "semget 1"); |
| | | } else { /* We didn't create the semaphore set */ |
| | | |
| | | } else { /* Someone else already created it */ |
| | | const int MAX_TRIES = 10; |
| | | int j; |
| | | union semun arg; |
| | | struct semid_ds ds; |
| | | if (errno != EEXIST) { /* Unexpected error from semget() */ |
| | | err_exit(errno, "semget 1"); |
| | | |
| | | semid = semget(key, 1, perms); /* So just get ID */ |
| | | if (semid == -1) |
| | | err_exit(errno, "semget 2"); |
| | | } else { /* Someone else already created it */ |
| | | const int MAX_TRIES = 10; |
| | | int j; |
| | | union semun arg; |
| | | struct semid_ds ds; |
| | | |
| | | fprintf(stderr, "%ld: got semaphore key\n", (long) getpid()); |
| | | /* Wait until another process has called semop() */ |
| | | semid = semget(key, 1, perms); /* So just get ID */ |
| | | if (semid == -1) |
| | | err_exit(errno, "semget 2"); |
| | | |
| | | arg.buf = &ds; |
| | | for (j = 0; j < MAX_TRIES; j++) { |
| | | fprintf(stderr, "Try %d\n", j); |
| | | if (semctl(semid, 0, IPC_STAT, arg) == -1) |
| | | err_exit(errno, "semctl 2"); |
| | | logger.info("%ld: got semaphore key\n", (long)getpid()); |
| | | /* Wait until another process has called semop() */ |
| | | |
| | | if (ds.sem_otime != 0) /* Semop() performed? */ |
| | | break; /* Yes, quit loop */ |
| | | sleep(1); /* If not, wait and retry */ |
| | | } |
| | | arg.buf = &ds; |
| | | for (j = 0; j < MAX_TRIES; j++) { |
| | | logger.info("Try %d\n", j); |
| | | if (semctl(semid, 0, IPC_STAT, arg) == -1) |
| | | err_exit(errno, "semctl 2"); |
| | | |
| | | if (ds.sem_otime == 0) /* Loop ran to completion! */ |
| | | err_exit(errno, "Existing semaphore not initialized"); |
| | | } |
| | | if (ds.sem_otime != 0) /* Semop() performed? */ |
| | | break; /* Yes, quit loop */ |
| | | sleep(1); /* If not, wait and retry */ |
| | | } |
| | | |
| | | if (ds.sem_otime == 0) /* Loop ran to completion! */ |
| | | err_exit(errno, "Existing semaphore not initialized"); |
| | | } |
| | | return semid; |
| | | } |
| | | return semid; |
| | | } |
| | | |
| | | |
| | | /* Reserve semaphore (blocking), return 0 on success, or -1 with 'errno' |
| | | set to EINTR if operation was interrupted by a signal handler */ |
| | | |
| | | /* Reserve semaphore - decrement it by 1 */ |
| | | int SemUtil::dec(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | int SemUtil::dec(int semId) { |
| | | struct sembuf sops; |
| | | |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = 0; |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = 0; |
| | | |
| | | while (semop(semId, &sops, 1) == -1) |
| | | if (errno != EINTR ) { |
| | | err_msg(errno, "SemUtil::dec"); |
| | | return -1; |
| | | } |
| | | while (semop(semId, &sops, 1) == -1) |
| | | if (errno != EINTR) { |
| | | err_msg(errno, "SemUtil::dec"); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | int SemUtil::dec_nowait(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | int SemUtil::dec_nowait(int semId) { |
| | | struct sembuf sops; |
| | | |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = IPC_NOWAIT; |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = IPC_NOWAIT; |
| | | |
| | | while (semop(semId, &sops, 1) == -1) |
| | | if (errno != EINTR ) { |
| | | err_msg(errno, "SemUtil::dec_nowait"); |
| | | return -1; |
| | | } |
| | | while (semop(semId, &sops, 1) == -1) |
| | | if (errno != EINTR) { |
| | | err_msg(errno, "SemUtil::dec_nowait"); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | int SemUtil::dec_timeout(int semId, struct timespec * timeout) |
| | | { |
| | | struct sembuf sops; |
| | | int SemUtil::dec_timeout(int semId, struct timespec *timeout) { |
| | | struct sembuf sops; |
| | | |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = 0; |
| | | sops.sem_num = 0; |
| | | sops.sem_op = -1; |
| | | sops.sem_flg = 0; |
| | | |
| | | while ( semtimedop(semId, &sops, 1, timeout) == -1) |
| | | if (errno != EINTR ) { |
| | | err_msg(errno, "SemUtil::dec_timeout"); |
| | | return -1; |
| | | } |
| | | while (semtimedop(semId, &sops, 1, timeout) == -1) |
| | | if (errno != EINTR) { |
| | | err_msg(errno, "SemUtil::dec_timeout"); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | |
| | | /* Release semaphore - increment it by 1 */ |
| | | int SemUtil::inc(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | int SemUtil::inc(int semId) { |
| | | struct sembuf sops; |
| | | |
| | | sops.sem_num = 0; |
| | | sops.sem_op = 1; |
| | | sops.sem_flg = 0; |
| | | sops.sem_num = 0; |
| | | sops.sem_op = 1; |
| | | sops.sem_flg = 0; |
| | | |
| | | int rv = semop(semId, &sops, 1); |
| | | if(rv == -1) { |
| | | err_msg(errno, "SemUtil::inc"); |
| | | } |
| | | return rv; |
| | | int rv = semop(semId, &sops, 1); |
| | | if (rv == -1) { |
| | | err_msg(errno, "SemUtil::inc"); |
| | | } |
| | | return rv; |
| | | } |
| | | |
| | | void SemUtil::remove(int semid) { |
| | | union semun dummy; |
| | | if (semctl(semid, 0, IPC_RMID, dummy) == -1) |
| | | err_msg(errno, "SemUtil::remove"); |
| | | |
| | | union semun dummy; |
| | | if (semctl(semid, 0, IPC_RMID, dummy) == -1) |
| | | err_msg(errno, "SemUtil::remove"); |
| | | } |
| | | |
| | | |
| | | void SemUtil::set(int semId, int val) |
| | | { |
| | | union semun arg; |
| | | arg.val = val; |
| | | if (semctl(semId, 0, SETVAL, arg) == -1) |
| | | err_msg(errno, "SemUtil::set"); |
| | | void SemUtil::set(int semId, int val) { |
| | | union semun arg; |
| | | arg.val = val; |
| | | if (semctl(semId, 0, SETVAL, arg) == -1) |
| | | err_msg(errno, "SemUtil::set"); |
| | | } |
| | | |
| | | |