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 <trnsz@pobox.com>
  10  * Copyright (c) 2021-2022 The DPS8M Development Team
  11  *
  12  * All rights reserved.
  13  *
  14  * This software is made available under the terms of the ICU
  15  * License, version 1.8.1 or later.  For more details, see the
  16  * LICENSE.md file at the top-level directory of this distribution.
  17  *
  18  * ---------------------------------------------------------------------------
  19  */
  20 
  21 /* Shared memory functions */
  22 
  23 #if ( defined( USE_FLOCK ) && defined( USE_FCNTL ))
  24 # ifndef USE_BFLOCK
  25 #  define USE_BFLOCK
  26 # endif /* ifndef USE_BFLOCK */
  27 #endif /* if ( defined(USE_FLOCK) && defined(USE_FCNTL) ) */
  28 
  29 #include <errno.h>
  30 #include <fcntl.h> /* For O_* constants, locks */
  31 #include <limits.h>
  32 #include <stdio.h>
  33 #include <stdlib.h>
  34 #include <string.h>
  35 #include <sys/file.h>
  36 #include <sys/mman.h>
  37 #include <sys/stat.h> /* For mode constants */
  38 #include <sys/types.h>
  39 #include <unistd.h>
  40 
  41 #include "shm.h"
  42 
  43 #ifndef TRUE
  44 # define TRUE 1
  45 #endif /* ifndef TRUE */
  46 
  47 #ifndef FALSE
  48 # define FALSE 0
  49 #endif /* ifndef FALSE */
  50 
  51 extern int sim_randstate;
  52 extern int sim_randompst;
  53 extern int sim_nostate;
  54 extern int sim_iglock;
  55 extern int sim_nolock;
  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 #ifdef USE_BFLOCK
  64   char lck[260];
  65 #endif /* ifdef USE_BFLOCK */
  66 
  67   sprintf(buf, "dps8m.%s", key);
  68 
  69 #ifdef USE_BFLOCK
  70   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       fprintf(
  76         stderr,
  77         "%s(): Failed to open \"%s\" (error %d)\r\n",
  78         __func__,
  79         lck,
  80         errno);
  81       return NULL;
  82     }
  83 
  84   if (sim_randstate && !sim_randompst)
  85     {
  86       unlink(lck);
  87     }
  88 
  89 #endif /* ifdef USE_BFLOCK */
  90 
  91   int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  92   if (fd == -1)
  93     {
  94       fprintf(
  95         stderr,
  96         "%s(): Failed to open \"%s\" (error %d)\r\n",
  97         __func__,
  98         buf,
  99         errno);
 100       return NULL;
 101     }
 102 
 103   if (sim_randstate && !sim_randompst)
 104     {
 105       unlink(buf);
 106     }
 107 
 108 #ifdef USE_BFLOCK
 109 # define SPIDLEN 128
 110 
 111 # ifndef HOST_NAME_MAX
 112 #  ifdef _POSIX_HOST_NAME_MAX
 113 #   define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
 114 #  else
 115 #   define HOST_NAME_MAX 255
 116 #  endif /* ifdef _POSIX_HOST_NAME_MAX */
 117 # endif /* ifndef HOST_NAME_MAX */
 118 
 119   struct flock bflock;
 120   memset(&bflock, 0, sizeof ( bflock ));
 121   bflock.l_type = F_WRLCK;
 122   int brc = 0;
 123   if (!sim_nolock)
 124     {
 125       brc = fcntl(lck_fd, F_SETLK, &bflock);
 126     }
 127 
 128   int fct = 0;
 129   char spid[SPIDLEN];
 130   unsigned long lkpid = 0;
 131   char sthostname[HOST_NAME_MAX + 1];
 132   char shostname[HOST_NAME_MAX * 2];
 133   /* cppcheck-suppress unreadVariable */
 134   int pch = 0;
 135   int ypch = 0;
 136   FILE *lck_fp;
 137   if (brc < 0)
 138     {
 139       fprintf(
 140         stderr,
 141         "%s(): Failed to lock \"%s\" (error %d)\r\n",
 142         __func__,
 143         lck,
 144         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       (void)close(lck_fd);
 154       lck_fp = fopen(lck, "r");
 155       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                       fprintf(stderr, " as PID ");
 166                     }
 167 
 168                   fprintf(stderr, "%c", pch);
 169                 }
 170 
 171               fct++;
 172             }
 173         }
 174 
 175       if (lkpid != 0 && ypch == 0)
 176         {
 177           fprintf(stderr, " as PID %lu", lkpid);
 178         }
 179 
 180       fprintf(stderr, "? ***\r\n\r\n");
 181       if (!sim_iglock)
 182         {
 183           return NULL;
 184         }
 185     }
 186 
 187   if (ftruncate(lck_fd, (off_t)0) == -1)
 188     {
 189       fprintf(
 190         stderr,
 191         "%s(): Failed to clear \"%s\" (error %d)\r\n",
 192         __func__,
 193         lck,
 194         errno);
 195       if (!sim_iglock)
 196         {
 197           return NULL;
 198         }
 199     }
 200 
 201 # if !defined ( __APPLE__ ) && !defined ( __HAIKU__ ) && !defined ( __serenity__ )
 202   if ( !(sim_nostate) )
 203     (void)fdatasync(lck_fd);
 204 # endif /* if !defined ( __APPLE__ ) && !defined ( __HAIKU__ ) && !defined ( __serenity__) */
 205 
 206   (void)snprintf(spid, SPIDLEN, "%ld ", (long)getpid());
 207 
 208   memset(&sthostname, 0, sizeof ( sthostname ));
 209   int hrc = gethostname(sthostname, HOST_NAME_MAX + 1);
 210   if (hrc != 0)
 211     {
 212       (void)sprintf(sthostname, "(unknown)");
 213     }
 214 
 215   (void)sprintf(shostname, "on %s\n", sthostname);
 216   if (write(lck_fd, spid, strlen(spid)) != strlen(spid))
 217     {
 218       fprintf(
 219         stderr,
 220         "%s(): Failed to save PID to \"%s\" (error %d)\r\n",
 221         __func__,
 222         lck,
 223         errno);
 224       if (!sim_iglock)
 225         {
 226           return NULL;
 227         }
 228     }
 229 
 230   if ( !(sim_nostate) )
 231     (void)fsync(lck_fd);
 232 
 233   if (write(lck_fd, shostname, strlen(shostname)) != strlen(shostname))
 234     {
 235       fprintf(
 236         stderr,
 237         "%s(): Failed to save host to \"%s\" (error %d)\r\n",
 238         __func__,
 239         lck,
 240         errno);
 241       if (!sim_iglock)
 242         {
 243           return NULL;
 244         }
 245     }
 246 
 247   if ( !(sim_nostate) )
 248     (void)fsync(lck_fd);
 249 #endif /* ifdef USE_BFLOCK */
 250 
 251 #ifdef USE_FLOCK
 252   int rc = 0;
 253   if (!sim_nolock)
 254     {
 255       rc = flock(fd, LOCK_EX | LOCK_NB);
 256     }
 257 
 258   if (rc < 0)
 259     {
 260       fprintf(
 261         stderr,
 262         "%s(): Failed to lock \"%s\" (error %d)\r\n",
 263         __func__,
 264         buf,
 265         errno);
 266       if (!sim_iglock)
 267         {
 268           return NULL;
 269         }
 270     }
 271 
 272 #elif USE_FCNTL /* ifdef USE_FLOCK */
 273   struct flock lock;
 274   memset(&lock, 0, sizeof ( lock ));
 275   lock.l_type = F_WRLCK;
 276   int rc = 0;
 277   if (!sim_nolock)
 278     {
 279       rc = fcntl(fd, F_SETLK, &lock);
 280     }
 281 
 282   if (rc < 0)
 283     {
 284       fprintf(
 285         stderr,
 286         "%s(): Failed to lock \"%s\" (error %d)\r\n",
 287         __func__,
 288         buf,
 289         errno);
 290       if (fcntl(fd, F_GETLK, &lock) == FALSE && lock.l_pid > 0)
 291         {
 292           fprintf(
 293             stderr,
 294             "\r\n*** Is another simulator running as PID %lu? ***\r\n\r\n",
 295             (unsigned long)lock.l_pid);
 296         }
 297       if (!sim_iglock)
 298         {
 299           return NULL;
 300         }
 301     }
 302 #endif /* elif USE_FCNTL */
 303 
 304   if (ftruncate(fd, (off_t)shm_size) == -1)
 305     {
 306       fprintf(
 307         stderr,
 308         "%s(): Failed to size \"%s\" (error %d)\r\n",
 309         __func__,
 310         buf,
 311         errno);
 312       return NULL;
 313     }
 314 
 315 #if !defined ( __APPLE__ ) && !defined ( __HAIKU__ ) && !defined ( __serenity__ )
 316   if ( !(sim_nostate) )
 317     (void)fdatasync(fd);
 318 #endif /* if !defined ( __APPLE__ ) && !defined ( __HAIKU__ ) && !defined ( __serenity__ ) */
 319 
 320   p = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 321   if (p == MAP_FAILED)
 322     {
 323       fprintf(
 324         stderr,
 325         "%s(): Failed to memory map \"%s\" (error %d)\r\n",
 326         __func__,
 327         buf,
 328         errno);
 329       return NULL;
 330     }
 331 
 332   if ( !(sim_nostate) )
 333     if (msync(p, shm_size, MS_SYNC) == -1)
 334       {
 335         fprintf(
 336           stderr,
 337           "%s(): Failed to synchronize \"%s\" (error %d)\r\n",
 338           __func__,
 339           buf,
 340           errno);
 341         return NULL;
 342       }
 343 
 344   return p;
 345 }
 346 
 347 #ifdef API
 348 void *
 349 open_shm(char *key, size_t shm_size)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351   void *p;
 352   char buf[256];
 353 
 354 # ifdef USE_BFLOCK
 355   char lck[260];
 356 # endif /* USE_BFLOCK */
 357 
 358   sprintf(buf, "dps8m.%s", key);
 359 
 360 # ifdef USE_BFLOCK
 361   sprintf(lck, ".%s", buf);
 362 
 363   int lck_fd = open(lck, O_RDWR, 0);
 364   if (lck_fd == -1)
 365     {
 366       fprintf(
 367         stderr,
 368         "%s(): Failed to open \"%s\" (error %d)\r\n",
 369         __func__,
 370         lck,
 371         errno);
 372       return NULL;
 373     }
 374 # endif /* ifdef USE_BFLOCK */
 375 
 376   int fd = open(buf, O_RDWR, 0);
 377   if (fd == -1)
 378     {
 379       fprintf(
 380         stderr,
 381         "%s(); Failed to open \"%s\" (error %d)\r\n",
 382         __func__,
 383         buf,
 384         errno);
 385       return NULL;
 386     }
 387 
 388 # ifdef USE_BFLOCK
 389   struct flock bflock;
 390   memset(&bflock, 0, sizeof ( bflock ));
 391   bflock.l_type = F_WRLCK;
 392   int brc = 0;
 393   if (!sim_nolock)
 394     {
 395       brc = fcntl(lck_fd, F_SETLK, &bflock);
 396     }
 397 
 398   if (brc < 0)
 399     {
 400       fprintf(
 401         stderr,
 402         "%s(): Failed to lock \"%s\": %d\r\n",
 403         __func__,
 404         lck,
 405         errno);
 406       if (!sim_iglock)
 407         {
 408           return NULL;
 409         }
 410     }
 411 # endif /* ifdef USE_BFLOCK */
 412 
 413 # ifdef USE_FLOCK
 414   int rc = 0;
 415   if (!sim_nolock)
 416     {
 417       rc = flock(fd, LOCK_EX | LOCK_NB);
 418     }
 419 
 420   if (rc < 0)
 421     {
 422       fprintf(
 423         stderr,
 424         "%s(): Failed to lock \"%s\" (error %d)\r\n",
 425         __func__,
 426         buf,
 427         errno);
 428       if(!sim_iglock) return NULL;
 429     }
 430 
 431 # elif USE_FCNTL /* ifdef USE_FLOCK */
 432   struct flock lock;
 433   memset(&lock, 0, sizeof ( lock ));
 434   lock.l_type = F_WRLCK;
 435   int rc = 0;
 436   if (!sim_nolock)
 437     {
 438       rc = fcntl(fd, F_SETLK, &lock);
 439     }
 440 
 441   if (rc < 0)
 442     {
 443       fprintf(
 444         stderr,
 445         "%s(): Failed to lock \"%s\" (error %d)\r\n",
 446         __func__,
 447         buf,
 448         errno);
 449       if (!sim_iglock)
 450         {
 451           return NULL;
 452         }
 453     }
 454 # endif          /* elif USE_FCNTL */
 455 
 456   p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 457   if (p == MAP_FAILED)
 458     {
 459 # ifdef USE_FCNTL
 460       lock.l_type = F_UNLCK;
 461       if (!sim_nolock)
 462         {
 463           (void)fcntl(fd, F_SETLK, &lock);
 464         }
 465 
 466       if ( !(sim_nostate) )
 467         (void)fsync(fd);
 468       (void)close(fd);
 469 # endif /* ifdef USE_FCNTL */
 470 
 471 # ifdef USE_BFLOCK
 472       bflock.l_type = F_UNLCK;
 473       if (!sim_nolock)
 474         {
 475           (void)fcntl(lck_fd, F_SETLK, &bflock);
 476         }
 477 
 478       if ( !(sim_nostate) )
 479         (void)fsync(lck_fd);
 480       (void)close(lck_fd);
 481 # endif /* ifdef USE_BFLOCK */
 482 
 483       fprintf(
 484         stderr,
 485         "%s(): Failed to memory map \"%s\" (error %d)\r\n",
 486         __func__,
 487         buf,
 488         errno);
 489       return NULL;
 490     }
 491 
 492   if ( !(sim_nostate) )
 493     (void)msync(p, shm_size, MS_SYNC);
 494 
 495   return p;
 496 }
 497 #endif /* ifdef API */

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