OpenVMS port; checkin for "Colin R. Blake" <colin@theblakes.com>.
authorsrinivas%netscape.com
Wed, 19 May 1999 00:53:52 +0000
changeset 617 c8d426520b310d68732e9066699f702934b0745a
parent 616 ffebdef4fafe3ff5b3366c455be2bbbed6ccdc98
child 620 49594522fa515da6b21d79346bb10f27e8838ba9
child 621 c42f7d39db7d19f0bf2660c4ee84238d42bad33e
child 622 3197a207f167cbc59176f23f39f50fc726e4181e
child 623 e10583a89ef706a9fd3f32bb5873d7610218fc3c
child 624 3d3064da7eab028c696587f68e35ab04366e573f
child 625 08cb1aef81b0a005a690e19922f2577023d453f0
child 626 2dfa1e5e62bff7164fdb12a55c008a7f234b8016
child 627 a3f632ce7873ab5df9040eb5ade504254cd38294
push idunknown
push userunknown
push dateunknown
OpenVMS port; checkin for "Colin R. Blake" <colin@theblakes.com>.
config/OpenVMS.mk
lib/ds/plevent.c
lib/prstreams/prstrms.cpp
pr/include/md/_openvms.cfg
pr/include/md/_openvms.h
pr/include/md/_pth.h
pr/include/md/_unixos.h
pr/include/md/prosdep.h
pr/include/obsolete/protypes.h
pr/src/Makefile
pr/src/io/prpolevt.c
pr/src/md/unix/Makefile
pr/src/md/unix/objs.mk
pr/src/md/unix/openvms.c
pr/src/md/unix/unix.c
pr/src/pthreads/ptio.c
pr/src/pthreads/ptthread.c
pr/tests/op_filok.c
--- a/config/OpenVMS.mk
+++ b/config/OpenVMS.mk
@@ -18,23 +18,23 @@
 #
 # Config stuff for Compaq OpenVMS
 #
 
 include $(MOD_DEPTH)/config/UNIX.mk
 
 ifdef INTERNAL_TOOLS
 CC			= c89
+CCC			= cxx
 OPTIMIZER		= -O
 else
 CC			= ccc
+CCC			= ccc
 endif
 
 RANLIB			= /bin/true
 
 CPU_ARCH_TAG		= _$(CPU_ARCH)
 
-NON_LD_FLAGS		= -ieee_with_inexact
-
-OS_CFLAGS		= -DOSF1 -DVMS
+OS_CFLAGS		= -DVMS
 
 # The command to build a shared library in POSIX on OpenVMS.
-MKSHLIB = c89 -wl,share
+XXXMKSHLIB = c89 -Wl,share
--- a/lib/ds/plevent.c
+++ b/lib/ds/plevent.c
@@ -45,16 +45,28 @@ typedef MPARAM WPARAM,LPARAM;
 #include <AppleEvents.h>
 #include "pprthred.h"
 #include "primpl.h"
 #else
 #include "private/pprthred.h"
 #include "private/primpl.h"
 #endif /* XP_MAC */
 
