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

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