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       (void)close(lck_fd);
 142       lck_fp = fopen(lck, "r");
 143       (void)fprintf(stderr, "\r\n*** Is another simulator running");
 144       if (lck_fp != NULL)
 145         {
 146           while (( pch = fgetc(lck_fp)) != EOF || fct < SPIDLEN)
 147             {
 148               if (!( pch < 32 || pch > 126 ))
 149                 {
 150                   ypch++;
 151                   if (ypch == 1)
 152                     {
 153                       (void)fprintf(stderr, " as PID ");
 154                     }
 155 
 156                   (void)fprintf(stderr, "%c", pch);
 157                 }
 158 
 159               fct++;
 160             }
 161         }
 162 
 163       if (lkpid != 0 && ypch == 0)
 164         {
 165           (void)fprintf(stderr, " as PID %lu", lkpid);
 166         }
 167 
 168       (void)fprintf(stderr, "? ***\r\n\r\n");
 169       if (!sim_iglock)
 170         {
 171           return NULL;
 172         }
 173     }
 174 
 175   if (ftruncate(lck_fd, (off_t)0) == -1)
 176     {
 177       (void)fprintf(stderr, "%s(): Failed to clear \"%s\": %s (Error %d)\r\n",
 178                     __func__, lck, xstrerror_l(errno), errno);
 179       if (!sim_iglock)
 180         {
 181           return NULL;
 182         }
 183     }
 184 
 185   (void)snprintf(spid, SPIDLEN, "%ld ", (long)getpid());
 186 
 187   (void)memset(&sthostname, 0, sizeof ( sthostname ));
 188   int hrc = gethostname(sthostname, HOST_NAME_MAX + 1);
 189   if (hrc != 0)
 190     {
 191       (void)sprintf (sthostname, "(unknown)");
 192     }
 193 
 194   (void)sprintf (shostname, "on %s\n", sthostname);
 195   if (write(lck_fd, spid, strlen(spid)) != strlen(spid))
 196     {
 197       (void)fprintf(stderr, "%s(): Failed to save PID to \"%s\": %s (Error %d)\r\n",
 198                     __func__, lck, xstrerror_l(errno), errno);
 199       if (!sim_iglock)
 200         {
 201           return NULL;
 202         }
 203     }
 204 
 205   if ( !(sim_nostate) )
 206     (void)fsync(lck_fd);
 207 
 208   if (write(lck_fd, shostname, strlen(shostname)) != strlen(shostname))
 209     {
 210       (void)fprintf(stderr, "%s(): Failed to save host to \"%s\": %s (Error %d)\r\n",
 211                     __func__, lck, xstrerror_l(errno), errno);
 212       if (!sim_iglock)
 213         {
 214           return NULL;
 215         }
 216     }
 217 
 218   if ( !(sim_nostate) )
 219     (void)fsync(lck_fd);
 220 #endif /* if defined(USE_BFLOCK) */
 221 
 222 #if defined(USE_FLOCK)
 223   int rc = 0;
 224   if (!sim_nolock)
 225     {
 226       rc = flock(fd, LOCK_EX | LOCK_NB);
 227     }
 228 
 229   if (rc < 0)
 230     {
 231       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 232                     __func__, buf, xstrerror_l(errno), errno);
 233       if (!sim_iglock)
 234         {
 235           return NULL;
 236         }
 237     }
 238 
 239 #elif USE_FCNTL /* if defined(USE_FLOCK) */
 240   struct flock lock;
 241   (void)memset(&lock, 0, sizeof ( lock ));
 242   lock.l_type = F_WRLCK;
 243   int rc = 0;
 244   if (!sim_nolock)
 245     {
 246       rc = fcntl(fd, F_SETLK, &lock);
 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 (fcntl(fd, F_GETLK, &lock) == FALSE && lock.l_pid > 0)
 254         {
 255           (void)fprintf(stderr,
 256                         "\r\n*** Is another simulator running as PID %lu? ***\r\n\r\n",
 257                         (unsigned long)lock.l_pid);
 258         }
 259       if (!sim_iglock)
 260         {
 261           return NULL;
 262         }
 263     }
 264 #endif /* elif USE_FCNTL */
 265 
 266 #if !defined(__OpenBSD__) && !(defined(__APPLE__) && defined(__MACH__))
 267   if (posix_fallocate(fd, 0, (off_t)shm_size) != 0)
 268     {
 269 #endif
 270       if (ftruncate(fd, (off_t)shm_size) == -1)
 271         {
 272           (void)fprintf(stderr, "%s(): Failed to initialize \"%s\": %s (Error %d)\r\n",
 273                         __func__, buf, xstrerror_l(errno), errno);
 274           return NULL;
 275         }
 276 #if !defined(__OpenBSD__) && !(defined(__APPLE__) && defined(__MACH__))
 277     }
 278 #endif
 279 
 280   p = mmap(NULL, shm_size, PROT_READ | PROT_WRITE,
 281 #if defined(MAP_NOSYNC)
 282            MAP_NOSYNC |
 283 #endif
 284            MAP_SHARED, fd, 0);
 285   if (p == MAP_FAILED)
 286     {
 287       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 288                     __func__, buf, xstrerror_l(errno), errno);
 289       return NULL;
 290     }
 291 
 292   return p;
 293 }
 294 
 295 #if defined(API)
 296 void *
 297 open_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299   void *p;
 300   char buf[256];
 301 
 302 # if defined(USE_BFLOCK)
 303   char lck[260];
 304 # endif /* if defined(USE_BFLOCK) */
 305 
 306   (void)sprintf (buf, "dps8m.%s", key);
 307 
 308 # if defined(USE_BFLOCK)
 309   (void)sprintf (lck, ".%s", buf);
 310 
 311   int lck_fd = open(lck, O_RDWR, 0);
 312   if (lck_fd == -1)
 313     {
 314       (void)fprintf(stderr, "%s(): Failed to open \"%s\": %s (Error %d)\r\n",
 315                     __func__, lck, xstrerror_l(errno), errno);
 316       return NULL;
 317     }
 318 # endif /* if defined(USE_BFLOCK) */
 319 
 320   int fd = open(buf, O_RDWR, 0);
 321   if (fd == -1)
 322     {
 323       (void)fprintf(stderr, "%s(); Failed to open \"%s\": %s (Error %d)\r\n",
 324                     __func__, buf, xstrerror_l(errno), errno);
 325       return NULL;
 326     }
 327 
 328 # if defined(USE_BFLOCK)
 329   struct flock bflock;
 330   (void)memset(&bflock, 0, sizeof ( bflock ));
 331   bflock.l_type = F_WRLCK;
 332   int brc = 0;
 333   if (!sim_nolock)
 334     {
 335       brc = fcntl(lck_fd, F_SETLK, &bflock);
 336     }
 337 
 338   if (brc < 0)
 339     {
 340       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 341                     __func__, lck, xstrerror_l(errno), errno);
 342       if (!sim_iglock)
 343         {
 344           return NULL;
 345         }
 346     }
 347 # endif /* if defined(USE_BFLOCK) */
 348 
 349 # if defined(USE_FLOCK)
 350   int rc = 0;
 351   if (!sim_nolock)
 352     {
 353       rc = flock(fd, LOCK_EX | LOCK_NB);
 354     }
 355 
 356   if (rc < 0)
 357     {
 358       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 359                     __func__, buf, xstrerror_l(errno), errno);
 360       if(!sim_iglock) return NULL;
 361     }
 362 
 363 # elif defined(USE_FCNTL)
 364   struct flock lock;
 365   (void)memset(&lock, 0, sizeof ( lock ));
 366   lock.l_type = F_WRLCK;
 367   int rc = 0;
 368   if (!sim_nolock)
 369     {
 370       rc = fcntl(fd, F_SETLK, &lock);
 371     }
 372 
 373   if (rc < 0)
 374     {
 375       (void)fprintf(stderr, "%s(): Failed to lock \"%s\": %s (Error %d)\r\n",
 376                     __func__, buf, xstrerror_l(errno), errno);
 377       if (!sim_iglock)
 378         {
 379           return NULL;
 380         }
 381     }
 382 # endif
 383 
 384   p = mmap(NULL, size, PROT_READ | PROT_WRITE,
 385 # if defined(MAP_NOSYNC)
 386            MAP_NOSYNC |
 387 # endif
 388            MAP_SHARED, fd, 0);
 389   if (p == MAP_FAILED)
 390     {
 391 # if defined(USE_FCNTL)
 392       lock.l_type = F_UNLCK;
 393       if (!sim_nolock)
 394         {
 395           (void)fcntl(fd, F_SETLK, &lock);
 396         }
 397 
 398       if ( !(sim_nostate) )
 399         (void)fsync(fd);
 400       (void)close(fd);
 401 # endif /* if defined(USE_FCNTL) */
 402 
 403 # if defined(USE_BFLOCK)
 404       bflock.l_type = F_UNLCK;
 405       if (!sim_nolock)
 406         {
 407           (void)fcntl(lck_fd, F_SETLK, &bflock);
 408         }
 409 
 410       if ( !(sim_nostate) )
 411         (void)fsync(lck_fd);
 412       (void)close(lck_fd);
 413 # endif /* if defined(USE_BFLOCK) */
 414 
 415       (void)fprintf(stderr, "%s(): Failed to memory map \"%s\": %s (Error %d)\r\n",
 416                     __func__, buf, xstrerror_l(errno), errno);
 417       return NULL;
 418     }
 419 
 420   return p;
 421 }
 422 #endif /* if defined(API) */

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