1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "Semaphore.h"
#define MAX_RETRIES 10
union semun
{
int val;
struct semid_ds *buf;
ushort *array;
};
Semaphore::Semaphore(int nsems)
{
nSems = nsems;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
if((key = ftok("Semaphore.h", 'R')) == -1)
{
perror("ftok");
exit(1);
}
initSem();
}
int Semaphore::initSem()
{
int i;
union semun arg;
struct semid_ds buf;
struct sembuf sb;
semid = semget(key, nSems, IPC_CREAT | IPC_EXCL | 0666);
if(semid >= 0)
{
sb.sem_op = 1;
sb.sem_flg = 0;
arg.val = 1;
for(sb.sem_num = 0; sb.sem_num < nSems; sb.sem_num++)
{
if(semop(semid, &sb, 1) == -1)
{
int e = errno;
semctl(semid, 0, IPC_RMID);
errno = e;
return -1;
}
}
}
else if(errno == EEXIST)
{
int ready = 0;
semid = semget(key, nSems, 0);
if(semid < 0)
return semid;
arg.buf = &buf;
for(i = 0; i < MAX_RETRIES && !ready; i++)
{
semctl(semid, nSems - 1, IPC_STAT, arg);
if(arg.buf->sem_otime != 0)
{
ready = 1;
}
else
{
sleep(1);
}
}
if(!ready)
{
errno = ETIME;
return -1;
}
}
else
{
return semid;
}
return semid;
}
void Semaphore::getLock()
{
if(semop(semid, &sb, 1) == -1)
{
perror("semop");
exit(1);
}
}
void Semaphore::ReleaseLock()
{
sb.sem_op = 1;
if(semop(semid, &sb, 1) == -1)
{
perror("semop");
exit(1);
}
}
|