Belle II Software  release-06-02-00
SharedMem.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 
9 #include "daq/rfarm/manager/SharedMem.h"
10 
11 #include <fcntl.h>
12 #include <sys/ipc.h>
13 #include <sys/sem.h>
14 #include <sys/shm.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 
18 #include <cstring>
19 
20 using namespace Belle2;
21 using namespace std;
22 
23 // Constructor / Destructor
24 
25 SharedMem::SharedMem(const char* name, int size)
26 {
27  // 0. Determine shared memory type
28  if (strcmp(name, "private") != 0) { // Global
29  m_file = true;
30  m_pathname = string("/tmp/") + string(getenv("USER"))
31  + string("_SHM_") + string(name);
32  m_pathfd = open(m_pathname.c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
33  if (m_pathfd > 0) { // a new shared memory file created
34  printf("SharedMem: Creating a shared memory with key %s\n", name);
35  m_new = true;
36  } else if (m_pathfd == -1 && errno == EEXIST) { // shm already there
37  printf("SharedMem: Attaching the ring buffer with key %s\n", name);
38  m_new = false;
39  } else {
40  printf("SharedMem: error to open shm file\n");
41  return;
42  }
43  m_shmkey = ftok(m_pathname.c_str(), 1);
44  m_semkey = ftok(m_pathname.c_str(), 2);
45  } else { // Private
46  m_file = false;
47  m_new = true;
48  m_shmkey = IPC_PRIVATE;
49  m_semkey = IPC_PRIVATE;
50  printf("SharedMem: Opening private shared memory\n");
51  }
52 
53  // 1. Open shared memory
54  m_shmid = shmget(m_shmkey, size * 4, IPC_CREAT | 0644);
55  if (m_shmid < 0) {
56  perror("SharedMem::shmget");
57  return;
58  }
59  m_shmadr = (int*) shmat(m_shmid, 0, 0);
60  if (m_shmadr == (int*) - 1) {
61  perror("SharedMem::shmat");
62  return;
63  }
64  m_shmsize = size;
65 
66  // 2. Open semaphore
67  m_semid = semget(m_semkey, 1, IPC_CREAT | 0644);
68  if (m_semid >= 0) {
69  // POSIX doesn't guarantee any particular state of our fresh semaphore
70  int semval = 1; //unlocked state
71  if (semctl(m_semid, 0, SETVAL, semval) == -1) { //set 0th semaphore to semval
72  printf("Initializing semaphore with semctl() failed.\n");
73  }
74  } else if (errno == EEXIST) {
75  m_semid = semget(m_semkey, 1, 0600);
76  }
77  if (m_semid < 0) {
78  perror("SharedMem::shmget");
79  return;
80  }
81 
82  // 3. Leave id of shm and semaphore in file name
83  if (m_new) {
84  /*
85  m_strbuf = new char[1024];
86  sprintf(m_strbuf, "/tmp/SHM%d-SEM%d-SHM_%s", m_shmid, m_semid, name);
87  int fd = open(m_strbuf, O_CREAT | O_TRUNC | O_RDWR, 0644);
88  if (fd < 0) {
89  printf("SharedMem ID file could not be created.\n");
90  } else {
91  close(fd);
92  }
93  */
94  // printf("SharedMem: leaving shmid and semid in the path file %d %d fd=%d\n", m_shmid, m_semid, m_pathfd);
95  char shminfo[256];
96  sprintf(shminfo, "%d %d\n", m_shmid, m_semid);
97  int is = write(m_pathfd, shminfo, strlen(shminfo));
98  if (is < 0) perror("write");
99  close(m_pathfd);
100  }
101  printf("SharedMem: created. shmid = %d, semid = %d\n", m_shmid, m_semid);
102 
103 }
104 
105 SharedMem::SharedMem(int shm_id)
106 {
107  m_shmid = shm_id;
108  m_shmadr = (int*) shmat(m_shmid, 0, 0);
109  if (m_shmadr == (int*) - 1) {
110  perror("SharedMem::shmat");
111  return;
112  }
113 }
114 
115 SharedMem::SharedMem(int shm_id, int sem_id, int size)
116 {
117  m_shmid = shm_id;
118  m_shmadr = (int*) shmat(m_shmid, 0, SHM_RDONLY);
119  if (m_shmadr == (int*) - 1) {
120  perror("SharedMem::shmat");
121  return;
122  }
123  m_shmsize = size;
124  m_semid = sem_id;
125  printf("SharedMem: open shmid = %d, semid = %d\n", m_shmid, m_semid);
126 }
127 
128 SharedMem::~SharedMem(void)
129 {
130  shmdt((const void*) m_shmadr);
131  shmctl(m_shmid, IPC_RMID, NULL);
132  // char idfile[256];
133  // sprintf ( idfile, "%s/.rfshmid", getenv("HOME") );
134  // unlink ( idfile );
135  if (m_new) {
136  unlink(m_strbuf);
137  delete[] m_strbuf;
138  }
139  printf("SharedMem: destructor called for %s\n", m_strbuf);
140 }
141 
142 void* SharedMem::ptr(void)
143 {
144  return (void*) m_shmadr;
145 }
146 
147 int SharedMem::shmid(void)
148 {
149  return m_shmid;
150 }
151 
152 bool SharedMem::IsCreated(void)
153 {
154  return m_new;
155 }
156 
157 void SharedMem::lock()
158 {
159  struct sembuf sb;
160  sb.sem_num = 0;
161  sb.sem_op = -1;
162  sb.sem_flg = 0;
163  while (semop(m_semid, &sb, 1) == -1) {
164  if (errno == EINTR) {
165  //interrupted by signal (e.g. window size changed), try again
166  continue;
167  } else {
168  perror("lock:semop");
169  exit(-1);
170  }
171  }
172 }
173 
174 void SharedMem::unlock()
175 {
176  struct sembuf sb;
177  sb.sem_num = 0;
178  sb.sem_op = 1;
179  sb.sem_flg = 0;
180  while (semop(m_semid, &sb, 1) == -1) {
181  if (errno == EINTR) {
182  //interrupted by signal (e.g. window size changed), try again
183  continue;
184  } else {
185  perror("unlock:semop");
186  exit(-1);
187  }
188  }
189 }
190 
191 bool SharedMem::isLocked()
192 {
193  int ignored = 0;
194  int val = semctl(m_semid, 0, GETVAL, ignored);
195  return (val == 0); //0: locked, 1: unlocked
196 
197 }
198 
199 
Abstract base class for different kinds of events.