+#if defined(VMS)
+/*
+** On OpenVMS, XtAppAddInput doesn't want a regular fd, instead it 
+** wants an event flag. So, we don't create and use a pipe for 
+** notification of when an event queue has something ready, instead
+** we use an event flag. Shouldn't be a problem if we only have
+** a few event queues.
+*/
+#include <lib$routines.h>
+#include <starlet.h>
+#include <stsdef.h>
+#endif /* VMS */
 
 static PRLogModuleInfo *event_lm = NULL;
 
 /*******************************************************************************
  * Private Stuff
  ******************************************************************************/
 
 /*
@@ -70,17 +82,20 @@ typedef enum
 
 struct PLEventQueue {
     char*        name;
     PRCList      queue;
     PRMonitor*   monitor;
     PRThread*    handlerThread;
     EventQueueType type;
     PRBool       processingEvents;
-#if defined(XP_UNIX)
+#if defined(VMS)
+    int		 efn;
+    int		 notifyCount;
+#elif defined(XP_UNIX)
     PRInt32      eventPipe[2];
 	int          notifyCount;
 #elif defined(_WIN32) || defined(WIN16)
     HWND         eventReceiverWindow;
 #elif defined(XP_OS2)
     HWND         eventReceiverWindow;
 #endif
 };
@@ -580,17 +595,36 @@ PL_EventLoop(PLEventQueue* self)
 
 static PRStatus
 _pl_SetupNativeNotifier(PLEventQueue* self)
 {
 #if defined(XP_MAC)
 #pragma unused (self)
 #endif
 
-#if defined(XP_UNIX)
+#if defined(VMS)
+    {
+#ifdef VMS_USE_GETEF
+        unsigned int status;
+        status = LIB$GET_EF(&self->efn);
+        if (!$VMS_STATUS_SUCCESS(status))
+            return PR_FAILURE;
+#else
+        static int next_event_flag = 2;
+        if (next_event_flag <= 23) {
+            self->efn = next_event_flag++;
+        }
+        else {
+            printf("ERROR: Out of event flags\n");
+            return PR_FAILURE;
+        }
+#endif
+	return PR_SUCCESS;
+    }
+#elif defined(XP_UNIX)
     int err;
     int flags;
 
     err = pipe(self->eventPipe);
     if (err != 0) {
         return PR_FAILURE;
     }
 
@@ -624,17 +658,24 @@ failed:
 
 static void
 _pl_CleanupNativeNotifier(PLEventQueue* self)
 {
 #if defined(XP_MAC)
 #pragma unused (self)
 #endif
 
-#if defined(XP_UNIX)
+#if defined(VMS)
+#ifdef VMS_USE_GETEF
+    {
+        unsigned int status;
+        status = LIB$FREE_EF(&self->efn);
+    }
+#endif /* VMS_USE_GETEF */
+#elif defined(XP_UNIX)
     close(self->eventPipe[0]);
     close(self->eventPipe[1]);
 #endif
 }
 
 #if defined(_WIN32) || defined(WIN16)
 static PRStatus
 _pl_NativeNotify(PLEventQueue* self)
@@ -650,17 +691,30 @@ static PRStatus
 _pl_NativeNotify(PLEventQueue* self)
 {
     BOOL rc = WinPostMsg( self->eventReceiverWindow, _pr_PostEventMsgId,
                        0, MPFROMP(self));
     return (rc == TRUE) ? PR_SUCCESS : PR_FAILURE;
 }/* --- end _pl_NativeNotify() --- */
 #endif /* XP_OS2 */
 
-#if defined(XP_UNIX)
+#if defined(VMS)
+/* Just set the event flag */
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+        unsigned int status;
+        status = SYS$SETEF(self->efn);
+        self->notifyCount++;
+        if ($VMS_STATUS_SUCCESS(status))
+            return PR_SUCCESS;
+        else
+            return PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#elif defined(XP_UNIX)
 static PRStatus
 _pl_NativeNotify(PLEventQueue* self)
 {
 #define NOTIFY_TOKEN    0xFA
     PRInt32 count;
     unsigned char buf[] = { NOTIFY_TOKEN };
 
     count = write(self->eventPipe[1], buf, 1);
@@ -685,17 +739,30 @@ static PRStatus
 #pragma unused (self)
     return PR_SUCCESS;    /* XXX can fail? */
 }
 #endif /* XP_MAC */
 
 static PRStatus
 _pl_AcknowledgeNativeNotify(PLEventQueue* self)
 {
-#if defined(XP_UNIX)
+#if defined(VMS)
+/* Clear the event flag if we're all done */
+/* NOTE that we might want to always clear the event flag, even if the */
+/* notifyCount says we shouldn't. */
+    if (self->notifyCount <= 0) return PR_SUCCESS;
+    self->notifyCount--;
+    if (self->notifyCount == 0) {
+        unsigned int status;
+        status = SYS$CLREF(self->efn);
+        if (!$VMS_STATUS_SUCCESS(status))
+            return PR_FAILURE;
+    }
+    return PR_SUCCESS;
+#elif defined(XP_UNIX)
 
     PRInt32 count;
     unsigned char c;
 
 	if (self->notifyCount <= 0) return PR_SUCCESS;
     /* consume the byte NativeNotify put in our pipe: */
     count = read(self->eventPipe[0], &c, 1);
 	self->notifyCount--;
@@ -715,17 +782,19 @@ static PRStatus
 }
 
 PR_IMPLEMENT(PRInt32)
 PL_GetEventQueueSelectFD(PLEventQueue* self)
 {
     if (self == NULL)
     return -1;
 
-#if defined(XP_UNIX)
+#if defined(VMS)
+    return self->efn;
+#elif defined(XP_UNIX)
     return self->eventPipe[0];
 #else
     return -1;    /* other platforms don't handle this (yet) */
 #endif
 }
 
 
 #if defined(WIN16) || defined(_WIN32)
