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

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