예전에 구현해 놓은 것 같은데, 실제로 잘 동작하는지는 확인해보지 않았다.
(어딘가에 쓴 것 같은 기억이 드니까.. 동작은 잘 하지 않았을까?;)
소스를 첨부한다.
#include <sys/ipc.h>
#include <sys/sem.h>
struct sembuf WR_LK_SEM_P = {0, -1, 0} ;
struct sembuf WR_LK_SEM_V = {0, 1, 0} ;
struct sembuf RD_LK_SEM_P = {1, -1, 0} ;
struct sembuf RD_LK_SEM_V = {1, 1, 0} ;
struct sembuf RD_LK_SEM_Z = {1, 0, 0} ;
struct sembuf WR_OP_SEM_P = {2, -1, 0} ;
struct sembuf WR_OP_SEM_V = {2, 1, 0} ;
struct sembuf RD_OP_SEM_P = {3, -1, 0} ;
struct sembuf RD_OP_SEM_V = {3, 1, 0} ;
int initialize_rwlock(key_t semkey)
{
int lockkey;
if ((lockkey = semget(semkey, 4, IPC_CREAT | 0666)) < 0)
return -1;
if (semctl(lockkey, 0, SETVAL, 1) < 0 ||
semctl(lockkey, 1, SETVAL, 0) < 0 ||
semctl(lockkey, 2, SETVAL, 1) < 0 ||
semctl(lockkey, 3, SETVAL, 1) < 0)
return -1;
return lockkey;
}
void write_lock(int key)
{
if (key < 0) return;
semop(key, &WR_OP_SEM_P, 1);
semop(key, &RD_LK_SEM_Z, 1);
semop(key, &WR_LK_SEM_P, 1);
semop(key, &WR_OP_SEM_V, 1);
}
void read_lock(int key)
{
if (key < 0) return;
semop(key, &RD_OP_SEM_P, 1);
if (semctl(key, 0, GETVAL) == 0 && semctl(key, 1, GETVAL) == 0)
semop(key, &WR_LK_SEM_P, 1);
semop(key, &RD_LK_SEM_V, 1);
semop(key, &RD_OP_SEM_V, 1);
}
void read_unlock(int key)
{
if (key < 0) return;
semop(key, &RD_OP_SEM_V, 1);
semop(key, &RD_LK_SEM_P, 1);
if (semctl(key, 0, GETVAL) == 0 && semctl(key, 1, GETVAL) == 0)
semop(key, &WR_LK_SEM_V, 1);
semop(key, &RD_OP_SEM_P, 1);
}