--- a/lib/prstreams/prstrms.cpp
+++ b/lib/prstreams/prstrms.cpp
@@ -40,16 +40,20 @@
 #if defined(__GNUC__)
 #define _PRSTR_BP _strbuf
 #define _PRSTR_DELBUF(x)    /* as nothing */
 #define _PRSTR_DELBUF_C(c, x)  /* as nothing */
 #elif defined(WIN32)
 #define _PRSTR_BP bp
 #define _PRSTR_DELBUF(x)	delbuf(x)
 #define _PRSTR_DELBUF_C(c, x)	c::_PRSTR_DELBUF(x)
+#elif defined(VMS)
+#undef  _PRSTR_BP /* as nothing */
+#define _PRSTR_DELBUF(x) /* as nothing */
+#define _PRSTR_DELBUF_C(c, x)	/* as nothing */
 #elif defined(OSF1)
 #define _PRSTR_BP m_psb
 #define _PRSTR_DELBUF(x) /* as nothing */
 #define _PRSTR_DELBUF_C(c, x)	/* as nothing */
 #else
 #define _PRSTR_BP bp
 // Unix compilers don't believe in encapsulation
 // At least on Solaris this is also ignored
--- a/pr/include/md/_openvms.cfg
+++ b/pr/include/md/_openvms.cfg
@@ -18,20 +18,16 @@
 
 #ifndef nspr_cpucfg___
 #define nspr_cpucfg___
 
 #ifndef XP_UNIX
 #define XP_UNIX
 #endif
 
-#ifndef OSF1
-#define OSF1
-#endif
-
 #ifndef VMS
 #define VMS
 #endif
 
 #define IS_LITTLE_ENDIAN 1
 #undef  IS_BIG_ENDIAN
 #define	HAVE_LONG_LONG
 #define HAVE_ALIGNED_DOUBLES
--- a/pr/include/md/_openvms.h
+++ b/pr/include/md/_openvms.h
@@ -29,42 +29,59 @@
  */
 
 #define PR_LINKER_ARCH	"OpenVMS"
 #define _PR_SI_SYSNAME	"OpenVMS"
 #ifdef __alpha
 #define _PR_SI_ARCHITECTURE "alpha"
 #else
 #define _PR_SI_ARCHITECTURE "vax"
-endif
-#define PR_DLL_SUFFIX		".so"
+#endif
+#define PR_DLL_SUFFIX		".exe"
 
 #define _PR_VMBASE		0x30000000
 #define _PR_STACK_VMBASE	0x50000000
 #define _MD_DEFAULT_STACK_SIZE	131072L
+
+/*
+** This is not defined on OpenVMS. I believe its only used in GC code, and
+** isn't that only used in Java? Anyway, for now, let's keep the compiler
+** happy.
+*/
+#define SA_RESTART 0
+
+/*
+** OpenVMS doesn't have these in socket.h.
+*/
+struct ip_mreq {
+    struct in_addr  imr_multiaddr;      /* IP multicast address of group */
+    struct in_addr  imr_interface;      /* local IP address of interface */
+};
+
 /*
  * OSF1 needs the MAP_FIXED flag to ensure that mmap returns a pointer
  * with the upper 32 bits zero.  This is because Java sticks a pointer
  * into an int.
  */
 #define _MD_MMAP_FLAGS          MAP_PRIVATE|MAP_FIXED
 
 #undef  HAVE_STACK_GROWING_UP
 #undef 	HAVE_WEAK_IO_SYMBOLS
 #undef 	HAVE_WEAK_MALLOC_SYMBOLS
-#undef  HAVE_DLL
 #undef  HAVE_BSD_FLOCK
 
 #define NEED_TIME_R
+
+#undef  HAVE_DLL
 #undef  USE_DLFCN
 
 #define _PR_POLL_AVAILABLE
 #define _PR_USE_POLL
 #define _PR_STAT_HAS_ONLY_ST_ATIME
-#define _PR_HAVE_LARGE_OFF_T
+#define _PR_NO_LARGE_FILES
 
 #undef  USE_SETJMP
 
 #include <setjmp.h>
 
 /*
  * A jmp_buf is actually a struct sigcontext.  The sc_sp field of
  * struct sigcontext is the stack pointer.
@@ -192,19 +209,17 @@ struct _MDCPU {
  * The following are copied from _sunos.h, _aix.h.  This means
  * some of them should probably be moved into _unixos.h.  But
  * _irix.h seems to be quite different in regard to these macros.
  */
 #define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
 #define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
-#ifdef __VMS
 void _MD_EarlyInit(void);
