summaryrefslogtreecommitdiff
path: root/mpeix
diff options
context:
space:
mode:
authorKen Hirsch <kenhirsch@ftml.net>2006-01-12 08:26:16 -0500
committerH.Merijn Brand <h.m.brand@xs4all.nl>2006-01-12 19:52:01 +0000
commitf382e41b709944009ae4d545ba1b94e4ddc6a66e (patch)
tree9c07b2e33d89bbf664dc11b20215e0d1ce3cfc5d /mpeix
parenta11019f8bfc1b4438fdb32560361d443c701e293 (diff)
downloadperl-f382e41b709944009ae4d545ba1b94e4ddc6a66e.tar.gz
Re: Today's compiling adventure
Message-ID: <43C69F48.7090600@ftml.net> p4raw-id: //depot/perl@26807
Diffstat (limited to 'mpeix')
-rw-r--r--mpeix/mpeix.c502
-rw-r--r--mpeix/mpeix_setjmp.c355
-rw-r--r--mpeix/mpeixish.h40
3 files changed, 793 insertions, 104 deletions
diff --git a/mpeix/mpeix.c b/mpeix/mpeix.c
index 4898fd7625..a758c23be9 100644
--- a/mpeix/mpeix.c
+++ b/mpeix/mpeix.c
@@ -194,10 +194,19 @@ void __perl_mpe_move_fast(int len, // %r26 == byte length
*
*/
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#ifndef _SOCKET_SOURCE
+# define _SOCKET_SOURCE
+#endif
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <limits.h>
#include <mpe.h>
extern void FCONTROL(short, short, longpointer);
@@ -205,23 +214,28 @@ extern void PRINTFILEINFO(int);
int ftruncate(int fd, long wantsize);
-int ftruncate(int fd, long wantsize) {
-
-int ccode_return,dummy=0;
-
-if (lseek(fd, wantsize, SEEK_SET) < 0) {
- return (-1);
-}
+int
+ftruncate(int fd, long wantsize)
+{
+ int ccode_return,dummy=0;
-FCONTROL(_mpe_fileno(fd),6,__perl_mpe_longaddr(&dummy)); /* Write new EOF */
-if ((ccode_return=ccode()) != CCE) {
- fprintf(stderr,"MPE ftruncate failed, ccode=%d, wantsize=%ld\n",ccode_return,wantsize);
- PRINTFILEINFO(_mpe_fileno(fd));
- errno = ESYSERR;
- return (-1);
-}
+ if (lseek(fd, wantsize, SEEK_SET) < 0)
+ {
+ return (-1);
+ }
-return (0);
+ FCONTROL(_mpe_fileno(fd),6,__perl_mpe_longaddr(&dummy)); /* Write new EOF */
+ if ((ccode_return=ccode()) != CCE)
+ {
+ fprintf(stderr,
+ "MPE ftruncate failed, ccode=%d, wantsize=%ld\n",
+ ccode_return, wantsize);
+ PRINTFILEINFO(_mpe_fileno(fd));
+ errno = ESYSERR;
+ return (-1);
+ }
+
+ return (0);
}
/*
@@ -268,74 +282,71 @@ return (0);
PRINT_ERROR - make this function print an error message to stderr
*/
-#ifndef _POSIX_SOURCE
-# define _POSIX_SOURCE
-#endif
-#include <sys/types.h> /* off_t, required by open() */
-#include <sys/stat.h> /* required by open() */
-#include <fcntl.h> /* open() */
-#include <unistd.h> /* close() */
-#include <stdio.h> /* perror(), sprintf() */
+#include <sys/types.h> /* off_t, required by open() */
+#include <sys/stat.h> /* required by open() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* close() */
+#include <stdio.h> /* perror(), sprintf() */
int
truncate(const char *pathname, off_t length)
{
- int fd;
+ int fd;
#ifdef PRINT_ERROR
- char error_msg[80+1];
+ char error_msg[80+1];
#endif
- if (length == 0)
- {
- if ( (fd = open(pathname, O_WRONLY | O_TRUNC)) < 0)
- {
- /* errno already set */
+ if (length == 0)
+ {
+ if ( (fd = open(pathname, O_WRONLY | O_TRUNC)) < 0)
+ {
+ /* errno already set */
#ifdef PRINT_ERROR
- sprintf(error_msg,
- "truncate(): open(%s, O_WRONLY | OTRUNC)\0",
- pathname);
- perror(error_msg);
+ sprintf(error_msg,
+ "truncate(): open(%s, O_WRONLY | OTRUNC)\0",
+ pathname);
+ perror(error_msg);
#endif
- return -1;
- }
- }
- else
- {
- if ( (fd = open(pathname, O_WRONLY)) < 0)
- {
- /* errno already set */
+ return -1;
+ }
+ }
+ else
+ {
+ if ( (fd = open(pathname, O_WRONLY)) < 0)
+ {
+ /* errno already set */
#ifdef PRINT_ERROR
- sprintf(error_msg,
- "truncate(): open(%s, O_WRONLY)\0",
- pathname);
- perror(error_msg);
+ sprintf(error_msg,
+ "truncate(): open(%s, O_WRONLY)\0",
+ pathname);
+ perror(error_msg);
#endif
- return -1;
- }
+ return -1;
+ }
- if (ftruncate(fd, length) < 0)
- {
- /* errno already set */
+ if (ftruncate(fd, length) < 0)
+ {
+ /* errno already set */
#ifdef PRINT_ERROR
- perror("truncate(): ftruncate()");
+ perror("truncate(): ftruncate()");
#endif
- return -1;
- }
- }
+ return -1;
+ }
+ }
- if (close(fd) < 0)
- {
- /* errno already set */
+ if (close(fd) < 0)
+ {
+ /* errno already set */
#ifdef PRINT_ERROR
- perror("truncate(): close()");
+ perror("truncate(): close()");
#endif
- return -1;
- }
+ return -1;
+ }
- return 0;
+ return 0;
} /* truncate() */
/*
@@ -378,9 +389,8 @@ truncate(const char *pathname, off_t length)
# define _SOCKET_SOURCE
#endif
-#include <time.h> /* structs timeval & timezone,
- difftime(), localtime(), mktime(), time() */
-#include <sys/time.h> /* gettimeofday() */
+#include <time.h> /* structs timeval & timezone,
+ difftime(), localtime(), mktime(), time() */
extern int TIMER();
@@ -455,15 +465,15 @@ struct timezone *tpz;
/*
** MPE_FCNTL -- shadow function for fcntl()
**
-** MPE requires sfcntl() for sockets, and fcntl() for everything
-** else. This shadow routine determines the descriptor type and
-** makes the appropriate call.
+** MPE requires sfcntl() for sockets, and fcntl() for everything
+** else. This shadow routine determines the descriptor type and
+** makes the appropriate call.
**
-** Parameters:
-** same as fcntl().
+** Parameters:
+** same as fcntl().
**
-** Returns:
-** same as fcntl().
+** Returns:
+** same as fcntl().
*/
#include <stdarg.h>
@@ -472,35 +482,321 @@ struct timezone *tpz;
int
mpe_fcntl(int fildes, int cmd, ...)
{
- int len, result;
- struct sockaddr sa;
-
- void *arg;
- va_list ap;
-
- va_start(ap, cmd);
- arg = va_arg(ap, void *);
- va_end(ap);
-
- len = sizeof sa;
- if (getsockname(fildes, &sa, &len) == -1)
- {
- if (errno == EAFNOSUPPORT)
- /* AF_UNIX socket */
- return sfcntl(fildes, cmd, arg);
-
- if (errno == ENOTSOCK)
- /* file or pipe */
- return fcntl(fildes, cmd, arg);
-
- /* unknown getsockname() failure */
- return (-1);
- }
- else
- {
- /* AF_INET socket */
- if ((result = sfcntl(fildes, cmd, arg)) != -1 && cmd == F_GETFL)
- result |= O_RDWR; /* fill in some missing flags */
- return result;
- }
+ int len, result;
+ struct sockaddr sa;
+
+ void *arg;
+ va_list ap;
+
+ va_start(ap, cmd);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ len = sizeof sa;
+ if (getsockname(fildes, &sa, &len) == -1)
+ {
+ if (errno == EAFNOSUPPORT)
+ /* AF_UNIX socket */
+ return sfcntl(fildes, cmd, arg);
+
+ if (errno == ENOTSOCK)
+ /* file or pipe */
+ return fcntl(fildes, cmd, arg);
+
+ /* unknown getsockname() failure */
+ return (-1);
+ }
+ else
+ {
+ /* AF_INET socket */
+ if ((result = sfcntl(fildes, cmd, arg)) != -1 && cmd == F_GETFL)
+ result |= O_RDWR; /* fill in some missing flags */
+ return result;
+ }
+}
+
+
+
+/*
+ * Stuff from here on down is written by Ken Hirsch
+ * and you may use it for any purpose.
+ * No warranty, express or implied.
+ */
+
+#include <stddef.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+
+#ifndef _SOCKLEN_T
+typedef unsigned int socklen_t;
+#define _SOCKLEN_T
+#endif
+
+static int max_io_size(int filedes);
+
+ssize_t
+mpe_read(int filedes, void *buffer, size_t len)
+{
+ int maxio;
+ if (len > 4096 && (len > (maxio = max_io_size(filedes))))
+ len = maxio;
+
+ return read(filedes, buffer, len);
+}
+
+ssize_t
+mpe_write(int filedes, const void *buffer, size_t len)
+{
+ int written = 0;
+ int orig_len = len;
+ int maxio = (len>4096)?max_io_size(filedes):INT_MAX;
+ const char *buf = (const char *)buffer;
+
+ do {
+ written = write(filedes, buf, len>maxio?maxio:len);
+ if (written < 0)
+ break;
+ len -= written;
+ buf += written;
+ } while (len > 0);
+
+ if (written < 0 && len == orig_len)
+ return -1;
+ else
+ return orig_len - len;
+}
+
+
+ssize_t
+mpe_send(int socket, const void *buffer, size_t len, int flags)
+{
+ int written = 0;
+ int orig_len = len;
+ int maxio = (len>4096)?max_io_size(socket):INT_MAX;
+ const char *buf = (const char *)buffer;
+
+ do {
+ written = send(socket, buf, len>maxio?maxio:len, flags);
+ if (written < 0)
+ break;
+ len -= written;
+ buf += written;
+ } while (len > 0);
+
+ if (written < 0 && len == orig_len)
+ return -1;
+ else
+ return orig_len - len;
+}
+
+ssize_t
+mpe_sendto(int socket, const void *buffer, size_t len,
+ int flags, const struct sockaddr *dest_addr,
+ socklen_t dest_len)
+{
+ int written = 0;
+ int orig_len = len;
+ int maxio = (len>4096)?max_io_size(socket):INT_MAX;
+ const char *buf = (const char *)buffer;
+
+ do {
+ written =
+ sendto(socket, buf, len>maxio?maxio:len, flags, dest_addr, dest_len);
+ if (written < 0)
+ break;
+ len -= written;
+ buf += written;
+ } while (len > 0);
+
+ if (written < 0 && len == orig_len)
+ return -1;
+ else
+ return orig_len - len;
+}
+
+
+ssize_t
+mpe_recv(int socket, void *buffer, size_t len, int flags)
+{
+ int maxio;
+ if (len > 4096 && (len > (maxio = max_io_size(socket))))
+ len = maxio;
+ return recv(socket, buffer, len, flags);
+}
+
+ssize_t
+mpe_recvfrom(int socket, void *buffer, size_t len,
+ int flags, struct sockaddr *address,
+ socklen_t *address_len)
+{
+ int maxio;
+ if (len > 4096 && (len > (maxio = max_io_size(socket))))
+ len = maxio;
+ return recvfrom(socket, buffer, len, flags, address, address_len);
+}
+
+/*
+ I didn't do thse two:
+ssize_t mpe_recvmsg(int, struct msghdr *, int);
+ssize_t mpe_sendmsg(int, const struct msghdr *, int);
+*/
+
+/*
+ * On MPE/iX (at least version 6.0), a getsockname()
+ * performed on a socket that is listening
+ * will return INADDR_ANY, even if you used
+ * bind to bind it to a particular IP address.
+ *
+ * (In fact, it appears that the socket always acts as
+ * if you used INADDR_ANY.)
+ *
+ * Here I save the IP address used in bind
+ * So I can get it in getsockname()
+ *
+ */
+
+/* I just save 40. Usually one or two should be enough
+ */
+
+int
+mpe_connect(int socket,
+ const struct sockaddr *address,
+ socklen_t address_len)
+{
+ int ret = connect(socket, address, address_len);
+ if (ret < 0 && errno == EINPROGRESS)
+ {
+ /* Need to call getsockopt to clear socket error */
+ int socket_error;
+ socklen_t err_size = sizeof(socket_error);
+ (void)getsockopt(socket, SOL_SOCKET, SO_ERROR,
+ &socket_error, &err_size);
+ errno = EINPROGRESS;
+ }
+ return ret;
+}
+
+static struct {
+ int fd;
+ struct in_addr holdaddr;
+} holdbind[40];
+#define HOLDBINDLAST ((sizeof(holdbind))/(sizeof(holdbind[0])))
+static int nextbind;
+
+/*
+ * Fix peculiarities of bind() on MPE
+ * 1. call GETPRIVMODE to bind to ports < 1024
+ * 2. save IP address for future calls to getsockname
+ * 3. set IP address to 0 (INADDR_ANY)
+ */
+
+int
+mpe_bind(int socket, const struct sockaddr *address, socklen_t address_len)
+{
+ int i;
+ int result;
+ int mpeprivmode=0;
+ extern void GETPRIVMODE(void);
+ extern void GETUSERMODE(void);
+
+ for (i = 0; i<HOLDBINDLAST; i++) {
+ if (holdbind[i].fd == socket)
+ break;
+ }
+ /* If we didn't find previously used slot, use next */
+ if (i == HOLDBINDLAST)
+ i = nextbind;
+
+ holdbind[i].fd = socket;
+
+ memset(&holdbind[i].holdaddr, '\0', sizeof(holdbind[i].holdaddr));
+ if (address->sa_family == AF_INET
+ && address_len >= offsetof(struct sockaddr_in, sin_addr)
+ +sizeof(struct in_addr)) {
+ holdbind[i].holdaddr = ((struct sockaddr_in *)address)->sin_addr;
+ }
+ if (i == nextbind)
+ {
+ if (++nextbind >= HOLDBINDLAST)
+ nextbind = 0;
+ }
+
+ if (address->sa_family == AF_INET)
+ {
+ /* The address *MUST* stupidly be zero. */
+ ((struct sockaddr_in *)address)->sin_addr.s_addr = INADDR_ANY;
+ /* PRIV mode is required to bind() to ports < 1024. */
+ if (((struct sockaddr_in *)address)->sin_port < 1024 &&
+ ((struct sockaddr_in *)address)->sin_port > 0) {
+ GETPRIVMODE(); /* If this fails, we are aborted by MPE/iX. */
+ mpeprivmode = 1;
+ }
+ }
+ result = bind(socket, address, address_len);
+ if (mpeprivmode)
+ {
+ GETUSERMODE();
+ }
+ return result;
+
+}
+
+int
+mpe_getsockname(int socket, struct sockaddr *address, socklen_t *address_len)
+{
+ int ret;
+ ret = getsockname(socket, address, address_len);
+ if (ret == 0
+ && address->sa_family == AF_INET
+ && *address_len >= offsetof(struct sockaddr_in, sin_addr)
+ +sizeof(struct in_addr)
+ && ((struct sockaddr_in *)address)->sin_addr.s_addr == INADDR_ANY) {
+ int i;
+ for (i=0; i<HOLDBINDLAST; i++) {
+ if (holdbind[i].fd == socket)
+ {
+ ((struct sockaddr_in *)address)->sin_addr.s_addr
+ = holdbind[i].holdaddr.s_addr;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+int
+mpe_getpeername(int socket, struct sockaddr *address, socklen_t *address_len)
+{
+ int ret;
+ ret = getpeername(socket, address, address_len);
+ if (ret == 0)
+ {
+ /* Try a zero-length write to see if socket really connected */
+ int written = write(socket, "", 0);
+ if (written < 0)
+ ret = -1;
+ }
+ return ret;
+}
+
+
+static int
+max_io_size(int filedes)
+{
+ int save_errno;
+ struct sockaddr sa;
+ int len;
+ int result = INT_MAX; /* all other files */
+
+ save_errno = errno;
+ len = sizeof sa;
+ if (getsockname(filedes, &sa, &len) == -1)
+ {
+ if (errno == EAFNOSUPPORT) /* AF_UNIX socket */
+ result = 4096;
+ errno = save_errno;
+ } else {
+ result = 30000; /* AF_INET sock max */
+ }
+ return result;
}
diff --git a/mpeix/mpeix_setjmp.c b/mpeix/mpeix_setjmp.c
new file mode 100644
index 0000000000..955fe03d15
--- /dev/null
+++ b/mpeix/mpeix_setjmp.c
@@ -0,0 +1,355 @@
+/* Workaround for CR JAGab60546 setjmp/longjmp and
+ JAGad55982 sigsetjmp/siglongjmp from shared libraries. */
+
+/*
+ * tabstop=4
+ *
+ * _setjmp/setjmp/sigsetjmp and
+ *_longjmp/longjmp/siglongjmp.
+ *
+ * Written by Mark Klein, 10 October, 2000
+ * Updated for gcc 3.x 6 October, 2005
+ *
+ * These routines are GCC specific and MUST BE COMPILED
+ * WITH -O2
+ *
+ * The existing setjmp/longjmp code in both libc.a and XL.PUB.SYS
+ * are not SR4 aware and cause problems when working with shared
+ * libraries (XLs), especially when executing a longjmp between
+ * XLs. This code preserves SR4 and will successfully handle
+ * a cross space longjmp. However, the setjmp code must be
+ * bound into each XL from which it will be called as well as
+ * being bound into the main program.
+ */
+
+/*
+ * The following macro takes the contents of the jmpbuf and
+ * restores the registers from them. There is other code
+ * elsewhere that ensures that __jmpbuf is %r26 at this
+ * point in time. If it becomes some other register, that
+ * register must be the last restored. At the end will
+ * be a branch external that will cause a cross space
+ * return if needed.
+ */
+#define RESTORE_REGS_AND_RETURN(__jmpbuf, __retval) \
+({ \
+ __asm__ __volatile__ ( \
+ " ldw 0(%%sr0, %0), %%rp\n" \
+ "\t ldw 4(%%sr0, %0), %%sp\n" \
+ "\t ldw 16(%%sr0, %0), %%r3\n" \
+ "\t ldw 20(%%sr0, %0), %%r4\n" \
+ "\t ldw 24(%%sr0, %0), %%r5\n" \
+ "\t ldw 28(%%sr0, %0), %%r6\n" \
+ "\t ldw 32(%%sr0, %0), %%r7\n" \
+ "\t ldw 36(%%sr0, %0), %%r8\n" \
+ "\t ldw 40(%%sr0, %0), %%r9\n" \
+ "\t ldw 44(%%sr0, %0), %%r10\n" \
+ "\t ldw 48(%%sr0, %0), %%r11\n" \
+ "\t ldw 52(%%sr0, %0), %%r12\n" \
+ "\t ldw 56(%%sr0, %0), %%r13\n" \
+ "\t ldw 60(%%sr0, %0), %%r14\n" \
+ "\t ldw 64(%%sr0, %0), %%r15\n" \
+ "\t ldw 68(%%sr0, %0), %%r16\n" \
+ "\t ldw 72(%%sr0, %0), %%r17\n" \
+ "\t ldw 76(%%sr0, %0), %%r18\n" \
+ "\t ldw 80(%%sr0, %0), %%r19\n" \
+ "\t ldw 84(%%sr0, %0), %%r20\n" \
+ "\t ldw 88(%%sr0, %0), %%r21\n" \
+ "\t ldw 92(%%sr0, %0), %%r22\n" \
+ "\t ldw 96(%%sr0, %0), %%r23\n" \
+ "\t ldw 100(%%sr0, %0), %%r24\n" \
+ "\t ldw 104(%%sr0, %0), %%r25\n" \
+ "\t ldw 112(%%sr0, %0), %%r27\n" \
+ "\t ldw 116(%%sr0, %0), %%r1\n" \
+ "\t mtsp %%r1, %%sr3\n" \
+ "\t ldw 120(%%sr0, %0), %%r1\n" \
+ "\t mtsp %%r1, %%sr1\n" \
+ "\t or,<> %%r0, %1, %%r0\n" \
+ "\t ldi 1, %%r28\n" \
+ "\t ldw 108(%%sr0, %0), %%r26\n" \
+ "\t be 0(%%sr1, %%rp)\n" \
+ "\t mtsp %%r1, %%sr4\n" \
+ : \
+ : "r" (__jmpbuf), \
+ "r" (__retval)); \
+})
+
+/*
+ * The following macro extracts the signal mask
+ * from __jmpbuf from the 3rd and 4th words and
+ * if non-zero, calls sigprocmask with that value
+ * to set the signal mask. This macro is usually
+ * invoked before the registers are restored in
+ * the longjmp routines and it can clobber things
+ * without needing to spill them as a result.
+ * A quick frame is built before making the
+ * call and cut back just afterwards.
+ * The ldi 2, %r26 is actually SIG_SETMASK from
+ * /usr/include/signal.h.
+ */
+#define RESTORE_SIGNAL_MASK(__jmpbuf) \
+({ \
+ __asm__ __volatile__ ( \
+ " ldw 8(%0), %%r26\n" \
+ "\t comibt,=,n 0,%%r26,.+36\n" \
+ "\t ldo 64(%%sp), %%sp\n" \
+ "\t stw %0, -28(%%sp)\n" \
+ "\t ldi 0, %%r24\n" \
+ "\t ldo 8(%0), %%r25\n" \
+ "\t .import sigprocmask,code\n" \
+ "\t bl sigprocmask,%%rp\n" \
+ "\t ldi 2, %%r26\n" \
+ "\t ldw -28(%%sr0, %%sp), %0\n" \
+ "\t ldo -64(%%sp), %%sp\n" \
+ : \
+ : "r" (__jmpbuf)); \
+})
+
+/*
+ * This macro saves the current contents of the
+ * registers to __jmpbuf. Note that __jmpbuf is
+ * guaranteed elsewhere to be in %r26. We do not
+ * want it spilled, nor do we want a new frame
+ * built.
+ */
+#define SAVE_REGS(__jmpbuf) \
+({ \
+ __asm__ __volatile__ ( \
+ " stw %%rp, 0(%%sr0, %0)\n" \
+ "\t stw %%sp, 4(%%sr0, %0)\n" \
+ "\t stw %%r0, 8(%%sr0, %0)\n" \
+ "\t stw %%r3, 16(%%sr0, %0)\n" \
+ "\t stw %%r4, 20(%%sr0, %0)\n" \
+ "\t stw %%r5, 24(%%sr0, %0)\n" \
+ "\t stw %%r6, 28(%%sr0, %0)\n" \
+ "\t stw %%r7, 32(%%sr0, %0)\n" \
+ "\t stw %%r8, 36(%%sr0, %0)\n" \
+ "\t stw %%r9, 40(%%sr0, %0)\n" \
+ "\t stw %%r10, 44(%%sr0, %0)\n" \
+ "\t stw %%r11, 48(%%sr0, %0)\n" \
+ "\t stw %%r12, 52(%%sr0, %0)\n" \
+ "\t stw %%r13, 56(%%sr0, %0)\n" \
+ "\t stw %%r14, 60(%%sr0, %0)\n" \
+ "\t stw %%r15, 64(%%sr0, %0)\n" \
+ "\t stw %%r16, 68(%%sr0, %0)\n" \
+ "\t stw %%r17, 72(%%sr0, %0)\n" \
+ "\t stw %%r18, 76(%%sr0, %0)\n" \
+ "\t stw %%r19, 80(%%sr0, %0)\n" \
+ "\t stw %%r20, 84(%%sr0, %0)\n" \
+ "\t stw %%r21, 88(%%sr0, %0)\n" \
+ "\t stw %%r22, 92(%%sr0, %0)\n" \
+ "\t stw %%r23, 96(%%sr0, %0)\n" \
+ "\t stw %%r24, 100(%%sr0, %0)\n" \
+ "\t stw %%r25, 104(%%sr0, %0)\n" \
+ "\t stw %%r26, 108(%%sr0, %0)\n" \
+ "\t stw %%r27, 112(%%sr0, %0)\n" \
+ "\t mfsp %%sr3, %%r1\n" \
+ "\t stw %%r1, 116(%%sr0, %0)\n" \
+ "\t mfsp %%sr4, %%r1\n" \
+ "\t stw %%r1, 120(%%sr0, %0)\n" \
+ : \
+ : "r" (__jmpbuf)); \
+})
+
+/*
+ * This macro will save the signal mask to the
+ * __jmpbuf if __savemask is non-zero. By this
+ * point in time, the other resisters have been
+ * saved into the __jmpbuf.
+ * The ldi 0, %r26 is actually SIG_BLOCK from
+ * /usr/include/signal.h. Since the block is
+ * an OR of the bits, this does not change the
+ * mask, but returns it into the double word at
+ * the address in %r24.
+ */
+#define SAVE_SIGNAL_MASK(__jmpbuf,__savemask) \
+({ \
+ __asm__ __volatile__ ( \
+ " comibt,=,n 0,%1,.+36\n" \
+ "\t stw %%rp, -20(%%sr0, %%sp)\n" \
+ "\t ldo 64(%%sp), %%sp\n" \
+ "\t ldo 8(%0), %%r24\n" \
+ "\t ldi 0, %%r25\n" \
+ "\t .import sigprocmask,code\n" \
+ "\t bl sigprocmask,%%rp\n" \
+ "\t ldi 0, %%r26\n" \
+ "\t ldo -64(%%sp), %%sp\n" \
+ "\t ldw -20(%%sr0, %%sp), %%rp\n" \
+ : \
+ : "r" (__jmpbuf), \
+ "r" (__savemask)); \
+})
+
+/*
+ * Construct a jump buffer and unconditionally save
+ * the signal mask. Return a 0 unconditinoally.
+ * Care is taken here and in the macros to assume
+ * the __jumpbuf is in %r26 and that the return
+ * value will be in %r28. It is done this way to
+ * prevent a frame from being built and any registers
+ * from being spilled.
+ */
+int setjmp(register void *jmpbuf)
+{
+ register int __jmpbuf asm ("%r26");
+
+ SAVE_REGS(__jmpbuf);
+ SAVE_SIGNAL_MASK(__jmpbuf, 1);
+ return 0;
+}
+
+/*
+ * Construct a jump buffer but do not save the
+ * signal mask.
+ */
+int _setjmp(register void *jmpbuf)
+{
+ register int __jmpbuf asm ("%r26");
+
+ SAVE_REGS(__jmpbuf);
+ return 0;
+}
+
+/*
+ * Construct a jump buffer and conditionally save
+ * the signal mask. The mask is saved if the
+ * savemask parameter is non-zero.
+ */
+int sigsetjmp(register void *jmpbuf, register int savemask)
+{
+ register int __jmpbuf asm ("%r26");
+ register int __savemask asm ("%r25");
+
+ SAVE_REGS(__jmpbuf);
+ SAVE_SIGNAL_MASK(__jmpbuf, __savemask);
+ return 0;
+}
+
+/*
+ * Return to the location established in the jmpbuf,
+ * and place the value in i2 in %r28. Registers
+ * %r4 and %r5 are co-opted to save the address and
+ * value of jmpbuf and the return value. The signal
+ * mask is re-established if needed, then the
+ * address of jmpbuf and value of retval are placed
+ * into %r26 and %r28 correspondingly. This routine
+ * will never return to its caller and the stack
+ * will be cut back to whatever exists in the jmpbuf.
+ */
+void longjmp(register void *jmpbuf, register int i2)
+{
+ register int __jmpbuf asm ("%r26");
+ register int __retval asm ("%r28");
+
+ __asm__ __volatile__ (
+ " copy %0, %%r4\n"
+ "\t copy %1, %%r5\n"
+ :
+ : "r" (jmpbuf),
+ "r" (i2));
+
+ RESTORE_SIGNAL_MASK (__jmpbuf);
+
+ __asm__ __volatile__ (
+ " copy %%r4, %0\n"
+ "\t copy %%r5, %1\n"
+ : "=r" (__jmpbuf),
+ "=r" (__retval));
+
+ RESTORE_REGS_AND_RETURN (__jmpbuf, __retval);
+}
+
+/*
+ * Return to the location established in the jmpbuf,
+ * but do not restore the signal mask.
+ */
+void _longjmp(register void *jmpbuf, register int i2)
+{
+ register int __retval asm ("%r28");
+ register int __jmpbuf asm ("%r26");
+
+ __jmpbuf = (int)jmpbuf;
+ __retval = i2;
+
+ RESTORE_REGS_AND_RETURN (__jmpbuf, __retval);
+}
+
+/*
+ * Return to the location establsihed in the jmpbuf,
+ * and conditionally re-establish the signal mask.
+ */
+void siglongjmp(register void *jmpbuf, register int i2)
+{
+ register int __jmpbuf asm ("%r26");
+ register int __retval asm ("%r28");
+
+ __asm__ __volatile__ (
+ " copy %0, %%r4\n"
+ "\t copy %1, %%r5\n"
+ :
+ : "r" (jmpbuf),
+ "r" (i2));
+
+ RESTORE_SIGNAL_MASK (__jmpbuf);
+
+ __asm__ __volatile__ (
+ " copy %%r4, %0\n"
+ "\t copy %%r5, %1\n"
+ : "=r" (__jmpbuf),
+ "=r" (__retval));
+
+ RESTORE_REGS_AND_RETURN (__jmpbuf, __retval);
+}
+
+#ifdef TEST
+int buf1[50];
+int buf2[50];
+
+foo() {
+ printf("In routine foo(). Doing Longjmp.\n");
+ longjmp(buf1, 123);
+ printf("This is in foo after the longjmp() call. Should not reach here.\n");
+}
+
+bar(int ret) {
+ printf("In routine bar(%d). Doing siglongjmp.\n",ret);
+ siglongjmp(buf2, ret);
+ printf("This is in bar after the siglongjmp() call. Should not reach here.\n");
+}
+
+main() {
+ int i;
+ if ((i = setjmp(buf1)))
+ {
+ printf("This is the return from the longjmp. i: %d\n",i);
+ }
+ else
+ {
+ printf("Jump buffer established, i: %d. Calling foo()\n",i);
+ foo();
+ printf("This is in main after the foo() call. Should not reach here.\n ");
+ }
+
+ if ((i = sigsetjmp(buf2,0)))
+ {
+ printf("This is the return from the longjmp. i: %d\n",i);
+ }
+ else
+ {
+ printf("Jump buffer established, i: %d. Calling bar(456)\n",i);
+ bar(456);
+ printf("This is in main after the bar(456) call. Should not reach here.\n");
+ }
+
+ if ((i = sigsetjmp(buf2,1)))
+ {
+ printf("This is the return from the longjmp. i: %d\n",i);
+ }
+ else
+ {
+ printf("Jump buffer established, i: %d. Calling bar(789)\n",i);
+ bar(789);
+ printf("This is in main after the bar(789) call. Should not reach here.\n");
+ }
+}
+#endif
diff --git a/mpeix/mpeixish.h b/mpeix/mpeixish.h
index 49ef4355fe..165aae7f9e 100644
--- a/mpeix/mpeixish.h
+++ b/mpeix/mpeixish.h
@@ -138,6 +138,14 @@ extern key_t ftok (char *pathname, char id);
extern char *gcvt (double value, int ndigit, char *buf);
extern int isnan (double value);
extern void srand48(long int seedval);
+extern double drand48(void);
+extern double erand48(unsigned short xsubi[3]);
+extern long jrand48(unsigned short xsubi[3]);
+extern void lcong48(unsigned short param[7]);
+extern long lrand48(void);
+extern long mrand48(void);
+extern long nrand48(unsigned short xsubi[3]);
+extern unsigned short *seed48(unsigned short seed16v[3]);
/* various missing constants -- define 'em */
@@ -146,10 +154,40 @@ extern void srand48(long int seedval);
/* declarations for wrappers in mpeix.c */
#include <time.h>
-#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
extern int ftruncate(int fd, long wantsize);
extern int gettimeofday( struct timeval *tp, struct timezone *tpz );
extern int truncate(const char *pathname, off_t length);
+extern int mpe_read(int filedes, void *buffer, size_t len);
+extern int mpe_write(int filedes, const void *buffer, size_t len);
+extern int mpe_send(int socket, const void *buffer, size_t len, int flags);
+extern int mpe_sendto(int socket, const void *buffer, size_t len,
+ int flags, const struct sockaddr *dest_addr,
+ size_t dest_len);
+extern int mpe_recv(int socket, void *buffer, size_t length, int flags);
+extern int mpe_recvfrom(int socket, void *buffer, size_t length,
+ int flags, struct sockaddr *address,
+ size_t *address_len) ;
+extern int mpe_bind(int socket, const struct sockaddr *address,
+ size_t address_len);
+extern int mpe_getsockname(int socket, struct sockaddr *address,
+ size_t *address_len);
+extern int mpe_getpeername(int socket, struct sockaddr *address,
+ size_t *address_len);
+
+/* Replacements to fix various socket problems -- see mpeix.c */
#define fcntl mpe_fcntl
+#define read mpe_read
+#define write mpe_write
+#define send mpe_send
+#define sendto mpe_sendto
+#define recv mpe_recv
+#define recvfrom mpe_recvfrom
+#define bind mpe_bind
+#define getsockname mpe_getsockname
+#define getpeername mpe_getpeername