#include "bh_api.h"
|
#include "svsem.h"
|
#include "msg_mgr.h"
|
|
int svsem_get(key_t key, unsigned int value) {
|
int semid, perms;
|
|
perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
|
semid = semget(key, 2, IPC_CREAT | IPC_EXCL | perms);
|
|
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");
|
|
arg.val = 1;
|
if (semctl(semid, 1, SETVAL, arg) == -1)
|
err_exit(errno, "semctl 2");
|
|
/* Perform a "no-op" semaphore operation - changes sem_otime
|
so other processes can see we've initialized the set. */
|
|
sop.sem_num = 0; /* Operate on semaphore 0 */
|
sop.sem_op = value;
|
sop.sem_flg = SEM_UNDO;
|
if (semop(semid, &sop, 1) == -1)
|
err_exit(errno, "semop");
|
|
} else { /* We didn't create the semaphore set */
|
|
if (errno != EEXIST) { /* Unexpected error from semget() */
|
err_exit(errno, "semget 1");
|
|
} else { /* Someone else already created it */
|
const int MAX_TRIES = 10;
|
int j;
|
union semun arg;
|
struct semid_ds ds;
|
|
semid = semget(key, 1, perms); /* So just get ID */
|
if (semid == -1)
|
err_exit(errno, "semget 2");
|
|
/* Wait until another process has called semop() */
|
|
arg.buf = &ds;
|
for (j = 0; j < MAX_TRIES; j++) {
|
if (semctl(semid, 0, IPC_STAT, arg) == -1)
|
err_exit(errno, "semctl 2");
|
|
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;
|
}
|
|
/* 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 svsem_wait(int semid) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = -1;
|
sops.sem_flg = SEM_UNDO;
|
|
while (semop(semid, &sops, 1) == -1)
|
if (errno != EINTR) {
|
err_msg(errno, "svsem_dec");
|
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_GET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
int svsem_trywait(int semid) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = -1;
|
sops.sem_flg = IPC_NOWAIT | SEM_UNDO;
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_GET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return semop(semid, &sops, 1) ;
|
}
|
|
int svsem_timedwait(int semid, struct timespec *timeout) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = -1;
|
sops.sem_flg = SEM_UNDO;
|
|
while (semtimedop(semid, &sops, 1, timeout) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "svsem_psem_timedwait");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_GET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
int svsem_uni_wait(int semid) {
|
struct timespec res;
|
|
res.tv_sec = SEM_WT_TIMEOUT;
|
res.tv_nsec = 0;
|
|
while(1) {
|
if(svsem_timedwait(semid, &res) != 0) {
|
|
if(svsem_post(semid) != 0) {
|
err_msg(errno, "_inc");
|
}
|
|
} else {
|
|
break;
|
}
|
}
|
|
return 0;
|
}
|
|
/* Release semaphore - increment it by 1 */
|
int svsem_post(int semid) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = 1;
|
sops.sem_flg = SEM_UNDO;
|
|
int rv = semop(semid, &sops, 1);
|
if (rv == -1) {
|
// err_msg(errno, "svsem_inc");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_POST;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
int svsem_cond_wait(int semid ){
|
|
struct sembuf sops[2];
|
union semun arg;
|
|
arg.val = 1;
|
if (semctl(semid, 1, SETVAL, arg) == -1) {
|
err_msg(errno, "svsem_set");
|
return -1;
|
}
|
|
//释放mutex
|
sops[0].sem_num = 0;
|
sops[0].sem_op = 1;
|
sops[0].sem_flg = SEM_UNDO;
|
|
// 等待cond
|
sops[1].sem_num = 1;
|
sops[1].sem_op = 0;
|
sops[1].sem_flg = SEM_UNDO;
|
|
while (semop(semid, sops, 2) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "Svsvsem_dec");
|
return -1;
|
}
|
|
|
//重新获取mutex
|
sops[0].sem_num = 0;
|
sops[0].sem_op = -1;
|
sops[0].sem_flg = SEM_UNDO;
|
|
while (semop(semid, sops, 1) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "Svsvsem_dec");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_GET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
|
int svsem_cond_signal(int semid ){
|
union semun arg;
|
arg.val = 0;
|
|
if (semctl(semid, 1, SETVAL, arg) == -1) {
|
err_msg(errno, "svsem_set");
|
return -1;
|
}
|
return 0;
|
}
|
|
|
/**
|
* If sem_op equals 0, the value of the semaphore is checked to see whether it
|
* currently equals 0. If it does, the operation completes immediately; otherwise,
|
* semop() blocks until the semaphore value becomes 0.
|
*/
|
int svsem_zero(int semid) {
|
// logger.debug("%d: svsem_dec\n", semid);
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = 0;
|
sops.sem_flg = SEM_UNDO;
|
|
while (semop(semid, &sops, 1) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "svsem_zero");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_RESET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
|
int svsem_zero_nowait(int semid) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = 0;
|
sops.sem_flg = IPC_NOWAIT | SEM_UNDO;
|
|
while (semop(semid, &sops, 1) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "svsem_zero_nowait");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_RESET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
int svsem_zero_timeout(int semid, struct timespec *timeout) {
|
struct sembuf sops;
|
|
sops.sem_num = 0;
|
sops.sem_op = 0;
|
sops.sem_flg = SEM_UNDO;
|
|
while (semtimedop(semid, &sops, 1, timeout) == -1)
|
if (errno != EINTR) {
|
// err_msg(errno, "svsem_zero_timeout");
|
return -1;
|
}
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_RESET;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
return 0;
|
}
|
|
int svsem_set(int semid, int val) {
|
union semun arg;
|
arg.val = val;
|
|
return semctl(semid, 0, SETVAL, arg);
|
}
|
|
void svsem_remove(int semid) {
|
union semun dummy;
|
|
if (semctl(semid, 0, IPC_RMID, dummy) == -1)
|
err_msg(errno, "svsem_remove");
|
|
#if defined(MSG_HANDLER)
|
Msg_info msg_obj;
|
msg_obj.key = inter_key_get();
|
msg_obj.id = semid;
|
msg_obj.act = SEM_RM;
|
msg_distrib(SEM_TYPE_ID, &msg_obj);
|
#endif
|
|
}
|
|
|