-#endif
 #define _MD_FINAL_INIT		_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD         _MD_InitializeThread
 #ifdef _VMS_NOT_YET
 PR_EXTERN(void) _PR_InitThreads(
   PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs);
 #endif
 #define _MD_EXIT_THREAD(thread)
@@ -232,9 +247,12 @@ PR_EXTERN(void) _PR_MD_START_INTERRUPTS(
 #include <machine/builtins.h>
 #define _PR_HAVE_ATOMIC_OPS
 #define _MD_INIT_ATOMIC()
 #define _MD_ATOMIC_ADD(ptr,val) (__ATOMIC_ADD_LONG(ptr,val) + val)
 #define _MD_ATOMIC_INCREMENT(val) (__ATOMIC_INCREMENT_LONG(val) + 1)
 #define _MD_ATOMIC_DECREMENT(val) (__ATOMIC_DECREMENT_LONG(val) - 1)
 #define _MD_ATOMIC_SET(val, newval) __ATOMIC_EXCH_LONG(val, newval)
 
+extern int thread_suspend(PRThread *thr_id);
+extern int thread_resume(PRThread *thr_id);
+
 #endif /* nspr_openvms_defs_h___ */
--- a/pr/include/md/_pth.h
+++ b/pr/include/md/_pth.h
@@ -87,17 +87,18 @@
  */
 #if defined(_PR_DCETHREADS)
 #define PTHREAD_ZERO_THR_HANDLE(t)        memset(&(t), 0, sizeof(pthread_t))
 #define PTHREAD_THR_HANDLE_IS_ZERO(t) \
 	(!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
 #define PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
 	|| defined(HPUX) || defined(LINUX) || defined(FREEBSD) \
-	|| defined(NETBSD) || defined(OPENBSD) || defined(BSDI)
+	|| defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
+	|| defined(VMS)
 #define PTHREAD_ZERO_THR_HANDLE(t)        (t) = 0
 #define PTHREAD_THR_HANDLE_IS_ZERO(t)     (t) == 0
 #define PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
 #else 
 #error "pthreads is not supported for this architecture"
 #endif
 
 #if defined(_PR_DCETHREADS)
@@ -147,21 +148,21 @@
 #define PT_NO_ATFORK
 #endif
 
 /*
  * These platforms don't have sigtimedwait()
  */
 #if (defined(AIX) && !defined(AIX4_3)) || defined(LINUX) \
 	|| defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
-	|| defined(BSDI)
+	|| defined(BSDI) || defined(VMS)
 #define PT_NO_SIGTIMEDWAIT
 #endif
 
-#if defined(OSF1)
+#if defined(OSF1) || defined(VMS)
 #define PT_PRIO_MIN            PRI_OTHER_MIN
 #define PT_PRIO_MAX            PRI_OTHER_MAX
 #elif defined(IRIX)
 #include <sys/sched.h>
 #define PT_PRIO_MIN            PX_PRIO_MIN
 #define PT_PRIO_MAX            PX_PRIO_MAX
 #elif defined(AIX)
 #include <sys/priv.h>
@@ -204,17 +205,17 @@
 
 /*
  * The PTHREAD_YIELD function is called from a signal handler.
  * Needed for garbage collection -- Look at PR_Suspend/PR_Resume
  * implementation.
  */
 #if defined(_PR_DCETHREADS)
 #define PTHREAD_YIELD()            	pthread_yield()
-#elif defined(OSF1)
+#elif defined(OSF1) || defined(VMS)
 /*
  * sched_yield can't be called from a signal handler.  Must use
  * the _np version.
  */
 #define PTHREAD_YIELD()            	pthread_yield_np()
 #elif defined(AIX)
 extern int (*_PT_aix_yield_fcn)();
 #define PTHREAD_YIELD()			(*_PT_aix_yield_fcn)()
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -563,17 +563,21 @@ typedef off_t _MDOff64_t;
 typedef struct stat _MDStat64;
 typedef PRInt64 _MDOff64_t;
 #else
 #error "I don't know yet"
 #endif
 
 typedef PRIntn (*_MD_Fstat64)(PRIntn osfd, _MDStat64 *buf);
 typedef PRIntn (*_MD_Open64)(const char *path, int oflag, ...);
+#if defined(VMS)
+typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf, ...);
+#else
 typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf);
