mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-03 22:20:52 -08:00
Initial revision
This commit is contained in:
parent
66b3ecce8b
commit
76998edbfa
1 changed files with 263 additions and 0 deletions
263
src/unexaix.c
Normal file
263
src/unexaix.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue