Belle II Software development
SemaphoreLocker.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <framework/pcore/SemaphoreLocker.h>
9#include <framework/logging/Logger.h>
10
11#include <sys/ipc.h>
12#include <sys/sem.h>
13
14#include <cerrno>
15#include <cstring>
16
17using namespace Belle2;
18
19int SemaphoreLocker::create(key_t semkey)
20{
21 int semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600);
22 if (semid >= 0) {
23 // POSIX doesn't guarantee any particular state of our fresh semaphore
24 int semval = 1; //unlocked state
25 if (semctl(semid, 0, SETVAL, semval) == -1) { //set 0th semaphore to semval
26 B2ERROR("Initializing semaphore with semctl() failed.");
27 }
28 } else if (errno == EEXIST) {
29 semid = semget(semkey, 1, 0600);
30 }
31 if (semid < 0) {
32 B2ERROR("Couldn't create semaphore with semget()! Maybe you have too many semaphores from aborted processes lying around, you can clean those up by running 'clear_basf2_ipc'.");
33 return semid;
34 }
35
36 return semid;
37}
38
40{
41 if (semctl(semId, 1, IPC_RMID) == -1) { //semnum=1 has no meaning, ignored
42 B2ERROR("Error in SemaphoreLocker::destroy(), semaphore " << semId << ", error: " << strerror(errno));
43 }
44}
45
47{
48 int ignored = 0;
49 int val = semctl(semId, 0, GETVAL, ignored);
50 return (val == 0); //0: locked, 1: unlocked
51
52}
53
54namespace {
55 void doSemOp(int semID, int op)
56 {
57 struct sembuf sb;
58 sb.sem_num = 0;
59 sb.sem_op = op;
60 sb.sem_flg = 0;
61 while (semop(semID, &sb, 1) == -1) {
62 if (errno == EINTR) {
63 //interrupted by signal (e.g. window size changed), try again
64 continue;
65 } else {
66 B2FATAL("Another process was aborted, please check previous output for reasons. (" <<
67 strerror(errno) << " for semaphore " << semID << ")");
68 }
69 }
70 }
71}
73{
74 doSemOp(m_id, -1);
75}
76
78{
79 doSemOp(m_id, 1);
80}
81
static void destroy(int semId)
Destroy the given semaphore.
static int create(key_t semkey)
Create a new semaphore and initialize it.
void unlock()
Unlock the semaphore.
void lock()
Lock the semaphore.
int m_id
semaphore id, see semget(2).
static bool isLocked(int semId)
Return true if the given semaphore is locked.
Abstract base class for different kinds of events.