+#endif
 typedef _MDOff64_t (*_MD_Lseek64)(PRIntn osfd, _MDOff64_t, PRIntn whence);
 typedef void* (*_MD_Mmap64)(
     void *addr, PRSize len, PRIntn prot, PRIntn flags,
     PRIntn fildes, _MDOff64_t offset);
 struct _MD_IOVector
 {
     _MD_Open64 _open64;
     _MD_Mmap64 _mmap64;
--- a/pr/include/md/prosdep.h
+++ b/pr/include/md/prosdep.h
@@ -108,16 +108,19 @@ PR_BEGIN_EXTERN_C
 #include "md/_ncr.h"
 
 #elif defined(DGUX)
 #include "md/_dgux.h"
 
 #elif defined(QNX)
 #include "md/_qnx.h"
 
+#elif defined(VMS)
+#include "md/_openvms.h"
+
 #else
 #error unknown Unix flavor
 
 #endif
 
 #include "md/_unixos.h"
 #include "md/_unix_errors.h"
 
--- a/pr/include/obsolete/protypes.h
+++ b/pr/include/obsolete/protypes.h
@@ -34,17 +34,24 @@ typedef PRIntn intn;
 /*
  * BeOS already defines the integer types below in its standard
  * header file SupportDefs.h.
  */
 #ifdef XP_BEOS
 
 #include <support/SupportDefs.h>
 
-#else /* XP_BEOS */
+#elif VMS
+/*
+ * OpenVMS already defines the integer types below in its standard
+ * header files ints.h and types.h.
+ */
+#include <ints.h>
+#include <types.h>
+#else
 
 /* SVR4 typedef of uint is commonly found on UNIX machines. */
 #ifdef XP_UNIX
 #include <sys/types.h>
 #else
 typedef PRUintn uint;
 #endif
 
@@ -79,17 +86,17 @@ typedef PRInt32 int32;
 typedef long int32;
 #endif
 #endif
 typedef PRInt16 int16;
 typedef PRInt8 int8;
 #endif /* HPUX */
 #endif /* AIX4_3 */
 
-#endif /* XP_BEOS */
+#endif /* XP_BEOS VMS */
 
 typedef PRFloat64 float64;
 typedef PRUptrdiff uptrdiff_t;
 typedef PRUword uprword_t;
 typedef PRWord prword_t;
 
 
 /* Re: prbit.h */
--- a/pr/src/Makefile
+++ b/pr/src/Makefile
@@ -86,16 +86,20 @@ ifeq ($(OS_ARCH),AIX)
 ifneq (,$(filter-out 3.2 4.1,$(OS_RELEASE)))
 ifneq ($(USE_PTHREADS),1)
 BUILD_AIX_RTL_LIBC = 1
 AIX_RTL_LIBC	= $(OBJDIR)/libc.a
 endif
 endif
 endif
 
+ifeq ($(OS_ARCH),OpenVMS)
+OS_LIBS		= -lvms_jackets
+endif
+
 ifeq ($(OS_ARCH),OSF1)
 ifeq ($(USE_PTHREADS), 1)
 OS_LIBS 	= -lpthread -lrt
 endif
 ifneq ($(OS_RELEASE),V2.0)
 OS_LIBS		+= -lc_r
 endif
 ifeq ($(USE_IPV6), 1)
--- a/pr/src/io/prpolevt.c
+++ b/pr/src/io/prpolevt.c
@@ -27,17 +27,17 @@
 #include "primpl.h"
 
 typedef struct MyFilePrivate {
     PRFilePrivate copy;
     PRFileDesc *writeEnd;
     PRFilePrivate *oldSecret;
 } MyFilePrivate;
 
-#ifndef XP_UNIX
+#if !defined(XP_UNIX) || defined(VMS)
 #define USE_TCP_SOCKETPAIR
 #endif
 
 PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
 {
     PRFileDesc *fd[2]; /* fd[0] is the read end; fd[1] is the write end */
     MyFilePrivate *secret;
 
--- a/pr/src/md/unix/Makefile
+++ b/pr/src/md/unix/Makefile
@@ -69,16 +69,20 @@ OPENBSD_CSRCS = \
 BSDI_CSRCS = \
 	bsdi.c \
 	$(NULL)
 
 HPUX_CSRCS = \
 	hpux.c \
 	$(NULL)
 
+OPENVMS_CSRCS = \
+       openvms.c \
+       $(NULL)
+
 OSF1_CSRCS = \
 	osf1.c \
 	$(NULL)
 
 LINUX_CSRCS = \
 	linux.c \
 	$(NULL)
 
@@ -151,16 +155,19 @@ ifeq ($(OS_ARCH),OpenBSD)
 CSRCS += $(OPENBSD_CSRCS)
 endif
 ifeq ($(OS_ARCH),BSD_OS)
 CSRCS += $(BSDI_CSRCS)
 endif
 ifeq ($(OS_ARCH),HP-UX)
 CSRCS += $(HPUX_CSRCS)
 endif
+ifeq ($(OS_ARCH),OpenVMS)
+CSRCS += $(OPENVMS_CSRCS)
+endif
 ifeq ($(OS_ARCH),OSF1)
 CSRCS += $(OSF1_CSRCS)
 endif
 ifeq ($(OS_ARCH),Linux)
 CSRCS += $(LINUX_CSRCS)
 endif
 ifeq ($(OS_ARCH),UNIXWARE)
 CSRCS += $(UNIXWARE_CSRCS)
--- a/pr/src/md/unix/objs.mk
+++ b/pr/src/md/unix/objs.mk
@@ -65,16 +65,20 @@ BSDI_CSRCS = \
 HPUX_CSRCS = \
 	hpux.c \
 	$(NULL)
 
 OSF1_CSRCS = \
 	osf1.c \
 	$(NULL)
 
+OPENVMS_CSRCS = \
+	openvms.c \
+	$(NULL)
+
 LINUX_CSRCS = \
 	linux.c \
 	$(NULL)
 
 UNIXWARE_CSRCS = \
 	unixware.c \
 	$(NULL)
 
@@ -146,16 +150,19 @@ endif
 ifeq ($(OS_ARCH),BSD_OS)
 CSRCS += $(BSDI_CSRCS)
 endif
 ifeq ($(OS_ARCH),HP-UX)
 CSRCS += $(HPUX_CSRCS)
 endif
 ifeq ($(OS_ARCH),OSF1)
 CSRCS += $(OSF1_CSRCS)
+endi:
+ifeq ($(OS_ARCH),OpenVMS)
+CSRCS += $(OPENVMS_CSRCS)
 endif
 ifeq ($(OS_ARCH),Linux)
 CSRCS += $(LINUX_CSRCS)
 endif
 ifeq ($(OS_ARCH),UNIXWARE)
 CSRCS += $(UNIXWARE_CSRCS)
 endif
 ifeq ($(OS_ARCH),SINIX)
new file mode 100644
--- /dev/null
+++ b/pr/src/md/unix/openvms.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.1 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+    if (isCurrent) {
+	(void) setjmp(CONTEXT(t));
+    }
+    *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+    return (PRWord *) CONTEXT(t);
+#else
+	*np = 0;
+	return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+    return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+	return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+    PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+    _PR_MD_SWITCH_CONTEXT(thread);
+    return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+    if (thread) {
+	PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+    }
+    return PR_SUCCESS;
+}
+
+/* These functions should not be called for OSF1 */
+void
+_MD_YIELD(void)
+{
+    PR_NOT_REACHED("_MD_YIELD should not be called for OSF1.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+    PRThread *thread,
+    void (*start) (void *),
+    PRThreadPriority priority,
+    PRThreadScope scope,
+    PRThreadState state,
+    PRUint32 stackSize)
+{
+    PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1.");
+	return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include <c_asm.h>
+
+#define _PR_OSF_ATOMIC_LOCK 1
+
+void 
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+long locked;
+
+	do {
+		while ((long) stack->prstk_head.prstk_elem_next ==
+							_PR_OSF_ATOMIC_LOCK)
+			;
+		locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+								_PR_OSF_ATOMIC_LOCK);	
+
+	} while (locked == _PR_OSF_ATOMIC_LOCK);
+	stack_elem->prstk_elem_next = (PRStackElem *) locked;
+	/*
+	 * memory-barrier instruction
+	 */
+	asm("mb");
+	stack->prstk_head.prstk_elem_next = stack_elem;
+}
+
+PRStackElem * 
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+long locked;
+
+	do {
+		while ((long)stack->prstk_head.prstk_elem_next == _PR_OSF_ATOMIC_LOCK)
+			;
+		locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+								_PR_OSF_ATOMIC_LOCK);	
+
+	} while (locked == _PR_OSF_ATOMIC_LOCK);
+
+	element = (PRStackElem *) locked;
+
+	if (element == NULL) {
+		stack->prstk_head.prstk_elem_next = NULL;
+	} else {
+		stack->prstk_head.prstk_elem_next =
+			element->prstk_elem_next;
+	}
+	/*
+	 * memory-barrier instruction
+	 */
+	asm("mb");
+	return element;
+}
+#endif /* _PR_HAVE_ATOMIC_CAS */
+
+
+/*
+** thread_suspend and thread_resume are used by the gc code
+** in nsprpub/pr/src/pthreads/ptthread.c
+**
+** These routines are never called for the current thread, and
+** there is no check for that - so beware!
+*/
+int thread_suspend(PRThread *thr_id) {
+
+    extern int pthread_suspend_np (
+			pthread_t                       thread,
+			__pthreadLongUint_t             *regs,
+			void                            *spare);
+
+    __pthreadLongUint_t regs[34];
+    int res;
+
+    /*
+    ** A return res < 0 indicates that the thread was suspended
+    ** but register information could not be obtained
+    */
+
+    res = pthread_suspend_np(thr_id->id,&regs[0],0);
+    if (res==0)
+	thr_id->sp = (void *) regs[30]; 
+
+    thr_id->suspend |= PT_THREAD_SUSPENDED;
+
+    /* Always succeeds */
+    return 0;
+}
+
+int thread_resume(PRThread *thr_id) {
+    extern int pthread_resume_np(pthread_t thread);
+    int res;
+
+    res = pthread_resume_np (thr_id->id);
+	
+    thr_id->suspend |= PT_THREAD_RESUMED;
+
+    return 0;
+}
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -47,17 +47,17 @@
 #elif defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \
     || defined(AIX4_1) || defined(LINUX) || defined(SONY) \
     || defined(BSDI) || defined(SCO) || defined(NEC) || defined(SNI) \
     || defined(SUNOS4) || defined(NCR) || defined(RHAPSODY) \
     || defined(NEXTSTEP) || defined(QNX)
 #define _PRSockLen_t int
 #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
     || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) \
