Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

_shm.c

Go to the documentation of this file.
00001 #include "rcs_defs.hh"
00002 #include "_shm.h"
00003 #include "rcs_prnt.hh"
00004 #include "dbg_mem.h"            /* DEBUG_MALLOC, DEBUG_CALLOC, DEBUG_FREE */
00005 /*
00006   _shm.c
00007 
00008   C implementation of rcslib shared memory API
00009 
00010   Modification history:
00011 
00012   30-Mar-1998  FMP added this comment
00013   */
00014 
00015 #ifdef WIN32
00016 
00017 #include <windows.h>
00018 
00019 #ifndef NO_STDIO
00020 #include <stdio.h>              //sprintf()
00021 #endif
00022 
00023 #ifdef UNDER_CE
00024 #include "rcs_ce.h"
00025 #endif
00026 
00027 shm_t *
00028 rcs_shm_open (key_t key, size_t size, int oflag, /* int mode */ ...)
00029 {
00030   shm_t *shm;
00031   char name[64];
00032 #ifdef UNICODE
00033   wchar_t wname[64];
00034 #endif
00035 #ifndef UNDER_CE
00036   SECURITY_ATTRIBUTES sa;
00037   SECURITY_DESCRIPTOR sd;
00038 #endif
00039 
00040   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00041                    "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00042                    key, key, size, size, oflag);
00043 
00044   if (key < 1)
00045     {
00046       rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00047                        key, key, size, size, oflag, oflag);
00048       rcs_print_error ("RCS Shared Memory key may not be zero.\n");
00049       return NULL;
00050     }
00051 #ifndef UNDER_CE
00052   if (FALSE ==
00053       InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
00054     {
00055       rcs_print_error
00056         ("Can not initailize security descriptor.(Error = %d)\n",
00057          GetLastError ());
00058       return NULL;
00059     }
00060   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00061   sa.lpSecurityDescriptor = &sd;
00062   sa.bInheritHandle = TRUE;
00063 #endif
00064 
00065 #ifndef NO_STDIO
00066   sprintf (name, "shm%d", key);
00067 #else
00068   strcpy (name, "shm");
00069   _itoa (key, name + 3, 10);
00070 #endif
00071 
00072 
00073   shm = (shm_t *) DEBUG_MALLOC (sizeof (shm_t));
00074   if (NULL == shm)
00075     {
00076       rcs_print_error ("Out of memory.\n");
00077       return NULL;
00078     }
00079   memset (shm, 0, sizeof (shm_t));
00080   if (oflag)
00081     {
00082       shm->created = 1;
00083 #ifdef UNDER_CE
00084 #ifdef UNICODE
00085       RCS_CE_ASCII_TO_UNICODE (wname, name, 64);
00086       shm->hFileMap =
00087         CreateFileMapping ((HANDLE) (0xFFFFFFFF), NULL, PAGE_READWRITE, 0,
00088                            size, wname);
00089 #else
00090       shm->hFileMap =
00091         CreateFileMapping ((HANDLE) (0xFFFFFFFF), NULL, PAGE_READWRITE, 0,
00092                            size, name);
00093 #endif
00094 #else
00095       shm->hFileMap =
00096         CreateFileMapping ((HANDLE) (0xFFFFFFFF), &sa, PAGE_READWRITE, 0,
00097                            size, name);
00098 #endif
00099       if (NULL == shm->hFileMap)
00100         {
00101           rcs_print_error ("CreateFileMapping( failed!! (Error = %d)\n",
00102                            GetLastError ());
00103           DEBUG_FREE (shm);
00104           return NULL;
00105         }
00106       if ((shm->hFileMap != NULL) &&
00107           (GetLastError () == ERROR_ALREADY_EXISTS))
00108         {
00109           rcs_print_error ("File mapping name conflict, name = %s\n", name);;
00110           CloseHandle (shm->hFileMap);
00111           DEBUG_FREE (shm);
00112           return NULL;
00113         }
00114     }
00115   else
00116     {
00117 #ifdef UNDER_CE
00118 #ifdef UNICODE
00119       RCS_CE_ASCII_TO_UNICODE (wname, name, 64);
00120       shm->hFileMap =
00121         CreateFileMapping ((HANDLE) (0xFFFFFFFF), NULL, PAGE_READWRITE, 0,
00122                            size, wname);
00123 #else
00124       shm->hFileMap =
00125         CreateFileMapping ((HANDLE) (0xFFFFFFFF), NULL, PAGE_READWRITE, 0,
00126                            size, name);
00127 #endif
00128       if (NULL == shm->hFileMap)
00129         {
00130           rcs_print_error ("CreateFileMapping( failed!! (Error = %d)\n",
00131                            GetLastError ());
00132           DEBUG_FREE (shm);
00133           return NULL;
00134         }
00135 #else
00136       shm->hFileMap = OpenFileMapping (FILE_MAP_ALL_ACCESS, TRUE, name);
00137       if (NULL == shm->hFileMap)
00138         {
00139           rcs_print_error ("OpenFileMapping failed!! (Error = %d)\n",
00140                            GetLastError ());
00141           DEBUG_FREE (shm);
00142           return NULL;
00143         }
00144 #endif
00145     }
00146 
00147   shm->addr = MapViewOfFile (shm->hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, size);
00148   if (NULL == shm->addr)
00149     {
00150       rcs_print_error ("MapViewOfFile failed!! (Error = %d)\n",
00151                        GetLastError ());
00152       CloseHandle (shm->hFileMap);
00153       DEBUG_FREE (shm);
00154       return NULL;
00155     }
00156   return shm;
00157 }
00158 
00159 
00160 int
00161 rcs_shm_close (shm_t * shm)
00162 {
00163   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00164                    "rcs_shm_close(shm->key=%d(0x%X),shm->size=%d(0x%X),shm->addr=0x%X)\n",
00165                    shm->key, shm->key, shm->size, shm->size, shm->addr);
00166 
00167   if (shm != NULL)
00168     {
00169       if (shm->hFileMap != NULL)
00170         {
00171           UnmapViewOfFile (shm->addr);
00172           CloseHandle (shm->hFileMap);
00173           shm->addr = NULL;
00174           shm->hFileMap = NULL;
00175         }
00176     }
00177   return 0;
00178 }
00179 
00180 int
00181 rcs_shm_delete (shm_t * shm)
00182 {
00183   return rcs_shm_close (shm);
00184 }
00185 
00186 
00187 
00188 int
00189 rcs_shm_nattch (shm_t * shm)
00190 {
00191   // FIXME: I don't know how to get this number but it doesn't seem to
00192   // be neccessary since rcs_shm_delete and rcs_shm_close are identical
00193   // on this platform.
00194   return 1;
00195 }
00196 
00197 
00198 
00199 
00200 
00201 
00202 #else
00203 
00204 
00205 #if defined (VXWORKS)
00206 
00207 /* VxWorks shared memory */
00208 
00209 #include <vxWorks.h>
00210 #include <taskLib.h>
00211 
00212 #ifndef NO_STDIO
00213 #include <stdio.h>              /* stderr, etc */
00214 #endif
00215 #include <stdlib.h>             /* malloc, realloc, calloc, _itoa() */
00216 #include "_table.h"
00217 
00218 
00219 /* OS table of semaphore keys and sem_t's */
00220 _RCS_TABLE rcs_shm_table;
00221 int rcs_shm_table_inited = 0;
00222 int task_lock_shm_stuff = 1;
00223 int print_rcs_shm_warnings = 0;
00224 
00225 
00226 
00227 /* shell debug functions */
00228 
00229 void
00230 rcs_shm_table_print ()
00231 {
00232   if (!rcs_shm_table_inited)
00233     {
00234       printf ("RCS Shared Memory table NOT initialized.\n");
00235       return;
00236     }
00237   table_print (&rcs_shm_table);
00238   printf ("\t\tid\tkey\taddr\terrno\tsize\tcount\n");
00239 }
00240 
00241 void
00242 rcs_shm_table_clear ()
00243 {
00244   if (task_lock_shm_stuff)
00245     taskLock ();
00246   rcs_shm_table_inited = 0;
00247   table_clearall (&rcs_shm_table);
00248   if (task_lock_shm_stuff)
00249     taskUnlock ();
00250 }
00251 
00252 /* interface functions */
00253 
00254 shm_t *
00255 rcs_shm_open (key_t key, size_t size, int oflag, /* int mode */ ...)
00256 {
00257   int tid = taskIdSelf ();
00258   shm_t *shm;
00259 
00260   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00261                    "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00262                    key, key, size, size, oflag);
00263 
00264   if (task_lock_shm_stuff)
00265     taskLock ();
00266 
00267   /* ignore mode-- we always run privileged.  oflag non-zero means
00268      create it; 0 means it must exist */
00269   if (key == 0)
00270     {
00271       if (task_lock_shm_stuff)
00272         taskUnlock ();
00273       rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00274                        key, key, size, size, oflag, oflag);
00275       rcs_print_error ("RCS Shared Memory key is zero.\n");
00276       return NULL;
00277     }
00278 
00279   /* get shared mem data structure */
00280   shm = (shm_t *) DEBUG_CALLOC (sizeof (shm_t), 1);
00281   shm->id = (int) key;
00282   shm->addr = NULL;
00283   shm->size = -1;
00284   shm->created = 0;
00285 
00286   /* fill in address by consulting table */
00287   if (oflag)
00288     {
00289       if (rcs_shm_table_inited)
00290         {
00291           if (table_get (&rcs_shm_table, key, shm) >= 0)
00292             {
00293               /* got the id already-- just copy out the address */
00294               if (shm->id != key)
00295                 {
00296                   if (task_lock_shm_stuff)
00297                     taskUnlock ();
00298                   rcs_print_error
00299                     ("Shared Memory Key retrieved from table does not match. (%d) != (%d).\n",
00300                      key, shm->id);
00301                   return NULL;
00302                 }
00303               if (shm->addr <= 0)
00304                 {
00305                   if (task_lock_shm_stuff)
00306                     taskUnlock ();
00307                   return NULL;
00308                 }
00309               shm->count++;
00310               table_add (&rcs_shm_table, key, shm);
00311               if (task_lock_shm_stuff)
00312                 taskUnlock ();
00313               if (shm->size < size)
00314                 {
00315                   rcs_print_error
00316                     ("This process(%d(0x%X)) was configured to create a shared memory area with key = (%d(0x%X)) and size=(%d(0x%X)\n",
00317                      tid, tid, key, key, size, size);
00318                   rcs_print_error
00319                     (" but a shared memory area with this key and a size of only (%d(0x%X)) already exists.",
00320                      shm->size, shm->size);
00321                   return NULL;
00322                 }
00323               if (print_rcs_shm_warnings)
00324                 {
00325                   rcs_print_error
00326                     ("Warning: This process(%d(0x%X)) was configured to create a shared memory area with key = (%d(0x%X)), and size=(%d(0x%X)\n",
00327                      tid, tid, key, key, size, size);
00328                   rcs_print_error
00329                     ("Warning: but a shared memory area with this key has already been created.\n");
00330                   rcs_print_error ("\n");
00331                 }
00332               return shm;
00333             }
00334         }
00335       shm->addr = (void *) DEBUG_MALLOC (size);
00336       shm->size = size;
00337       shm->id = key;
00338       shm->count = 1;
00339       shm->created = 1;
00340       if (!rcs_shm_table_inited)
00341         {
00342           /* get a new table of rcs_shm_table_t's */
00343           table_new (&rcs_shm_table, sizeof (shm_t));
00344           rcs_shm_table_inited = 1;
00345         }
00346       table_add (&rcs_shm_table, key, shm);
00347     }
00348   else
00349     {
00350       /* it's connecting to created memory-- increment the reference count */
00351       if (!rcs_shm_table_inited)
00352         {
00353 #if 0
00354           shm->addr = (void *) DEBUG_CALLOC (size, 1);
00355           shm->size = size;
00356           shm->count = 1;
00357           shm->id = key;
00358           if (!rcs_shm_table_inited)
00359             {
00360               /* get a new table of rcs_shm_t's */
00361               table_new (&rcs_shm_table, sizeof (shm_t));
00362               rcs_shm_table_inited = 1;
00363             }
00364           table_add (&rcs_shm_table, key, shm);
00365           if (task_lock_shm_stuff)
00366             taskUnlock ();
00367 
00368           if (print_rcs_shm_warnings)
00369             {
00370               rcs_print_error
00371                 ("Warning: RCS Shared Memory Area table contains no entry for (%d(0x%X)), creating one.\n",
00372                  key, key);
00373             }
00374 #endif
00375           shm->create_errno = ENOENT;
00376           return shm;
00377         }
00378       else
00379         {
00380           if (table_get (&rcs_shm_table, key, shm) < 0)
00381             {
00382 #if 0
00383               shm->addr = (void *) DEBUG_CALLOC (size, 1);
00384               shm->size = size;
00385               shm->count = 1;
00386               shm->id = key;
00387               if (!rcs_shm_table_inited)
00388                 {
00389                   /* get a new table of rcs_shm_t's */
00390                   table_new (&rcs_shm_table, sizeof (shm_t));
00391                   rcs_shm_table_inited = 1;
00392                 }
00393               table_add (&rcs_shm_table, key, shm);
00394               if (task_lock_shm_stuff)
00395                 taskUnlock ();
00396 
00397               if (print_rcs_shm_warnings)
00398                 {
00399                   rcs_print_error
00400                     ("Warning: RCS Shared Memory Area table contains no entry for (%d(0x%X)), creating one.\n",
00401                      key, key);
00402                 }
00403 #endif
00404               shm->create_errno = ENOENT;
00405               return shm;
00406             }
00407           if (shm->id != key)
00408             {
00409               if (task_lock_shm_stuff)
00410                 taskUnlock ();
00411               rcs_print_error
00412                 ("Shared Memory Key retrieved from table does not match. (%d) != (%d).\n",
00413                  key, shm->id);
00414               return NULL;
00415             }
00416           if (shm->addr <= 0)
00417             {
00418               if (task_lock_shm_stuff)
00419                 taskUnlock ();
00420               return NULL;
00421             }
00422           if (shm->size < size)
00423             {
00424               if (task_lock_shm_stuff)
00425                 taskUnlock ();
00426               rcs_print_error
00427                 ("This process(%d(0x%X)) was configured to connect a shared memory area with key = (%d(0x%X)) and size=(%d(0x%X)\n",
00428                  tid, tid, key, key, size, size);
00429               rcs_print_error
00430                 (" but a shared memory area with this key and a size of only (%d(0x%X)) already exists.",
00431                  shm->size, shm->size);
00432               return NULL;
00433             }
00434           shm->count++;
00435           table_add (&rcs_shm_table, key, shm);
00436           /* got the id already-- just copy out the address */
00437         }
00438     }
00439 
00440   if (task_lock_shm_stuff)
00441     taskUnlock ();
00442 
00443   return shm;
00444 }
00445 
00446 int
00447 rcs_shm_close (shm_t * shm)
00448 {
00449   shm_t entry;
00450 
00451   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00452                    "rcs_shm_close(shm->key=%d(0x%X),shm->size=%d(0x%X),shm->addr=0x%X)\n",
00453                    shm->key, shm->key, shm->size, shm->size, shm->addr);
00454 
00455   if (task_lock_shm_stuff)
00456     taskLock ();
00457 
00458 
00459   /* decrement the reference count, and if it's zero remove the
00460      shared mem */
00461   table_get (&rcs_shm_table, shm->id, &entry);
00462   entry.count--;
00463   if (entry.count == 0 && entry.addr != NULL)
00464     {
00465       DEBUG_FREE (entry.addr);
00466       entry.addr = NULL;
00467       shm->addr = NULL;
00468       table_clear (&rcs_shm_table, shm->id);
00469     }
00470   else
00471     {
00472       /* rewrite the entry to reflect decremented ref count */
00473       table_add (&rcs_shm_table, shm->id, &entry);
00474     }
00475 
00476   if (task_lock_shm_stuff)
00477     taskUnlock ();
00478   DEBUG_FREE (shm);
00479   return 0;
00480 }
00481 
00482 int
00483 rcs_shm_delete (shm_t * shm)
00484 {
00485   shm_t entry;
00486 
00487   if (task_lock_shm_stuff)
00488     taskLock ();
00489 
00490   /* decrement the reference count, and if it's zero remove the
00491      shared mem */
00492   table_get (&rcs_shm_table, shm->id, &entry);
00493   entry.count--;
00494   if (entry.addr != NULL)
00495     {
00496       DEBUG_FREE (entry.addr);
00497       entry.addr = NULL;
00498       shm->addr = NULL;
00499       table_clear (&rcs_shm_table, shm->id);
00500     }
00501   else
00502     {
00503       /* rewrite the entry to reflect decremented ref count */
00504       table_add (&rcs_shm_table, shm->id, &entry);
00505     }
00506 
00507   if (task_lock_shm_stuff)
00508     taskUnlock ();
00509 
00510   DEBUG_FREE (shm);
00511   return 0;
00512 }
00513 
00514 int
00515 rcs_shm_nattch (shm_t * shm)
00516 {
00517   shm_t entry;
00518 
00519   if (task_lock_shm_stuff)
00520     taskLock ();
00521 
00522   table_get (&rcs_shm_table, shm->id, &entry);
00523   shm->count = entry.count;
00524   if (task_lock_shm_stuff)
00525     taskUnlock ();
00526   return shm->count;
00527 }
00528 
00529 #else
00530 
00531 /* Unix shared memory */
00532 
00533 #ifndef NO_STDIO
00534 #include <stdio.h>              /* NULL */
00535 #endif
00536 
00537 #ifdef linux_2_4
00538 #include <linux/posix_types.h>
00539 #endif
00540 
00541 #include <stdlib.h>
00542 #ifdef __CENTERLINE__
00543 #define USING_VARARGS
00544 #include <varargs.h>
00545 #else
00546 #include <stdarg.h>
00547 #endif
00548 #include <errno.h>
00549 #include <stddef.h>
00550 #include <sys/types.h>
00551 #include <unistd.h>
00552 #include <sys/ipc.h>
00553 #if defined(qnx) && !defined(USE_POSIX_SHAREDMEM)
00554 #define USE_POSIX_SHAREDMEM 1
00555 #endif
00556 #ifdef USE_POSIX_SHAREDMEM
00557 #include <fcntl.h>
00558 #include <sys/mman.h>
00559 #else
00560 #include <sys/shm.h>
00561 #endif
00562 #include <string.h>
00563 
00564 static int shmems_created_list[100];
00565 static int shmems_created_list_initialized = 0;
00566 
00567 shm_t *
00568 rcs_shm_open (key_t key, size_t size, int oflag, /* int mode */ ...)
00569 {
00570   va_list ap;
00571   int mode;
00572   int shmflg = 0;
00573   shm_t *shm;
00574 #ifdef USE_POSIX_SHAREDMEM
00575   int existed_before = 0;
00576   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00577                    "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00578                    key, key, size, size, oflag);
00579 
00580   if (key == 0)
00581     {
00582       rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00583                        key, key, size, size, oflag, oflag);
00584       rcs_print_error ("RCS Shared Memory key may not be zero.\n");
00585       return NULL;
00586     }
00587 
00588   shm = (shm_t *) DEBUG_CALLOC (sizeof (shm_t), 1);
00589   if (NULL == shm)
00590     {
00591       rcs_print_error ("rcs_shm_open: calloc failed\n");
00592       return NULL;
00593     }
00594   shm->create_errno = 0;
00595   shm->addr = NULL;
00596   shm->key = key;
00597   shm->size = size;
00598   sprintf (shm->name, "/rcs_shm%d", key);
00599   shm->id = 0;
00600   errno = 0;
00601 
00602 
00603 #if defined(IPC_CREAT)
00604 #if O_CREAT != IPC_CREAT
00605   if ((oflag & IPC_CREAT) && !(oflag & O_CREAT))
00606     {
00607       oflag &= ~(IPC_CREAT);
00608       oflag |= O_CREAT;
00609     }
00610 #endif
00611 #endif
00612 
00613   if ((oflag & O_CREAT))
00614     {
00615       shm->id = shm_open (shm->name, O_RDWR, mode);
00616       if (shm->id > 0)
00617         {
00618           shm->created = 0;
00619           existed_before = 1;
00620         }
00621     }
00622 
00623   /* Create a new memory object */
00624   if (shm->id <= 0)
00625     {
00626       shm->id = shm_open (shm->name, oflag | O_RDWR, mode);
00627       if (shm->id == -1)
00628         {
00629           rcs_print_error ("shm_open(%s,%d(0x%X),%d(0x%X)) failed:%s %d\n",
00630                            shm->name, oflag | O_RDWR, oflag | O_RDWR,
00631                            mode, mode, strerror (errno), errno);
00632           shm->create_errno = errno;
00633           return shm;
00634         }
00635       shm->created = 1;
00636       existed_before = 0;
00637     }
00638 
00639   /* Set the memory object's size */
00640   if (ftruncate (shm->id, size + 16) == -1)
00641     {
00642       rcs_print_error ("ftruncate(%d,%d): %s %d\n",
00643                        shm->id, size, strerror (errno), errno);
00644       shm->create_errno = errno;
00645       return shm;
00646     }
00647 
00648   /* Map the memory object */
00649   shm->addr = mmap (0, size + 16,
00650                     PROT_READ | PROT_WRITE, MAP_SHARED, shm->id, 0);
00651   if (shm->addr == MAP_FAILED)
00652     {
00653       rcs_print_error
00654         ("mmap(0,%d,PROT_READ | PROT_WRITE, MAP_SHARED,%d,0) failed: %s %d\n",
00655          shm->id, size, strerror (errno), errno);
00656       shm->create_errno = errno;
00657     }
00658   if (oflag & O_CREAT && !existed_before)
00659     {
00660       *((int *) ((char *) shm->addr + size)) = 0;
00661     }
00662   else
00663     {
00664       (*((int *) ((char *) shm->addr + size)))++;
00665     }
00666 
00667   return (shm);
00668 #else
00669 
00670   struct shmid_ds shared_mem_info;
00671   int pid;
00672   int i;
00673 
00674   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00675                    "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00676                    key, key, size, size, oflag);
00677 
00678   if (key == 0)
00679     {
00680       rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00681                        key, key, size, size, oflag, oflag);
00682       rcs_print_error ("RCS Shared Memory key may not be zero.\n");
00683       return NULL;
00684     }
00685 
00686 #if defined(O_CREAT)
00687 #if O_CREAT != IPC_CREAT
00688   if ((oflag & O_CREAT) && !(oflag & IPC_CREAT))
00689     {
00690       oflag &= ~(O_CREAT);
00691       oflag |= IPC_CREAT;
00692     }
00693 #endif
00694 #endif
00695 
00696   if (oflag)
00697     {
00698       shmflg |= IPC_CREAT;
00699     }
00700   if (shmflg & IPC_CREAT)
00701     {
00702 #ifdef USING_VARARGS
00703       va_start (ap);
00704 #else
00705       va_start (ap, oflag);
00706 #endif
00707       mode = va_arg (ap, int);
00708       shmflg |= mode;
00709     }
00710 
00711   shm = (shm_t *) DEBUG_CALLOC (sizeof (shm_t), 1);
00712   if (NULL == shm)
00713     {
00714       rcs_print_error ("rcs_shm_open: calloc failed\n");
00715       return NULL;
00716     }
00717   shm->create_errno = 0;
00718   shm->addr = NULL;
00719   shm->key = key;
00720   errno = 0;
00721 
00722   if ((shm->id = shmget (key, (int) size, shmflg)) == -1)
00723     {
00724       shm->create_errno = errno;
00725       rcs_print_error ("shmget(%d(0x%X),%d,%d) failed: (errno = %d): %s\n",
00726                        key, key, size, shmflg, errno, strerror (errno));
00727       switch (errno)
00728         {
00729         case EEXIST:
00730           rcs_print_error
00731             ("A shared memory buffer for this key already exists.\n");
00732           break;
00733 
00734         case EINVAL:
00735           rcs_print_error
00736             ("Either the size is too big or the shared memory buffer already exists but is of the wrong size.\n");
00737           break;
00738 
00739         case ENOSPC:
00740           rcs_print_error
00741             ("The system imposed limit on the maximum number of shared memory segments has been exceeded.\n");
00742           break;
00743         }
00744       return (shm);
00745     }
00746 
00747   /* map shmem area into local address space */
00748   shmflg = 0;
00749   shmflg &= ~SHM_RDONLY;
00750   if ((shm->addr = (void *) shmat (shm->id, 0, shmflg)) == (void *) -1)
00751     {
00752       shm->create_errno = errno;
00753       rcs_print_error ("shmat(%d,0,%d) failed:(errno = %d): %s\n", shm->id,
00754                        shmflg, errno, strerror (errno));
00755       rcs_print_error ("key = %d (0x%X)\n", key, key);
00756       shm->addr = NULL;
00757       return (shm);
00758     }
00759 
00760   /* Check to see if I am the creator of this shared memory buffer. */
00761   if (shmctl (shm->id, IPC_STAT, &shared_mem_info) < 0)
00762     {
00763       rcs_print_error ("shmctl error: %d %s\n", errno, strerror (errno));
00764       return shm;
00765     }
00766 
00767   /* If oflag was not set this process couldn't be the creator. */
00768   if (!oflag)
00769     {
00770       return shm;
00771     }
00772 
00773   if (!shmems_created_list_initialized)
00774     {
00775       memset (shmems_created_list, 0, 100 * sizeof (int));
00776       shmems_created_list_initialized = 1;
00777     }
00778   else
00779     {
00780       for (i = 0; i < 100; i++)
00781         {
00782           if (shmems_created_list[i] == key)
00783             {
00784               return shm;
00785             }
00786         }
00787     }
00788 
00789   pid = (int) getpid ();
00790   if (pid <= 0)
00791     {
00792       rcs_print_error ("getpid error: %d %s\n", errno, strerror (errno));
00793       return shm;
00794     }
00795   shm->created = (shared_mem_info.shm_cpid == pid);
00796 #if defined(darwin) || defined(linux_2_4_0)
00797   shm->created = 1;
00798 #endif
00799 
00800   if (shm->created)
00801     {
00802       for (i = 0; i < 100; i++)
00803         {
00804           if (shmems_created_list[i] <= 0)
00805             {
00806               shmems_created_list[i] = shm->key;
00807               break;
00808             }
00809         }
00810     }
00811   return shm;
00812 #endif
00813 }
00814 
00815 int
00816 rcs_shm_close (shm_t * shm)
00817 {
00818 #ifdef USE_POSIX_SHAREDMEM
00819   if (shm == 0)
00820     {
00821       return -1;
00822     }
00823   if (shm->addr > 0)
00824     {
00825       (*((int *) ((char *) shm->addr + shm->size)))--;
00826       if (munmap (shm->addr, shm->size + 16) == -1)
00827         {
00828           rcs_print_error ("munmap(%p,%d) failed. %s %d\n",
00829                            shm->addr, shm->size, strerror (errno), errno);
00830           return -1;
00831         }
00832       shm->addr = NULL;
00833       if (shm->id > 0)
00834         {
00835           if (close (shm->id) == -1)
00836             {
00837               rcs_print_error ("close(%d) failed. %s %d\n",
00838                                shm->id, strerror (errno), errno);
00839             }
00840         }
00841       shm->id = 0;
00842     }
00843 #else
00844   struct shmid_ds shm_ds;       /* dummy */
00845   int i;
00846 
00847   /* check for invalid ptr */
00848   if (shm == NULL)
00849     return -1;
00850 
00851   rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00852                    "rcs_shm_close(shm->key=%d(0x%X),shm->size=%d(0x%X),shm->addr=0x%X)\n",
00853                    shm->key, shm->key, shm->size, shm->size, shm->addr);
00854 
00855   /* detach from shmem */
00856   shmdt ((char *) shm->addr);
00857 
00858   /* remove OS shmem if there are no attached processes */
00859   if (rcs_shm_nattch (shm) == 0)
00860     {
00861       shmctl (shm->id, IPC_RMID, &shm_ds);
00862     }
00863 
00864   if (shm->created && shmems_created_list_initialized)
00865     {
00866       for (i = 0; i < 100; i++)
00867         {
00868           if (shmems_created_list[i] == shm->key)
00869             {
00870               shmems_created_list[i] = 0;
00871               break;
00872             }
00873         }
00874     }
00875 
00876 #endif
00877 
00878   /* DEBUG_FREE the shm_t data struct */
00879 #ifdef sparcworks_sun4          /* free is defined as int free(char *) for this platform
00880                                    it should be void free(void *); */
00881   DEBUG_FREE ((char *) shm);
00882 #else
00883   DEBUG_FREE (shm);
00884 #endif
00885 
00886   return 0;
00887 }
00888 
00889 int
00890 rcs_shm_delete (shm_t * shm)
00891 {
00892 #ifdef USE_POSIX_SHAREDMEM
00893   if (shm == 0)
00894     {
00895       return -1;
00896     }
00897   if (shm->addr > 0)
00898     {
00899       (*((int *) ((char *) shm->addr + shm->size)))--;
00900       if (munmap (shm->addr, shm->size + 16) == -1)
00901         {
00902           rcs_print_error ("munmap(%p,%d) failed. %s %d\n",
00903                            shm->addr, shm->size, strerror (errno), errno);
00904           return -1;
00905         }
00906       shm->addr = NULL;
00907       if (shm->id > 0)
00908         {
00909           if (close (shm->id) == -1)
00910             {
00911               rcs_print_error ("close(%d) failed. %s %d\n",
00912                                shm->id, strerror (errno), errno);
00913             }
00914         }
00915       shm->id = 0;
00916     }
00917   shm_unlink (shm->name);
00918 #else
00919   struct shmid_ds shm_ds;       /* dummy */
00920 
00921   /* check for invalid ptr */
00922   if (shm == NULL)
00923     return -1;
00924 
00925   /* detach from shmem */
00926   shmdt ((char *) shm->addr);
00927 
00928   /* remove OS shmem regardless of whether there are attached processes */
00929   shmctl (shm->id, IPC_RMID, &shm_ds);
00930 #endif
00931 
00932   /* DEBUG_FREE the shm_t data struct */
00933 #ifdef sparcworks_sun4          /* free is defined as int free(char *) for this platform
00934                                    it should be void free(void *); */
00935   DEBUG_FREE ((char *) shm);
00936 #else
00937   DEBUG_FREE (shm);
00938 #endif
00939 
00940   return 0;
00941 }
00942 
00943 int
00944 rcs_shm_nattch (shm_t * shm)
00945 {
00946 #ifdef USE_POSIX_SHAREDMEM
00947   if (shm == 0)
00948     {
00949       return -1;
00950     }
00951   if (shm->addr == 0)
00952     {
00953       return -1;
00954     }
00955   return *((int *) (((char *) shm->addr) + shm->size));
00956 #else
00957   struct shmid_ds shm_ds;
00958 
00959   /* check for invalid ptr */
00960   if (shm == NULL)
00961     return -1;
00962 
00963   /* get the status of shared memory */
00964   shmctl (shm->id, IPC_STAT, &shm_ds);
00965 
00966   return shm_ds.shm_nattch;
00967 #endif
00968 
00969 }
00970 
00971 #endif
00972 
00973 #endif

Generated on Sun Dec 2 15:56:48 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001