rllib  1
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);
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 
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);
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);
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);
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);
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;
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 
506 unsigned long rlSharedMemory::size()
507 {
508  return _size;
509 }
510 
int read(unsigned long offset, void *buf, int len)
int rlwthread_mutex_destroy(pthread_mutex_t *mptr)
Definition: rlwthread.cpp:178
unsigned long _size
pthread_mutex_t * mutex
virtual ~rlSharedMemory()
rlSharedMemory(const char *name, unsigned long size, int rwmode=0600)
float readFloat(unsigned long offset, int index)
int writeInt(unsigned long offset, int index, int val)
HANDLE pthread_mutex_t
Definition: rlwthread.h:70
unsigned long size()
int readShort(unsigned long offset, int index)
int writeShort(unsigned long offset, int index, int val)
int writeFloat(unsigned long offset, int index, float val)
OVERLAPPED overlapped
int readByte(unsigned long offset, int index)
long start
int write(unsigned long offset, const void *buf, int len)
int writeByte(unsigned long offset, int index, unsigned char val)
int readInt(unsigned long offset, int index)
int rlwthread_sleep(long msec)
Definition: rlwthread.cpp:366
long end