-    || defined(DGUX)
+    || defined(DGUX) || defined(VMS)
 #define _PRSockLen_t size_t
 #else
 #error "Cannot determine architecture"
 #endif
 
 /*
 ** Global lock variable used to bracket calls into rusty libraries that
 ** aren't thread safe (like libc, libX, etc).
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -118,31 +118,31 @@ static ssize_t (*pt_aix_sendfile_fptr)()
 /* On Alpha Linux, these are already defined in sys/socket.h */
 #if !(defined(LINUX) && defined(__alpha))
 #include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
 #endif
 
 #if defined(SOLARIS)
 #define _PRSockOptVal_t char *
 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \
-    || defined(LINUX) || defined(FREEBSD) || defined(BSDI)
+    || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS)
 #define _PRSockOptVal_t void *
 #else
 #error "Cannot determine architecture"
 #endif
 
 #if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))
 #define _PRSelectFdSetArg_t int *
 #elif defined(AIX4_1)
 #define _PRSelectFdSetArg_t void *
 #elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \
     || defined(OSF1) || defined(SOLARIS) \
     || defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \
     || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
-    || defined(BSDI)
+    || defined(BSDI) || defined(VMS)
 #define _PRSelectFdSetArg_t fd_set *
 #else
 #error "Cannot determine architecture"
 #endif
 
 static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type);
 
 static PRLock *_pr_flock_lock;  /* For PR_LockFile() etc. */
