]> git.eshelyaron.com Git - emacs.git/commitdiff
Initial revision
authorJim Blandy <jimb@redhat.com>
Tue, 23 Oct 1990 19:15:41 +0000 (19:15 +0000)
committerJim Blandy <jimb@redhat.com>
Tue, 23 Oct 1990 19:15:41 +0000 (19:15 +0000)
src/unexaix.c [new file with mode: 0644]

diff --git a/src/unexaix.c b/src/unexaix.c
new file mode 100644 (file)
index 0000000..2957f96
--- /dev/null
@@ -0,0 +1,263 @@
+/* Dumping and loading data areas, for Emacs under AIX.
+   (It may also work on other kinds of system V.)
+   Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This is based on a public domain program written by IBM.  */
+
+/*************** SYSTEM DEFINES *********************************/
+
+#include "config.h"
+#include "paths.h"
+#include <sys/types.h>
+#include <sys/files.h>
+#include <fcntl.h>
+#include <sys/mode.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <malloc.h>
+#include <stdio.h>                             /* MWW */
+#include "lisp.h"
+
+/*************** LOCAL DEFINES **********************************/
+
+struct data_header             /* saved data header            */
+{
+  char *start;                 /* dump _data addr              */
+  char *end;                   /* dump _end addr               */
+  char *sbrk1;                 /* dump original sbrk addr      */
+  char *sbrk2;                 /* dump final sbrk addr */
+  int puresize;                        /* size of pure data dumped  */
+};
+
+#define EMACSSHMKEY "EMACSSHMKEY"
+#define EMACS_DATA_FILE "EMACS-DATA"
+#define NEW_SHMGET_FLAGS (IPC_CREAT | S_IWUSR | S_IRUSR \
+      | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH)
+#define OLD_SHMAT_FLAGS SHM_RDONLY
+#define OLD_SHMGET_FLAGS (S_IRUSR | S_IRGRP | S_IROTH) 
+#define OLD_OPEN_FLAGS O_RDONLY
+#define NEW_OPEN_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
+
+/*************** EXTERNAL / GLOBAL DATA AREA ********************/
+
+extern char _data;             /* start of data addr           */
+extern char _end;              /* end of all data + 1 addr     */
+static char *original_sbrk;    /* sbrk when dump first run     */
+
+void
+map_in_data (use_dumped_data)
+     int use_dumped_data;
+{
+  int bufsize;                 /* malloc buffer size           */
+  struct data_header dh;       /* saved data header            */
+  int fd;                      /* saved data file descriptor   */
+  char *finaladdr;             /* last addr in bucket          */
+  char *ipckey = getenv (EMACSSHMKEY); /* env ipc key string   */
+  int length;                  /* dumped data lengths          */
+  char *newaddr;               /* new malloc buffer addr       */
+  int numblks;                 /* number of remaining mallocs  */
+  int shmid;                   /* shared memory id             */
+  key_t shmkey;                        /* shared memory key            */
+  /* Note that using malloc here may not be safe.  */
+  char name[sizeof (PATH_EXEC) + sizeof (EMACS_DATA_FILE) + 2];
+
+  /* Consume remaining malloc space without increasing         */
+  /* the end of data space                                     */
+  original_sbrk = sbrk (0);
+  for (bufsize = 16; bufsize < getpagesize (); bufsize *= 2)
+    {
+      while ((newaddr = (char *)malloc (bufsize - 8)) < original_sbrk)
+       ;
+      for (numblks = (getpagesize () / bufsize) - 1; numblks > 0; numblks--)
+       malloc (bufsize - 8);
+      finaladdr = sbrk (0);
+    }
+  original_sbrk = sbrk (0);
+
+  /* If we don't want the dumped data, get an unshared segment.  */
+  if (!use_dumped_data)
+    {
+      shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
+      if (shmid == -1
+         || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+       {
+         fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
+         exit (1);
+       }
+      return;
+    }
+
+  /* Compute the file name with the dumped data.  */
+  strcpy (name, PATH_EXEC);
+  strcat (name, "/");
+  strcat (name, EMACS_DATA_FILE);
+
+  /* Open the file and make sure the addresses have not changed.  */
+  fd = open (name, OLD_OPEN_FLAGS, 0);
+  if (fd < 0)
+    {
+      fprintf (stderr, "emacs: failure opening `%s'\n", name);
+      exit (1);
+    }
+  if (read (fd, (char *)&dh, sizeof (dh)) != sizeof (dh)
+      || dh.start != &_data
+      || dh.end != &_end
+      || dh.sbrk1 != original_sbrk
+      || dh.puresize != PURESIZE)
+    {
+      fprintf (stderr, "emacs: header mismatch in `%s'\n", name);
+      exit (1);
+    }
+
+  /* Load in the unshared contents.  */
+  if (!(length = dh.end - dh.start)
+      || read (fd, (char *)&_data, length) != length
+      || !(length = dh.sbrk2 - dh.sbrk1)
+      || brk (dh.sbrk2) == -1
+      || read (fd, dh.sbrk1, length) != length)
+    {
+      fprintf (stderr, "emacs: failure loading unshared data.\n");
+      exit (1);
+    }
+
+  /* Determine ipc key from environment or default             */
+  if (ipckey && *ipckey)
+    shmkey = atoi (ipckey);
+  else
+    shmkey = SHMKEY;
+
+  /* Attach to "pure data" shared memory segment               */
+  if ((shmid = shmget (shmkey, 0, 0)) == -1
+      || (newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS)) == -1)
+    {
+      /* We were unable to open an existing segment.  Make a new one.  */
+      struct shmid_ds buf;
+
+      /* First get rid of the one we tried to get.  */
+      shmdt ((char *)PURE_SEG_BITS);
+      shmctl (shmid, IPC_RMID, 0);
+
+      /* If we could not write the data file,
+        don't make a shared segment that we could write.
+        Make an unshared segment instead.  */
+      if (access (name, W_OK) == 0)
+       {
+         shmid = shmget (IPC_PRIVATE, PURESIZE, NEW_SHMGET_FLAGS);
+         if (shmid == -1
+             || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+           {
+             fprintf (stderr, "emacs: failure obtaining new unshared memory segment.\n");
+             exit (1);
+           }
+
+         /* Load the proper data into it.  */
+         if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
+           {
+             fprintf (stderr, "emacs: failure loading shared memory data.\n");
+             shmdt ((char *)PURE_SEG_BITS);
+             shmctl (shmid, IPC_RMID, 0);
+             exit (1);
+           }
+
+         close (fd);
+         return;
+       }
+
+      /* Allocate the new shared segment and arrange to write it.  */
+      if ((shmid = shmget (shmkey, PURESIZE, NEW_SHMGET_FLAGS)) == -1
+         || shmat (shmid, (char *)PURE_SEG_BITS, 0) == -1)
+       {
+         fprintf (stderr, "emacs: failure obtaining new shared memory segment.\n");
+         shmdt ((char *)PURE_SEG_BITS);
+         shmctl (shmid, IPC_RMID, 0);
+         exit (1);
+       }
+
+      /* Load the proper data into it.  */
+      if (read (fd, PURE_SEG_BITS, PURESIZE) != PURESIZE)
+       {
+         fprintf (stderr, "emacs: failure loading shared memory data.\n");
+         shmdt ((char *)PURE_SEG_BITS);
+         shmctl (shmid, IPC_RMID, 0);
+         exit (1);
+       }
+
+      /* Detach from the segment and bring it back readonly.  */
+      shmdt ((char *)PURE_SEG_BITS);
+
+      shmctl (shmid, IPC_STAT, &buf);
+      buf.shm_perm.mode = OLD_SHMGET_FLAGS;
+      shmctl (shmid, IPC_SET, &buf);
+
+      newaddr = shmat (shmid, (char *)PURE_SEG_BITS, OLD_SHMAT_FLAGS);
+      if (newaddr == -1)
+       {
+         fprintf (stderr, "emacs: failure reattaching shared memory segment.\n");
+         shmctl (shmid, IPC_RMID, 0);
+         exit (1);
+       }
+    }
+
+  close (fd);
+}
+
+/* Dump the appropriate parts of memory into a file named NEW
+   from which the shared segment can be initialized.  */
+
+void
+map_out_data (new)
+     char *new;
+{
+  struct data_header dh;       /* saved data header                    */
+  int fd;                      /* saved data file descriptor           */
+  int length;                  /* dumped data length; */
+
+                                  
+  /* Create "saved data" file header */
+  dh.start = &_data;
+  dh.end = &_end;
+  dh.sbrk1 = original_sbrk;
+  dh.sbrk2 = sbrk (0);
+  dh.puresize = PURESIZE;
+
+  /* Create new "saved data" dump file                         */
+  unlink (new);
+  fd = open (new, NEW_OPEN_FLAGS, 0666);
+  if (fd < 0)
+    report_file_error ("Opening dump file", Fcons (build_string (new), Qnil));
+
+  /* Write saved header and data                               */
+  length = sizeof (dh);
+  if (write (fd, (char *)&dh, length) != length)
+    report_file_error ("Writing dump file header",
+                      Fcons (build_string (new), Qnil));
+  length = dh.end - dh.start;
+  if (write (fd, dh.start, length) != length)
+    report_file_error ("Writing low core in dump file",
+                      Fcons (build_string (new), Qnil));
+  length = dh.sbrk2 - dh.sbrk1;
+  if (write (fd, dh.sbrk1, length) != length)
+    report_file_error ("Writing heap in dump file",
+                      Fcons (build_string (new), Qnil));
+  length = PURESIZE;
+  if (write (fd, PURE_SEG_BITS, length) != length)
+    report_file_error ("Writing pure data in dump file",
+                      Fcons (build_string (new), Qnil));
+  close (fd);
+}