|
rllib
1
|
00001 /*************************************************************************** 00002 rlsharedmemory.cpp - description 00003 ------------------- 00004 begin : Tue Jan 02 2001 00005 copyright : (C) 2001 by Rainer Lehrig 00006 email : lehrig@t-online.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as * 00013 * published by the Free Software Foundation * 00014 * * 00015 ***************************************************************************/ 00016 #include "rlsharedmemory.h" 00017 #include <stdio.h> 00018 #include <stdlib.h> 00019 #include <string.h> 00020 #ifndef RLWIN32 00021 #include <unistd.h> 00022 #endif 00023 00024 #ifdef RLUNIX 00025 #include <sys/ipc.h> 00026 #include <sys/shm.h> 00027 #endif 00028 00029 #ifdef __VMS 00030 #include <starlet.h> 00031 #include <lib$routines.h> 00032 #include <descrip.h> 00033 #include <ssdef.h> 00034 #include <syidef.h> 00035 #include <secdef.h> 00036 #include <rms.h> 00037 #include <errno.h> 00038 #include <psldef.h> 00039 #include <dvidef.h> 00040 typedef struct 00041 { 00042 long start; 00043 long end; 00044 } 00045 ADD; 00046 #endif 00047 00048 #ifdef RLWIN32 00049 #include <windows.h> 00050 #endif 00051 00052 static void myinit(pthread_mutex_t *mutex) 00053 { 00054 int *cnt = (int *) mutex; 00055 *cnt = 0; 00056 } 00057 00058 static void mylock(pthread_mutex_t *mutex, int increment) 00059 { 00060 volatile int *cnt = (int *) mutex; 00061 while(1) 00062 { 00063 retry: 00064 if(*cnt == 0) 00065 { // try to lock the counter 00066 (*cnt) += increment; 00067 if(*cnt > 1) 00068 { 00069 (*cnt) -= increment; 00070 goto retry; // another process also wanted to lock the counter 00071 } 00072 return; // now we can do it 00073 } 00074 rlwthread_sleep(1); 00075 } 00076 } 00077 00078 static void myunlock(pthread_mutex_t *mutex) 00079 { 00080 int *cnt = (int *) mutex; 00081 if(*cnt > 0) (*cnt)--; 00082 } 00083 00084 rlSharedMemory::rlSharedMemory(const char *shmname, unsigned long Size, int rwmode) 00085 { 00086 #ifdef RLUNIX 00087 struct shmid_ds buf; 00088 FILE *fp; 00089 int file_existed; 00090 00091 status = OK; 00092 name = new char[strlen(shmname)+1]; 00093 strcpy(name,shmname); 00094 size = Size + sizeof(*mutex); 00095 00096 // create file 00097 file_existed = 1; 00098 fp = fopen(name,"r"); 00099 if(fp == NULL) 00100 { 00101 file_existed = 0; 00102 fp = fopen(name,"w"); 00103 if(fp == NULL) 00104 { 00105 int ret; 00106 char buf[1024]; 00107 sprintf(buf,"could not write shm=%s\n",shmname); 00108 ret = ::write(1,buf,strlen(buf)); 00109 if(ret < 0) exit(-1); 00110 sprintf(buf,"you have to run this program as root !!!\n"); 00111 ret = ::write(1,buf,strlen(buf)); 00112 if(ret < 0) exit(-1); 00113 status=ERROR_FILE; 00114 exit(-1); 00115 } 00116 } 00117 fclose(fp); 00118 00119 // old stuff, without suggestions from Stefan Lievens 00120 //shmkey = ftok(name,0); 00121 // 00122 //id = shmget(shmkey, size, IPC_CREAT); 00123 00124 //shmkey = ftok(name, 'R'); 00125 shmkey = ftok(name, 'b'); 00126 00127 //id = shmget(shmkey, size, 0600 | IPC_CREAT); 00128 id = shmget(shmkey, size, rwmode | IPC_CREAT); 00129 if(id < 0) { status=ERROR_SHMGET; return; } 00130 00131 base_adr = (char *) shmat(id,NULL,0); 00132 if(base_adr == NULL) { status=ERROR_SHMAT; return; } 00133 00134 if(shmctl(id, IPC_STAT, &buf) != 0) { status=ERROR_SHMCTL; return; }; 00135 00136 mutex = (pthread_mutex_t *) base_adr; 00137 user_adr = base_adr + sizeof(*mutex); 00138 //if(file_existed == 0) rlwthread_mutex_init(mutex,NULL); 00139 if(file_existed == 0) myinit(mutex); 00140 #endif 00141 00142 #ifdef __VMS 00143 int file_existed = 0; 00144 long ret,fd,page_size,pagelets,pagelet_size,file_block_size,flags,item,ident[2]; 00145 FILE *fp; 00146 ADD add_in,add_ret; 00147 struct dsc$descriptor_s section_name; 00148 struct FAB fab; 00149 00150 status = OK; 00151 name = new char[strlen(shmname)+1]; 00152 strcpy(name,shmname); 00153 size = Size + sizeof(*mutex); 00154 // The file block size is fixed 00155 file_block_size = 512; // Bytes 00156 // Get the page size 00157 item = SYI$_PAGE_SIZE; 00158 ret = lib$getsyi( &item , 00159 &page_size , 00160 0 , 00161 0 , 00162 0 , 00163 0 00164 ); 00165 if(ret != SS$_NORMAL) { status=ERROR_FILE; return; } 00166 // Fill descriptor for section name 00167 section_name.dsc$w_length = strlen(name); 00168 section_name.dsc$a_pointer = name; 00169 section_name.dsc$b_dtype = DSC$K_DTYPE_T; 00170 section_name.dsc$b_class = DSC$K_CLASS_S; 00171 // The pagelet size is fixed 00172 pagelet_size = 512; // Bytes 00173 // Get memory 00174 if(size % page_size == 0) pagelets = size / pagelet_size; 00175 else pagelets = (size / page_size + 1) * (page_size / pagelet_size); 00176 ret = sys$expreg(pagelets,&add_ret,0,0); 00177 if(ret != SS$_NORMAL) { status=ERROR_FILE; return; } 00178 // Set the addresses 00179 base_adr = (char *) add_ret.start; 00180 user_adr = base_adr + sizeof(*mutex); 00181 mutex = (pthread_mutex_t *) base_adr; 00182 if(base_adr == NULL) { status=ERROR_SHMAT; return; } 00183 // Fill the fab 00184 fab = cc$rms_fab; // Initialize fab 00185 fab.fab$b_fac = fab.fab$b_fac | FAB$M_PUT | FAB$M_DEL | FAB$M_GET | FAB$M_UPD; 00186 fab.fab$l_fna = name; 00187 fab.fab$b_fns = strlen(name); 00188 fab.fab$l_fop = fab.fab$l_fop 00189 | FAB$M_CIF // create file if not existent 00190 | FAB$M_CTG // contiguous 00191 | FAB$M_UFO; // user open 00192 fab.fab$b_shr = fab.fab$b_shr // shareble access 00193 | FAB$M_SHRPUT 00194 | FAB$M_UPI; 00195 fab.fab$l_alq = pagelets * pagelet_size / file_block_size; 00196 // Open the section file 00197 ret = sys$create (&fab); 00198 if(ret != RMS$_NORMAL && ret != RMS$_CREATED) 00199 { 00200 sys$close (&fab); 00201 status=ERROR_FILE; 00202 return; 00203 } 00204 // Set the channel 00205 fd = fab.fab$l_stv; 00206 // Fill the input address 00207 add_in.start = add_ret.start; 00208 add_in.end = add_ret.end; 00209 // Clear ident 00210 ident[0] = 0; 00211 ident[1] = 0; 00212 // Set flags 00213 flags = 0; 00214 flags = SEC$M_GBL | SEC$M_WRT | SEC$M_PERM; 00215 // Create and map the section 00216 ret = sys$crmpsc(&add_in ,&add_ret, 00217 (long)0 , // acmode 00218 flags , // flags 00219 §ion_name , // gsdnam 00220 &ident , // ident 00221 (long)0 , // relpag 00222 (short)fd , // chan 00223 pagelets , // pagcnt 00224 (long)0 , // vbn 00225 (long)0 , // prot 00226 (long)0 // pfc 00227 ); 00228 if(ret != SS$_NORMAL && ret != SS$_CREATED) 00229 { 00230 sys$close(&fab); 00231 status=ERROR_FILE; 00232 return; 00233 } 00234 // Test the section addresses 00235 if(add_in.start != add_ret.start || add_in.end != add_ret.end) 00236 { 00237 sys$close(&fab); 00238 status=ERROR_FILE; 00239 return; 00240 } 00241 // Close the section file 00242 ret = sys$close(&fab); 00243 // rlwthread_mutex_init(mutex,NULL); 00244 if(file_existed == 0) myinit(mutex); 00245 #endif 00246 00247 #ifdef RLWIN32 00248 HANDLE hFile, hShmem; 00249 int file_existed; 00250 00251 status = OK; 00252 name = new char[strlen(shmname)+1]; 00253 strcpy(name,shmname); 00254 size = Size + sizeof(*mutex); 00255 00256 file_existed = 1; 00257 hFile = CreateFile(name, 00258 GENERIC_READ | GENERIC_WRITE, 00259 FILE_SHARE_READ | FILE_SHARE_WRITE, 00260 NULL, 00261 OPEN_EXISTING, 00262 FILE_ATTRIBUTE_NORMAL, 00263 NULL 00264 ); 00265 if(hFile == INVALID_HANDLE_VALUE) 00266 { 00267 file_existed = 0; 00268 hFile = CreateFile(name, 00269 GENERIC_READ | GENERIC_WRITE, 00270 FILE_SHARE_READ | FILE_SHARE_WRITE, 00271 NULL, 00272 CREATE_NEW, 00273 FILE_ATTRIBUTE_NORMAL, 00274 NULL 00275 ); 00276 } 00277 if(hFile == INVALID_HANDLE_VALUE) { status=ERROR_FILE; return; } 00278 hShmem = CreateFileMapping( 00279 hFile, 00280 NULL, // no security attributes 00281 PAGE_READWRITE, // read/write access 00282 0, // size: high 32-bits 00283 size, // size: low 32-bits 00284 NULL); // name of map object 00285 if(hShmem == NULL) { status=ERROR_FILE; return; } 00286 base_adr = (char *) MapViewOfFile( 00287 hShmem, // object to map view of 00288 FILE_MAP_WRITE, // read/write access 00289 0, // high offset: map from 00290 0, // low offset: beginning 00291 0); // default: map entire file 00292 if(base_adr == NULL) { status=ERROR_FILE; return; } 00293 id = (int) hShmem; 00294 shmkey = (int) hFile; 00295 mutex = (pthread_mutex_t *) base_adr; 00296 user_adr = base_adr + sizeof(*mutex); 00297 if(file_existed == 0) rlwthread_mutex_init(mutex,NULL); 00298 #endif 00299 if(rwmode == 0) return; // no warning of unused parameter 00300 } 00301 00302 rlSharedMemory::~rlSharedMemory() 00303 { 00304 delete [] name; 00305 #ifdef RLWIN32 00306 if(status != OK) return; 00307 CloseHandle((HANDLE) id); 00308 CloseHandle((HANDLE) shmkey); 00309 #endif 00310 } 00311 00312 int rlSharedMemory::deleteSharedMemory() 00313 { 00314 #ifdef RLUNIX 00315 struct shmid_ds buf; 00316 if(status != OK) return -1; 00317 rlwthread_mutex_destroy(mutex); 00318 shmctl(id, IPC_RMID, &buf); 00319 size = 0; 00320 return 0; 00321 #endif 00322 00323 #ifdef __VMS 00324 int ret; 00325 ADD add_in,add_ret; 00326 struct dsc$descriptor_s section_name; 00327 00328 if(status != OK) return -1; 00329 rlwthread_mutex_destroy(mutex); 00330 // Fill descriptor for section name 00331 section_name.dsc$w_length = strlen(name); 00332 section_name.dsc$a_pointer = name; 00333 section_name.dsc$b_dtype = DSC$K_DTYPE_T; 00334 section_name.dsc$b_class = DSC$K_CLASS_S; 00335 // Delete the section 00336 ret = sys$dgblsc(0,§ion_name,0); 00337 if(ret != SS$_NORMAL) return -1; 00338 // Fill the input address 00339 add_in.start = (long) base_adr; 00340 add_in.end = (long) base_adr + size; 00341 // Free the memory 00342 ret = sys$deltva(&add_in,&add_ret,0); 00343 if(ret != SS$_NORMAL) return -1; 00344 // Test the section addresses 00345 if(add_in.start != add_ret.start || add_in.end != add_ret.end) return -1; 00346 return 0; 00347 #endif 00348 00349 #ifdef RLWIN32 00350 if(status != OK) return -1; 00351 rlwthread_mutex_destroy(mutex); 00352 UnmapViewOfFile(base_adr); 00353 CloseHandle((HANDLE) id); 00354 CloseHandle((HANDLE) shmkey); 00355 status = ~OK; 00356 return 0; 00357 #endif 00358 } 00359 00360 int rlSharedMemory::write(unsigned long offset, const void *buf, int len) 00361 { 00362 void *ptr; 00363 if(status != OK) return -1; 00364 if(len <= 0) return -1; 00365 if(offset+len > size) return -1; 00366 ptr = user_adr + offset; 00367 #ifdef RLWIN32 00368 rlwthread_mutex_lock(mutex); // Linux and OpenVMS don't support PTHREAD_PROCESS_SHARED (windows does not support pthread at all) 00369 #else 00370 mylock(mutex,1); 00371 #endif 00372 memcpy(ptr,buf,len); 00373 #ifdef RLWIN32 00374 rlwthread_mutex_unlock(mutex); // Linux and OpenVMS don't support PTHREAD_PROCESS_SHARED (windows does not support pthread at all) 00375 #else 00376 myunlock(mutex); 00377 #endif 00378 return len; 00379 } 00380 00381 int rlSharedMemory::read(unsigned long offset, void *buf, int len) 00382 { 00383 void *ptr; 00384 if(status != OK) return -1; 00385 if(len <= 0) return -1; 00386 if(offset+len > size) return -1; 00387 ptr = user_adr + offset; 00388 #ifdef RLWIN32 00389 rlwthread_mutex_lock(mutex); // Linux and OpenVMS don't support PTHREAD_PROCESS_SHARED (windows does not support pthread at all) 00390 #else 00391 mylock(mutex,1); 00392 #endif 00393 memcpy(buf,ptr,len); 00394 #ifdef RLWIN32 00395 rlwthread_mutex_unlock(mutex); // Linux and OpenVMS don't support PTHREAD_PROCESS_SHARED (windows does not support pthread at all) 00396 #else 00397 myunlock(mutex); 00398 #endif 00399 return len; 00400 } 00401 00402 int rlSharedMemory::readInt(unsigned long offset, int index) 00403 { 00404 int val; 00405 if(index < 0) return -1; 00406 read(offset+index*sizeof(val),&val,sizeof(val)); 00407 return val; 00408 } 00409 00410 int rlSharedMemory::readShort(unsigned long offset, int index) 00411 { 00412 short int val; 00413 if(index < 0) return -1; 00414 read(offset+index*sizeof(val),&val,sizeof(val)); 00415 return val; 00416 } 00417 00418 int rlSharedMemory::readByte(unsigned long offset, int index) 00419 { 00420 char val; 00421 if(index < 0) return -1; 00422 read(offset+index*sizeof(val),&val,sizeof(val)); 00423 return val; 00424 } 00425 00426 float rlSharedMemory::readFloat(unsigned long offset, int index) 00427 { 00428 float val; 00429 if(index < 0) return -1; 00430 read(offset+index*sizeof(val),&val,sizeof(val)); 00431 return val; 00432 } 00433 00434 int rlSharedMemory::writeInt(unsigned long offset, int index, int val) 00435 { 00436 int ret; 00437 if(index < 0) return -1; 00438 ret = write(offset+index*sizeof(val),&val,sizeof(val)); 00439 return ret; 00440 } 00441 00442 int rlSharedMemory::writeShort(unsigned long offset, int index, int val) 00443 { 00444 int ret; 00445 short int val2; 00446 00447 if(index < 0) return -1; 00448 val2 = (short int) val; 00449 ret = write(offset+index*sizeof(val2),&val2,sizeof(val2)); 00450 return ret; 00451 } 00452 00453 int rlSharedMemory::writeByte(unsigned long offset, int index, unsigned char val) 00454 { 00455 int ret; 00456 if(index < 0) return -1; 00457 ret = write(offset+index*sizeof(val),&val,sizeof(val)); 00458 return ret; 00459 } 00460 00461 int rlSharedMemory::writeFloat(unsigned long offset, int index, float val) 00462 { 00463 int ret; 00464 if(index < 0) return -1; 00465 ret = write(offset+index*sizeof(val),&val,sizeof(val)); 00466 return ret; 00467 } 00468 00469 void *rlSharedMemory::getUserAdr() 00470 { 00471 return (void *) user_adr; 00472 } 00473 00474 int rlSharedMemory::shmKey() 00475 { 00476 return shmkey; 00477 } 00478 00479 int rlSharedMemory::shmId() 00480 { 00481 return id; 00482 } 00483
1.7.5.1