@@ -196,17 +196,18 @@ static PRBool IsValidNetAddrLen(const PR
  * Latest POSIX defines this type as socklen_t.  It may also be
  * size_t or int.
  */
 #if defined(HAVE_SOCKLEN_T) \
     || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2 \
     && !defined(__alpha))
 typedef socklen_t pt_SockLen;
 #elif (defined(AIX) && !defined(AIX4_1)) \
-    || (defined(LINUX) && defined(__alpha))
+    || (defined(LINUX) && defined(__alpha)) \
+    || defined(VMS)
 typedef PRSize pt_SockLen;
 #else
 typedef PRIntn pt_SockLen;
 #endif
 
 typedef struct pt_Continuation pt_Continuation;
 typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents);
 
@@ -2808,17 +2809,17 @@ static PRIOMethods _pr_socketpollfd_meth
 };
 
 #if defined(_PR_FCNTL_FLAGS)
 #undef _PR_FCNTL_FLAGS
 #endif
 
 #if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \
     || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD) \
-    || defined(OPENBSD) || defined(BSDI)
+    || defined(OPENBSD) || defined(BSDI) || defined(VMS)
 #define _PR_FCNTL_FLAGS O_NONBLOCK
 #else
 #error "Can't determine architecture"
 #endif
 
 static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type)
 {
     PRInt32 flags, one = 1;
@@ -3702,48 +3703,48 @@ PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRF
 
 /*
  * The next two entry points should not be in the API, but they are
  * defined here for historical (or hysterical) reasons.
  */
 
 PRInt32 PR_GetSysfdTableMax(void)
 {
-#if defined(XP_UNIX) && !defined(AIX)
+#if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)
     struct rlimit rlim;
 
     if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) 
        return -1;
 
     return rlim.rlim_max;
-#elif defined(AIX)
+#elif defined(AIX) || defined(VMS)
     return sysconf(_SC_OPEN_MAX);
 #endif
 }
 
 PRInt32 PR_SetSysfdTableSize(PRIntn table_size)
 {
-#if defined(XP_UNIX) && !defined(AIX)
+#if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)
     struct rlimit rlim;
     PRInt32 tableMax = PR_GetSysfdTableMax();
 
     if (tableMax < 0) return -1;
     rlim.rlim_max = tableMax;
 
     /* Grow as much as we can; even if too big */
     if ( rlim.rlim_max < table_size )
         rlim.rlim_cur = rlim.rlim_max;
     else
         rlim.rlim_cur = table_size;
 
     if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) 
         return -1;
 
     return rlim.rlim_cur;
