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-2025 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 /* Don't use libsir functions in this file! */
  36 
  37 #if defined(NO_LOCALE)
  38 # define xstrerror_l strerror
  39 #endif
  40 
  41 #if defined(USE_FLOCK) && defined(USE_FCNTL)
  42 # if !defined(USE_BFLOCK)
  43 #  define USE_BFLOCK
  44 # endif /* if !defined(USE_BFLOCK) */
  45 #endif /* if defined(USE_FLOCK) && defined(USE_FCNTL) */
  46 
  47 #if !defined(TRUE)
  48 # define TRUE 1
  49 #endif /* if !defined(TRUE) */
  50 
  51 #if !defined(FALSE)
  52 # define FALSE 0
  53 #endif /* if !defined(FALSE) */
  54 
  55 extern int sim_randstate;
  56 extern int sim_randompst;
  57 extern int sim_nostate;
  58 extern int sim_iglock;
  59 extern int sim_nolock;
  60 
  61 #if !defined(NO_LOCALE)
  62 const char *xstrerror_l(int errnum);
  63 #endif
  64 
  65 void *
  66 create_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68   void *p;
  69   char buf[256];
  70 
  71 #if defined(USE_BFLOCK)
  72   char lck[260];
  73 #endif /* if defined(USE_BFLOCK) */
  74 
  75   (void)sprintf (buf, "dps8m.%s", key);
  76 
  77 #if defined(USE_BFLOCK)
  78   (void)sprintf (lck, ".%s", buf);
  79 
  80   int lck_fd = open(lck, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  81   if (lck_fd == -1)
  82     {
  83       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
  84                     __func__, lck, xstrerror_l(errno), errno);
  85       return NULL;
  86     }
  87 
  88   if (sim_randstate && !sim_randompst)
  89     {
  90       unlink(lck);
  91     }
  92 
  93 #endif /* if defined(USE_BFLOCK) */
  94 
  95   int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  96   if (fd == -1)
  97     {
  98       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
  99                     __func__, buf, xstrerror_l(errno), errno);
 100 #if defined(USE_BFLOCK)
 101       (void)close(lck_fd);
 102 #endif /* if defined(USE_BFLOCK) */
 103       return NULL;
 104     }
 105 
 106   if (sim_randstate && !sim_randompst)
 107     {
 108       unlink(buf);
 109     }
 110 
 111 #if defined(USE_BFLOCK)
 112 # define SPIDLEN 128
 113 
 114 # if !defined(HOST_NAME_MAX)
 115 #  if defined(_POSIX_HOST_NAME_MAX)
 116 #   define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
 117 #  else
 118 #   define HOST_NAME_MAX 255
 119 #  endif /* if defined(_POSIX_HOST_NAME_MAX) */
 120 # endif /* if !defined(HOST_NAME_MAX) */
 121 
 122   struct flock bflock;
 123   (void)memset(&bflock, 0, sizeof ( bflock ));
 124   bflock.l_type = F_WRLCK;
 125   int brc = 0;
 126   if (!sim_nolock)
 127     {
 128       brc = fcntl(lck_fd, F_SETLK, &bflock);
 129     }
 130 
 131   int fct = 0;
 132   char spid[SPIDLEN];
 133   unsigned long lkpid = 0;
 134   char sthostname[HOST_NAME_MAX + 1];
 135   char shostname[HOST_NAME_MAX * 2];
 136   /* cppcheck-suppress unreadVariable */
 137   int pch = 0;
 138   int ypch = 0;
 139   int lck_ftr = 0;
 140   FILE *lck_fp;
 141   if (brc < 0)
 142     {
 143       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 144                     __func__, lck, xstrerror_l(errno), errno);
 145       if (!sim_nolock)
 146         {
 147           if (fcntl(lck_fd, F_GETLK, &bflock) == 0 && bflock.l_pid > 0)
 148             {
 149               lkpid = (unsigned long)bflock.l_pid;
 150             }
 151         }
 152 
 153 # if !defined(__clang_analyzer__)
 154       (void)close(lck_fd);
 155       lck_ftr = 1;
 156       lck_fp = fopen(lck, "r");
 157       (void)fprintf(stderr, "\r\n*** Is another simulator running");
 158       if (lck_fp != NULL)
 159         {
 160           while (( pch = fgetc(lck_fp)) != EOF || fct < SPIDLEN)
 161             {
 162               if (!( pch < 32 || pch > 126 ))
 163                 {
 164                   ypch++;
 165                   if (ypch == 1)
 166                     {
 167                       (void)fprintf(stderr, " as PID ");
 168                     }
 169 
 170                   (void)fprintf(stderr, "%c", pch);
 171                 }
 172 
 173               fct++;
 174             }
 175           (void)fclose(lck_fp);
 176         }
 177 # endif
 178 
 179       if (lkpid != 0 && ypch == 0)
 180         {
 181           (void)fprintf(stderr, " as PID %lu", lkpid);
 182         }
 183 
 184       (void)fprintf(stderr, "? ***\r\n\r\n");
 185       if (!sim_iglock)
 186         {
 187           (void)close(fd);
 188           return NULL;
 189         }
 190     }
 191 
 192   if (!lck_ftr && (ftruncate(lck_fd, (off_t)0) == -1))
 193     {
 194       (void)fprintf(stderr, "%s(): Failed to clear \"%s\": %s (Error %d)\r\n",
 195                     __func__, lck, xstrerror_l(errno), errno);
 196       if (!sim_iglock)
 197         {
 198           return NULL;
 199         }
 200     }
 201 
 202   (void)snprintf(spid, SPIDLEN, "%ld ", (long)getpid());
 203 
 204   (void)memset(&sthostname, 0, sizeof ( sthostname ));
 205   int hrc = gethostname(sthostname, HOST_NAME_MAX + 1);
 206   if (hrc != 0)
 207     {
 208       (void)sprintf (sthostname, "(unknown)");
 209     }
 210 
 211   (void)sprintf (shostname, "on %s\n", sthostname); //-NLOK
 212   if (!lck_ftr && (write(lck_fd, spid, strlen(spid)) != strlen(spid)))
 213     {
 214       (void)fprintf(stderr, "%s(): Failed to save PID to \"%s\": %s (Error %d)\r\n",
 215                     __func__, lck, xstrerror_l(errno), errno);
 216       if (!sim_iglock)
 217         {
 218           (void)close(fd);
 219           (void)close(lck_fd);
 220           return NULL;
 221         }
 222     }
 223 
 224   if (!lck_ftr && !(sim_nostate))
 225     (void)fsync(lck_fd);
 226 
 227   if (!lck_ftr && (write(lck_fd, shostname, strlen(shostname)) != strlen(shostname)))
 228     {
 229       (void)fprintf(stderr, "%s(): Failed to save host to \"%s\": %s (Error %d)\r\n",
 230                     __func__, lck, xstrerror_l(errno), errno);
 231       if (!sim_iglock)
 232         {
 233           (void)close(fd);
 234           return NULL;
 235         }
 236     }
 237 
 238   if (!lck_ftr && !(sim_nostate))
 239     (void)fsync(lck_fd);
 240 #endif /* if defined(USE_BFLOCK) */
 241 
 242 #if defined(USE_FLOCK)
 243   int rc = 0;
 244   if (!sim_nolock)
 245     {
 246       rc = flock(fd, LOCK_EX | LOCK_NB);
 247     }
 248 
 249   if (rc < 0)
 250     {
 251       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 252                     __func__, buf, xstrerror_l(errno), errno);
 253       if (!sim_iglock)
 254         {
 255           return NULL;
 256         }
 257     }
 258 
 259 #elif USE_FCNTL /* if defined(USE_FLOCK) */
 260   struct flock lock;
 261   (void)memset(&lock, 0, sizeof ( lock ));
 262   lock.l_type = F_WRLCK;
 263   int rc = 0;
 264   if (!sim_nolock)
 265     {
 266       rc = fcntl(fd, F_SETLK, &lock);
 267     }
 268 
 269   if (rc < 0)
 270     {
 271       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 272                     __func__, buf, xstrerror_l(errno), errno);
 273       if (fcntl(fd, F_GETLK, &lock) == FALSE && lock.l_pid > 0)
 274         {
 275           (void)fprintf(stderr,
 276                         "\r\n*** Is another simulator running as PID %lu? ***\r\n\r\n",
 277                         (unsigned long)lock.l_pid);
 278         }
 279       if (!sim_iglock)
 280         {
 281           return NULL;
 282         }
 283     }
 284 #endif /* elif USE_FCNTL */
 285 
 286   if (ftruncate(fd, (off_t)shm_size) == -1)
 287     {
 288       (void)fprintf(stderr, "%s(): Failed to initialize \"%s\": %s (Error %d)\r\n",
 289                     __func__, buf, xstrerror_l(errno), errno);
 290       return NULL;
 291     }
 292 
 293   p = mmap(NULL, shm_size, PROT_READ | PROT_WRITE,
 294 #if defined(MAP_POPULATE)
 295           MAP_POPULATE |
 296 #elif defined(MAP_PREFAULT_READ)
 297           MAP_PREFAULT_READ |
 298 #endif
 299 #if defined(MAP_NOSYNC)
 300            MAP_NOSYNC |
 301 #endif
 302            MAP_SHARED, fd, 0);
 303   if (p == MAP_FAILED)
 304     {
 305       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 306                     __func__, buf, xstrerror_l(errno), errno);
 307       return NULL;
 308     }
 309 
 310   return p;
 311 }
 312 
 313 #if defined(API)
 314 void *
 315 open_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
 316 {
 317   void *p;
 318   char buf[256];
 319 
 320 # if defined(USE_BFLOCK)
 321   char lck[260];
 322 # endif /* if defined(USE_BFLOCK) */
 323 
 324   (void)sprintf (buf, "dps8m.%s", key);
 325 
 326 # if defined(USE_BFLOCK)
 327   (void)sprintf (lck, ".%s", buf);
 328 
 329   int lck_fd = open(lck, O_RDWR, 0);
 330   if (lck_fd == -1)
 331     {
 332       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
 333                     __func__, lck, xstrerror_l(errno), errno);
 334       return NULL;
 335     }
 336 # endif /* if defined(USE_BFLOCK) */
 337 
 338   int fd = open(buf, O_RDWR, 0);
 339   if (fd == -1)
 340     {
 341       (void)fprintf(stderr, "%s(); Failed to open \"%s\": %s (Error %d)\r\n",
 342                     __func__, buf, xstrerror_l(errno), errno);
 343       return NULL;
 344     }
 345 
 346 # if defined(USE_BFLOCK)
 347   struct flock bflock;
 348   (void)memset(&bflock, 0, sizeof ( bflock ));
 349   bflock.l_type = F_WRLCK;
 350   int brc = 0;
 351   if (!sim_nolock)
 352     {
 353       brc = fcntl(lck_fd, F_SETLK, &bflock);
 354     }
 355 
 356   if (brc < 0)
 357     {
 358       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 359                     __func__, lck, xstrerror_l(errno), errno);
 360       if (!sim_iglock)
 361         {
 362           return NULL;
 363         }
 364     }
 365 # endif /* if defined(USE_BFLOCK) */
 366 
 367 # if defined(USE_FLOCK)
 368   int rc = 0;
 369   if (!sim_nolock)
 370     {
 371       rc = flock(fd, LOCK_EX | LOCK_NB);
 372     }
 373 
 374   if (rc < 0)
 375     {
 376       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 377                     __func__, buf, xstrerror_l(errno), errno);
 378       if(!sim_iglock) return NULL;
 379     }
 380 
 381 # elif defined(USE_FCNTL)
 382   struct flock lock;
 383   (void)memset(&lock, 0, sizeof ( lock ));
 384   lock.l_type = F_WRLCK;
 385   int rc = 0;
 386   if (!sim_nolock)
 387     {
 388       rc = fcntl(fd, F_SETLK, &lock);
 389     }
 390 
 391   if (rc < 0)
 392     {
 393       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 394                     __func__, buf, xstrerror_l(errno), errno);
 395       if (!sim_iglock)
 396         {
 397           return NULL;
 398         }
 399     }
 400 # endif
 401 
 402   p = mmap(NULL, size, PROT_READ | PROT_WRITE,
 403 # if defined(MAP_POPULATE)
 404           MAP_POPULATE |
 405 # elif defined(MAP_PREFAULT_READ)
 406           MAP_PREFAULT_READ |
 407 # endif
 408 # if defined(MAP_NOSYNC)
 409            MAP_NOSYNC |
 410 # endif
 411            MAP_SHARED, fd, 0);
 412   if (p == MAP_FAILED)
 413     {
 414 # if defined(USE_FCNTL)
 415       lock.l_type = F_UNLCK;
 416       if (!sim_nolock)
 417         {
 418           (void)fcntl(fd, F_SETLK, &lock);
 419         }
 420 
 421       if ( !(sim_nostate) )
 422         (void)fsync(fd);
 423       (void)close(fd);
 424 # endif /* if defined(USE_FCNTL) */
 425 
 426 # if defined(USE_BFLOCK)
 427       bflock.l_type = F_UNLCK;
 428       if (!sim_nolock)
 429         {
 430           (void)fcntl(lck_fd, F_SETLK, &bflock);
 431         }
 432 
 433       if ( !(sim_nostate) )
 434         (void)fsync(lck_fd);
 435       (void)close(lck_fd);
 436 # endif /* if defined(USE_BFLOCK) */
 437 
 438       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 439                     __func__, buf, xstrerror_l(errno), errno);
 440       return NULL;
 441     }
 442 
 443   return p;
 444 }
 445 #endif /* if defined(API) */

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