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

shmem.cc

Go to the documentation of this file.
00001 /*************************************************************************
00002 * File: shmem.cc                                                         *
00003 * Authors: Fred Proctor, Will Shackleford                                *
00004 * Purpose: C++ file for the Communication Management System (CMS).       *
00005 *          Includes:                                                     *
00006 *                    1. Member Functions for class SHMEM.                *
00007 * Notes: The class SHMEM should be used by procedures accessing a shared *
00008 *  memory buffer on the same processor.                                  *
00009 * The RCS_SEMAPHORE is no longer used. Instead a section of the shared   *
00010 * memory buffer itself is used to guarantee mutual exclusion.            *
00011 *************************************************************************/
00012 
00013 /* Include Files */
00014 #include "rcs_defs.hh"          /* EXTERN_C_STD_HEADERS  */
00015 
00016 #ifdef EXTERN_C_STD_HEADERS
00017 extern "C"
00018 {
00019 #endif
00020 
00021 
00022 #ifdef UNDER_CE
00023 #include <winbase.h>
00024 #endif
00025 
00026 #ifndef UNDER_CE
00027 #include <stdio.h>              /* sscanf() */
00028 #include <stddef.h>             /* size_t */
00029 #include <sys/stat.h>           /* S_IRUSR, etc. */
00030 #include <sys/types.h>          /* key_t */
00031 #include <errno.h>              // errno
00032 #endif
00033 #include <string.h>             /* strchr(), memcpy(), memset() */
00034 #include <stdlib.h>             /* strtod */
00035 
00036 #ifdef VXWORKS
00037 #include <taskLib.h>
00038 #include <intLib.h>             // intLock()
00039 #endif
00040 
00041 #ifdef lynxosPC
00042 #include <fa.h>                 // struct fa_info,  fast_enable_preemption()
00043 #include <kernel.h>             // disable(), sdisable(),restore(),srestore()
00044 #endif
00045 
00046 #ifdef EXTERN_C_STD_HEADERS
00047 }
00048 #endif
00049 
00050 #include "rcs_prnt.hh"          /* rcs_print_error() */
00051 
00052 #ifdef VXWORKS
00053 typedef int key_t;
00054 #endif
00055 
00056 #include "cms.hh"               /* class CMS */
00057 #include "shmem.hh"             /* class SHMEM */
00058 #include "shm.hh"               /* class RCS_SHAREDMEM */
00059 //#include "sem.hh"             /* class RCS_SEMAPHORE */
00060 #include "memsem.hh"            /* mem_get_access(), mem_release_access() */
00061 #include "timer.hh"             /* etime(), esleep() */
00062 
00063 #ifdef UNDER_CE
00064 #include "rcs_ce.h"
00065 #endif
00066 
00067 /* Common Definitions. */
00068 
00069 #include "autokey.h"
00070 
00071 /* rw-rw-r-- permissions */
00072 #ifndef WIN32
00073 #define MODE (0777)
00074 #else
00075 #define MODE (0)
00076 #endif
00077 
00078 #ifdef lynxosPC
00079 struct fa_info *fa_ptr = NULL;
00080 #endif
00081 
00082 static double last_non_zero_x;
00083 static double last_x;
00084 
00085 static int
00086 not_zero (volatile double x)
00087 {
00088   last_x = x;
00089   if (x < -1E-6 && last_x < -1E-6)
00090     {
00091       last_non_zero_x = x;
00092       return 1;
00093     }
00094   if (x > 1E-6 && last_x > 1E-6)
00095     {
00096       last_non_zero_x = x;
00097       return 1;
00098     }
00099   return 0;
00100 }
00101 
00102 /* SHMEM Member Functions. */
00103 
00104 /* Constructor for hard coded tests. */
00105 SHMEM::SHMEM (char *n, long s, int nt, key_t k, int m):
00106 CMS (s)
00107 {
00108   /* Set pointers to null so only properly opened pointers are closed. */
00109   shm = NULL;
00110 //  sem = NULL;
00111 
00112   /* save constructor args */
00113   master = m;
00114   key = k;
00115 
00116   /* open the shared mem buffer and create mutual exclusion semaphore */
00117   open ();
00118 }
00119 
00120 /* Constructor for use with cms_config. */
00121 SHMEM::SHMEM (char *bufline, char *procline, int set_to_server,
00122               int set_to_master):
00123 CMS (bufline, procline, set_to_server)
00124 {
00125   /* Set pointers to null so only properly opened pointers are closed. */
00126   shm = NULL;
00127   sem = NULL;
00128   sem_delay = 0.00001;
00129   char *semdelay_equation;
00130   use_os_sem = 1;
00131   use_os_sem_only = 1;
00132   mutex_type = OS_SEM_MUTEX;
00133   bsem_key = -1;
00134   second_read = 0;
00135 
00136   if (status < 0)
00137     {
00138       rcs_print_error ("SHMEM: status = %d\n", status);
00139       return;
00140     }
00141 
00142   /* Save parameters from configuration file. */
00143 #ifndef UNDER_CE
00144   if (sscanf (bufline, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %d", &key) != 1)
00145     {
00146       rcs_print_error ("SHMEM: Invalid configuration file format.\n");
00147       return;
00148     }
00149 #else
00150   char *word[32];
00151   if (separate_words (word, 10, bufline) != 10)
00152     {
00153       rcs_print_error ("CMS: Error in buffer line from config file.\n");
00154       rcs_print_error ("%s\n", bufline);
00155       status = CMS_CONFIG_ERROR;
00156       return;
00157     }
00158   key = atol (word[9]);
00159 #endif
00160 
00161   master = is_local_master;
00162   if (1 == set_to_master)
00163     {
00164       master = 1;
00165     }
00166   else if (-1 == set_to_master)
00167     {
00168       master = 0;
00169     }
00170 
00171 #ifndef UNDER_CE
00172   if (NULL != (semdelay_equation = strstr (proclineupper, "SEMDELAY=")))
00173     {
00174       sem_delay = strtod (semdelay_equation + 9, (char **) NULL);
00175     }
00176   else if (NULL != (semdelay_equation = strstr (buflineupper, "SEMDELAY=")))
00177     {
00178       sem_delay = strtod (semdelay_equation + 9, (char **) NULL);
00179     }
00180 #endif
00181 
00182   if (NULL != (semdelay_equation = strstr (buflineupper, "BSEM=")))
00183     {
00184 #ifndef UNDER_CE
00185       bsem_key = strtol (semdelay_equation + 5, (char **) NULL, 0);
00186 #else
00187       bsem_key = atol (semdelay_equation + 5);
00188 #endif
00189     }
00190 
00191   if (NULL != strstr (buflineupper, "MUTEX=NONE"))
00192     {
00193       mutex_type = NO_MUTEX;
00194       use_os_sem = 0;
00195       use_os_sem_only = 0;
00196     }
00197 
00198   if (NULL != strstr (buflineupper, "MUTEX=OS_SEM"))
00199     {
00200       mutex_type = OS_SEM_MUTEX;
00201       use_os_sem = 1;
00202       use_os_sem_only = 1;
00203     }
00204 
00205   if (NULL != strstr (buflineupper, "MUTEX=NO_INTERRUPTS"))
00206     {
00207       mutex_type = NO_INTERRUPTS_MUTEX;
00208       use_os_sem = 0;
00209       use_os_sem_only = 0;
00210     }
00211 
00212   if (NULL != strstr (buflineupper, "MUTEX=NO_SWITCHING"))
00213     {
00214       mutex_type = NO_SWITCHING_MUTEX;
00215 #ifdef lynxosPC
00216       if (fa_ptr == NULL)
00217         {
00218           fa_ptr = fast_info_attach ((char *) 0xC0000000);
00219         }
00220 #endif
00221       use_os_sem = 0;
00222       use_os_sem_only = 0;
00223     }
00224 
00225   if (NULL != strstr (buflineupper, "MUTEX=MAO"))
00226     {
00227       mutex_type = MAO_MUTEX;
00228       use_os_sem = 0;
00229       use_os_sem_only = 0;
00230     }
00231 
00232   if (NULL != strstr (buflineupper, "MAO_W_OS_SEM"))
00233     {
00234       mutex_type = MAO_MUTEX_W_OS_SEM;
00235       use_os_sem = 1;
00236       use_os_sem_only = 0;
00237     }
00238 
00239   /* Open the shared memory buffer and create mutual exclusion semaphore. */
00240   open ();
00241 }
00242 
00243 SHMEM::~SHMEM ()
00244 {
00245   /* detach from shared memory and semaphores */
00246   close ();
00247 }
00248 
00249 /*
00250   Open the SHMEM buffer
00251   */
00252 int
00253 SHMEM::open ()
00254 {
00255   /* Set pointers to NULL incase error occurs. */
00256   sem = NULL;
00257   shm = NULL;
00258   bsem = NULL;
00259   shm_addr_offset = NULL;
00260   second_read = 0;
00261   autokey_table_size = 0;
00262 
00263   if (use_autokey_for_connection_number)
00264     {
00265       autokey_table_size = sizeof (AUTOKEY_TABLE_ENTRY) * total_connections;
00266     }
00267 
00268   /* set up the shared memory address and semaphore, in given state */
00269   if (master)
00270     {
00271       shm = new RCS_SHAREDMEM (key, size, RCS_SHAREDMEM_CREATE, (int) MODE);
00272       if (shm->addr == NULL)
00273         {
00274           switch (shm->create_errno)
00275             {
00276 #ifndef UNDER_CE
00277             case EACCES:
00278               status = CMS_PERMISSIONS_ERROR;
00279               break;
00280 
00281             case EEXIST:
00282               status = CMS_RESOURCE_CONFLICT_ERROR;
00283               break;
00284 
00285             case ENOMEM:
00286             case ENOSPC:
00287               status = CMS_CREATE_ERROR;
00288               break;
00289 
00290 #endif
00291 
00292             default:
00293               status = CMS_MISC_ERROR;
00294             }
00295           delete shm;
00296           shm = NULL;
00297           return -1;
00298         }
00299       if (use_os_sem)
00300         {
00301           sem =
00302             new RCS_SEMAPHORE (key, RCS_SEMAPHORE_CREATE, timeout, (int) MODE,
00303                                (use_os_sem_only != 0));
00304           if (NULL == sem)
00305             {
00306               rcs_print_error ("CMS: couldn't create RCS_SEMAPHORE.\n");
00307               rcs_print_error (" Possibly out of memory?\n");
00308               status = CMS_CREATE_ERROR;
00309               return -1;
00310             }
00311           if (!sem->valid ())
00312             {
00313               rcs_print_error ("CMS: RCS_SEMAPHORE is invalid.\n");
00314               status = CMS_MISC_ERROR;
00315               return -1;
00316             }
00317         }
00318       if (bsem_key > 0)
00319         {
00320 #ifndef WIN32
00321           bsem = new RCS_SEMAPHORE (bsem_key, RCS_SEMAPHORE_CREATE,
00322                                     timeout, (int) MODE, 0);
00323           if (NULL == bsem)
00324             {
00325               rcs_print_error ("CMS: couldn't create RCS_SEMAPHORE.\n");
00326               rcs_print_error (" Possibly out of memory?\n");
00327               status = CMS_CREATE_ERROR;
00328               return -1;
00329             }
00330           if (!bsem->valid ())
00331             {
00332               rcs_print_error ("CMS: RCS_SEMAPHORE is invalid.\n");
00333               status = CMS_MISC_ERROR;
00334               return -1;
00335             }
00336 #else
00337           char bsem_event_name[80];
00338 #ifndef NO_STDIO
00339           sprintf (bsem_event_name, "event%d", bsem_key);
00340 #else
00341           strcpy (bsem_event_name, "event");
00342           _itoa (bsem_key, bsem_event_name + 5, 10);
00343 #endif
00344 #ifndef UNDER_CE
00345           SECURITY_ATTRIBUTES sa;
00346           SECURITY_DESCRIPTOR sd;
00347           if (FALSE ==
00348               InitializeSecurityDescriptor (&sd,
00349                                             SECURITY_DESCRIPTOR_REVISION))
00350             {
00351               rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE,
00352                                    "Can not initailize security descriptor.\n");
00353               status = CMS_MISC_ERROR;
00354               return -1;
00355             }
00356           sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00357           sa.lpSecurityDescriptor = &sd;
00358           sa.bInheritHandle = TRUE;
00359           bsem = CreateEvent (&sa, TRUE, FALSE, bsem_event_name);
00360 #else
00361 #ifdef UNICODE
00362           wchar_t wbsem_event_name[80];
00363           RCS_CE_ASCII_TO_UNICODE (wbsem_event_name, bsem_event_name, 80);
00364           bsem = CreateEvent (NULL, TRUE, FALSE, wbsem_event_name);
00365 #else
00366           bsem = CreateEvent (NULL, TRUE, FALSE, bsem_event_name);
00367 #endif
00368 #endif
00369           if (NULL == bsem)
00370             {
00371               rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE,
00372                                    "CreateEvent error:");
00373             }
00374 #endif
00375         }
00376       in_buffer_id = 0;
00377     }
00378   else
00379     {
00380       shm = new RCS_SHAREDMEM (key, size, RCS_SHAREDMEM_NOCREATE);
00381       if (NULL == shm)
00382         {
00383           rcs_print_error
00384             ("CMS: couldn't create RCS_SHAREDMEM(%d(0x%X), %d(0x%X), RCS_SHAREDMEM_NOCREATE).\n",
00385              key, key, size, size);
00386           status = CMS_CREATE_ERROR;
00387           return -1;
00388         }
00389       if (shm->addr == NULL)
00390         {
00391           switch (shm->create_errno)
00392             {
00393 #ifndef UNDER_CE
00394             case EACCES:
00395               status = CMS_PERMISSIONS_ERROR;
00396               break;
00397 
00398             case EEXIST:
00399               status = CMS_RESOURCE_CONFLICT_ERROR;
00400               break;
00401 
00402             case ENOENT:
00403               status = CMS_NO_MASTER_ERROR;
00404               break;
00405 
00406             case ENOMEM:
00407             case ENOSPC:
00408               status = CMS_CREATE_ERROR;
00409               break;
00410 
00411 #endif
00412 
00413             default:
00414               status = CMS_MISC_ERROR;
00415             }
00416           delete shm;
00417           shm = NULL;
00418           return -1;
00419         }
00420       if (use_os_sem)
00421         {
00422           sem = new RCS_SEMAPHORE (key, RCS_SEMAPHORE_NOCREATE, timeout);
00423           if (NULL == sem)
00424             {
00425               rcs_print_error ("CMS: couldn't create RCS_SEMAPHORE.\n");
00426               rcs_print_error (" Possibly out of memory?\n");
00427               status = CMS_CREATE_ERROR;
00428               return -1;
00429             }
00430           if (!sem->valid ())
00431             {
00432               rcs_print_error ("CMS: RCS_SEMAPHORE is invalid.\n");
00433               status = CMS_MISC_ERROR;
00434               return -1;
00435             }
00436         }
00437       if (bsem_key > 0)
00438         {
00439 #ifndef WIN32
00440           bsem =
00441             new RCS_SEMAPHORE (bsem_key, RCS_SEMAPHORE_NOCREATE, timeout);
00442           if (NULL == bsem)
00443             {
00444               rcs_print_error ("CMS: couldn't create RCS_SEMAPHORE.\n");
00445               rcs_print_error (" Possibly out of memory?\n");
00446               status = CMS_CREATE_ERROR;
00447               return -1;
00448             }
00449           if (!bsem->valid ())
00450             {
00451               rcs_print_error ("CMS: RCS_SEMAPHORE is invalid.\n");
00452               status = CMS_MISC_ERROR;
00453               return -1;
00454             }
00455 #else
00456           char bsem_event_name[80];
00457 #ifndef NO_STDIO
00458           sprintf (bsem_event_name, "event%d", bsem_key);
00459 #else
00460           strcpy (bsem_event_name, "event");
00461           _itoa (bsem_key, bsem_event_name + 5, 10);
00462 #endif
00463 #ifndef UNDER_CE
00464           bsem = OpenEvent (EVENT_ALL_ACCESS, TRUE, bsem_event_name);
00465 #else
00466 #ifdef UNICODE
00467           wchar_t wbsem_event_name[80];
00468           RCS_CE_ASCII_TO_UNICODE (wbsem_event_name, bsem_event_name, 80);
00469           bsem = CreateEvent (NULL, TRUE, FALSE, wbsem_event_name);
00470 #else
00471           bsem = CreateEvent (NULL, TRUE, FALSE, bsem_event_name);
00472 #endif
00473 #endif
00474           if (NULL == bsem)
00475             {
00476               rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE,
00477                                    "OpenEvent error:");
00478             }
00479 #endif
00480         }
00481     }
00482 
00483   if (min_compatible_version < 3.44 && min_compatible_version > 0)
00484     {
00485       total_subdivisions = 1;
00486     }
00487 
00488   if (min_compatible_version > 2.57 || min_compatible_version <= 0)
00489     {
00490       if (!shm->created)
00491         {
00492           char *cptr = (char *) shm->addr;
00493           cptr[31] = 0;
00494           if (strncmp (cptr, BufferName, 31))
00495             {
00496               rcs_print_error
00497                 ("Shared memory buffers %s and %s may conflict. (key=%d(0x%X))\n",
00498                  BufferName, cptr, key, key);
00499               strncpy (cptr, BufferName, 32);
00500             }
00501         }
00502       if (master)
00503         {
00504           if (use_autokey_for_connection_number)
00505             {
00506               void *autokey_table_end =
00507                 (void *) (((char *) shm->addr) + 32 + autokey_table_size);
00508               memset (autokey_table_end, 0, size - 32 - autokey_table_size);
00509             }
00510           strncpy ((char *) shm->addr, BufferName, 32);
00511         }
00512       if (use_autokey_for_connection_number)
00513         {
00514           void *autokey_table = (void *) (((char *) shm->addr) + 32);
00515           connection_number =
00516             autokey_getkey (autokey_table, total_connections, ProcessName);
00517           shm_addr_offset =
00518             (void *) ((char *) (shm->addr) + 32 + autokey_table_size);
00519           max_message_size -= (32 + autokey_table_size);        /* size of cms buffer available for user */
00520         }
00521       else
00522         {
00523           shm_addr_offset = (void *) ((char *) (shm->addr) + 32);
00524           max_message_size -= 32;       /* size of cms buffer available for user */
00525         }
00526       /* messages = size - CMS Header space */
00527       if (enc_max_size <= 0 || enc_max_size > size)
00528         {
00529           if (neutral)
00530             {
00531               max_encoded_message_size -= 32;
00532             }
00533           else
00534             {
00535               max_encoded_message_size -=
00536                 (cms_encoded_data_explosion_factor * 32);
00537             }
00538         }
00539       /* Maximum size of message after being encoded. */
00540       guaranteed_message_space -= 32;   /* Largest size message before being encoded
00541                                            that can be guaranteed to fit after xdr. */
00542       size -= 32;
00543       size_without_diagnostics -= 32;
00544       subdiv_size =
00545         (size_without_diagnostics - total_connections) / total_subdivisions;
00546       subdiv_size -= (subdiv_size % 4);
00547     }
00548   else
00549     {
00550       if (master)
00551         {
00552           memset (shm->addr, 0, size);
00553         }
00554       shm_addr_offset = shm->addr;
00555     }
00556   skip_area = 32 + total_connections + autokey_table_size;
00557   mao.data = shm_addr_offset;
00558   mao.timeout = timeout;
00559   mao.total_connections = total_connections;
00560   mao.sem_delay = sem_delay;
00561   mao.connection_number = connection_number;
00562   mao.split_buffer = split_buffer;
00563   mao.read_only = 0;
00564   mao.sem = sem;
00565 
00566   fast_mode = !queuing_enabled && !split_buffer && !neutral &&
00567     (mutex_type == NO_SWITCHING_MUTEX);
00568   handle_to_global_data = dummy_handle = new PHYSMEM_HANDLE;
00569   handle_to_global_data->set_to_ptr (shm_addr_offset, size);
00570   if ((connection_number < 0 || connection_number >= total_connections)
00571       && (mutex_type == MAO_MUTEX || mutex_type == MAO_MUTEX_W_OS_SEM))
00572     {
00573       rcs_print_error ("Bad connection number %d\n", connection_number);
00574       status = CMS_MISC_ERROR;
00575       return -1;
00576     }
00577   return 0;
00578 }
00579 
00580 /* Closes the  shared memory and mutual exclusion semaphore  descriptors. */
00581 int
00582 SHMEM::close ()
00583 {
00584   int nattch = 0;
00585   second_read = 0;
00586 
00587   if (use_autokey_for_connection_number)
00588     {
00589       void *autokey_table = (void *) (((char *) shm->addr) + 32);
00590       autokey_releasekey (autokey_table, total_connections, ProcessName,
00591                           connection_number);
00592     }
00593   if (NULL != shm)
00594     {
00595       /* see if we're the last one */
00596       nattch = shm->nattch ();
00597       shm->delete_totally = delete_totally;
00598       delete shm;
00599       shm = NULL;
00600     }
00601   if (NULL != sem)
00602     {
00603       /* if we're the last one, then make us the master so that the
00604          semaphore will go away */
00605       if (nattch <= 1 || delete_totally)
00606         {
00607           sem->setflag (RCS_SEMAPHORE_CREATE);
00608         }
00609       else
00610         {
00611           sem->setflag (RCS_SEMAPHORE_NOCREATE);
00612         }
00613       delete sem;
00614     }
00615 #ifndef WIN32
00616   if (NULL != bsem)
00617     {
00618       /* if we're the last one, then make us the master so that the
00619          semaphore will go away */
00620       if (nattch <= 1 || delete_totally)
00621         {
00622           bsem->setflag (RCS_SEMAPHORE_CREATE);
00623         }
00624       else
00625         {
00626           bsem->setflag (RCS_SEMAPHORE_NOCREATE);
00627         }
00628       delete bsem;
00629     }
00630 #endif
00631 
00632 #ifdef DEBUG
00633   printf ("SHMEM(%s): nattch = %d\n", BufferName, nattch);
00634 #endif
00635 
00636   return 0;
00637 }
00638 
00639 /* Access the shared memory buffer. */
00640 CMS_STATUS
00641 SHMEM::main_access (void *_local)
00642 {
00643 #if defined(LYNX) && !defined(lynxosPC)
00644   int interrupt_disable_number = 0;
00645   int switching_disable_number = 1;
00646 #endif
00647 
00648   /* Check pointers. */
00649   if (shm == NULL)
00650     {
00651       second_read = 0;
00652       return (status = CMS_MISC_ERROR);
00653     }
00654 
00655   if (bsem == NULL && not_zero (blocking_timeout))
00656     {
00657       rcs_print_error
00658         ("No blocking semaphore available. Can not call blocking_read(%f).\n",
00659          blocking_timeout);
00660       second_read = 0;
00661       return (status = CMS_NO_BLOCKING_SEM_ERROR);
00662     }
00663 
00664   mao.read_only = ((internal_access_type == CMS_CHECK_IF_READ_ACCESS) ||
00665                    (internal_access_type == CMS_PEEK_ACCESS) ||
00666                    (internal_access_type == CMS_READ_ACCESS));
00667 
00668 #ifdef VXWORKS
00669   int intLockKey = 0;
00670 #endif
00671 
00672   switch (mutex_type)
00673     {
00674     case NO_MUTEX:
00675       break;
00676 
00677     case MAO_MUTEX:
00678     case MAO_MUTEX_W_OS_SEM:
00679       switch (mem_get_access (&mao))
00680         {
00681         case -1:
00682           rcs_print_error ("SHMEM: Can't take semaphore\n");
00683           second_read = 0;
00684           return (status = CMS_MISC_ERROR);
00685         case -2:
00686           if (timeout > 0)
00687             {
00688               rcs_print_error ("SHMEM: Timed out waiting for semaphore.\n");
00689               rcs_print_error ("buffer = %s, timeout = %lf sec.\n",
00690                                BufferName, timeout);
00691             }
00692           second_read = 0;
00693           return (status = CMS_TIMED_OUT);
00694         default:
00695           break;
00696         }
00697       toggle_bit = mao.toggle_bit;
00698       break;
00699 
00700     case OS_SEM_MUTEX:
00701       if (sem == NULL)
00702         {
00703           second_read = 0;
00704           return (status = CMS_MISC_ERROR);
00705         }
00706       switch (sem->wait ())
00707         {
00708         case -1:
00709           rcs_print_error ("SHMEM: Can't take semaphore\n");
00710           second_read = 0;
00711           return (status = CMS_MISC_ERROR);
00712         case -2:
00713           if (timeout > 0)
00714             {
00715               rcs_print_error ("SHMEM: Timed out waiting for semaphore.\n");
00716               rcs_print_error ("buffer = %s, timeout = %lf sec.\n",
00717                                BufferName, timeout);
00718             }
00719           second_read = 0;
00720           return (status = CMS_TIMED_OUT);
00721         default:
00722           break;
00723         }
00724       break;
00725 
00726     case NO_INTERRUPTS_MUTEX:
00727 #ifdef LYNX
00728       disable (interrupt_disable_number);
00729       break;
00730 #else
00731 #ifdef VXWORKS
00732       intLockKey = intLock ();
00733       break;
00734 #else
00735       rcs_print_error ("Interrupts can not be disabled.\n");
00736       second_read = 0;
00737       return (status = CMS_MISC_ERROR);
00738       break;
00739 #endif
00740 #endif
00741 
00742     case NO_SWITCHING_MUTEX:
00743 #ifdef lynxosPC
00744       fa_ptr->preempt++;
00745       break;
00746 #else
00747 #if 0
00748 // The  LYNX documentation says this should work but the
00749 // symbol sdisable is not available.
00750       sdisable (switching_disable_number);
00751       break;
00752 #else
00753 #ifdef VXWORKS
00754       taskLock ();
00755       break;
00756 #else
00757       rcs_print_error ("Interrupts can not be disabled.\n");
00758       return (status = CMS_MISC_ERROR);
00759       break;
00760 #endif
00761 #endif
00762 #endif
00763     default:
00764       rcs_print_error ("SHMEM: Invalid mutex type.(%d)\n", mutex_type);
00765       second_read = 0;
00766       return (status = CMS_MISC_ERROR);
00767       break;
00768     }
00769 
00770   if (second_read > 0 && enable_diagnostics)
00771     {
00772       disable_diag_store = 1;
00773     }
00774 
00775   /* Perform access function. */
00776   internal_access (shm->addr, size, _local);
00777 
00778   disable_diag_store = 0;
00779 
00780   if (NULL != bsem &&
00781       (internal_access_type == CMS_WRITE_ACCESS
00782        || internal_access_type == CMS_WRITE_IF_READ_ACCESS))
00783     {
00784 #ifndef WIN32
00785       bsem->flush ();
00786 #else
00787       if (!PulseEvent (bsem))
00788         {
00789           rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE, "PulseEvent error");
00790         }
00791 #endif
00792     }
00793   switch (mutex_type)
00794     {
00795     case NO_MUTEX:
00796       break;
00797 
00798     case MAO_MUTEX:
00799     case MAO_MUTEX_W_OS_SEM:
00800       mem_release_access (&mao);
00801       break;
00802 
00803     case OS_SEM_MUTEX:
00804       sem->post ();
00805       break;
00806     case NO_INTERRUPTS_MUTEX:
00807 #ifdef LYNX
00808       restore (interrupt_disable_number);
00809       break;
00810 #else
00811 #ifdef VXWORKS
00812       intUnlock (intLockKey);
00813 #else
00814       rcs_print_error ("Can not restore interrupts.\n");
00815       break;
00816 #endif
00817 #endif
00818 
00819     case NO_SWITCHING_MUTEX:
00820 #ifdef lynxosPC
00821       if ((!(--(fa_ptr->preempt)) || fa_ptr->preempt > 0x40) && fa_ptr->flag)
00822         {
00823           fast_enable_preemption ();
00824         }
00825       break;
00826 #else
00827 #if 0
00828       // The  LYNX documentation says this should work but
00829       // the symbol srestore is not available.
00830       srestore (switching_disable_number);
00831       break;
00832 #else
00833 #ifdef VXWORKS
00834       taskUnlock ();
00835       break;
00836 #else
00837       rcs_print_error ("Can not restore interrupts.\n");
00838       break;
00839 #endif
00840 #endif
00841 #endif
00842     }
00843 
00844   switch (internal_access_type)
00845     {
00846 
00847     case CMS_READ_ACCESS:
00848       if (NULL != bsem && status == CMS_READ_OLD &&
00849           (blocking_timeout > 1e-6 || blocking_timeout < -1E-6))
00850         {
00851           if (second_read > 10 && total_subdivisions <= 1)
00852             {
00853               status = CMS_MISC_ERROR;
00854               rcs_print_error
00855                 ("CMS: Blocking semaphore error. The semaphore wait has returned %d times but there is still no new data.\n",
00856                  second_read);
00857               second_read = 0;
00858               return (status);
00859             }
00860 #ifndef WIN32
00861           second_read++;
00862           bsem->timeout = blocking_timeout;
00863 #if !defined(VXWORKS) && !defined(WIN32)
00864           sem_force_fifo = 1;
00865 #endif
00866           int bsem_ret = bsem->wait ();
00867 #if !defined(VXWORKS) && !defined(WIN32)
00868           sem_force_fifo = 0;
00869 #endif
00870           if (bsem_ret == -2)
00871             {
00872               status = CMS_TIMED_OUT;
00873               second_read = 0;
00874               return (status);
00875             }
00876           if (bsem_ret == -1)
00877             {
00878               rcs_print_error ("CMS: Blocking semaphore error.\n");
00879               status = CMS_MISC_ERROR;
00880               second_read = 0;
00881               return (status);
00882             }
00883 #else
00884           DWORD timeoutMillis = (DWORD) (blocking_timeout * 1000.0);
00885           if (blocking_timeout < 0)
00886             {
00887               timeoutMillis = INFINITE;
00888             }
00889           switch (WaitForSingleObject (bsem, timeoutMillis))
00890             {
00891             case WAIT_TIMEOUT:
00892               status = CMS_TIMED_OUT;
00893               second_read = 0;
00894               return (status);
00895 
00896             case WAIT_OBJECT_0:
00897               second_read++;
00898               break;
00899 
00900             default:
00901               rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE,
00902                                    "WaitForSingleObject error");
00903               status = CMS_MISC_ERROR;
00904               second_read = 0;
00905               return (status);
00906             }
00907 #endif
00908           main_access (_local);
00909         }
00910       break;
00911 
00912     case CMS_WRITE_ACCESS:
00913     case CMS_WRITE_IF_READ_ACCESS:
00914 #if 0
00915       if (NULL != bsem)
00916         {
00917 #ifndef WIN32
00918           bsem->flush ();
00919 #else
00920           if (!PulseEvent (bsem))
00921             {
00922               rcs_print_sys_error (GETLASTERROR_ERROR_SOURCE,
00923                                    "PulseEvent error");
00924             }
00925 #endif
00926         }
00927 #endif
00928       break;
00929 
00930     default:
00931       break;
00932 
00933     }
00934 
00935   second_read = 0;
00936   return (status);
00937 }
00938 
00939 
00940 #ifdef VXWORKS
00941 CMS_STATUS
00942 SHMEM::read ()
00943 {
00944   if (fast_mode)
00945     {
00946       handle_to_global_data->offset = total_connections;
00947       taskLock ();
00948       read_raw ();
00949       taskUnlock ();
00950       return (status);
00951     }
00952   internal_access_type = CMS_READ_ACCESS;
00953   main_access (data);
00954   return (status);
00955 }
00956 
00957 CMS_STATUS
00958 SHMEM::peek ()
00959 {
00960   if (fast_mode)
00961     {
00962       handle_to_global_data->offset = total_connections;
00963       taskLock ();
00964       peek_raw ();
00965       taskUnlock ();
00966       return (status);
00967     }
00968   internal_access_type = CMS_PEEK_ACCESS;
00969   main_access (data);
00970   return (status);
00971 }
00972 
00973 CMS_STATUS
00974 SHMEM::write (void *user_data)
00975 {
00976   if (fast_mode)
00977     {
00978       handle_to_global_data->offset = total_connections;
00979       taskLock ();
00980       write_raw (user_data);
00981       taskUnlock ();
00982       return (status);
00983     }
00984   internal_access_type = CMS_WRITE_ACCESS;
00985   main_access (user_data);
00986   return (status);
00987 }
00988 
00989 CMS_STATUS
00990 SHMEM::write_if_read (void *user_data)
00991 {
00992   if (fast_mode)
00993     {
00994       handle_to_global_data->offset = total_connections;
00995       taskLock ();
00996       write_if_read_raw (user_data);
00997       taskUnlock ();
00998       return (status);
00999     }
01000   internal_access_type = CMS_WRITE_IF_READ_ACCESS;
01001   main_access (user_data);
01002   return (status);
01003 }
01004 #endif
01005 
01006 
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014 // Taken from main_access, but this code was later replaced
01015 // by having internal_access handle this.
01016 //  6-Oct-1999
01017 
01018 #if 0
01019 
01020 char *internal_access_buffer;
01021 long internal_access_buffer_size;
01022 
01023   /* Select the section and size of the buffer to use.  */
01024 if (split_buffer)
01025   {
01026     if (internal_access_type == CMS_WRITE_IF_READ_ACCESS)
01027       {
01028         was_read_byte = *(((char *) shm_addr_offset) + total_connections + 1);
01029         header.was_read = (was_read_byte == mao.toggle_bit + 1);
01030         if (!header.was_read)
01031           {
01032             mem_release_access (&mao);
01033             second_read = 0;
01034             return (status = CMS_WRITE_WAS_BLOCKED);
01035           }
01036         internal_access_type = CMS_WRITE_ACCESS;
01037       }
01038     if (mao.read_only == mao.toggle_bit)
01039       {
01040         internal_access_buffer =
01041           ((char *) shm_addr_offset) + total_connections + 2;
01042         internal_access_buffer_size = (size / 2) - total_connections - 2;
01043       }
01044     else
01045       {
01046         internal_access_buffer = ((char *) shm_addr_offset) + (size / 2);
01047         internal_access_buffer_size = (size / 2);
01048       }
01049   }
01050 else
01051   {
01052     int cur_offset = total_connections;
01053     internal_access_buffer_size = (size) - total_connections;
01054     if (total_subdivisions > 0)
01055       {
01056         cur_offset = total_connections + current_subdivision * subdiv_size;
01057         internal_access_buffer_size = subdiv_size;
01058       }
01059     internal_access_buffer = ((char *) shm_addr_offset) + cur_offset;
01060 
01061   }
01062 
01063 internal_access (internal_access_buffer, internal_access_buffer_size, _local);
01064 
01065 if (split_buffer && internal_access_type == CMS_READ_ACCESS)
01066   {
01067     *(((char *) shm_addr_offset) + total_connections + 1) =
01068       mao.toggle_bit + 1;
01069   }
01070 #endif

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