-#elif defined(AIX)
+#elif defined(AIX) || defined(VMS)
     return -1;
 #endif
 }
 
 /*
  * PR_Stat is supported for backward compatibility; some existing Java
  * code uses it.  New code should use PR_GetFileInfo.
  */
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -1141,17 +1141,17 @@ static void suspend_signal_handler(PRInt
 	/*
 	 * now, block current thread
 	 */
 #if defined(PT_NO_SIGTIMEDWAIT)
 	pthread_cond_signal(&me->suspendResumeCV);
 	while (me->suspend & PT_THREAD_SUSPENDED)
 	{
 #if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
-    && !defined(BSDI)  /*XXX*/
+    && !defined(BSDI) && !defined(VMS)  /*XXX*/
         PRIntn rv;
 	    sigwait(&sigwait_set, &rv);
 #endif
 	}
 	me->suspend |= PT_THREAD_RESUMED;
 	pthread_cond_signal(&me->suspendResumeCV);
 #else /* defined(PT_NO_SIGTIMEDWAIT) */
 	while (me->suspend & PT_THREAD_SUSPENDED)
@@ -1185,17 +1185,21 @@ static void PR_SuspendSet(PRThread *thre
      * Check the thread state and signal the thread to suspend
      */
 
     PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0);
 
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
 	   ("doing pthread_kill in PR_SuspendSet thred %X tid = %X\n",
 	   thred, thred->id));
+#if defined(VMS)
+    rv = thread_suspend(thred);
+#else
     rv = pthread_kill (thred->id, SIGUSR2);
+#endif
     PR_ASSERT(0 == rv);
 }
 
 static void PR_SuspendTest(PRThread *thred)
 {
     PRIntn rv;
 
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
@@ -1239,18 +1243,22 @@ PR_IMPLEMENT(void) PR_ResumeSet(PRThread
      */
 
     PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED);
 
 
     thred->suspend &= ~PT_THREAD_SUSPENDED;
 
 #if defined(PT_NO_SIGTIMEDWAIT)
+#if defined(VMS)
+	thread_resume(thred);
+#else
 	pthread_kill(thred->id, SIGUSR1);
 #endif
+#endif
 
 }  /* PR_ResumeSet */
 
 PR_IMPLEMENT(void) PR_ResumeTest(PRThread *thred)
 {
     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, 
 	   ("Begin PR_ResumeTest thred %X thread id = %X\n", thred, thred->id));
 
--- a/pr/tests/op_filok.c
+++ b/pr/tests/op_filok.c
@@ -41,17 +41,19 @@
 #define printf PR_LogPrint
 #else
 #endif
 
 /*
  * The name of a file that is guaranteed to exist
  * on every machine of a particular OS.
  */
-#ifdef XP_UNIX
+#ifdef VMS
+#define EXISTING_FILENAME "SYS$LOGIN:LOGIN.COM"
+#elif XP_UNIX
 #define EXISTING_FILENAME "/bin/sh"
 #elif defined(WIN32)
 #define EXISTING_FILENAME "c:/autoexec.bat"
 #elif defined(OS2)
 #define EXISTING_FILENAME "c:/config.sys"
 #elif defined(BEOS)
 #define EXISTING_FILENAME "/boot/beos/bin/sh"
 #else