root/src/dps8/shm.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_shm
  2. open_shm

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: db14885d-f62f-11ec-9741-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2014-2016 Charles Anthony
   9  * Copyright (c) 2021 Jeffrey H. Johnson
  10  * Copyright (c) 2021-2024 The DPS8M Development Team
  11  *
  12  * This software is made available under the terms of the ICU License.
  13  * See the LICENSE.md file at the top-level directory of this distribution.
  14  *
  15  * ---------------------------------------------------------------------------
  16  */
  17 
  18 /* Shared memory functions */
  19 
  20 #include <errno.h>
  21 #include <fcntl.h> /* For O_* constants, locks */
  22 #include <limits.h>
  23 #include <stdio.h>
  24 #include <stdlib.h>
  25 #include <string.h>
  26 #include <sys/file.h>
  27 #include <sys/mman.h>
  28 #include <sys/stat.h> /* For mode constants */
  29 #include <sys/types.h>
  30 #include <unistd.h>
  31 
  32 #include "../simh/sim_defs.h"
  33 #include "shm.h"
  34 
  35 #if defined(USE_FLOCK) && defined(USE_FCNTL)
  36 # if !defined(USE_BFLOCK)
  37 #  define USE_BFLOCK
  38 # endif /* if !defined(USE_BFLOCK) */
  39 #endif /* if defined(USE_FLOCK) && defined(USE_FCNTL) */
  40 
  41 #if !defined(TRUE)
  42 # define TRUE 1
  43 #endif /* if !defined(TRUE) */
  44 
  45 #if !defined(FALSE)
  46 # define FALSE 0
  47 #endif /* if !defined(FALSE) */
  48 
  49 extern int sim_randstate;
  50 extern int sim_randompst;
  51 extern int sim_nostate;
  52 extern int sim_iglock;
  53 extern int sim_nolock;
  54 
  55 const char *xstrerror_l(int errnum);
  56 
  57 void *
  58 create_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60   void *p;
  61   char buf[256];
  62 
  63 #if defined(USE_BFLOCK)
  64   char lck[260];
  65 #endif /* if defined(USE_BFLOCK) */
  66 
  67   (void)sprintf (buf, "dps8m.%s", key);
  68 
  69 #if defined(USE_BFLOCK)
  70   (void)sprintf (lck, ".%s", buf);
  71 
  72   int lck_fd = open(lck, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  73   if (lck_fd == -1)
  74     {
  75       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
  76                     __func__, lck, xstrerror_l(errno), errno);
  77       return NULL;
  78     }
  79 
  80   if (sim_randstate && !sim_randompst)
  81     {
  82       unlink(lck);
  83     }
  84 
  85 #endif /* if defined(USE_BFLOCK) */
  86 
  87   int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  88   if (fd == -1)
  89     {
  90       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
  91                     __func__, buf, xstrerror_l(errno), errno);
  92       return NULL;
  93     }
  94 
  95   if (sim_randstate && !sim_randompst)
  96     {
  97       unlink(buf);
  98     }
  99 
 100 #if defined(USE_BFLOCK)
 101 # define SPIDLEN 128
 102 
 103 # if !defined(HOST_NAME_MAX)
 104 #  if defined(_POSIX_HOST_NAME_MAX)
 105 #   define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
 106 #  else
 107 #   define HOST_NAME_MAX 255
 108 #  endif /* if defined(_POSIX_HOST_NAME_MAX) */
 109 # endif /* if !defined(HOST_NAME_MAX) */
 110 
 111   struct flock bflock;
 112   (void)memset(&bflock, 0, sizeof ( bflock ));
 113   bflock.l_type = F_WRLCK;
 114   int brc = 0;
 115   if (!sim_nolock)
 116     {
 117       brc = fcntl(lck_fd, F_SETLK, &bflock);
 118     }
 119 
 120   int fct = 0;
 121   char spid[SPIDLEN];
 122   unsigned long lkpid = 0;
 123   char sthostname[HOST_NAME_MAX + 1];
 124   char shostname[HOST_NAME_MAX * 2];
 125   /* cppcheck-suppress unreadVariable */
 126   int pch = 0;
 127   int ypch = 0;
 128   FILE *lck_fp;
 129   if (brc < 0)
 130     {
 131       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 132                     __func__, lck, xstrerror_l(errno), errno);
 133       if (!sim_nolock)
 134         {
 135           if (fcntl(lck_fd, F_GETLK, &bflock) == 0 && bflock.l_pid > 0)
 136             {
 137               lkpid = (unsigned long)bflock.l_pid;
 138             }
 139         }
 140 
 141 # if !defined(__clang_analyzer__)
 142       (void)close(lck_fd);
 143       lck_fp = fopen(lck, "r");
 144       (void)fprintf(stderr, "\r\n*** Is another simulator running");
 145       if (lck_fp != NULL)
 146         {
 147           while (( pch = fgetc(lck_fp)) != EOF || fct < SPIDLEN)
 148             {
 149               if (!( pch < 32 || pch > 126 ))
 150                 {
 151                   ypch++;
 152                   if (ypch == 1)
 153                     {
 154                       (void)fprintf(stderr, " as PID ");
 155                     }
 156 
 157                   (void)fprintf(stderr, "%c", pch);
 158                 }
 159 
 160               fct++;
 161             }
 162         }
 163 # endif
 164 
 165       if (lkpid != 0 && ypch == 0)
 166         {
 167           (void)fprintf(stderr, " as PID %lu", lkpid);
 168         }
 169 
 170       (void)fprintf(stderr, "? ***\r\n\r\n");
 171       if (!sim_iglock)
 172         {
 173           return NULL;
 174         }
 175     }
 176 
 177   if (ftruncate(lck_fd, (off_t)0) == -1)
 178     {
 179       (void)fprintf(stderr, "%s(): Failed to clear \"%s\": %s (Error %d)\r\n",
 180                     __func__, lck, xstrerror_l(errno), errno);
 181       if (!sim_iglock)
 182         {
 183           return NULL;
 184         }
 185     }
 186 
 187   (void)snprintf(spid, SPIDLEN, "%ld ", (long)getpid());
 188 
 189   (void)memset(&sthostname, 0, sizeof ( sthostname ));
 190   int hrc = gethostname(sthostname, HOST_NAME_MAX + 1);
 191   if (hrc != 0)
 192     {
 193       (void)sprintf (sthostname, "(unknown)");
 194     }
 195 
 196   (void)sprintf (shostname, "on %s\n", sthostname);
 197   if (write(lck_fd, spid, strlen(spid)) != strlen(spid))
 198     {
 199       (void)fprintf(stderr, "%s(): Failed to save PID to \"%s\": %s (Error %d)\r\n",
 200                     __func__, lck, xstrerror_l(errno), errno);
 201       if (!sim_iglock)
 202         {
 203           return NULL;
 204         }
 205     }
 206 
 207   if ( !(sim_nostate) )
 208     (void)fsync(lck_fd);
 209 
 210   if (write(lck_fd, shostname, strlen(shostname)) != strlen(shostname))
 211     {
 212       (void)fprintf(stderr, "%s(): Failed to save host to \"%s\": %s (Error %d)\r\n",
 213                     __func__, lck, xstrerror_l(errno), errno);
 214       if (!sim_iglock)
 215         {
 216           return NULL;
 217         }
 218     }
 219 
 220   if ( !(sim_nostate) )
 221     (void)fsync(lck_fd);
 222 #endif /* if defined(USE_BFLOCK) */
 223 
 224 #if defined(USE_FLOCK)
 225   int rc = 0;
 226   if (!sim_nolock)
 227     {
 228       rc = flock(fd, LOCK_EX | LOCK_NB);
 229     }
 230 
 231   if (rc < 0)
 232     {
 233       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 234                     __func__, buf, xstrerror_l(errno), errno);
 235       if (!sim_iglock)
 236         {
 237           return NULL;
 238         }
 239     }
 240 
 241 #elif USE_FCNTL /* if defined(USE_FLOCK) */
 242   struct flock lock;
 243   (void)memset(&lock, 0, sizeof ( lock ));
 244   lock.l_type = F_WRLCK;
 245   int rc = 0;
 246   if (!sim_nolock)
 247     {
 248       rc = fcntl(fd, F_SETLK, &lock);
 249     }
 250 
 251   if (rc < 0)
 252     {
 253       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 254                     __func__, buf, xstrerror_l(errno), errno);
 255       if (fcntl(fd, F_GETLK, &lock) == FALSE && lock.l_pid > 0)
 256         {
 257           (void)fprintf(stderr,
 258                         "\r\n*** Is another simulator running as PID %lu? ***\r\n\r\n",
 259                         (unsigned long)lock.l_pid);
 260         }
 261       if (!sim_iglock)
 262         {
 263           return NULL;
 264         }
 265     }
 266 #endif /* elif USE_FCNTL */
 267 
 268   if (ftruncate(fd, (off_t)shm_size) == -1)
 269     {
 270       (void)fprintf(stderr, "%s(): Failed to initialize \"%s\": %s (Error %d)\r\n",
 271                     __func__, buf, xstrerror_l(errno), errno);
 272       return NULL;
 273     }
 274 
 275   p = mmap(NULL, shm_size, PROT_READ | PROT_WRITE,
 276 #if defined(MAP_NOSYNC)
 277            MAP_NOSYNC |
 278 #endif
 279            MAP_SHARED, fd, 0);
 280   if (p == MAP_FAILED)
 281     {
 282       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 283                     __func__, buf, xstrerror_l(errno), errno);
 284       return NULL;
 285     }
 286 
 287   return p;
 288 }
 289 
 290 #if defined(API)
 291 void *
 292 open_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294   void *p;
 295   char buf[256];
 296 
 297 # if defined(USE_BFLOCK)
 298   char lck[260];
 299 # endif /* if defined(USE_BFLOCK) */
 300 
 301   (void)sprintf (buf, "dps8m.%s", key);
 302 
 303 # if defined(USE_BFLOCK)
 304   (void)sprintf (lck, ".%s", buf);
 305 
 306   int lck_fd = open(lck, O_RDWR, 0);
 307   if (lck_fd == -1)
 308     {
 309       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
 310                     __func__, lck, xstrerror_l(errno), errno);
 311       return NULL;
 312     }
 313 # endif /* if defined(USE_BFLOCK) */
 314 
 315   int fd = open(buf, O_RDWR, 0);
 316   if (fd == -1)
 317     {
 318       (void)fprintf(stderr, "%s(); Failed to open \"%s\": %s (Error %d)\r\n",
 319                     __func__, buf, xstrerror_l(errno), errno);
 320       return NULL;
 321     }
 322 
 323 # if defined(USE_BFLOCK)
 324   struct flock bflock;
 325   (void)memset(&bflock, 0, sizeof ( bflock ));
 326   bflock.l_type = F_WRLCK;
 327   int brc = 0;
 328   if (!sim_nolock)
 329     {
 330       brc = fcntl(lck_fd, F_SETLK, &bflock);
 331     }
 332 
 333   if (brc < 0)
 334     {
 335       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 336                     __func__, lck, xstrerror_l(errno), errno);
 337       if (!sim_iglock)
 338         {
 339           return NULL;
 340         }
 341     }
 342 # endif /* if defined(USE_BFLOCK) */
 343 
 344 # if defined(USE_FLOCK)
 345   int rc = 0;
 346   if (!sim_nolock)
 347     {
 348       rc = flock(fd, LOCK_EX | LOCK_NB);
 349     }
 350 
 351   if (rc < 0)
 352     {
 353       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 354                     __func__, buf, xstrerror_l(errno), errno);
 355       if(!sim_iglock) return NULL;
 356     }
 357 
 358 # elif defined(USE_FCNTL)
 359   struct flock lock;
 360   (void)memset(&lock, 0, sizeof ( lock ));
 361   lock.l_type = F_WRLCK;
 362   int rc = 0;
 363   if (!sim_nolock)
 364     {
 365       rc = fcntl(fd, F_SETLK, &lock);
 366     }
 367 
 368   if (rc < 0)
 369     {
 370       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 371                     __func__, buf, xstrerror_l(errno), errno);
 372       if (!sim_iglock)
 373         {
 374           return NULL;
 375         }
 376     }
 377 # endif
 378 
 379   p = mmap(NULL, size, PROT_READ | PROT_WRITE,
 380 # if defined(MAP_NOSYNC)
 381            MAP_NOSYNC |
 382 # endif
 383            MAP_SHARED, fd, 0);
 384   if (p == MAP_FAILED)
 385     {
 386 # if defined(USE_FCNTL)
 387       lock.l_type = F_UNLCK;
 388       if (!sim_nolock)
 389         {
 390           (void)fcntl(fd, F_SETLK, &lock);
 391         }
 392 
 393       if ( !(sim_nostate) )
 394         (void)fsync(fd);
 395       (void)close(fd);
 396 # endif /* if defined(USE_FCNTL) */
 397 
 398 # if defined(USE_BFLOCK)
 399       bflock.l_type = F_UNLCK;
 400       if (!sim_nolock)
 401         {
 402           (void)fcntl(lck_fd, F_SETLK, &bflock);
 403         }
 404 
 405       if ( !(sim_nostate) )
 406         (void)fsync(lck_fd);
 407       (void)close(lck_fd);
 408 # endif /* if defined(USE_BFLOCK) */
 409 
 410       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 411                     __func__, buf, xstrerror_l(errno), errno);
 412       return NULL;
 413     }
 414 
 415   return p;
 416 }
 417 #endif /* if defined(API) */

/* [previous][next][first][last][top][bottom][index][help] */