rllib  1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
rlsharedmemory.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlsharedmemory.cpp - description
3  -------------------
4  begin : Tue Jan 02 2001
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rlsharedmemory.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #ifndef RLWIN32
21 #include <unistd.h>
22 #endif
23 
24 #ifdef RLUNIX
25 #include <sys/ipc.h>
26 #include <sys/shm.h>
27 #include <sys/file.h>
28 #endif
29 
30 #ifdef __VMS
31 #include <starlet.h>
32 #include <lib$routines.h>
33 #include <descrip.h>
34 #include <ssdef.h>
35 #include <syidef.h>
36 #include <secdef.h>
37 #include <rms.h>
38 #include <errno.h>
39 #include <psldef.h>
40 #include <dvidef.h>
41 typedef struct
42 {
43  long start;
44  long end;
45 }
46 ADD;
47 #endif
48 
49 #ifdef RLWIN32
50 #include <windows.h>
51 //#include <sddl.h>
52 #endif
53 
54 #ifndef RLWIN32
55 #ifndef RLUNIX
56 static void myinit(pthread_mutex_t *mutex)
57 {
58  int *cnt = (int *) mutex;
59  *cnt = 0;
60 }
61 
62 static void mylock(pthread_mutex_t *mutex, int increment)
63 {
64  volatile int *cnt = (int *) mutex;
65  while(1)
66  {
67 retry:
68  if(*cnt == 0)
69  { // try to lock the counter
70  (*cnt) += increment;
71  if(*cnt > 1)
72  {
73  (*cnt) -= increment;
74  goto retry; // another process also wanted to lock the counter
75  }
76  return; // now we can do it
77  }
78  rlwthread_sleep(1);
79  }
80 }
81 
82 static void myunlock(pthread_mutex_t *mutex)
83 {
84  int *cnt = (int *) mutex;
85  if(*cnt > 0) (*cnt)--;
86 }
87 #endif
88 #endif
89 
90 rlSharedMemory::rlSharedMemory(const char *shmname, unsigned long Size, int rwmode)
91 {
92 #ifdef RLUNIX
93  struct shmid_ds buf;
94 
95  status = OK;
96  name = new char[strlen(shmname)+1];
97  strcpy(name,shmname);
98  size = Size + sizeof(*mutex);
99 
100  // create file
101  fdlock = open(name, O_RDWR | O_CREAT, rwmode );
102  if(fdlock < 0)
103  {
104  int ret;
105  char buf[1024];
106  sprintf(buf,"could not write shm=%s\n",shmname);
107  ret = ::write(1,buf,strlen(buf));
108  if(ret < 0) exit(-1);
109  sprintf(buf,"you have to run this program as root !!!\n");
110  ret = ::write(1,buf,strlen(buf));
111  if(ret < 0) exit(-1);
112  status=ERROR_FILE;
113  exit(-1);
114  }
115 
116  // old stuff, without suggestions from Stefan Lievens
117  //shmkey = ftok(name,0);
118  //
119  //id = shmget(shmkey, size, IPC_CREAT);
120 
121  //shmkey = ftok(name, 'R');
122  shmkey = ftok(name, 'b');
123 
124  //id = shmget(shmkey, size, 0600 | IPC_CREAT);
125  id = shmget(shmkey, size, rwmode | IPC_CREAT);
126  if(id < 0) { status=ERROR_SHMGET; return; }
127 
128  base_adr = (char *) shmat(id,NULL,0);
129  if(base_adr == NULL) { status=ERROR_SHMAT; return; }
130 
131  if(shmctl(id, IPC_STAT, &buf) != 0) { status=ERROR_SHMCTL; return; };
132 
133  mutex = (pthread_mutex_t *) base_adr;
134  user_adr = base_adr + sizeof(*mutex);
135  flock(fdlock,LOCK_UN);
136 #endif
137 
138 #ifdef __VMS
139  int file_existed = 0;
140  long ret,fd,page_size,pagelets,pagelet_size,file_block_size,flags,item,ident[2];
141  FILE *fp;
142  ADD add_in,add_ret;
143  struct dsc$descriptor_s section_name;
144  struct FAB fab;
145 
146  status = OK;
147  name = new char[strlen(shmname)+1];
148  strcpy(name,shmname);
149  size = Size + sizeof(*mutex);
150  // The file block size is fixed
151  file_block_size = 512; // Bytes
152  // Get the page size
153  item = SYI$_PAGE_SIZE;
154  ret = lib$getsyi( &item ,
155  &page_size ,
156  0 ,
157  0 ,
158  0 ,
159  0
160  );
161  if(ret != SS$_NORMAL) { status=ERROR_FILE; return; }
162  // Fill descriptor for section name
163  section_name.dsc$w_length = strlen(name);
164  section_name.dsc$a_pointer = name;
165  section_name.dsc$b_dtype = DSC$K_DTYPE_T;
166  section_name.dsc$b_class = DSC$K_CLASS_S;
167  // The pagelet size is fixed
168  pagelet_size = 512; // Bytes
169  // Get memory
170  if(size % page_size == 0) pagelets = size / pagelet_size;
171  else pagelets = (size / page_size + 1) * (page_size / pagelet_size);
172  ret = sys$expreg(pagelets,&add_ret,0,0);
173  if(ret != SS$_NORMAL) { status=ERROR_FILE; return; }
174  // Set the addresses
175  base_adr = (char *) add_ret.start;
176  user_adr = base_adr + sizeof(*mutex);
177  mutex = (pthread_mutex_t *) base_adr;
178  if(base_adr == NULL) { status=ERROR_SHMAT; return; }
179  // Fill the fab
180  fab = cc$rms_fab; // Initialize fab
181  fab.fab$b_fac = fab.fab$b_fac | FAB$M_PUT | FAB$M_DEL | FAB$M_GET | FAB$M_UPD;
182  fab.fab$l_fna = name;
183  fab.fab$b_fns = strlen(name);
184  fab.fab$l_fop = fab.fab$l_fop
185  | FAB$M_CIF // create file if not existent
186  | FAB$M_CTG // contiguous
187  | FAB$M_UFO; // user open
188  fab.fab$b_shr = fab.fab$b_shr // shareble access
189  | FAB$M_SHRPUT
190  | FAB$M_UPI;
191  fab.fab$l_alq = pagelets * pagelet_size / file_block_size;
192  // Open the section file
193  ret = sys$create (&fab);
194  if(ret != RMS$_NORMAL && ret != RMS$_CREATED)
195  {
196  sys$close (&fab);
197  status=ERROR_FILE;
198  return;
199  }
200  // Set the channel
201  fd = fab.fab$l_stv;
202  // Fill the input address
203  add_in.start = add_ret.start;
204  add_in.end = add_ret.end;
205  // Clear ident
206  ident[0] = 0;
207  ident[1] = 0;
208  // Set flags
209  flags = 0;
210  flags = SEC$M_GBL | SEC$M_WRT | SEC$M_PERM;
211  // Create and map the section
212  ret = sys$crmpsc(&add_in ,&add_ret,
213  (long)0 , // acmode
214  flags , // flags
215  &section_name , // gsdnam
216  &ident , // ident
217  (long)0 , // relpag
218  (short)fd , // chan
219  pagelets , // pagcnt
220  (long)0 , // vbn
221  (long)0 , // prot
222  (long)0 // pfc
223  );
224  if(ret != SS$_NORMAL && ret != SS$_CREATED)
225  {
226  sys$close(&fab);
227  status=ERROR_FILE;
228  return;
229  }
230  // Test the section addresses
231  if(add_in.start != add_ret.start || add_in.end != add_ret.end)
232  {
233  sys$close(&fab);
234  status=ERROR_FILE;
235  return;
236  }
237  // Close the section file
238  ret = sys$close(&fab);
239  // rlwthread_mutex_init(mutex,NULL);
240  if(file_existed == 0) myinit(mutex);
241 #endif
242 
243 #ifdef RLWIN32
244  HANDLE hShmem;
245  int file_existed;
246 
247  status = OK;
248  name = new char[strlen(shmname)+1];
249  strcpy(name,shmname);
250  size = Size + sizeof(HANDLE); // sizeof(*mutex);
251 
252  file_existed = 1;
253  hSharedFile = CreateFile(name,
254  GENERIC_READ | GENERIC_WRITE,
255  FILE_SHARE_READ | FILE_SHARE_WRITE,
256  NULL,
257  OPEN_EXISTING,
258  FILE_ATTRIBUTE_NORMAL,
259  NULL
260  );
261  if(hSharedFile == INVALID_HANDLE_VALUE)
262  {
263  file_existed = 0;
264  hSharedFile = CreateFile(name,
265  GENERIC_READ | GENERIC_WRITE,
266  FILE_SHARE_READ | FILE_SHARE_WRITE,
267  NULL,
268  CREATE_NEW,
269  FILE_ATTRIBUTE_NORMAL,
270  NULL
271  );
272  }
273  if(hSharedFile == INVALID_HANDLE_VALUE) { status=ERROR_FILE; return; }
274  //char *global_name = new char[strlen(name)+40];
275  //strcpy(global_name,"Global\\"); strcat(global_name, name);
276  //for(int i=7; i<strlen(global_name); i++)
277  //{
278  // if (global_name[i] == ':') global_name[i] = '_';
279  // else if(global_name[i] == '\\') global_name[i] = '_';
280  // else if(global_name[i] == '.') global_name[i] = '_';
281  // else if(global_name[i] == ' ') global_name[i] = '_';
282  //}
283  hShmem = CreateFileMapping(
284  hSharedFile,
285  NULL, // no security attributes
286  PAGE_READWRITE, // read/write access
287  0, // size: high 32-bits
288  size, // size: low 32-bits
289  0); // name of map object // changed by FMakkinga 25-03-2013 global_name);
290  // global_name); // name of map object
291  //delete [] global_name;
292  if(hShmem == NULL) { status=ERROR_FILE; return; }
293  base_adr = (char *) MapViewOfFile(
294  hShmem, // object to map view of
295  FILE_MAP_WRITE, // read/write access
296  0, // high offset: map from
297  0, // low offset: beginning
298  0); // default: map entire file
299  if(base_adr == NULL) { status=ERROR_FILE; return; }
300  id = (int) hShmem;
301  shmkey = (int) hSharedFile;
302  mutex = (pthread_mutex_t *) base_adr;
303  user_adr = base_adr + sizeof(*mutex);
304  memset(&overlapped, 0, sizeof(overlapped)); // Changed by FMakkinga 22-03-2013
305  UnlockFileEx(hSharedFile,0,size,0,&overlapped);
306 #endif
307  if(rwmode == 0) return; // no warning of unused parameter
308 }
309 
311 {
312  delete [] name;
313  printf("We are within the destructor\n");
314 #ifdef RLWIN32
315  if(status != OK) return;
316  CloseHandle((HANDLE) id);
317  CloseHandle((HANDLE) shmkey);
318 #elif defined(RLUNIX)
319  if(fdlock >= 0) close(fdlock);
320 #endif
321 }
322 
324 {
325 #ifdef RLUNIX
326  struct shmid_ds buf;
327  if(status != OK) return -1;
328  //rlwthread_mutex_destroy(mutex);
329  flock(fdlock,LOCK_UN);
330  shmctl(id, IPC_RMID, &buf);
331  size = 0;
332  return 0;
333 #endif
334 
335 #ifdef __VMS
336  int ret;
337  ADD add_in,add_ret;
338  struct dsc$descriptor_s section_name;
339 
340  if(status != OK) return -1;
342  // Fill descriptor for section name
343  section_name.dsc$w_length = strlen(name);
344  section_name.dsc$a_pointer = name;
345  section_name.dsc$b_dtype = DSC$K_DTYPE_T;
346  section_name.dsc$b_class = DSC$K_CLASS_S;
347  // Delete the section
348  ret = sys$dgblsc(0,&section_name,0);
349  if(ret != SS$_NORMAL) return -1;
350  // Fill the input address
351  add_in.start = (long) base_adr;
352  add_in.end = (long) base_adr + size;
353  // Free the memory
354  ret = sys$deltva(&add_in,&add_ret,0);
355  if(ret != SS$_NORMAL) return -1;
356  // Test the section addresses
357  if(add_in.start != add_ret.start || add_in.end != add_ret.end) return -1;
358  return 0;
359 #endif
360 
361 #ifdef RLWIN32
362  if(status != OK) return -1;
363  //rlwthread_mutex_destroy(mutex);
364  UnmapViewOfFile(base_adr);
365  CloseHandle((HANDLE) id);
366  CloseHandle((HANDLE) shmkey);
367  UnlockFile(hSharedFile,0,0,size,0); // Changed by FMakkinga 18-03-2013
368  CloseHandle(hSharedFile); // Changed by FMakkinga 18-03-2013
369  status = ~OK;
370  return 0;
371 #endif
372 }
373 
374 int rlSharedMemory::write(unsigned long offset, const void *buf, int len)
375 {
376  void *ptr;
377  if(status != OK) return -1;
378  if(len <= 0) return -1;
379  if(offset+len > size) return -1;
380  ptr = user_adr + offset;
381 #ifdef RLWIN32
382  LockFileEx(hSharedFile,LOCKFILE_EXCLUSIVE_LOCK,0,size,0,&overlapped); // Changed by FMakkinga 18-03-2013
383 #elif defined(RLUNIX)
384  flock(fdlock,LOCK_EX);
385 #else
386  mylock(mutex,1);
387 #endif
388  memcpy(ptr,buf,len);
389 #ifdef RLWIN32
390  UnlockFileEx(hSharedFile,0,size,0,&overlapped); // Changed by FMakkinga 18-03-2013
391 #elif defined(RLUNIX)
392  flock(fdlock,LOCK_UN);
393 #else
394  myunlock(mutex);
395 #endif
396  return len;
397 }
398 
399 int rlSharedMemory::read(unsigned long offset, void *buf, int len)
400 {
401  void *ptr;
402  if(status != OK) return -1;
403  if(len <= 0) return -1;
404  if(offset+len > size) return -1;
405  ptr = user_adr + offset;
406 #ifdef RLWIN32
407  LockFileEx(hSharedFile,LOCKFILE_EXCLUSIVE_LOCK,0,size,0,&overlapped); // Changed by FMakkinga 18-03-2013
408 #elif defined(RLUNIX)
409  flock(fdlock,LOCK_EX);
410 #else
411  mylock(mutex,1);
412 #endif
413  memcpy(buf,ptr,len);
414 #ifdef RLWIN32
415  UnlockFileEx(hSharedFile,0,size,0,&overlapped); // Changed by FMakkinga 18-03-2013
416 #elif defined(RLUNIX)
417  flock(fdlock,LOCK_UN);
418 #else
419  myunlock(mutex);
420 #endif
421  return len;
422 }
423 
424 int rlSharedMemory::readInt(unsigned long offset, int index)
425 {
426  int val;
427  if(index < 0) return -1;
428  read(offset+index*sizeof(val),&val,sizeof(val));
429  return val;
430 }
431 
432 int rlSharedMemory::readShort(unsigned long offset, int index)
433 {
434  short int val;
435  if(index < 0) return -1;
436  read(offset+index*sizeof(val),&val,sizeof(val));
437  return val;
438 }
439 
440 int rlSharedMemory::readByte(unsigned long offset, int index)
441 {
442  char val;
443  if(index < 0) return -1;
444  read(offset+index*sizeof(val),&val,sizeof(val));
445  return val;
446 }
447 
448 float rlSharedMemory::readFloat(unsigned long offset, int index)
449 {
450  float val;
451  if(index < 0) return -1;
452  read(offset+index*sizeof(val),&val,sizeof(val));
453  return val;
454 }
455 
456 int rlSharedMemory::writeInt(unsigned long offset, int index, int val)
457 {
458  int ret;
459  if(index < 0) return -1;
460  ret = write(offset+index*sizeof(val),&val,sizeof(val));
461  return ret;
462 }
463 
464 int rlSharedMemory::writeShort(unsigned long offset, int index, int val)
465 {
466  int ret;
467  short int val2;
468 
469  if(index < 0) return -1;
470  val2 = (short int) val;
471  ret = write(offset+index*sizeof(val2),&val2,sizeof(val2));
472  return ret;
473 }
474 
475 int rlSharedMemory::writeByte(unsigned long offset, int index, unsigned char val)
476 {
477  int ret;
478  if(index < 0) return -1;
479  ret = write(offset+index*sizeof(val),&val,sizeof(val));
480  return ret;
481 }
482 
483 int rlSharedMemory::writeFloat(unsigned long offset, int index, float val)
484 {
485  int ret;
486  if(index < 0) return -1;
487  ret = write(offset+index*sizeof(val),&val,sizeof(val));
488  return ret;
489 }
490 
492 {
493  return (void *) user_adr;
494 }
495 
497 {
498  return shmkey;
499 }
500 
502 {
503  return id;
504 }
505