mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-14 13:28:31 +00:00
add js to tree
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3693 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
855c7b9a77
commit
fff98f6316
1137 files changed
+386873
No files matched your search
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,4 @@
|
||||
/.cvsignore/1.2/Sat May 12 04:24:53 2001//
|
||||
/Makefile.in/1.12/Sun Apr 25 15:00:58 2004//
|
||||
/prosdep.c/3.12/Sat Dec 24 08:25:29 2005//
|
||||
D
|
||||
@@ -0,0 +1,5 @@
|
||||
A D/beos////
|
||||
A D/mac////
|
||||
A D/os2////
|
||||
A D/unix////
|
||||
A D/windows////
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
DIRS = $(PR_MD_ARCH_DIR)
|
||||
|
||||
CSRCS = \
|
||||
prosdep.c \
|
||||
$(NULL)
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include
|
||||
|
||||
DEFINES += -D_NSPR_BUILD_
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,17 @@
|
||||
/.cvsignore/1.2/Sat May 12 06:08:09 2001//
|
||||
/Makefile.in/1.10/Sun Apr 25 15:00:59 2004//
|
||||
/bcpu.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/beos.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/beos_errors.c/3.8/Wed Mar 9 22:57:05 2005//
|
||||
/bfile.c/3.15/Wed Mar 9 22:57:05 2005//
|
||||
/bmemory.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/bmisc.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/bmmap.c/3.7/Sun Apr 25 15:00:59 2004//
|
||||
/bnet.c/3.15/Sun Apr 25 15:00:59 2004//
|
||||
/bproc.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/brng.c/3.4/Wed Aug 30 16:59:51 2000//
|
||||
/bseg.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/bsrcs.mk/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/btime.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/objs.mk/3.6/Sun Apr 25 15:00:59 2004//
|
||||
D
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md/beos
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
MOD_DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(srcdir)/bsrcs.mk
|
||||
CSRCS += $(MDCSRCS)
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
|
||||
|
||||
DEFINES += -D_NSPR_BUILD_
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(void) _PR_MD_INIT_CPUS();
|
||||
PR_EXTERN(void) _PR_MD_WAKEUP_CPUS();
|
||||
PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void);
|
||||
PR_EXTERN(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);
|
||||
PR_EXTERN(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);
|
||||
PR_EXTERN(PRInt32) _PR_MD_GET_INTSOFF(void);
|
||||
PR_EXTERN(void) _PR_MD_SET_INTSOFF(PRInt32 _val);
|
||||
PR_EXTERN(_PRCPU*) _PR_MD_CURRENT_CPU(void);
|
||||
PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);
|
||||
PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
|
||||
PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
|
||||
@@ -0,0 +1,264 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
|
||||
* PRInt32* pointer to a _PRSockLen_t* pointer.
|
||||
*/
|
||||
#define _PRSockLen_t int
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
static PRMonitor *_pr_Xfe_mon = NULL;
|
||||
|
||||
/*
|
||||
* Variables used by the GC code, initialized in _MD_InitSegs().
|
||||
* _pr_zero_fd should be a static variable. Unfortunately, there is
|
||||
* still some Unix-specific code left in function PR_GrowSegment()
|
||||
* in file memory/prseg.c that references it, so it needs
|
||||
* to be a global variable for now.
|
||||
*/
|
||||
PRInt32 _pr_zero_fd = -1;
|
||||
static PRLock *_pr_md_lock = NULL;
|
||||
|
||||
sigset_t timer_set;
|
||||
|
||||
void _PR_UnixInit()
|
||||
{
|
||||
struct sigaction sigact;
|
||||
int rv;
|
||||
|
||||
sigemptyset(&timer_set);
|
||||
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
rv = sigaction(SIGPIPE, &sigact, 0);
|
||||
PR_ASSERT(0 == rv);
|
||||
|
||||
_pr_rename_lock = PR_NewLock();
|
||||
PR_ASSERT(NULL != _pr_rename_lock);
|
||||
_pr_Xfe_mon = PR_NewMonitor();
|
||||
PR_ASSERT(NULL != _pr_Xfe_mon);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
* PR_Now --
|
||||
*
|
||||
* Returns the current time in microseconds since the epoch.
|
||||
* The epoch is midnight January 1, 1970 GMT.
|
||||
* The implementation is machine dependent. This is the Unix
|
||||
* implementation.
|
||||
* Cf. time_t time(time_t *tp)
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(PRTime)
|
||||
PR_Now(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
PRInt64 s, us, s2us;
|
||||
|
||||
GETTIMEOFDAY(&tv);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_I2L(s, tv.tv_sec);
|
||||
LL_I2L(us, tv.tv_usec);
|
||||
LL_MUL(s, s, s2us);
|
||||
LL_ADD(s, s, us);
|
||||
return s;
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_PR_UNIX_GetInterval()
|
||||
{
|
||||
struct timeval time;
|
||||
PRIntervalTime ticks;
|
||||
|
||||
(void)GETTIMEOFDAY(&time); /* fallicy of course */
|
||||
ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
|
||||
ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
|
||||
return ticks;
|
||||
} /* _PR_SUNOS_GetInterval */
|
||||
|
||||
PRIntervalTime _PR_UNIX_TicksPerSecond()
|
||||
{
|
||||
return 1000; /* this needs some work :) */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
|
||||
** safe. Unfortunately, neither is mozilla. To make these programs work
|
||||
** in a pre-emptive threaded environment, we need to use a lock.
|
||||
*/
|
||||
|
||||
void PR_XLock()
|
||||
{
|
||||
PR_EnterMonitor(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
void PR_XUnlock()
|
||||
{
|
||||
PR_ExitMonitor(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
PRBool PR_XIsLocked()
|
||||
{
|
||||
return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
void PR_XWait(int ms)
|
||||
{
|
||||
PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
|
||||
}
|
||||
|
||||
void PR_XNotify(void)
|
||||
{
|
||||
PR_Notify(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
void PR_XNotifyAll(void)
|
||||
{
|
||||
PR_NotifyAll(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
#if !defined(BEOS)
|
||||
#ifdef HAVE_BSD_FLOCK
|
||||
|
||||
#include <sys/file.h>
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_LOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_EX);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_TLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_EX|LOCK_NB);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_UNLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_UN);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#else
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_LOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_LOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_TLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_TLOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_UNLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_ULOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_GETHOSTNAME (char *name, PRUint32 namelen)
|
||||
{
|
||||
PRIntn rv;
|
||||
|
||||
rv = gethostname(name, namelen);
|
||||
if (0 == rv) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
_PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,902 @@
|
||||
/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
|
||||
void
|
||||
_MD_InitIO (void)
|
||||
{
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_open_dir (_MDDir *md,const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
md->d = opendir(name);
|
||||
if (!md->d) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_OPENDIR_ERROR(err);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
char*
|
||||
_MD_read_dir (_MDDir *md, PRIntn flags)
|
||||
{
|
||||
struct dirent *de;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* XXX: readdir() is not MT-safe
|
||||
*/
|
||||
_MD_ERRNO() = 0;
|
||||
de = readdir(md->d);
|
||||
|
||||
if (!de) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_READDIR_ERROR(err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((flags & PR_SKIP_DOT) &&
|
||||
(de->d_name[0] == '.') && (de->d_name[1] == 0))
|
||||
continue;
|
||||
|
||||
if ((flags & PR_SKIP_DOT_DOT) &&
|
||||
(de->d_name[0] == '.') && (de->d_name[1] == '.') &&
|
||||
(de->d_name[2] == 0))
|
||||
continue;
|
||||
|
||||
if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
return de->d_name;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
_MD_close_dir (_MDDir *md)
|
||||
{
|
||||
int rv = 0, err;
|
||||
|
||||
if (md->d) {
|
||||
rv = closedir(md->d);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_CLOSEDIR_ERROR(err);
|
||||
}
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_make_nonblock (PRFileDesc *fd)
|
||||
{
|
||||
int blocking = 1;
|
||||
setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
|
||||
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
|
||||
if (-1 == rv) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
|
||||
{
|
||||
if (imported) {
|
||||
fd->secret->inheritable = _PR_TRI_UNKNOWN;
|
||||
} else {
|
||||
int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
|
||||
if (flags == -1) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
|
||||
return;
|
||||
}
|
||||
fd->secret->inheritable = (flags & FD_CLOEXEC) ?
|
||||
_PR_TRI_TRUE : _PR_TRI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_MD_query_fd_inheritable (PRFileDesc *fd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
|
||||
flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
|
||||
PR_ASSERT(-1 != flags);
|
||||
fd->secret->inheritable = (flags & FD_CLOEXEC) ?
|
||||
_PR_TRI_FALSE : _PR_TRI_TRUE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_open (const char *name, PRIntn flags, PRIntn mode)
|
||||
{
|
||||
PRInt32 osflags;
|
||||
PRInt32 rv, err;
|
||||
|
||||
if (flags & PR_RDWR) {
|
||||
osflags = O_RDWR;
|
||||
} else if (flags & PR_WRONLY) {
|
||||
osflags = O_WRONLY;
|
||||
} else {
|
||||
osflags = O_RDONLY;
|
||||
}
|
||||
|
||||
if (flags & PR_EXCL)
|
||||
osflags |= O_EXCL;
|
||||
if (flags & PR_APPEND)
|
||||
osflags |= O_APPEND;
|
||||
if (flags & PR_TRUNCATE)
|
||||
osflags |= O_TRUNC;
|
||||
if (flags & PR_SYNC) {
|
||||
/* Ummmm. BeOS doesn't appear to
|
||||
support sync in any way shape or
|
||||
form. */
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** On creations we hold the 'create' lock in order to enforce
|
||||
** the semantics of PR_Rename. (see the latter for more details)
|
||||
*/
|
||||
if (flags & PR_CREATE_FILE)
|
||||
{
|
||||
osflags |= O_CREAT ;
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
}
|
||||
|
||||
rv = open(name, osflags, mode);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_OPEN_ERROR(err);
|
||||
}
|
||||
|
||||
if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_close_file (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = close(osfd);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_CLOSE_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
rv = read( osfd, buf, amount );
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_READ_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
rv = write( osfd, buf, amount );
|
||||
|
||||
if( rv < 0 ) {
|
||||
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_WRITE_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
#ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
|
||||
PRInt32
|
||||
_MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
PRInt32
|
||||
_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = lseek (fd->secret->md.osfd, offset, whence);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LSEEK_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
PRInt64
|
||||
_MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
/* According to the BeOS headers, lseek accepts a
|
||||
* variable of type off_t for the offset, and off_t
|
||||
* is defined to be a 64-bit value. So no special
|
||||
* cracking needs to be done on "offset".
|
||||
*/
|
||||
|
||||
rv = lseek (fd->secret->md.osfd, offset, whence);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LSEEK_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_fsync (PRFileDesc *fd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fsync(fd->secret->md.osfd);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSYNC_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_delete (const char *name)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = unlink(name);
|
||||
if (rv == -1)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_UNLINK_ERROR(err);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getfileinfo (const char *fn, PRFileInfo *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt32 rv, err;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
rv = stat(fn, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_STAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
|
||||
/* Must truncate file size for the 32 bit
|
||||
version */
|
||||
info->size = (sb.st_size & 0xffffffff);
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt32 rv, err;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
rv = stat(fn, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_STAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
|
||||
/* For the 64 bit version we can use
|
||||
* the native st_size without modification
|
||||
*/
|
||||
info->size = sb.st_size;
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt64 s, s2us;
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fstat(fd->secret->md.osfd, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSTAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE ;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
/* Use lower 32 bits of file size */
|
||||
info->size = ( sb.st_size & 0xffffffff);
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt64 s, s2us;
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fstat(fd->secret->md.osfd, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSTAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE ;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
info->size = sb.st_size;
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_rename (const char *from, const char *to)
|
||||
{
|
||||
PRInt32 rv = -1, err;
|
||||
|
||||
/*
|
||||
** This is trying to enforce the semantics of WINDOZE' rename
|
||||
** operation. That means one is not allowed to rename over top
|
||||
** of an existing file. Holding a lock across these two function
|
||||
** and the open function is known to be a bad idea, but ....
|
||||
*/
|
||||
if (NULL != _pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
if (0 == access(to, F_OK))
|
||||
PR_SetError(PR_FILE_EXISTS_ERROR, 0);
|
||||
else
|
||||
{
|
||||
rv = rename(from, to);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_RENAME_ERROR(err);
|
||||
}
|
||||
}
|
||||
if (NULL != _pr_rename_lock)
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_access (const char *name, PRIntn how)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
int checkFlags;
|
||||
struct stat buf;
|
||||
|
||||
switch (how) {
|
||||
case PR_ACCESS_WRITE_OK:
|
||||
checkFlags = S_IWUSR | S_IWGRP | S_IWOTH;
|
||||
break;
|
||||
|
||||
case PR_ACCESS_READ_OK:
|
||||
checkFlags = S_IRUSR | S_IRGRP | S_IROTH;
|
||||
break;
|
||||
|
||||
case PR_ACCESS_EXISTS:
|
||||
/* we don't need to examine st_mode. */
|
||||
break;
|
||||
|
||||
default:
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = stat(name, &buf);
|
||||
if (rv == 0 && how != PR_ACCESS_EXISTS && (!(buf.st_mode & checkFlags))) {
|
||||
PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_STAT_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_stat (const char *name, struct stat *buf)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_mkdir (const char *name, PRIntn mode)
|
||||
{
|
||||
status_t rv;
|
||||
int err;
|
||||
|
||||
/*
|
||||
** This lock is used to enforce rename semantics as described
|
||||
** in PR_Rename. Look there for more fun details.
|
||||
*/
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
|
||||
rv = mkdir(name, mode);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_MKDIR_ERROR(err);
|
||||
}
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_rmdir (const char *name)
|
||||
{
|
||||
int rv, err;
|
||||
|
||||
rv = rmdir(name);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_RMDIR_ERROR(err);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv = 0;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
/*
|
||||
* This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
|
||||
*/
|
||||
fd_set rd, wt, ex;
|
||||
PRFileDesc *bottom;
|
||||
PRPollDesc *pd, *epd;
|
||||
PRInt32 maxfd = -1, ready, err;
|
||||
PRIntervalTime remaining, elapsed, start;
|
||||
|
||||
struct timeval tv, *tvp = NULL;
|
||||
|
||||
if (_PR_PENDING_INTERRUPT(me))
|
||||
{
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == npds) {
|
||||
PR_Sleep(timeout);
|
||||
return rv;
|
||||
}
|
||||
|
||||
FD_ZERO(&rd);
|
||||
FD_ZERO(&wt);
|
||||
FD_ZERO(&ex);
|
||||
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
PRInt16 in_flags_read = 0, in_flags_write = 0;
|
||||
PRInt16 out_flags_read = 0, out_flags_write = 0;
|
||||
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
if (pd->in_flags & PR_POLL_READ)
|
||||
{
|
||||
in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
|
||||
}
|
||||
if (pd->in_flags & PR_POLL_WRITE)
|
||||
{
|
||||
in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
|
||||
}
|
||||
if ((0 != (in_flags_read & out_flags_read))
|
||||
|| (0 != (in_flags_write & out_flags_write)))
|
||||
{
|
||||
/* this one's ready right now */
|
||||
if (0 == ready)
|
||||
{
|
||||
/*
|
||||
* We will have to return without calling the
|
||||
* system poll/select function. So zero the
|
||||
* out_flags fields of all the poll descriptors
|
||||
* before this one.
|
||||
*/
|
||||
PRPollDesc *prev;
|
||||
for (prev = pds; prev < pd; prev++)
|
||||
{
|
||||
prev->out_flags = 0;
|
||||
}
|
||||
}
|
||||
ready += 1;
|
||||
pd->out_flags = out_flags_read | out_flags_write;
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->out_flags = 0; /* pre-condition */
|
||||
|
||||
/* make sure this is an NSPR supported stack */
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
PR_ASSERT(NULL != bottom); /* what to do about that? */
|
||||
if ((NULL != bottom)
|
||||
&& (_PR_FILEDESC_OPEN == bottom->secret->state))
|
||||
{
|
||||
if (0 == ready)
|
||||
{
|
||||
PRInt32 osfd = bottom->secret->md.osfd;
|
||||
if (osfd > maxfd) maxfd = osfd;
|
||||
if (in_flags_read & PR_POLL_READ)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_READ_SYS_READ;
|
||||
FD_SET(osfd, &rd);
|
||||
}
|
||||
if (in_flags_read & PR_POLL_WRITE)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
|
||||
FD_SET(osfd, &wt);
|
||||
}
|
||||
if (in_flags_write & PR_POLL_READ)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
|
||||
FD_SET(osfd, &rd);
|
||||
}
|
||||
if (in_flags_write & PR_POLL_WRITE)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
|
||||
FD_SET(osfd, &wt);
|
||||
}
|
||||
if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == ready)
|
||||
{
|
||||
PRPollDesc *prev;
|
||||
for (prev = pds; prev < pd; prev++)
|
||||
{
|
||||
prev->out_flags = 0;
|
||||
}
|
||||
}
|
||||
ready += 1; /* this will cause an abrupt return */
|
||||
pd->out_flags = PR_POLL_NVAL; /* bogii */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->out_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != ready) return ready; /* no need to block */
|
||||
|
||||
remaining = timeout;
|
||||
start = PR_IntervalNow();
|
||||
|
||||
retry:
|
||||
if (timeout != PR_INTERVAL_NO_TIMEOUT)
|
||||
{
|
||||
PRInt32 ticksPerSecond = PR_TicksPerSecond();
|
||||
tv.tv_sec = remaining / ticksPerSecond;
|
||||
tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
|
||||
|
||||
if (ready == -1 && errno == EINTR)
|
||||
{
|
||||
if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
|
||||
else
|
||||
{
|
||||
elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
|
||||
if (elapsed > timeout) ready = 0; /* timed out */
|
||||
else
|
||||
{
|
||||
remaining = timeout - elapsed;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Now to unravel the select sets back into the client's poll
|
||||
** descriptor list. Is this possibly an area for pissing away
|
||||
** a few cycles or what?
|
||||
*/
|
||||
if (ready > 0)
|
||||
{
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
PRInt16 out_flags = 0;
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
PRInt32 osfd;
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
PR_ASSERT(NULL != bottom);
|
||||
|
||||
osfd = bottom->secret->md.osfd;
|
||||
|
||||
if (FD_ISSET(osfd, &rd))
|
||||
{
|
||||
if (pd->out_flags & _PR_POLL_READ_SYS_READ)
|
||||
out_flags |= PR_POLL_READ;
|
||||
if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
|
||||
out_flags |= PR_POLL_WRITE;
|
||||
}
|
||||
if (FD_ISSET(osfd, &wt))
|
||||
{
|
||||
if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
|
||||
out_flags |= PR_POLL_READ;
|
||||
if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
|
||||
out_flags |= PR_POLL_WRITE;
|
||||
}
|
||||
if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
|
||||
|
||||
/* Workaround for nonblocking connects under net_server */
|
||||
#ifndef BONE_VERSION
|
||||
if (out_flags)
|
||||
{
|
||||
/* check if it is a pending connect */
|
||||
int i = 0, j = 0;
|
||||
PR_Lock( _connectLock );
|
||||
for( i = 0; i < connectCount; i++ )
|
||||
{
|
||||
if(connectList[i].osfd == osfd)
|
||||
{
|
||||
int connectError;
|
||||
int connectResult;
|
||||
|
||||
connectResult = connect(connectList[i].osfd,
|
||||
&connectList[i].addr,
|
||||
connectList[i].addrlen);
|
||||
connectError = errno;
|
||||
|
||||
if(connectResult < 0 )
|
||||
{
|
||||
if(connectError == EINTR || connectError == EWOULDBLOCK ||
|
||||
connectError == EINPROGRESS || connectError == EALREADY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == (connectCount - 1))
|
||||
{
|
||||
connectList[i].osfd = -1;
|
||||
} else {
|
||||
for(j = i; j < connectCount; j++ )
|
||||
{
|
||||
memcpy( &connectList[j], &connectList[j+1],
|
||||
sizeof(connectList[j]));
|
||||
}
|
||||
}
|
||||
connectCount--;
|
||||
|
||||
bottom->secret->md.connectReturnValue = connectResult;
|
||||
bottom->secret->md.connectReturnError = connectError;
|
||||
bottom->secret->md.connectValueValid = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PR_Unlock( _connectLock );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pd->out_flags = out_flags;
|
||||
if (out_flags) ready++;
|
||||
}
|
||||
PR_ASSERT(ready > 0);
|
||||
}
|
||||
else if (ready < 0)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
if (err == EBADF)
|
||||
{
|
||||
/* Find the bad fds */
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
pd->out_flags = 0;
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
|
||||
{
|
||||
pd->out_flags = PR_POLL_NVAL;
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
}
|
||||
PR_ASSERT(ready > 0);
|
||||
}
|
||||
else _PR_MD_MAP_SELECT_ERROR(err);
|
||||
}
|
||||
|
||||
return ready;
|
||||
} /* _MD_pr_poll */
|
||||
|
||||
/*
|
||||
* File locking.
|
||||
*/
|
||||
|
||||
PRStatus
|
||||
_MD_lockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_SETLKW, &linfo);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_tlockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_SETLK, &linfo);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_unlockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_UNLCK, &linfo);
|
||||
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(void) _PR_MD_INIT_SEGS(void);
|
||||
PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
|
||||
PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg);
|
||||
@@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
PRLock *_connectLock = NULL;
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
/* Workaround for nonblocking connects under net_server */
|
||||
PRUint32 connectCount = 0;
|
||||
ConnectListNode connectList[64];
|
||||
#endif
|
||||
|
||||
void
|
||||
_MD_cleanup_before_exit (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_MD_exit (PRIntn status)
|
||||
{
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_early_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
static PRLock *monitor = NULL;
|
||||
|
||||
void
|
||||
_MD_final_init (void)
|
||||
{
|
||||
_connectLock = PR_NewLock();
|
||||
PR_ASSERT(NULL != _connectLock);
|
||||
#ifndef BONE_VERSION
|
||||
/* Workaround for nonblocking connects under net_server */
|
||||
connectCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_MD_AtomicInit (void)
|
||||
{
|
||||
if (monitor == NULL) {
|
||||
monitor = PR_NewLock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This is exceedingly messy. atomic_add returns the last value, NSPR expects the new value.
|
||||
** We just add or subtract 1 from the result. The actual memory update is atomic.
|
||||
*/
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicAdd( PRInt32 *ptr, PRInt32 val )
|
||||
{
|
||||
return( ( atomic_add( (long *)ptr, val ) ) + val );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicIncrement( PRInt32 *val )
|
||||
{
|
||||
return( ( atomic_add( (long *)val, 1 ) ) + 1 );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicDecrement( PRInt32 *val )
|
||||
{
|
||||
return( ( atomic_add( (long *)val, -1 ) ) - 1 );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicSet( PRInt32 *val, PRInt32 newval )
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
if (!_pr_initialized) {
|
||||
_PR_ImplicitInitialization();
|
||||
}
|
||||
PR_Lock(monitor);
|
||||
rv = *val;
|
||||
*val = newval;
|
||||
PR_Unlock(monitor);
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_EXTERN(PRInt32)
|
||||
_PR_MD_GET_MEM_MAP_ALIGNMENT(void)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
PR_EXTERN(void *)
|
||||
_PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_MEM_UNMAP(void *addr, PRUint32 size)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return PR_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,929 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/*
|
||||
* Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
|
||||
* PRInt32* pointer to a _PRSockLen_t* pointer.
|
||||
*/
|
||||
#define _PRSockLen_t int
|
||||
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
static PRMonitor *_pr_Xfe_mon = NULL;
|
||||
|
||||
#define READ_FD 1
|
||||
#define WRITE_FD 2
|
||||
|
||||
/*
|
||||
** This is a support routine to handle "deferred" i/o on sockets.
|
||||
** It uses "select", so it is subject to all of the BeOS limitations
|
||||
** (only READ notification, only sockets)
|
||||
*/
|
||||
|
||||
/*
|
||||
* socket_io_wait --
|
||||
*
|
||||
* wait for socket i/o, periodically checking for interrupt
|
||||
*
|
||||
*/
|
||||
|
||||
static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv = -1;
|
||||
struct timeval tv;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRIntervalTime epoch, now, elapsed, remaining;
|
||||
PRBool wait_for_remaining;
|
||||
PRInt32 syserror;
|
||||
fd_set rd_wr;
|
||||
|
||||
switch (timeout) {
|
||||
case PR_INTERVAL_NO_WAIT:
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
break;
|
||||
case PR_INTERVAL_NO_TIMEOUT:
|
||||
/*
|
||||
* This is a special case of the 'default' case below.
|
||||
* Please see the comments there.
|
||||
*/
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rd_wr);
|
||||
do {
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
|
||||
else
|
||||
rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
|
||||
if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
|
||||
#ifdef BONE_VERSION
|
||||
_PR_MD_MAP_SELECT_ERROR(syserror);
|
||||
#else
|
||||
if (syserror == EBADF) {
|
||||
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, syserror);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
default:
|
||||
now = epoch = PR_IntervalNow();
|
||||
remaining = timeout;
|
||||
FD_ZERO(&rd_wr);
|
||||
do {
|
||||
/*
|
||||
* We block in _MD_SELECT for at most
|
||||
* _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
|
||||
* so that there is an upper limit on the delay
|
||||
* before the interrupt bit is checked.
|
||||
*/
|
||||
wait_for_remaining = PR_TRUE;
|
||||
tv.tv_sec = PR_IntervalToSeconds(remaining);
|
||||
if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
|
||||
wait_for_remaining = PR_FALSE;
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
} else {
|
||||
tv.tv_usec = PR_IntervalToMicroseconds(
|
||||
remaining -
|
||||
PR_SecondsToInterval(tv.tv_sec));
|
||||
}
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
|
||||
else
|
||||
rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
|
||||
/*
|
||||
* we don't consider EINTR a real error
|
||||
*/
|
||||
if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
|
||||
#ifdef BONE_VERSION
|
||||
_PR_MD_MAP_SELECT_ERROR(syserror);
|
||||
#else
|
||||
if (syserror == EBADF) {
|
||||
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, syserror);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We loop again if _MD_SELECT timed out or got interrupted
|
||||
* by a signal, and the timeout deadline has not passed yet.
|
||||
*/
|
||||
if (rv == 0 || (rv == -1 && syserror == EINTR)) {
|
||||
/*
|
||||
* If _MD_SELECT timed out, we know how much time
|
||||
* we spent in blocking, so we can avoid a
|
||||
* PR_IntervalNow() call.
|
||||
*/
|
||||
if (rv == 0) {
|
||||
if (wait_for_remaining) {
|
||||
now += remaining;
|
||||
} else {
|
||||
now += PR_SecondsToInterval(tv.tv_sec)
|
||||
+ PR_MicrosecondsToInterval(tv.tv_usec);
|
||||
}
|
||||
} else {
|
||||
now = PR_IntervalNow();
|
||||
}
|
||||
elapsed = (PRIntervalTime) (now - epoch);
|
||||
if (elapsed >= timeout) {
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
} else {
|
||||
remaining = timeout - elapsed;
|
||||
}
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
|
||||
_PR_MD_MAP_RECV_ERROR(EPIPE);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
/*
|
||||
** Gah, stupid hack. If reading a zero amount, instantly return success.
|
||||
** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
|
||||
** mozilla use to check for socket availability.
|
||||
*/
|
||||
|
||||
if( 0 == amount ) return(0);
|
||||
#endif
|
||||
|
||||
while ((rv = recv(osfd, buf, amount, flags)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
/* If socket was supposed to be blocking,
|
||||
wait a while for the condition to be
|
||||
satisfied. */
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECV_ERROR(err);
|
||||
}
|
||||
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
|
||||
PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((*addrlen = PR_NETADDR_SIZE(addr)),
|
||||
((rv = recvfrom(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr,
|
||||
(_PRSockLen_t *)addrlen)) == -1)) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECVFROM_ERROR(err);
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if (rv != -1) {
|
||||
/* ignore the sa_len field of struct sockaddr */
|
||||
if (addr) {
|
||||
addr->raw.family = ((struct sockaddr *) addr)->sa_family;
|
||||
}
|
||||
}
|
||||
#endif /* _PR_HAVE_SOCKADDR_LEN */
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
|
||||
{
|
||||
_PR_MD_MAP_SEND_ERROR(EPIPE);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
while ((rv = send(osfd, buf, amount, flags)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* in UNIX implementations, you could do a socket_io_wait here.
|
||||
* but since BeOS doesn't yet support WRITE notification in select,
|
||||
* you're spanked.
|
||||
*/
|
||||
snooze( 10000L );
|
||||
continue;
|
||||
#else /* BONE_VERSION */
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
|
||||
goto done;
|
||||
#endif
|
||||
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
/*
|
||||
* optimization; if bytes sent is less than "amount" call
|
||||
* select before returning. This is because it is likely that
|
||||
* the next writev() call will return EWOULDBLOCK.
|
||||
*/
|
||||
if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
|
||||
&& (timeout != PR_INTERVAL_NO_WAIT)) {
|
||||
if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
|
||||
rv = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#endif /* BONE_VERSION */
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SEND_ERROR(err);
|
||||
}
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
done:
|
||||
#endif
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
|
||||
const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
PRNetAddr addrCopy;
|
||||
|
||||
addrCopy = *addr;
|
||||
((struct sockaddr *) &addrCopy)->sa_len = addrlen;
|
||||
((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
|
||||
|
||||
while ((rv = sendto(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) &addrCopy, addrlen)) == -1) {
|
||||
#else
|
||||
while ((rv = sendto(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr, addrlen)) == -1) {
|
||||
#endif
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
|
||||
goto done;
|
||||
#endif
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SENDTO_ERROR(err);
|
||||
}
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
done:
|
||||
#endif
|
||||
return(rv);
|
||||
}
|
||||
|
||||
#ifdef BONE_VERSION
|
||||
|
||||
PRInt32 _MD_writev(
|
||||
PRFileDesc *fd, const PRIOVec *iov,
|
||||
PRInt32 iov_size, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRInt32 index, amount = 0;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
/*
|
||||
* Calculate the total number of bytes to be sent; needed for
|
||||
* optimization later.
|
||||
* We could avoid this if this number was passed in; but it is
|
||||
* probably not a big deal because iov_size is usually small (less than
|
||||
* 3)
|
||||
*/
|
||||
if (!fd->secret->nonblocking) {
|
||||
for (index=0; index<iov_size; index++) {
|
||||
amount += iov[index].iov_len;
|
||||
}
|
||||
}
|
||||
|
||||
while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
|
||||
goto done;
|
||||
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* optimization; if bytes sent is less than "amount" call
|
||||
* select before returning. This is because it is likely that
|
||||
* the next writev() call will return EWOULDBLOCK.
|
||||
*/
|
||||
if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
|
||||
&& (timeout != PR_INTERVAL_NO_WAIT)) {
|
||||
if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
|
||||
rv = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_WRITEV_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
#endif /* BONE_VERSION */
|
||||
|
||||
PRInt32
|
||||
_MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = accept(osfd, (struct sockaddr *) addr,
|
||||
(_PRSockLen_t *)addrlen)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
/* If it's SUPPOSED to be a blocking thread, wait
|
||||
* a while to see if the triggering condition gets
|
||||
* satisfied.
|
||||
*/
|
||||
/* Assume that we're always using a native thread */
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_ACCEPT_ERROR(err);
|
||||
} else if (addr != NULL) {
|
||||
/* bug 134099 */
|
||||
err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
|
||||
}
|
||||
done:
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if (rv != -1) {
|
||||
/* Mask off the first byte of struct sockaddr (the length field) */
|
||||
if (addr) {
|
||||
addr->raw.family = ((struct sockaddr *) addr)->sa_family;
|
||||
}
|
||||
}
|
||||
#endif /* _PR_HAVE_SOCKADDR_LEN */
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
fd->secret->md.connectValueValid = PR_FALSE;
|
||||
#endif
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
PRNetAddr addrCopy;
|
||||
|
||||
addrCopy = *addr;
|
||||
((struct sockaddr *) &addrCopy)->sa_len = addrlen;
|
||||
((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
|
||||
#endif
|
||||
|
||||
/* (Copied from unix.c)
|
||||
* We initiate the connection setup by making a nonblocking connect()
|
||||
* call. If the connect() call fails, there are two cases we handle
|
||||
* specially:
|
||||
* 1. The connect() call was interrupted by a signal. In this case
|
||||
* we simply retry connect().
|
||||
* 2. The NSPR socket is nonblocking and connect() fails with
|
||||
* EINPROGRESS. We first wait until the socket becomes writable.
|
||||
* Then we try to find out whether the connection setup succeeded
|
||||
* or failed.
|
||||
*/
|
||||
|
||||
retry:
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
|
||||
#else
|
||||
if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
|
||||
#endif
|
||||
err = _MD_ERRNO();
|
||||
#ifndef BONE_VERSION
|
||||
fd->secret->md.connectReturnValue = rv;
|
||||
fd->secret->md.connectReturnError = err;
|
||||
fd->secret->md.connectValueValid = PR_TRUE;
|
||||
#endif
|
||||
if( err == EINTR ) {
|
||||
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
#ifndef BONE_VERSION
|
||||
snooze( 100000L );
|
||||
#endif
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
|
||||
|
||||
/*
|
||||
** There's no timeout on this connect, but that's not
|
||||
** a big deal, since the connect times out anyways
|
||||
** after 30 seconds. Just sleep for 1/10th of a second
|
||||
** and retry until we go through or die.
|
||||
*/
|
||||
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
|
||||
PR_Lock(_connectLock);
|
||||
if (connectCount < sizeof(connectList)/sizeof(connectList[0])) {
|
||||
connectList[connectCount].osfd = osfd;
|
||||
memcpy(&connectList[connectCount].addr, addr, addrlen);
|
||||
connectList[connectCount].addrlen = addrlen;
|
||||
connectList[connectCount].timeout = timeout;
|
||||
connectCount++;
|
||||
PR_Unlock(_connectLock);
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
} else {
|
||||
PR_Unlock(_connectLock);
|
||||
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#else /* BONE_VERSION */
|
||||
if(!fd->secret->nonblocking && (err == EINTR)) {
|
||||
|
||||
rv = socket_io_wait(osfd, WRITE_FD, timeout);
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PR_ASSERT(rv == 1);
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
err = _MD_beos_get_nonblocking_connect_error(osfd);
|
||||
if (err != 0) {
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
PRNetAddr addrCopy;
|
||||
|
||||
addrCopy = *addr;
|
||||
((struct sockaddr *) &addrCopy)->sa_len = addrlen;
|
||||
((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
|
||||
rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
|
||||
#else
|
||||
rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
|
||||
#endif
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_BIND_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_listen (PRFileDesc *fd, PRIntn backlog)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
/* Bug workaround! Setting listen to 0 on Be accepts no connections.
|
||||
** On most UN*Xes this sets the default.
|
||||
*/
|
||||
|
||||
if( backlog == 0 ) backlog = 5;
|
||||
#endif
|
||||
|
||||
rv = listen(fd->secret->md.osfd, backlog);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LISTEN_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_shutdown (PRFileDesc *fd, PRIntn how)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
if (how == PR_SHUTDOWN_SEND)
|
||||
fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
|
||||
else if (how == PR_SHUTDOWN_RCV)
|
||||
fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
|
||||
else if (how == PR_SHUTDOWN_BOTH) {
|
||||
fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else /* BONE_VERSION */
|
||||
rv = shutdown(fd->secret->md.osfd, how);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SHUTDOWN_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
#endif
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_close_socket (PRInt32 osfd)
|
||||
{
|
||||
#ifdef BONE_VERSION
|
||||
close( osfd );
|
||||
#else
|
||||
closesocket( osfd );
|
||||
#endif
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockname(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if (rv == 0) {
|
||||
/* ignore the sa_len field of struct sockaddr */
|
||||
if (addr) {
|
||||
addr->raw.family = ((struct sockaddr *) addr)->sa_family;
|
||||
}
|
||||
}
|
||||
#endif /* _PR_HAVE_SOCKADDR_LEN */
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETSOCKNAME_ERROR(err);
|
||||
}
|
||||
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getpeername(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
|
||||
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if (rv == 0) {
|
||||
/* ignore the sa_len field of struct sockaddr */
|
||||
if (addr) {
|
||||
addr->raw.family = ((struct sockaddr *) addr)->sa_family;
|
||||
}
|
||||
}
|
||||
#endif /* _PR_HAVE_SOCKADDR_LEN */
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETPEERNAME_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getsockopt (PRFileDesc *fd, PRInt32 level,
|
||||
PRInt32 optname, char* optval, PRInt32* optlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockopt(fd->secret->md.osfd, level, optname,
|
||||
optval, (_PRSockLen_t *)optlen);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETSOCKOPT_ERROR(err);
|
||||
}
|
||||
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_setsockopt (PRFileDesc *fd, PRInt32 level,
|
||||
PRInt32 optname, const char* optval, PRInt32 optlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SETSOCKOPT_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
|
||||
void *buf, PRInt32 amount, PRIntervalTime timeout)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
PRInt32
|
||||
_MD_socket (int af, int type, int flags)
|
||||
{
|
||||
PRInt32 osfd, err;
|
||||
|
||||
osfd = socket( af, type, 0 );
|
||||
|
||||
if( -1 == osfd ) {
|
||||
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SOCKET_ERROR( err );
|
||||
}
|
||||
|
||||
return( osfd );
|
||||
}
|
||||
#else
|
||||
PRInt32
|
||||
_MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
|
||||
{
|
||||
PRInt32 osfd, err;
|
||||
|
||||
osfd = socket(domain, type, proto);
|
||||
|
||||
if (osfd == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SOCKET_ERROR(err);
|
||||
}
|
||||
|
||||
return(osfd);
|
||||
}
|
||||
#endif
|
||||
|
||||
PRInt32
|
||||
_MD_socketavailable (PRFileDesc *fd)
|
||||
{
|
||||
#ifdef BONE_VERSION
|
||||
PRInt32 result;
|
||||
|
||||
if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
|
||||
_PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_get_socket_error (void)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_gethostname (char *name, PRUint32 namelen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = gethostname(name, namelen);
|
||||
if (rv == 0)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETHOSTNAME_ERROR(err);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
PRInt32
|
||||
_MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
|
||||
{
|
||||
int rv;
|
||||
int flags = 0;
|
||||
|
||||
rv = recv(fd->secret->md.osfd, NULL, 0, flags);
|
||||
PR_ASSERT(-1 == rv || 0 == rv);
|
||||
if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
return errno;
|
||||
}
|
||||
return 0; /* no error */
|
||||
}
|
||||
#else
|
||||
PRInt32
|
||||
_MD_beos_get_nonblocking_connect_error(int osfd)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
// int err;
|
||||
// _PRSockLen_t optlen = sizeof(err);
|
||||
// if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
|
||||
// return errno;
|
||||
// } else {
|
||||
// return err;
|
||||
// }
|
||||
}
|
||||
#endif /* BONE_VERSION */
|
||||
@@ -0,0 +1,237 @@
|
||||
/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define _PR_SIGNALED_EXITSTATUS 256
|
||||
|
||||
PRProcess*
|
||||
_MD_create_process (const char *path, char *const *argv,
|
||||
char *const *envp, const PRProcessAttr *attr)
|
||||
{
|
||||
PRProcess *process;
|
||||
int nEnv, idx;
|
||||
char *const *childEnvp;
|
||||
char **newEnvp = NULL;
|
||||
int flags;
|
||||
|
||||
process = PR_NEW(PRProcess);
|
||||
if (!process) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
childEnvp = envp;
|
||||
if (attr && attr->fdInheritBuffer) {
|
||||
if (NULL == childEnvp) {
|
||||
childEnvp = environ;
|
||||
}
|
||||
for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
|
||||
}
|
||||
newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
|
||||
if (NULL == newEnvp) {
|
||||
PR_DELETE(process);
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
return NULL;
|
||||
}
|
||||
for (idx = 0; idx < nEnv; idx++) {
|
||||
newEnvp[idx] = childEnvp[idx];
|
||||
}
|
||||
newEnvp[idx++] = attr->fdInheritBuffer;
|
||||
newEnvp[idx] = NULL;
|
||||
childEnvp = newEnvp;
|
||||
}
|
||||
|
||||
process->md.pid = fork();
|
||||
|
||||
if ((pid_t) -1 == process->md.pid) {
|
||||
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
|
||||
PR_DELETE(process);
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
return NULL;
|
||||
} else if (0 == process->md.pid) { /* the child process */
|
||||
/*
|
||||
* If the child process needs to exit, it must call _exit().
|
||||
* Do not call exit(), because exit() will flush and close
|
||||
* the standard I/O file descriptors, and hence corrupt
|
||||
* the parent process's standard I/O data structures.
|
||||
*/
|
||||
|
||||
if (attr) {
|
||||
/* the osfd's to redirect stdin, stdout, and stderr to */
|
||||
int in_osfd = -1, out_osfd = -1, err_osfd = -1;
|
||||
|
||||
if (attr->stdinFd
|
||||
&& attr->stdinFd->secret->md.osfd != 0) {
|
||||
in_osfd = attr->stdinFd->secret->md.osfd;
|
||||
if (dup2(in_osfd, 0) != 0) {
|
||||
_exit(1); /* failed */
|
||||
}
|
||||
flags = fcntl(0, F_GETFL, 0);
|
||||
if (flags & O_NONBLOCK) {
|
||||
fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
if (attr->stdoutFd
|
||||
&& attr->stdoutFd->secret->md.osfd != 1) {
|
||||
out_osfd = attr->stdoutFd->secret->md.osfd;
|
||||
if (dup2(out_osfd, 1) != 1) {
|
||||
_exit(1); /* failed */
|
||||
}
|
||||
flags = fcntl(1, F_GETFL, 0);
|
||||
if (flags & O_NONBLOCK) {
|
||||
fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
if (attr->stderrFd
|
||||
&& attr->stderrFd->secret->md.osfd != 2) {
|
||||
err_osfd = attr->stderrFd->secret->md.osfd;
|
||||
if (dup2(err_osfd, 2) != 2) {
|
||||
_exit(1); /* failed */
|
||||
}
|
||||
flags = fcntl(2, F_GETFL, 0);
|
||||
if (flags & O_NONBLOCK) {
|
||||
fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
if (in_osfd != -1) {
|
||||
close(in_osfd);
|
||||
}
|
||||
if (out_osfd != -1 && out_osfd != in_osfd) {
|
||||
close(out_osfd);
|
||||
}
|
||||
if (err_osfd != -1 && err_osfd != in_osfd
|
||||
&& err_osfd != out_osfd) {
|
||||
close(err_osfd);
|
||||
}
|
||||
if (attr->currentDirectory) {
|
||||
if (chdir(attr->currentDirectory) < 0) {
|
||||
_exit(1); /* failed */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (childEnvp) {
|
||||
(void)execve(path, argv, childEnvp);
|
||||
} else {
|
||||
/* Inherit the environment of the parent. */
|
||||
(void)execv(path, argv);
|
||||
}
|
||||
/* Whoops! It returned. That's a bad sign. */
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_detach_process (PRProcess *process)
|
||||
{
|
||||
/* If we kept a process table like unix does,
|
||||
* we'd remove the entry here.
|
||||
* Since we dont', just delete the process variable
|
||||
*/
|
||||
PR_DELETE(process);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_wait_process (PRProcess *process, PRInt32 *exitCode)
|
||||
{
|
||||
PRStatus retVal = PR_SUCCESS;
|
||||
int ret, status;
|
||||
|
||||
/* Ignore interruptions */
|
||||
do {
|
||||
ret = waitpid(process->md.pid, &status, 0);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
/*
|
||||
* waitpid() cannot return 0 because we did not invoke it
|
||||
* with the WNOHANG option.
|
||||
*/
|
||||
PR_ASSERT(0 != ret);
|
||||
|
||||
if (ret < 0) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/* If child process exited normally, return child exit code */
|
||||
if (WIFEXITED(status)) {
|
||||
*exitCode = WEXITSTATUS(status);
|
||||
} else {
|
||||
PR_ASSERT(WIFSIGNALED(status));
|
||||
*exitCode = _PR_SIGNALED_EXITSTATUS;
|
||||
}
|
||||
|
||||
PR_DELETE(process);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_kill_process (PRProcess *process)
|
||||
{
|
||||
PRErrorCode prerror;
|
||||
PRInt32 oserror;
|
||||
|
||||
if (kill(process->md.pid, SIGKILL) == 0) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
oserror = errno;
|
||||
switch (oserror) {
|
||||
case EPERM:
|
||||
prerror = PR_NO_ACCESS_RIGHTS_ERROR;
|
||||
break;
|
||||
case ESRCH:
|
||||
prerror = PR_INVALID_ARGUMENT_ERROR;
|
||||
break;
|
||||
default:
|
||||
prerror = PR_UNKNOWN_ERROR;
|
||||
break;
|
||||
}
|
||||
PR_SetError(prerror, oserror);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include "primpl.h"
|
||||
|
||||
extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
|
||||
{
|
||||
struct timeval tv;
|
||||
int n = 0;
|
||||
int s;
|
||||
|
||||
GETTIMEOFDAY(&tv);
|
||||
|
||||
if ( size >= 0 ) {
|
||||
s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
|
||||
size -= s;
|
||||
n += s;
|
||||
}
|
||||
if ( size >= 0 ) {
|
||||
s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
|
||||
size -= s;
|
||||
n += s;
|
||||
}
|
||||
|
||||
return n;
|
||||
} /* end _PR_MD_GetRandomNoise() */
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_init_segs (void)
|
||||
{
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_alloc_segment (PRSegment *seg, PRUint32 size, void *vaddr)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_free_segment (PRSegment *seg)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
# this file lists the source files to be compiled (used in Makefile) and
|
||||
# then enumerated as object files (in objs.mk) for inclusion in the NSPR
|
||||
# shared library
|
||||
|
||||
MDCSRCS = \
|
||||
beos.c \
|
||||
beos_errors.c \
|
||||
bfile.c \
|
||||
bmisc.c \
|
||||
bnet.c \
|
||||
bproc.c \
|
||||
brng.c \
|
||||
bseg.c \
|
||||
btime.c \
|
||||
bmmap.c \
|
||||
$(NULL)
|
||||
@@ -0,0 +1,75 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
#include <kernel/OS.h>
|
||||
|
||||
static bigtime_t start;
|
||||
|
||||
PRTime
|
||||
_MD_now (void)
|
||||
{
|
||||
return (PRTime)real_time_clock_usecs();
|
||||
}
|
||||
|
||||
void
|
||||
_MD_interval_init (void)
|
||||
{
|
||||
/* grab the base interval time */
|
||||
start = real_time_clock_usecs();
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_MD_get_interval (void)
|
||||
{
|
||||
return( (PRIntervalTime) real_time_clock_usecs() / 10 );
|
||||
|
||||
#if 0
|
||||
/* return the number of tens of microseconds that have elapsed since
|
||||
we were initialized */
|
||||
bigtime_t now = real_time_clock_usecs();
|
||||
now -= start;
|
||||
now /= 10;
|
||||
return (PRIntervalTime)now;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_MD_interval_per_sec (void)
|
||||
{
|
||||
return 100000L;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# This makefile appends to the variable OBJS the platform-dependent
|
||||
# object modules that will be part of the nspr20 library.
|
||||
|
||||
include $(srcdir)/md/beos/bsrcs.mk
|
||||
|
||||
OBJS += $(MDCSRCS:%.c=md/beos/$(OBJDIR)/%.$(OBJ_SUFFIX))
|
||||
@@ -0,0 +1,18 @@
|
||||
/MANIFEST/1.1/Thu Jun 4 22:51:07 1998//
|
||||
/MacErrorHandling.h/3.4/Sun Apr 25 15:00:59 2004//
|
||||
/macdll.c/3.12/Sun Apr 25 15:00:59 2004//
|
||||
/macdll.h/1.5/Sun Apr 25 15:00:59 2004//
|
||||
/macio.c/3.37/Sun Apr 25 15:00:59 2004//
|
||||
/macio.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/macrng.c/1.7/Sun Apr 25 15:00:59 2004//
|
||||
/macsocket.h/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/macsockotpt.c/3.42/Sun Apr 25 15:00:59 2004//
|
||||
/macthr.c/3.22/Sun Apr 25 15:00:59 2004//
|
||||
/mactime.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/mactime.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/mdcriticalregion.c/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/mdcriticalregion.h/1.3/Sun Apr 25 15:00:59 2004//
|
||||
/mdmac.c/3.20/Mon Nov 7 22:39:01 2005//
|
||||
/mdmac.h/1.4/Sun Apr 25 15:00:59 2004//
|
||||
/prcpucfg.h/3.11/Sun Apr 25 15:00:59 2004//
|
||||
D
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md/mac
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
MacErrorHandling.h
|
||||
macsocket.h
|
||||
prcpucfg.h
|
||||
@@ -0,0 +1,668 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
FILENAME
|
||||
Exceptions.h
|
||||
|
||||
DESCRIPTION
|
||||
A collection of routines and macros to handle assertions and
|
||||
exceptions.
|
||||
|
||||
COPYRIGHT
|
||||
Copyright © Apple Computer, Inc. 1989-1991
|
||||
All rights reserved.
|
||||
|
||||
ROUTINES
|
||||
EXTERNALS
|
||||
dprintf
|
||||
check_dprintf
|
||||
checkpos_dprintf
|
||||
|
||||
MACROS
|
||||
EXTERNALS
|
||||
check
|
||||
ncheck
|
||||
check_action
|
||||
ncheck_action
|
||||
require
|
||||
nrequire
|
||||
require_action
|
||||
nrequire_action
|
||||
resume
|
||||
|
||||
MODIFICATION HISTORY
|
||||
Nov 12 95 BKJ Moved to MetroWerks environment & the NSPR
|
||||
|
||||
NOTE
|
||||
To keep code size down, use these routines and macros with the C
|
||||
compiler option -b2 or -b3. This will eliminate duplicate strings
|
||||
within a procedure.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef __MACERRORHANDLING__
|
||||
#define __MACERRORHANDLING__
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
INCLUDES
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <Types.h>
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
CONSTANTS AND CONTROL
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
These defines are used to control the amount of information
|
||||
displayed when an assertion fails. DEBUGOFF and WARN will run
|
||||
silently. MIN will simply break into the debugger. ON will break
|
||||
and display the assertion that failed and the exception (for
|
||||
require statements). FULL will also display the source file name
|
||||
and line number. SYM does a SysBreak and is usefull when using a
|
||||
symbolic debugger like SourceBug or SADE. They should be set into
|
||||
DEBUGLEVEL. The default LEVEL is OFF.
|
||||
*/
|
||||
|
||||
#define DEBUGOFF 0
|
||||
#define DEBUGWARN 1
|
||||
#define DEBUGMIN 2
|
||||
#define DEBUGON 3
|
||||
#define DEBUGFULL 4
|
||||
#define DEBUGSYM 6
|
||||
|
||||
#ifndef DEBUGLEVEL
|
||||
#define DEBUGLEVEL DEBUGOFF
|
||||
#endif DEBUGLEVEL
|
||||
|
||||
/*
|
||||
resumeLabel is used to control the insertion of labels for use with
|
||||
the resume macro. If you do not use the resume macro and you wish
|
||||
to have multible exceptions per label then you can add the
|
||||
following define to you source code.
|
||||
|
||||
*/
|
||||
#define resumeLabel(exception) // Multiple exceptions per label
|
||||
// #define resumeLabel(exception) resume_ ## exception: // Single exception per label
|
||||
|
||||
|
||||
/*
|
||||
traceon and debugon are used to test for options
|
||||
*/
|
||||
|
||||
#define traceon ((DEBUGLEVEL > DEBUGWARN) && defined(TRACEON))
|
||||
#define debugon (DEBUGLEVEL > DEBUGWARN)
|
||||
|
||||
/*
|
||||
Add some macros for DEBUGMIN and DEBUGSYM to keep the size down.
|
||||
*/
|
||||
|
||||
#define __DEBUGSMALL ((DEBUGLEVEL == DEBUGMIN) || \
|
||||
(DEBUGLEVEL == DEBUGSYM))
|
||||
|
||||
#if DEBUGLEVEL == DEBUGMIN
|
||||
#define __DebuggerBreak Debugger()
|
||||
#elif DEBUGLEVEL == DEBUGSYM
|
||||
#define __DebuggerBreak SysBreak()
|
||||
#endif
|
||||
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
check(assertion)
|
||||
|
||||
DESCRIPTION
|
||||
If debugging is on then check will test assertion and if it fails
|
||||
break into the debugger. Otherwise check does nothing.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define check(assertion) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else __DebuggerBreak; \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define check(assertion) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define check(assertion) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __FILE__, __LINE__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define check(assertion)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
ncheck(assertion)
|
||||
|
||||
DESCRIPTION
|
||||
If debugging is on then ncheck will test !assertion and if it fails
|
||||
break into the debugger. Otherwise ncheck does nothing.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define ncheck(assertion) \
|
||||
do { \
|
||||
if (assertion) __DebuggerBreak; \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define ncheck(assertion) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
|
||||
#assertion, __privateAssertion); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define ncheck(assertion) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __privateAssertion, __FILE__, __LINE__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define ncheck(assertion)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
check_action(assertion, action)
|
||||
|
||||
DESCRIPTION
|
||||
If debugging is on then check_action will test assertion and if it
|
||||
fails break into the debugger then execute action. Otherwise
|
||||
check_action does nothing.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define check_action(assertion, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
__DebuggerBreak; \
|
||||
{ action } \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define check_action(assertion, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
|
||||
{ action } \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define check_action(assertion, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __FILE__, __LINE__); \
|
||||
{ action } \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define check_action(assertion, action)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/**************************************************************************************
|
||||
|
||||
MACRO
|
||||
ncheck_action(assertion, action)
|
||||
|
||||
DESCRIPTION
|
||||
If debugging is on then ncheck_action will test !assertion and if
|
||||
it fails break into the debugger then execute action. Otherwise
|
||||
ncheck_action does nothing.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define ncheck_action(assertion, action) \
|
||||
do { \
|
||||
if (assertion) { \
|
||||
__DebuggerBreak; \
|
||||
{ action } \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define ncheck_action(assertion, action) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
|
||||
#assertion, __privateAssertion); \
|
||||
{ action } \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define ncheck_action(assertion, action) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __privateAssertion, __FILE__, __LINE__); \
|
||||
{ action } \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define ncheck_action(assertion, action)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
require(assertion, exception)
|
||||
|
||||
DESCRIPTION
|
||||
require will test assertion and if it fails:
|
||||
break into the debugger if debugging is on.
|
||||
goto exception.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define require(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
__DebuggerBreak; \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define require(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"Exception \"%s\" Raised", \
|
||||
#assertion, #exception); \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define require(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"Exception \"%s\" Raised\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, #exception, __FILE__, __LINE__); \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define require(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
nrequire(assertion, exception)
|
||||
|
||||
DESCRIPTION
|
||||
nrequire will test !assertion and if it fails:
|
||||
break into the debugger if debugging is on.
|
||||
goto exception.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define nrequire(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) { \
|
||||
DebugStr(); \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define nrequire(assertion, exception) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"Exception \"%s\" Raised", \
|
||||
#assertion, __privateAssertion, #exception); \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define nrequire(assertion, exception) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"Exception \"%s\" Raised\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __privateAssertion, #exception, __FILE__, \
|
||||
__LINE__); \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define nrequire(assertion, exception) \
|
||||
do { \
|
||||
if (assertion) { \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
require_action(assertion, exception, action)
|
||||
|
||||
DESCRIPTION
|
||||
require_action will test assertion and if it fails:
|
||||
break into the debugger if debugging is on.
|
||||
execute action.
|
||||
goto exception.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define require_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
__DebuggerBreak; \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define require_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"Exception \"%s\" Raised", \
|
||||
#assertion, #exception); \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define require_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
dprintf(notrace, "Assertion \"%s\" Failed\n" \
|
||||
"Exception \"%s\" Raised\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, #exception, __FILE__, __LINE__); \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define require_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) ; \
|
||||
else { \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
nrequire_action(assertion, exception, action)
|
||||
|
||||
DESCRIPTION
|
||||
nrequire_action will test !assertion and if it fails:
|
||||
break into the debugger if debugging is on.
|
||||
execute action.
|
||||
goto exception.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if __DEBUGSMALL
|
||||
|
||||
#define nrequire_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) { \
|
||||
__DebuggerBreak; \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGON
|
||||
|
||||
#define nrequire_action(assertion, exception, action) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"Exception \"%s\" Raised", \
|
||||
#assertion, __privateAssertion, #exception); \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#elif DEBUGLEVEL == DEBUGFULL
|
||||
|
||||
#define nrequire_action(assertion, exception, action) \
|
||||
do { \
|
||||
void* __privateAssertion = (void*)(assertion); \
|
||||
\
|
||||
if (__privateAssertion) { \
|
||||
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
|
||||
"Exception \"%s\" Raised\n" \
|
||||
"File: %s\n" \
|
||||
"Line: %d", \
|
||||
#assertion, __privateAssertion, #exception, __FILE__, \
|
||||
__LINE__); \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define nrequire_action(assertion, exception, action) \
|
||||
do { \
|
||||
if (assertion) { \
|
||||
{ action } \
|
||||
goto exception; \
|
||||
resumeLabel(exception); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/*<FF>*/
|
||||
/*********************************************************************
|
||||
|
||||
MACRO
|
||||
resume(exception)
|
||||
|
||||
DESCRIPTION
|
||||
resume will resume execution after the n/require/_action statement
|
||||
specified by exception. Resume lables must be on (the default) in
|
||||
order to use resume. If an action form of require was used then the
|
||||
action will not be re-executed.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
#define resume(exception) \
|
||||
do { \
|
||||
goto resume_ ## exception; \
|
||||
} while (false)
|
||||
|
||||
|
||||
/*<FF>*/
|
||||
/********************************************************************/
|
||||
#endif
|
||||
@@ -0,0 +1,587 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Files.h>
|
||||
#include <Errors.h>
|
||||
#include <Folders.h>
|
||||
#include <CodeFragments.h>
|
||||
#include <Aliases.h>
|
||||
#include <Resources.h>
|
||||
|
||||
#include "IterateDirectory.h" /* MoreFiles */
|
||||
|
||||
#include "MacErrorHandling.h"
|
||||
#include "macdll.h"
|
||||
#include "mdmac.h"
|
||||
#include "macio.h"
|
||||
|
||||
#include "primpl.h"
|
||||
#include "plstr.h"
|
||||
|
||||
/*
|
||||
turds used to iterate through the directories looking
|
||||
for the desired library.
|
||||
*/
|
||||
|
||||
struct GetSharedLibraryFilterProcData
|
||||
{
|
||||
Boolean inRecursive;
|
||||
StringPtr inName;
|
||||
|
||||
Boolean outFound;
|
||||
CFragConnectionID outID;
|
||||
Ptr outAddress;
|
||||
OSErr outError;
|
||||
};
|
||||
typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
|
||||
|
||||
static pascal void
|
||||
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
|
||||
|
||||
|
||||
/*
|
||||
NSGetSharedLibrary
|
||||
|
||||
Unfortunately CFM doesn't support user specified loader paths,
|
||||
so we emulate the behavior. Effectively this is a GetSharedLibrary
|
||||
where the loader path is user defined.
|
||||
*/
|
||||
|
||||
OSErr
|
||||
NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
|
||||
{
|
||||
char* curLibPath;
|
||||
char* freeCurLibPath;
|
||||
OSErr tempErr;
|
||||
Boolean recursive;
|
||||
FSSpec curFolder;
|
||||
GetSharedLibraryFilterProcData filterData;
|
||||
char *endCurLibPath;
|
||||
Boolean done;
|
||||
|
||||
filterData.outFound = false;
|
||||
filterData.outID = (CFragConnectionID)(-1);
|
||||
filterData.outAddress = NULL;
|
||||
filterData.inName = inLibName;
|
||||
|
||||
freeCurLibPath = curLibPath = PR_GetLibraryPath();
|
||||
|
||||
if (curLibPath == NULL)
|
||||
return (cfragNoLibraryErr);
|
||||
|
||||
tempErr = cfragNoLibraryErr;
|
||||
|
||||
do
|
||||
{
|
||||
endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
|
||||
done = (endCurLibPath == NULL);
|
||||
|
||||
#if 0
|
||||
// we overload the first character of a path if it's :
|
||||
// then we want to recursively search that path
|
||||
// see if path should be recursive
|
||||
if (*curLibPath == ':')
|
||||
{
|
||||
// ':' is an illegal character in the name of a file
|
||||
// if we start any path with this, we want to allow
|
||||
// search recursively
|
||||
curLibPath++;
|
||||
recursive = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
if (!done)
|
||||
*endCurLibPath = '\0'; // NULL terminate the string
|
||||
|
||||
// convert to FSSpec
|
||||
tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);
|
||||
|
||||
// now look in this directory
|
||||
if (noErr == tempErr)
|
||||
{
|
||||
filterData.inRecursive = recursive;
|
||||
FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
|
||||
|
||||
if (filterData.outFound)
|
||||
{
|
||||
*outID = filterData.outID;
|
||||
*outMainAddr = filterData.outAddress;
|
||||
tempErr = noErr;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempErr = cfragNoLibraryErr;
|
||||
}
|
||||
}
|
||||
|
||||
curLibPath = endCurLibPath + 1; // skip to next path (past the '\0');
|
||||
} while (!done);
|
||||
|
||||
free(freeCurLibPath);
|
||||
return (tempErr);
|
||||
}
|
||||
|
||||
|
||||
static Boolean
|
||||
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
|
||||
|
||||
|
||||
/*
|
||||
GetSharedLibraryFilterProc
|
||||
|
||||
Callback to FSpIterateDirectory, finds a library with the name matching the
|
||||
data in inFilterData (of type GetSharedLibraryFilterProcData). Forces a quit
|
||||
when a match is found.
|
||||
*/
|
||||
|
||||
static pascal void
|
||||
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
|
||||
{
|
||||
GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
|
||||
|
||||
if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
|
||||
{
|
||||
FSSpec fragSpec;
|
||||
OSErr tempErr;
|
||||
Str255 errName;
|
||||
Boolean crap;
|
||||
UInt32 codeOffset;
|
||||
UInt32 codeLength;
|
||||
|
||||
// it's a file
|
||||
|
||||
// ¥ fix-me do we really want to allow all 'APPL's' for in which to find this library?
|
||||
switch (inCpb->hFileInfo.ioFlFndrInfo.fdType)
|
||||
{
|
||||
case kCFragLibraryFileType:
|
||||
case 'APPL':
|
||||
tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
|
||||
|
||||
// this shouldn't fail
|
||||
if (noErr != tempErr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// resolve an alias if this was one
|
||||
tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
|
||||
|
||||
// if got here we have a shlb (or app-like shlb)
|
||||
if (noErr != tempErr)
|
||||
{
|
||||
// probably couldn't resolve an alias
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// see if this symbol is in this fragment
|
||||
if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
|
||||
tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
|
||||
else
|
||||
return;
|
||||
|
||||
// stop if we found a library by that name
|
||||
if (noErr == tempErr)
|
||||
{
|
||||
*inWantQuit = true;
|
||||
pFilterData->outFound = true;
|
||||
pFilterData->outError = tempErr;
|
||||
}
|
||||
}
|
||||
// FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
LibInPefContainer
|
||||
|
||||
Tell whether library inName is contained it the file pointed to by inSpec.
|
||||
Return the codeOffset and codeLength information, for a subsequent
|
||||
call to GetDiskFragment.
|
||||
*/
|
||||
|
||||
static Boolean
|
||||
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
|
||||
{
|
||||
short refNum;
|
||||
CFragResourceHandle hCfrg;
|
||||
CFragResourceMember* pCurItem;
|
||||
UInt32 curLibIndex;
|
||||
Boolean found;
|
||||
|
||||
// asume we didn't find it
|
||||
found = false;
|
||||
|
||||
// open the resource fork, if we can't bail
|
||||
refNum = FSpOpenResFile(inSpec, fsRdPerm);
|
||||
require(-1 != refNum, Exit);
|
||||
|
||||
// grab out the alias record, if it's not there bail
|
||||
hCfrg = (CFragResourceHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
|
||||
require(NULL != hCfrg, CloseResourceAndExit);
|
||||
|
||||
HLock((Handle)hCfrg);
|
||||
|
||||
// get ptr to first item
|
||||
pCurItem = &(*hCfrg)->firstMember;
|
||||
for (curLibIndex = 0; curLibIndex < (*hCfrg)->memberCount; curLibIndex++)
|
||||
{
|
||||
// is this our library?
|
||||
if ((pCurItem->name[0] == inName[0]) &&
|
||||
(strncmp((char*) inName + 1, (char*) pCurItem->name + 1, PR_MIN(pCurItem->name[0], inName[0])) == 0))
|
||||
{
|
||||
*outCodeOffset = pCurItem->offset;
|
||||
*outCodeLength = pCurItem->length;
|
||||
found = true;
|
||||
}
|
||||
|
||||
// skip to next one
|
||||
pCurItem = (CFragResourceMember*) ((char*) pCurItem + pCurItem->memberSize);
|
||||
}
|
||||
|
||||
HUnlock((Handle)hCfrg);
|
||||
|
||||
CloseResourceAndExit:
|
||||
CloseResFile(refNum);
|
||||
Exit:
|
||||
return (found);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
NSFindSymbol
|
||||
|
||||
Workaround bug in CFM FindSymbol (in at least 7.5.5) where symbols with lengths
|
||||
greater than 63 chars cause a "paramErr". We iterate through all symbols
|
||||
in the library to find the desired symbol.
|
||||
*/
|
||||
|
||||
OSErr
|
||||
NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr* outMainAddr, CFragSymbolClass *outSymClass)
|
||||
{
|
||||
OSErr err;
|
||||
|
||||
if (inSymName[0] > 63)
|
||||
{
|
||||
/*
|
||||
if there are greater than 63 characters in the
|
||||
name, CFM FindSymbol fails, so let's iterate through all
|
||||
of the symbols in the fragment and grab it
|
||||
that way.
|
||||
*/
|
||||
long symbolCount;
|
||||
Str255 curSymName;
|
||||
long curIndex;
|
||||
Boolean found;
|
||||
|
||||
found = false;
|
||||
err = CountSymbols(inID, &symbolCount);
|
||||
if (noErr == err)
|
||||
{
|
||||
/* now iterate through all the symbols in the library */
|
||||
/* per DTS the indices apparently go 0 to n-1 */
|
||||
for (curIndex = 0; (curIndex <= symbolCount - 1 && !found); curIndex++)
|
||||
{
|
||||
err = GetIndSymbol(inID, curIndex, curSymName, outMainAddr, outSymClass);
|
||||
if (noErr == err && curSymName[0] == inSymName[0] && !strncmp((char*)curSymName + 1, (char*)inSymName + 1, curSymName[0]))
|
||||
{
|
||||
/* found our symbol */
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we didn't find it set the error code so below it won't take this symbol */
|
||||
if (!found)
|
||||
err = cfragNoSymbolErr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
GetNamedFragmentOffsets
|
||||
|
||||
Get the offsets into the data fork of the named fragment,
|
||||
by reading the 'cfrg' resoruce.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
|
||||
UInt32 *outOffset, UInt32 *outLength)
|
||||
{
|
||||
CFragResourceHandle cFragHandle;
|
||||
short fileRefNum;
|
||||
OSErr err = noErr;
|
||||
|
||||
fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
|
||||
err = ResError();
|
||||
if (err != noErr) return err;
|
||||
|
||||
cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
|
||||
if (!cFragHandle)
|
||||
{
|
||||
err = resNotFound;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* nothing here moves memory, so no need to lock the handle */
|
||||
|
||||
err = cfragNoLibraryErr; /* in case of failure */
|
||||
*outOffset = 0;
|
||||
*outLength = 0;
|
||||
|
||||
/* Now look for the named fragment */
|
||||
if ((**cFragHandle).memberCount > 0)
|
||||
{
|
||||
CFragResourceMemberPtr memberPtr;
|
||||
UInt16 i;
|
||||
|
||||
for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
|
||||
i < (**cFragHandle).memberCount;
|
||||
i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
|
||||
{
|
||||
char memberName[256];
|
||||
UInt16 nameLen = PR_MIN(memberPtr->name[0], 255);
|
||||
|
||||
// avoid malloc here for speed
|
||||
strncpy(memberName, (char *)&memberPtr->name[1], nameLen);
|
||||
memberName[nameLen] = '\0';
|
||||
|
||||
// fragment names are case insensitive, so act like the system
|
||||
if (PL_strcasecmp(memberName, fragmentName) == 0)
|
||||
{
|
||||
*outOffset = memberPtr->offset;
|
||||
*outLength = memberPtr->length;
|
||||
err = noErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resource handle will go away when the res fork is closed */
|
||||
|
||||
done:
|
||||
CloseResFile(fileRefNum);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
GetIndexedFragmentOffsets
|
||||
|
||||
Get the offsets into the data fork of the indexed fragment,
|
||||
by reading the 'cfrg' resoruce.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
|
||||
UInt32 *outOffset, UInt32 *outLength, char **outFragmentName)
|
||||
{
|
||||
CFragResourceHandle cFragHandle;
|
||||
short fileRefNum;
|
||||
OSErr err = noErr;
|
||||
|
||||
fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
|
||||
err = ResError();
|
||||
if (err != noErr) return err;
|
||||
|
||||
cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
|
||||
if (!cFragHandle)
|
||||
{
|
||||
err = resNotFound;
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = cfragNoLibraryErr; /* in case of failure */
|
||||
*outOffset = 0;
|
||||
*outLength = 0;
|
||||
*outFragmentName = NULL;
|
||||
|
||||
/* the CStrFromPStr mallocs, so might move memory */
|
||||
HLock((Handle)cFragHandle);
|
||||
|
||||
/* Now look for the named fragment */
|
||||
if ((**cFragHandle).memberCount > 0)
|
||||
{
|
||||
CFragResourceMemberPtr memberPtr;
|
||||
UInt16 i;
|
||||
|
||||
for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
|
||||
i < (**cFragHandle).memberCount;
|
||||
i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
|
||||
{
|
||||
|
||||
if (i == fragmentIndex)
|
||||
{
|
||||
char *fragmentStr;
|
||||
CStrFromPStr(memberPtr->name, &fragmentStr);
|
||||
if (!fragmentStr) /* test for allocation failure */
|
||||
{
|
||||
err = memFullErr;
|
||||
break;
|
||||
}
|
||||
|
||||
*outFragmentName = fragmentStr;
|
||||
*outOffset = memberPtr->offset;
|
||||
*outLength = memberPtr->length;
|
||||
err = noErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HUnlock((Handle)cFragHandle);
|
||||
|
||||
/* Resource handle will go away when the res fork is closed */
|
||||
|
||||
done:
|
||||
CloseResFile(fileRefNum);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
NSLoadNamedFragment
|
||||
|
||||
Load the named fragment from the specified file. Aliases must
|
||||
have been resolved by this point.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
|
||||
{
|
||||
UInt32 fragOffset, fragLength;
|
||||
short fragNameLength;
|
||||
Ptr main;
|
||||
Str255 fragName;
|
||||
Str255 errName;
|
||||
OSErr err;
|
||||
|
||||
err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
|
||||
if (err != noErr) return err;
|
||||
|
||||
// convert fragment name to pascal string
|
||||
fragNameLength = strlen(fragmentName);
|
||||
if (fragNameLength > 255)
|
||||
fragNameLength = 255;
|
||||
BlockMoveData(fragmentName, &fragName[1], fragNameLength);
|
||||
fragName[0] = fragNameLength;
|
||||
|
||||
// Note that we pass the fragment name as the 4th param to GetDiskFragment.
|
||||
// This value affects the ability of debuggers, and the Talkback system,
|
||||
// to match code fragments with symbol files
|
||||
err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
|
||||
kLoadCFrag, outConnectionID, &main, errName);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
|
||||
NSLoadIndexedFragment
|
||||
|
||||
Load the indexed fragment from the specified file. Aliases must
|
||||
have been resolved by this point.
|
||||
|
||||
*outFragName is a malloc'd block containing the fragment name,
|
||||
if returning noErr.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
|
||||
char** outFragName, CFragConnectionID *outConnectionID)
|
||||
{
|
||||
UInt32 fragOffset, fragLength;
|
||||
char *fragNameBlock = NULL;
|
||||
Ptr main;
|
||||
Str255 fragName = "\p";
|
||||
Str255 errName;
|
||||
OSErr err;
|
||||
|
||||
*outFragName = NULL;
|
||||
|
||||
err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
|
||||
if (err != noErr) return err;
|
||||
|
||||
if (fragNameBlock)
|
||||
{
|
||||
UInt32 nameLen = strlen(fragNameBlock);
|
||||
if (nameLen > 63)
|
||||
nameLen = 63;
|
||||
BlockMoveData(fragNameBlock, &fragName[1], nameLen);
|
||||
fragName[0] = nameLen;
|
||||
}
|
||||
|
||||
// Note that we pass the fragment name as the 4th param to GetDiskFragment.
|
||||
// This value affects the ability of debuggers, and the Talkback system,
|
||||
// to match code fragments with symbol files
|
||||
err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
|
||||
kLoadCFrag, outConnectionID, &main, errName);
|
||||
if (err != noErr)
|
||||
{
|
||||
free(fragNameBlock);
|
||||
return err;
|
||||
}
|
||||
|
||||
*outFragName = fragNameBlock;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef macdll_h__
|
||||
#define macdll_h__
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
|
||||
UInt32 *outOffset, UInt32 *outLength);
|
||||
OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
|
||||
UInt32 *outOffset, UInt32 *outLength, char **outFragmentName);
|
||||
|
||||
OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID);
|
||||
OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
|
||||
char** outFragName, CFragConnectionID *outConnectionID);
|
||||
|
||||
|
||||
OSErr NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr);
|
||||
OSErr NSFindSymbol(CFragConnectionID inID, Str255 inSymName,
|
||||
Ptr* outMainAddr, CFragSymbolClass *outSymClass);
|
||||
|
||||
#endif /* macdll_h__ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef macio_h__
|
||||
#define macio_h__
|
||||
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
OSErr ConvertUnixPathToMacPath(const char *, char **);
|
||||
OSErr ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
|
||||
#endif /* macio_h__ */
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/* XXX are all these headers required for a call to TickCount()? */
|
||||
#include <Events.h>
|
||||
#include <OSUtils.h>
|
||||
#include <QDOffscreen.h>
|
||||
#include <PPCToolbox.h>
|
||||
#include <Processes.h>
|
||||
#include <LowMem.h>
|
||||
#include "primpl.h"
|
||||
|
||||
extern PRSize _PR_MD_GetRandomNoise( buf, size )
|
||||
{
|
||||
uint32 c = TickCount();
|
||||
return _pr_CopyLowBits((void *)buf, size, &c, sizeof(c));
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef macksocket_h___
|
||||
#define macksocket_h___
|
||||
|
||||
// macsock.h
|
||||
// Interface visible to xp code
|
||||
// C socket type definitions and routines
|
||||
// from sys/socket.h
|
||||
#include <Files.h>
|
||||
#include <OpenTptInternet.h> // All the internet typedefs
|
||||
#include <utime.h> // For timeval
|
||||
/*
|
||||
* sleep and delay conflict with the same in unistd.h from Metrowerks. OT
|
||||
* defines them as
|
||||
*
|
||||
* extern pascal void OTDelay(UInt32 seconds);
|
||||
* extern pascal void OTIdle(void);
|
||||
*
|
||||
* #define sleep(x) OTDelay(x)
|
||||
* #define delay(x) OTDelay(x)
|
||||
*/
|
||||
|
||||
#undef sleep
|
||||
#undef delay
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "prio.h"
|
||||
|
||||
struct sockaddr {
|
||||
unsigned char sa_len; /* total length */
|
||||
unsigned char sa_family; /* address family */
|
||||
char sa_data[14]; /* actually longer; address value */
|
||||
};
|
||||
|
||||
// from netinet/in.h
|
||||
struct in_addr {
|
||||
unsigned long s_addr;
|
||||
};
|
||||
|
||||
struct sockaddr_in {
|
||||
unsigned char sin_len;
|
||||
unsigned char sin_family; // AF_INET
|
||||
unsigned short sin_port;
|
||||
struct in_addr sin_addr;
|
||||
char sin_zero[8];
|
||||
};
|
||||
|
||||
struct hostent {
|
||||
char *h_name; /* official name of host */
|
||||
char **h_aliases; /* alias list */
|
||||
int h_addrtype; /* host address type */
|
||||
int h_length; /* length of address */
|
||||
char **h_addr_list; /* list of addresses from name server */
|
||||
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
|
||||
};
|
||||
|
||||
// Necessary network defines, found by grepping unix headers when XP code would not compile
|
||||
#define FIONBIO 1
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define IPPROTO_TCP INET_TCP // Default TCP protocol
|
||||
#define IPPROTO_UDP INET_UDP // Default UDP protocol
|
||||
#define INADDR_ANY kOTAnyInetAddress
|
||||
#define SOL_SOCKET XTI_GENERIC // Any type of socket
|
||||
#define SO_REUSEADDR IP_REUSEADDR
|
||||
#define SO_BROADCAST IP_BROADCAST
|
||||
#define MSG_PEEK 0x2 // Just look at a message waiting, donÕt actually read it.
|
||||
|
||||
typedef unsigned long u_long;
|
||||
|
||||
/* ldap.h has its own definition of fd_set */
|
||||
/* select support */
|
||||
#if !defined(FD_SET)
|
||||
#define NBBY 8
|
||||
typedef long fd_mask;
|
||||
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
#define FD_SETSIZE 64
|
||||
typedef struct fd_set{
|
||||
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
|
||||
} fd_set;
|
||||
|
||||
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||||
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||||
#define FD_ZERO(p) memset (p, 0, sizeof(*(p)))
|
||||
#endif /* !FD_SET */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern unsigned long inet_addr(const char *cp);
|
||||
extern char *inet_ntoa(struct in_addr in);
|
||||
|
||||
inline unsigned long htonl(unsigned long hostlong) {return hostlong;}
|
||||
inline unsigned long ntohl(unsigned long netlong) {return netlong;}
|
||||
inline unsigned short ntohs(unsigned short netshort) {return netshort;}
|
||||
inline unsigned short htons(unsigned short hostshort) {return hostshort;}
|
||||
|
||||
|
||||
// UNIX look-alike routines
|
||||
// They make sure that the arguments passed in are valid, and then
|
||||
//
|
||||
extern struct hostent *macsock_gethostbyaddr(const void *addr, int addrlen, int type);
|
||||
|
||||
extern int macsock_socket(int domain, int type, int protocol);
|
||||
extern int macsock_ioctl(int sID, unsigned int request, void *value);
|
||||
extern int macsock_connect(int sID, struct sockaddr *name, int namelen);
|
||||
extern int macsock_write(int sID, const void *buffer, unsigned buflen);
|
||||
extern int macsock_read(int sID, void *buf, unsigned nbyte);
|
||||
extern int macsock_close(int sID);
|
||||
|
||||
extern int macsock_accept(int sID, struct sockaddr *addr, int *addrlen);
|
||||
extern int macsock_bind(int sID, const struct sockaddr *name, int namelen);
|
||||
extern int macsock_listen(int sID, int backlog);
|
||||
|
||||
extern int macsock_shutdown(int sID, int how);
|
||||
extern int macsock_getpeername(int sID, struct sockaddr *name, int *namelen);
|
||||
extern int macsock_getsockname(int sID, struct sockaddr *name, int *namelen);
|
||||
extern int macsock_getsockopt(int sID, int level, int optname, void *optval,int *optlen);
|
||||
extern int macsock_setsockopt(int sID, int level, int optname, const void *optval,int optlen);
|
||||
extern int macsock_socketavailable(int sID, size_t *bytesAvailable);
|
||||
extern int macsock_dup(int sID);
|
||||
|
||||
extern int macsock_send(int sID, const void *msg, int len, int flags);
|
||||
extern int macsock_sendto(int sID, const void *msg, int len, int flags, struct sockaddr *toAddr, int toLen);
|
||||
extern int macsock_recvfrom(int sID, void *buf, int len, int flags, struct sockaddr *from, int *fromLen);
|
||||
extern int macsock_recv(int sID, void *buf, int len, int flags);
|
||||
|
||||
extern int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
|
||||
|
||||
#define macsock_gethostbyaddr PR_GetHostByAddr
|
||||
#define macsock_socket PR_Socket
|
||||
#define macsock_connect PR_Connect
|
||||
#define macsock_write PR_Write
|
||||
#define macsock_read PR_Read
|
||||
#define macsock_close PR_Close
|
||||
#define macsock_accept PR_Accept
|
||||
#define macsock_bind PR_Bind
|
||||
#define macsock_listen PR_Listen
|
||||
#define macsock_shutdown PR_Shutdown
|
||||
#define macsock_getpeername PR_GetPeerName
|
||||
#define macsock_getsockname PR_GetSockName
|
||||
#define macsock_socketavailable PR_SocketAvailable
|
||||
#define macsock_send PR_Send
|
||||
#define macsock_sendto PR_SendTo
|
||||
#define macsock_recvfrom PR_RecvFrom
|
||||
#define macsock_recv PR_Recv
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
//extern int errno;
|
||||
|
||||
/*
|
||||
macsock_sendmsg
|
||||
macsock_readv
|
||||
macsock_writev
|
||||
*/
|
||||
|
||||
/* New definitions that are not defined in macsock.h in macsock library */
|
||||
struct protoent {
|
||||
char *p_name; /* official protocol name */
|
||||
char **p_aliases; /* alias list */
|
||||
int p_proto; /* protocol # */
|
||||
};
|
||||
|
||||
extern struct protoent *getprotobyname(const char * name);
|
||||
extern struct protoent *getprotobynumber(int number);
|
||||
|
||||
extern int gethostname (char *name, int namelen);
|
||||
extern struct hostent *gethostbyname(const char * name);
|
||||
extern struct hostent *gethostbyaddr(const void *addr, int addrlen, int type);
|
||||
|
||||
#define INADDR_LOOPBACK 0x7F000001
|
||||
|
||||
#define SO_KEEPALIVE TCP_KEEPALIVE
|
||||
#define SO_RCVBUF XTI_RCVBUF
|
||||
#define SO_SNDBUF XTI_SNDBUF
|
||||
#define SO_LINGER XTI_LINGER /* linger on close if data present */
|
||||
|
||||
#define IPPROTO_IP INET_IP
|
||||
|
||||
/* Get/Set sock opt until fixed in NSPR 2.0 */
|
||||
struct linger {
|
||||
int l_onoff; /* option on/off */
|
||||
int l_linger; /* linger time */
|
||||
};
|
||||
|
||||
struct ip_mreq {
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
};
|
||||
|
||||
#endif /* macksocket_h___ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,721 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Timer.h>
|
||||
#include <OSUtils.h>
|
||||
#include <Math64.h>
|
||||
#include <LowMem.h>
|
||||
#include <Multiprocessing.h>
|
||||
#include <Gestalt.h>
|
||||
|
||||
#include "mdcriticalregion.h"
|
||||
|
||||
TimerUPP gTimerCallbackUPP = NULL;
|
||||
PRThread * gPrimaryThread = NULL;
|
||||
|
||||
ProcessSerialNumber gApplicationProcess;
|
||||
|
||||
PR_IMPLEMENT(PRThread *) PR_GetPrimaryThread()
|
||||
{
|
||||
return gPrimaryThread;
|
||||
}
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark CREATING MACINTOSH THREAD STACKS
|
||||
|
||||
#if defined(GC_LEAK_DETECTOR)
|
||||
extern void* GC_malloc_atomic(PRUint32 size);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Allocate a new memory segment. We allocate it from our figment heap. Currently,
|
||||
** it is being used for per thread stack space.
|
||||
**
|
||||
** Return the segment's access rights and size. vaddr is used on Unix platforms to
|
||||
** map an existing address for the segment.
|
||||
*/
|
||||
PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
|
||||
{
|
||||
PR_ASSERT(seg != 0);
|
||||
PR_ASSERT(size != 0);
|
||||
PR_ASSERT(vaddr == 0);
|
||||
|
||||
/*
|
||||
** Take the actual memory for the segment out of our Figment heap.
|
||||
*/
|
||||
|
||||
#if defined(GC_LEAK_DETECTOR)
|
||||
seg->vaddr = (char *)GC_malloc_atomic(size);
|
||||
#else
|
||||
seg->vaddr = (char *)malloc(size);
|
||||
#endif
|
||||
|
||||
if (seg->vaddr == NULL) {
|
||||
|
||||
#if DEBUG
|
||||
DebugStr("\p_MD_AllocSegment failed.");
|
||||
#endif
|
||||
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
seg->size = size;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Free previously allocated memory segment.
|
||||
*/
|
||||
void _MD_FreeSegment(PRSegment *seg)
|
||||
{
|
||||
PR_ASSERT((seg->flags & _PR_SEG_VM) == 0);
|
||||
|
||||
if (seg->vaddr != NULL)
|
||||
free(seg->vaddr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** The thread's stack has been allocated and its fields are already properly filled
|
||||
** in by PR. Perform any debugging related initialization here.
|
||||
**
|
||||
** Put a recognizable pattern so that we can find it from Macsbug.
|
||||
** Put a cookie at the top of the stack so that we can find it from Macsbug.
|
||||
*/
|
||||
void _MD_InitStack(PRThreadStack *ts, int redZoneBytes)
|
||||
{
|
||||
#pragma unused (redZoneBytes)
|
||||
#if DEVELOPER_DEBUG
|
||||
// Put a cookie at the top of the stack so that we can find
|
||||
// it from Macsbug.
|
||||
|
||||
memset(ts->allocBase, 0xDC, ts->stackSize);
|
||||
|
||||
((UInt32 *)ts->stackTop)[-1] = 0xBEEFCAFE;
|
||||
((UInt32 *)ts->stackTop)[-2] = (UInt32)gPrimaryThread;
|
||||
((UInt32 *)ts->stackTop)[-3] = (UInt32)(ts);
|
||||
((UInt32 *)ts->stackBottom)[0] = 0xCAFEBEEF;
|
||||
#else
|
||||
#pragma unused (ts)
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void _MD_ClearStack(PRThreadStack *ts)
|
||||
{
|
||||
#if DEVELOPER_DEBUG
|
||||
// Clear out our cookies.
|
||||
|
||||
memset(ts->allocBase, 0xEF, ts->allocSize);
|
||||
((UInt32 *)ts->stackTop)[-1] = 0;
|
||||
((UInt32 *)ts->stackTop)[-2] = 0;
|
||||
((UInt32 *)ts->stackTop)[-3] = 0;
|
||||
((UInt32 *)ts->stackBottom)[0] = 0;
|
||||
#else
|
||||
#pragma unused (ts)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark TIME MANAGER-BASED CLOCK
|
||||
|
||||
// On Mac OS X, it's possible for the application to spend lots of time
|
||||
// in WaitNextEvent, yielding to other applications. Since NSPR threads are
|
||||
// cooperative here, this means that NSPR threads will also get very little
|
||||
// time to run. To kick ourselves out of a WaitNextEvent call when we have
|
||||
// determined that it's time to schedule another thread, the Timer Task
|
||||
// (which fires every 8ms, even when other apps have the CPU) calls WakeUpProcess.
|
||||
// We only want to do this on Mac OS X; the gTimeManagerTaskDoesWUP variable
|
||||
// indicates when we're running on that OS.
|
||||
//
|
||||
// Note that the TimerCallback makes use of gApplicationProcess. We need to
|
||||
// have set this up before the first possible run of the timer task; we do
|
||||
// so in _MD_EarlyInit().
|
||||
static Boolean gTimeManagerTaskDoesWUP;
|
||||
|
||||
static TMTask gTimeManagerTaskElem;
|
||||
|
||||
extern void _MD_IOInterrupt(void);
|
||||
_PRInterruptTable _pr_interruptTable[] = {
|
||||
{ "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
|
||||
{ "i/o", _PR_MISSED_IO, _MD_IOInterrupt, },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define kMacTimerInMiliSecs 8L
|
||||
|
||||
pascal void TimerCallback(TMTaskPtr tmTaskPtr)
|
||||
{
|
||||
_PRCPU *cpu = _PR_MD_CURRENT_CPU();
|
||||
PRIntn is;
|
||||
|
||||
if (_PR_MD_GET_INTSOFF()) {
|
||||
cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
|
||||
PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
|
||||
return;
|
||||
}
|
||||
|
||||
_PR_INTSOFF(is);
|
||||
|
||||
// And tell nspr that a clock interrupt occured.
|
||||
_PR_ClockInterrupt();
|
||||
|
||||
if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority))) {
|
||||
if (gTimeManagerTaskDoesWUP) {
|
||||
// We only want to call WakeUpProcess if we know that NSPR has managed to switch threads
|
||||
// since the last call, otherwise we end up spewing out WakeUpProcess() calls while the
|
||||
// application is blocking somewhere. This can interfere with events loops other than
|
||||
// our own (see bug 158927).
|
||||
if (UnsignedWideToUInt64(cpu->md.lastThreadSwitch) > UnsignedWideToUInt64(cpu->md.lastWakeUpProcess))
|
||||
{
|
||||
WakeUpProcess(&gApplicationProcess);
|
||||
cpu->md.lastWakeUpProcess = UpTime();
|
||||
}
|
||||
}
|
||||
_PR_SET_RESCHED_FLAG();
|
||||
}
|
||||
|
||||
_PR_FAST_INTSON(is);
|
||||
|
||||
// Reset the clock timer so that we fire again.
|
||||
PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
|
||||
}
|
||||
|
||||
|
||||
void _MD_StartInterrupts(void)
|
||||
{
|
||||
gPrimaryThread = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
gTimeManagerTaskDoesWUP = RunningOnOSX();
|
||||
|
||||
if ( !gTimerCallbackUPP )
|
||||
gTimerCallbackUPP = NewTimerUPP(TimerCallback);
|
||||
|
||||
// Fill in the Time Manager queue element
|
||||
|
||||
gTimeManagerTaskElem.tmAddr = (TimerUPP)gTimerCallbackUPP;
|
||||
gTimeManagerTaskElem.tmCount = 0;
|
||||
gTimeManagerTaskElem.tmWakeUp = 0;
|
||||
gTimeManagerTaskElem.tmReserved = 0;
|
||||
|
||||
// Make sure that our time manager task is ready to go.
|
||||
InsTime((QElemPtr)&gTimeManagerTaskElem);
|
||||
|
||||
PrimeTime((QElemPtr)&gTimeManagerTaskElem, kMacTimerInMiliSecs);
|
||||
}
|
||||
|
||||
void _MD_StopInterrupts(void)
|
||||
{
|
||||
if (gTimeManagerTaskElem.tmAddr != NULL) {
|
||||
RmvTime((QElemPtr)&gTimeManagerTaskElem);
|
||||
gTimeManagerTaskElem.tmAddr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define MAX_PAUSE_TIMEOUT_MS 500
|
||||
|
||||
void _MD_PauseCPU(PRIntervalTime timeout)
|
||||
{
|
||||
if (timeout != PR_INTERVAL_NO_WAIT)
|
||||
{
|
||||
// There is a race condition entering the critical section
|
||||
// in AsyncIOCompletion (and probably elsewhere) that can
|
||||
// causes deadlock for the duration of this timeout. To
|
||||
// work around this, use a max 500ms timeout for now.
|
||||
// See bug 99561 for details.
|
||||
if (PR_IntervalToMilliseconds(timeout) > MAX_PAUSE_TIMEOUT_MS)
|
||||
timeout = PR_MillisecondsToInterval(MAX_PAUSE_TIMEOUT_MS);
|
||||
|
||||
WaitOnIdleSemaphore(timeout);
|
||||
(void) _MD_IOInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void _MD_InitRunningCPU(_PRCPU* cpu)
|
||||
{
|
||||
cpu->md.trackScheduling = RunningOnOSX();
|
||||
if (cpu->md.trackScheduling) {
|
||||
AbsoluteTime zeroTime = {0, 0};
|
||||
cpu->md.lastThreadSwitch = UpTime();
|
||||
cpu->md.lastWakeUpProcess = zeroTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark THREAD SUPPORT FUNCTIONS
|
||||
|
||||
#include <OpenTransport.h> /* for error codes */
|
||||
|
||||
PRStatus _MD_InitThread(PRThread *thread)
|
||||
{
|
||||
thread->md.asyncIOLock = PR_NewLock();
|
||||
PR_ASSERT(thread->md.asyncIOLock != NULL);
|
||||
thread->md.asyncIOCVar = PR_NewCondVar(thread->md.asyncIOLock);
|
||||
PR_ASSERT(thread->md.asyncIOCVar != NULL);
|
||||
|
||||
if (thread->md.asyncIOLock == NULL || thread->md.asyncIOCVar == NULL)
|
||||
return PR_FAILURE;
|
||||
else
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRStatus _MD_wait(PRThread *thread, PRIntervalTime timeout)
|
||||
{
|
||||
#pragma unused (timeout)
|
||||
|
||||
_MD_SWITCH_CONTEXT(thread);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout)
|
||||
{
|
||||
intn is;
|
||||
PRIntervalTime timein = PR_IntervalNow();
|
||||
PRStatus status = PR_SUCCESS;
|
||||
|
||||
// Turn interrupts off to avoid a race over lock ownership with the callback
|
||||
// (which can fire at any time). Interrupts may stay off until we leave
|
||||
// this function, or another NSPR thread turns them back on. They certainly
|
||||
// stay off until PR_WaitCondVar() relinquishes the asyncIOLock lock, which
|
||||
// is what we care about.
|
||||
_PR_INTSOFF(is);
|
||||
PR_Lock(thread->md.asyncIOLock);
|
||||
if (timeout == PR_INTERVAL_NO_TIMEOUT) {
|
||||
while ((thread->io_pending) && (status == PR_SUCCESS))
|
||||
status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
|
||||
} else {
|
||||
while ((thread->io_pending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
|
||||
status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
|
||||
}
|
||||
if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {
|
||||
thread->md.osErrCode = kEINTRErr;
|
||||
} else if (thread->io_pending) {
|
||||
thread->md.osErrCode = kETIMEDOUTErr;
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);
|
||||
}
|
||||
|
||||
thread->io_pending = PR_FALSE;
|
||||
PR_Unlock(thread->md.asyncIOLock);
|
||||
_PR_FAST_INTSON(is);
|
||||
}
|
||||
|
||||
|
||||
void DoneWaitingOnThisThread(PRThread *thread)
|
||||
{
|
||||
intn is;
|
||||
|
||||
PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
|
||||
|
||||
// DoneWaitingOnThisThread() is called from OT notifiers and async file I/O
|
||||
// callbacks that can run at "interrupt" time (Classic Mac OS) or on pthreads
|
||||
// that may run concurrently with the main threads (Mac OS X). They can thus
|
||||
// be called when any NSPR thread is running, or even while NSPR is in a
|
||||
// thread context switch. It is therefore vital that we can guarantee to
|
||||
// be able to get the asyncIOLock without blocking (thus avoiding code
|
||||
// that makes assumptions about the current NSPR thread etc). To achieve
|
||||
// this, we use NSPR interrrupts as a semaphore on the lock; all code
|
||||
// that grabs the lock also disables interrupts for the time the lock
|
||||
// is held. Callers of DoneWaitingOnThisThread() thus have to check whether
|
||||
// interrupts are already off, and, if so, simply set the missed_IO flag on
|
||||
// the CPU rather than calling this function.
|
||||
|
||||
_PR_INTSOFF(is);
|
||||
PR_Lock(thread->md.asyncIOLock);
|
||||
thread->io_pending = PR_FALSE;
|
||||
/* let the waiting thread know that async IO completed */
|
||||
PR_NotifyCondVar(thread->md.asyncIOCVar);
|
||||
PR_Unlock(thread->md.asyncIOLock);
|
||||
_PR_FAST_INTSON(is);
|
||||
}
|
||||
|
||||
|
||||
PR_IMPLEMENT(void) PR_Mac_WaitForAsyncNotify(PRIntervalTime timeout)
|
||||
{
|
||||
intn is;
|
||||
PRIntervalTime timein = PR_IntervalNow();
|
||||
PRStatus status = PR_SUCCESS;
|
||||
PRThread *thread = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
// See commments in WaitOnThisThread()
|
||||
_PR_INTSOFF(is);
|
||||
PR_Lock(thread->md.asyncIOLock);
|
||||
if (timeout == PR_INTERVAL_NO_TIMEOUT) {
|
||||
while ((!thread->md.asyncNotifyPending) && (status == PR_SUCCESS))
|
||||
status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
|
||||
} else {
|
||||
while ((!thread->md.asyncNotifyPending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
|
||||
status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
|
||||
}
|
||||
if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {
|
||||
thread->md.osErrCode = kEINTRErr;
|
||||
} else if (!thread->md.asyncNotifyPending) {
|
||||
thread->md.osErrCode = kETIMEDOUTErr;
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);
|
||||
}
|
||||
thread->md.asyncNotifyPending = PR_FALSE;
|
||||
PR_Unlock(thread->md.asyncIOLock);
|
||||
_PR_FAST_INTSON(is);
|
||||
}
|
||||
|
||||
|
||||
void AsyncNotify(PRThread *thread)
|
||||
{
|
||||
intn is;
|
||||
|
||||
PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
|
||||
|
||||
// See commments in DoneWaitingOnThisThread()
|
||||
_PR_INTSOFF(is);
|
||||
PR_Lock(thread->md.asyncIOLock);
|
||||
thread->md.asyncNotifyPending = PR_TRUE;
|
||||
/* let the waiting thread know that async IO completed */
|
||||
PR_NotifyCondVar(thread->md.asyncIOCVar);
|
||||
PR_Unlock(thread->md.asyncIOLock);
|
||||
_PR_FAST_INTSON(is);
|
||||
}
|
||||
|
||||
|
||||
PR_IMPLEMENT(void) PR_Mac_PostAsyncNotify(PRThread *thread)
|
||||
{
|
||||
_PRCPU * cpu = _PR_MD_CURRENT_CPU();
|
||||
|
||||
if (_PR_MD_GET_INTSOFF()) {
|
||||
thread->md.missedAsyncNotify = PR_TRUE;
|
||||
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
|
||||
} else {
|
||||
AsyncNotify(thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark PROCESS SUPPORT FUNCTIONS
|
||||
|
||||
PRProcess * _MD_CreateProcess(
|
||||
const char *path,
|
||||
char *const *argv,
|
||||
char *const *envp,
|
||||
const PRProcessAttr *attr)
|
||||
{
|
||||
#pragma unused (path, argv, envp, attr)
|
||||
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRStatus _MD_DetachProcess(PRProcess *process)
|
||||
{
|
||||
#pragma unused (process)
|
||||
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_WaitProcess(PRProcess *process, PRInt32 *exitCode)
|
||||
{
|
||||
#pragma unused (process, exitCode)
|
||||
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_KillProcess(PRProcess *process)
|
||||
{
|
||||
#pragma unused (process)
|
||||
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark ATOMIC OPERATIONS
|
||||
|
||||
#ifdef _PR_HAVE_ATOMIC_OPS
|
||||
PRInt32
|
||||
_MD_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
{
|
||||
PRInt32 rv;
|
||||
do {
|
||||
rv = *val;
|
||||
} while (!OTCompareAndSwap32(rv, newval, (UInt32*)val));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif // _PR_HAVE_ATOMIC_OPS
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark INTERRUPT SUPPORT
|
||||
|
||||
#if TARGET_CARBON
|
||||
|
||||
/*
|
||||
This critical region support is required for Mac NSPR to work correctly on dual CPU
|
||||
machines on Mac OS X. This note explains why.
|
||||
|
||||
NSPR uses a timer task, and has callbacks for async file I/O and Open Transport
|
||||
whose runtime behaviour differs depending on environment. On "Classic" Mac OS
|
||||
these run at "interrupt" time (OS-level interrupts, that is, not NSPR interrupts),
|
||||
and can thus preempt other code, but they always run to completion.
|
||||
|
||||
On Mac OS X, these are all emulated using MP tasks, which sit atop pthreads. Thus,
|
||||
they can be preempted at any time (and not necessarily run to completion), and can
|
||||
also run *concurrently* with eachother, and with application code, on multiple
|
||||
CPU machines. Note that all NSPR threads are emulated, and all run on the main
|
||||
application MP task.
|
||||
|
||||
We thus have to use MP critical sections to protect data that is shared between
|
||||
the various callbacks and the main MP thread. It so happens that NSPR has this
|
||||
concept of software interrupts, and making interrupt-off times be critical
|
||||
sections works.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Whether to use critical regions. True if running on Mac OS X and later
|
||||
*/
|
||||
|
||||
PRBool gUseCriticalRegions;
|
||||
|
||||
/*
|
||||
Count of the number of times we've entered the critical region.
|
||||
We need this because ENTER_CRITICAL_REGION() will *not* block when
|
||||
called from different NSPR threads (which all run on one MP thread),
|
||||
and we need to ensure that when code turns interrupts back on (by
|
||||
settings _pr_intsOff to 0) we exit the critical section enough times
|
||||
to leave it.
|
||||
*/
|
||||
|
||||
PRInt32 gCriticalRegionEntryCount;
|
||||
|
||||
|
||||
void _MD_SetIntsOff(PRInt32 ints)
|
||||
{
|
||||
ENTER_CRITICAL_REGION();
|
||||
gCriticalRegionEntryCount ++;
|
||||
|
||||
_pr_intsOff = ints;
|
||||
|
||||
if (!ints)
|
||||
{
|
||||
PRInt32 i = gCriticalRegionEntryCount;
|
||||
|
||||
gCriticalRegionEntryCount = 0;
|
||||
for ( ;i > 0; i --) {
|
||||
LEAVE_CRITICAL_REGION();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_CARBON */
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark CRITICAL REGION SUPPORT
|
||||
|
||||
|
||||
static PRBool RunningOnOSX()
|
||||
{
|
||||
long systemVersion;
|
||||
OSErr err = Gestalt(gestaltSystemVersion, &systemVersion);
|
||||
return (err == noErr) && (systemVersion >= 0x00001000);
|
||||
}
|
||||
|
||||
|
||||
#if MAC_CRITICAL_REGIONS
|
||||
|
||||
MDCriticalRegionID gCriticalRegion;
|
||||
|
||||
void InitCriticalRegion()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
// we only need to do critical region stuff on Mac OS X
|
||||
gUseCriticalRegions = RunningOnOSX();
|
||||
if (!gUseCriticalRegions) return;
|
||||
|
||||
err = MD_CriticalRegionCreate(&gCriticalRegion);
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
|
||||
void TermCriticalRegion()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
if (!gUseCriticalRegions) return;
|
||||
|
||||
err = MD_CriticalRegionDelete(gCriticalRegion);
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
|
||||
|
||||
void EnterCritialRegion()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
if (!gUseCriticalRegions) return;
|
||||
|
||||
PR_ASSERT(gCriticalRegion != kInvalidID);
|
||||
|
||||
/* Change to a non-infinite timeout for debugging purposes */
|
||||
err = MD_CriticalRegionEnter(gCriticalRegion, kDurationForever /* 10000 * kDurationMillisecond */ );
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
|
||||
void LeaveCritialRegion()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
if (!gUseCriticalRegions) return;
|
||||
|
||||
PR_ASSERT(gCriticalRegion != kInvalidID);
|
||||
|
||||
err = MD_CriticalRegionExit(gCriticalRegion);
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
|
||||
|
||||
#endif // MAC_CRITICAL_REGIONS
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark IDLE SEMAPHORE SUPPORT
|
||||
|
||||
/*
|
||||
Since the WaitNextEvent() in _MD_PauseCPU() is causing all sorts of
|
||||
headache under Mac OS X we're going to switch to MPWaitOnSemaphore()
|
||||
which should do what we want
|
||||
*/
|
||||
|
||||
#if TARGET_CARBON
|
||||
PRBool gUseIdleSemaphore = PR_FALSE;
|
||||
MPSemaphoreID gIdleSemaphore = NULL;
|
||||
#endif
|
||||
|
||||
void InitIdleSemaphore()
|
||||
{
|
||||
// we only need to do idle semaphore stuff on Mac OS X
|
||||
#if TARGET_CARBON
|
||||
gUseIdleSemaphore = RunningOnOSX();
|
||||
if (gUseIdleSemaphore)
|
||||
{
|
||||
OSStatus err = MPCreateSemaphore(1 /* max value */, 0 /* initial value */, &gIdleSemaphore);
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TermIdleSemaphore()
|
||||
{
|
||||
#if TARGET_CARBON
|
||||
if (gUseIdleSemaphore)
|
||||
{
|
||||
OSStatus err = MPDeleteSemaphore(gIdleSemaphore);
|
||||
PR_ASSERT(err == noErr);
|
||||
gUseIdleSemaphore = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void WaitOnIdleSemaphore(PRIntervalTime timeout)
|
||||
{
|
||||
#if TARGET_CARBON
|
||||
if (gUseIdleSemaphore)
|
||||
{
|
||||
OSStatus err = MPWaitOnSemaphore(gIdleSemaphore, kDurationMillisecond * PR_IntervalToMilliseconds(timeout));
|
||||
PR_ASSERT(err == noErr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
EventRecord theEvent;
|
||||
/*
|
||||
** Calling WaitNextEvent() here is suboptimal. This routine should
|
||||
** pause the process until IO or the timeout occur, yielding time to
|
||||
** other processes on operating systems that require this (Mac OS classic).
|
||||
** WaitNextEvent() may incur too much latency, and has other problems,
|
||||
** such as the potential to drop suspend/resume events.
|
||||
*/
|
||||
(void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignalIdleSemaphore()
|
||||
{
|
||||
#if TARGET_CARBON
|
||||
if (gUseIdleSemaphore)
|
||||
{
|
||||
// often we won't be waiting on the semaphore here, so ignore any errors
|
||||
(void)MPSignalSemaphore(gIdleSemaphore);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WakeUpProcess(&gApplicationProcess);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <OSUtils.h>
|
||||
#include <Timer.h>
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include "mactime.h"
|
||||
|
||||
unsigned long gJanuaryFirst1970Seconds;
|
||||
|
||||
/*
|
||||
* The geographic location and time zone information of a Mac
|
||||
* are stored in extended parameter RAM. The ReadLocation
|
||||
* produdure uses the geographic location record, MachineLocation,
|
||||
* to read the geographic location and time zone information in
|
||||
* extended parameter RAM.
|
||||
*
|
||||
* Because serial port and SLIP conflict with ReadXPram calls,
|
||||
* we cache the call here.
|
||||
*
|
||||
* Caveat: this caching will give the wrong result if a session
|
||||
* extend across the DST changeover time.
|
||||
*/
|
||||
|
||||
static void MyReadLocation(MachineLocation *loc)
|
||||
{
|
||||
static MachineLocation storedLoc;
|
||||
static Boolean didReadLocation = false;
|
||||
|
||||
if (!didReadLocation) {
|
||||
ReadLocation(&storedLoc);
|
||||
didReadLocation = true;
|
||||
}
|
||||
*loc = storedLoc;
|
||||
}
|
||||
|
||||
static long GMTDelta(void)
|
||||
{
|
||||
MachineLocation loc;
|
||||
long gmtDelta;
|
||||
|
||||
MyReadLocation(&loc);
|
||||
gmtDelta = loc.u.gmtDelta & 0x00ffffff;
|
||||
if (gmtDelta & 0x00800000) { /* test sign extend bit */
|
||||
gmtDelta |= 0xff000000;
|
||||
}
|
||||
return gmtDelta;
|
||||
}
|
||||
|
||||
void MacintoshInitializeTime(void)
|
||||
{
|
||||
/*
|
||||
* The NSPR epoch is midnight, Jan. 1, 1970 GMT.
|
||||
*
|
||||
* At midnight Jan. 1, 1970 GMT, the local time was
|
||||
* midnight Jan. 1, 1970 + GMTDelta().
|
||||
*
|
||||
* Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
|
||||
* = 2082844800 seconds since the Mac epoch.
|
||||
* (There were 17 leap years from 1904 to 1970.)
|
||||
*
|
||||
* So the NSPR epoch is 2082844800 + GMTDelta() seconds since
|
||||
* the Mac epoch. Whew! :-)
|
||||
*/
|
||||
gJanuaryFirst1970Seconds = 2082844800 + GMTDelta();
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
* PR_Now --
|
||||
*
|
||||
* Returns the current time in microseconds since the epoch.
|
||||
* The epoch is midnight January 1, 1970 GMT.
|
||||
* The implementation is machine dependent. This is the Mac
|
||||
* Implementation.
|
||||
* Cf. time_t time(time_t *tp)
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PRTime PR_Now(void)
|
||||
{
|
||||
unsigned long currentTime; /* unsigned 32-bit integer, ranging
|
||||
from midnight Jan. 1, 1904 to
|
||||
6:28:15 AM Feb. 6, 2040 */
|
||||
PRTime retVal;
|
||||
int64 usecPerSec;
|
||||
|
||||
/*
|
||||
* Get the current time expressed as the number of seconds
|
||||
* elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
|
||||
* On a Mac, current time accuracy is up to a second.
|
||||
*/
|
||||
GetDateTime(¤tTime);
|
||||
|
||||
/*
|
||||
* Express the current time relative to the NSPR epoch,
|
||||
* midnight, Jan. 1, 1970 GMT.
|
||||
*
|
||||
* At midnight Jan. 1, 1970 GMT, the local time was
|
||||
* midnight Jan. 1, 1970 + GMTDelta().
|
||||
*
|
||||
* Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
|
||||
* = 2082844800 seconds since the Mac epoch.
|
||||
* (There were 17 leap years from 1904 to 1970.)
|
||||
*
|
||||
* So the NSPR epoch is 2082844800 + GMTDelta() seconds since
|
||||
* the Mac epoch. Whew! :-)
|
||||
*/
|
||||
currentTime = currentTime - 2082844800 - GMTDelta();
|
||||
|
||||
/* Convert seconds to microseconds */
|
||||
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
|
||||
LL_I2L(retVal, currentTime);
|
||||
LL_MUL(retVal, retVal, usecPerSec);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* PR_LocalTimeParameters --
|
||||
*
|
||||
* returns the time parameters for the local time zone
|
||||
*
|
||||
* This is the machine-dependent implementation for Mac.
|
||||
*
|
||||
* Caveat: On a Mac, we only know the GMT and DST offsets for
|
||||
* the current time, not for the time in question.
|
||||
* Mac has no support for DST handling.
|
||||
* DST changeover is all manually set by the user.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PRTimeParameters PR_LocalTimeParameters(const PRExplodedTime *gmt)
|
||||
{
|
||||
#pragma unused (gmt)
|
||||
|
||||
PRTimeParameters retVal;
|
||||
MachineLocation loc;
|
||||
|
||||
MyReadLocation(&loc);
|
||||
|
||||
/*
|
||||
* On a Mac, the GMT value is in seconds east of GMT. For example,
|
||||
* San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
|
||||
* east of GMT. The gmtDelta field is a 3-byte value contained in a
|
||||
* long word, so you must take care to get it properly.
|
||||
*/
|
||||
|
||||
retVal.tp_gmt_offset = loc.u.gmtDelta & 0x00ffffff;
|
||||
if (retVal.tp_gmt_offset & 0x00800000) { /* test sign extend bit */
|
||||
retVal.tp_gmt_offset |= 0xff000000;
|
||||
}
|
||||
|
||||
/*
|
||||
* The daylight saving time value, dlsDelta, is a signed byte
|
||||
* value representing the offset for the hour field -- whether
|
||||
* to add 1 hour, subtract 1 hour, or make no change at all.
|
||||
*/
|
||||
|
||||
if (loc.u.dlsDelta) {
|
||||
retVal.tp_gmt_offset -= 3600;
|
||||
retVal.tp_dst_offset = 3600;
|
||||
} else {
|
||||
retVal.tp_dst_offset = 0;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
PRIntervalTime _MD_GetInterval(void)
|
||||
{
|
||||
PRIntervalTime retVal;
|
||||
PRUint64 upTime, microtomilli;
|
||||
|
||||
/*
|
||||
* Use the Microseconds procedure to obtain the number of
|
||||
* microseconds elapsed since system startup time.
|
||||
*/
|
||||
Microseconds((UnsignedWide *)&upTime);
|
||||
LL_I2L(microtomilli, PR_USEC_PER_MSEC);
|
||||
LL_DIV(upTime, upTime, microtomilli);
|
||||
LL_L2I(retVal, upTime);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
struct tm *Maclocaltime(const time_t * t)
|
||||
{
|
||||
DateTimeRec dtr;
|
||||
MachineLocation loc;
|
||||
time_t macLocal = *t + gJanuaryFirst1970Seconds; /* GMT Mac */
|
||||
static struct tm statictime;
|
||||
static const short monthday[12] =
|
||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||||
|
||||
SecondsToDate(macLocal, &dtr);
|
||||
statictime.tm_sec = dtr.second;
|
||||
statictime.tm_min = dtr.minute;
|
||||
statictime.tm_hour = dtr.hour;
|
||||
statictime.tm_mday = dtr.day;
|
||||
statictime.tm_mon = dtr.month - 1;
|
||||
statictime.tm_year = dtr.year - 1900;
|
||||
statictime.tm_wday = dtr.dayOfWeek - 1;
|
||||
statictime.tm_yday = monthday[statictime.tm_mon]
|
||||
+ statictime.tm_mday - 1;
|
||||
if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
|
||||
++statictime.tm_yday;
|
||||
MyReadLocation(&loc);
|
||||
statictime.tm_isdst = loc.u.dlsDelta;
|
||||
return(&statictime);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#ifndef mactime_h__
|
||||
#define mactime_h__
|
||||
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
void MacintoshInitializeTime(void);
|
||||
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
|
||||
#endif /* mactime_h__ */
|
||||
@@ -0,0 +1,173 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: NULL; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* George Warner, Apple Computer Inc.
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mdcriticalregion.h"
|
||||
#include <MacErrors.h>
|
||||
|
||||
/*
|
||||
This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion,
|
||||
which is broken on Mac OS 10.0.x builds, but fixed in 10.1. This code works
|
||||
everywhere.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct MDCriticalRegionData_struct {
|
||||
MPTaskID mMPTaskID; /* Who's in the critical region? */
|
||||
UInt32 mDepthCount; /* How deep? */
|
||||
MPSemaphoreID mMPSemaphoreID; /* ready semaphore */
|
||||
} MDCriticalRegionData, *MDCriticalRegionDataPtr;
|
||||
|
||||
|
||||
OSStatus
|
||||
MD_CriticalRegionCreate(MDCriticalRegionID * outCriticalRegionID)
|
||||
{
|
||||
MDCriticalRegionDataPtr newCriticalRegionPtr;
|
||||
MPSemaphoreID mpSemaphoreID;
|
||||
OSStatus err = noErr;
|
||||
|
||||
if (outCriticalRegionID == NULL)
|
||||
return paramErr;
|
||||
|
||||
*outCriticalRegionID = NULL;
|
||||
|
||||
newCriticalRegionPtr = (MDCriticalRegionDataPtr)MPAllocateAligned(sizeof(MDCriticalRegionData),
|
||||
kMPAllocateDefaultAligned, kMPAllocateClearMask);
|
||||
if (newCriticalRegionPtr == NULL)
|
||||
return memFullErr;
|
||||
|
||||
// Note: this semaphore is pre-fired (ready!)
|
||||
err = MPCreateBinarySemaphore(&mpSemaphoreID);
|
||||
if (err == noErr)
|
||||
{
|
||||
newCriticalRegionPtr->mMPTaskID = kInvalidID;
|
||||
newCriticalRegionPtr->mDepthCount = 0;
|
||||
newCriticalRegionPtr->mMPSemaphoreID = mpSemaphoreID;
|
||||
|
||||
*outCriticalRegionID = (MDCriticalRegionID)newCriticalRegionPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
MPFree((LogicalAddress)newCriticalRegionPtr);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus
|
||||
MD_CriticalRegionDelete(MDCriticalRegionID inCriticalRegionID)
|
||||
{
|
||||
MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
|
||||
OSStatus err = noErr;
|
||||
|
||||
if (criticalRegion == NULL)
|
||||
return paramErr;
|
||||
|
||||
if ((criticalRegion->mMPTaskID != kInvalidID) && (criticalRegion->mDepthCount > 0))
|
||||
return kMPInsufficientResourcesErr;
|
||||
|
||||
if (criticalRegion->mMPSemaphoreID != kInvalidID)
|
||||
err = MPDeleteSemaphore(criticalRegion->mMPSemaphoreID);
|
||||
if (noErr != err) return err;
|
||||
|
||||
criticalRegion->mMPSemaphoreID = kInvalidID;
|
||||
MPFree((LogicalAddress) criticalRegion);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus
|
||||
MD_CriticalRegionEnter(MDCriticalRegionID inCriticalRegionID, Duration inTimeout)
|
||||
{
|
||||
MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
|
||||
MPTaskID currentTaskID = MPCurrentTaskID();
|
||||
OSStatus err = noErr;
|
||||
|
||||
if (criticalRegion == NULL)
|
||||
return paramErr;
|
||||
|
||||
// if I'm inside the critical region...
|
||||
if (currentTaskID == criticalRegion->mMPTaskID)
|
||||
{
|
||||
// bump my depth
|
||||
criticalRegion->mDepthCount++;
|
||||
// and continue
|
||||
return noErr;
|
||||
}
|
||||
|
||||
// wait for the ready semaphore
|
||||
err = MPWaitOnSemaphore(criticalRegion->mMPSemaphoreID, inTimeout);
|
||||
// we didn't get it. return the error
|
||||
if (noErr != err) return err;
|
||||
|
||||
// we got it!
|
||||
criticalRegion->mMPTaskID = currentTaskID;
|
||||
criticalRegion->mDepthCount = 1;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus
|
||||
MD_CriticalRegionExit(MDCriticalRegionID inCriticalRegionID)
|
||||
{
|
||||
MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
|
||||
MPTaskID currentTaskID = MPCurrentTaskID();
|
||||
OSStatus err = noErr;
|
||||
|
||||
// if we don't own the critical region...
|
||||
if (currentTaskID != criticalRegion->mMPTaskID)
|
||||
return kMPInsufficientResourcesErr;
|
||||
|
||||
// if we aren't at a depth...
|
||||
if (criticalRegion->mDepthCount == 0)
|
||||
return kMPInsufficientResourcesErr;
|
||||
|
||||
// un-bump my depth
|
||||
criticalRegion->mDepthCount--;
|
||||
|
||||
// if we just bottomed out...
|
||||
if (criticalRegion->mDepthCount == 0)
|
||||
{
|
||||
// release ownership of the structure
|
||||
criticalRegion->mMPTaskID = kInvalidID;
|
||||
// and signal the ready semaphore
|
||||
err = MPSignalSemaphore(criticalRegion->mMPSemaphoreID);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* George Warner, Apple Computer Inc.
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mdcriticalregion_h___
|
||||
#define mdcriticalregion_h___
|
||||
|
||||
|
||||
#ifndef __MULTIPROCESSING__
|
||||
#include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
typedef struct OpaqueMDCriticalRegionID* MDCriticalRegionID;
|
||||
|
||||
OSStatus MD_CriticalRegionCreate(MDCriticalRegionID * pMDCriticalRegionID);
|
||||
|
||||
OSStatus MD_CriticalRegionDelete(MDCriticalRegionID pMDCriticalRegionID);
|
||||
|
||||
OSStatus MD_CriticalRegionEnter(MDCriticalRegionID pMDCriticalRegionID, Duration pTimeout);
|
||||
|
||||
OSStatus MD_CriticalRegionExit(MDCriticalRegionID pMDCriticalRegionID);
|
||||
|
||||
#endif /* mdcriticalregion_h___ */
|
||||
|
||||
@@ -0,0 +1,776 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <Types.h>
|
||||
#include <Timer.h>
|
||||
#include <Files.h>
|
||||
#include <Errors.h>
|
||||
#include <Folders.h>
|
||||
#include <Gestalt.h>
|
||||
#include <Events.h>
|
||||
#include <Processes.h>
|
||||
#include <TextUtils.h>
|
||||
#include <MixedMode.h>
|
||||
#include <LowMem.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <unix.h>
|
||||
|
||||
#include "MacErrorHandling.h"
|
||||
|
||||
#include "primpl.h"
|
||||
#include "prgc.h"
|
||||
|
||||
#include "mactime.h"
|
||||
|
||||
#include "mdmac.h"
|
||||
|
||||
// undefine getenv, so that _MD_GetEnv can call the version in NSStdLib::nsEnvironment.cpp.
|
||||
#undef getenv
|
||||
|
||||
//
|
||||
// Local routines
|
||||
//
|
||||
unsigned char GarbageCollectorCacheFlusher(PRUint32 size);
|
||||
|
||||
extern PRThread *gPrimaryThread;
|
||||
extern ProcessSerialNumber gApplicationProcess; // in macthr.c
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark CREATING MACINTOSH THREAD STACKS
|
||||
|
||||
|
||||
enum {
|
||||
uppExitToShellProcInfo = kPascalStackBased,
|
||||
uppStackSpaceProcInfo = kRegisterBased
|
||||
| RESULT_SIZE(SIZE_CODE(sizeof(long)))
|
||||
| REGISTER_RESULT_LOCATION(kRegisterD0)
|
||||
| REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(UInt16)))
|
||||
};
|
||||
|
||||
typedef CALLBACK_API( long , StackSpacePatchPtr )(UInt16 trapNo);
|
||||
typedef REGISTER_UPP_TYPE(StackSpacePatchPtr) StackSpacePatchUPP;
|
||||
|
||||
StackSpacePatchUPP gStackSpacePatchUPP = NULL;
|
||||
UniversalProcPtr gStackSpacePatchCallThru = NULL;
|
||||
long (*gCallOSTrapUniversalProc)(UniversalProcPtr,ProcInfoType,...) = NULL;
|
||||
|
||||
|
||||
pascal long StackSpacePatch(UInt16 trapNo)
|
||||
{
|
||||
char tos;
|
||||
PRThread *thisThread;
|
||||
|
||||
thisThread = PR_GetCurrentThread();
|
||||
|
||||
// If we are the primary thread, then call through to the
|
||||
// good ol' fashion stack space implementation. Otherwise,
|
||||
// compute it by hand.
|
||||
if ((thisThread == gPrimaryThread) ||
|
||||
(&tos < thisThread->stack->stackBottom) ||
|
||||
(&tos > thisThread->stack->stackTop)) {
|
||||
return gCallOSTrapUniversalProc(gStackSpacePatchCallThru, uppStackSpaceProcInfo, trapNo);
|
||||
}
|
||||
else {
|
||||
return &tos - thisThread->stack->stackBottom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void InstallStackSpacePatch(void)
|
||||
{
|
||||
long systemVersion;
|
||||
OSErr err;
|
||||
CFragConnectionID connID;
|
||||
Str255 errMessage;
|
||||
Ptr interfaceLibAddr;
|
||||
CFragSymbolClass symClass;
|
||||
UniversalProcPtr (*getOSTrapAddressProc)(UInt16);
|
||||
void (*setOSTrapAddressProc)(StackSpacePatchUPP, UInt16);
|
||||
UniversalProcPtr (*newRoutineDescriptorProc)(ProcPtr,ProcInfoType,ISAType);
|
||||
|
||||
|
||||
err = Gestalt(gestaltSystemVersion,&systemVersion);
|
||||
if (systemVersion >= 0x00000A00) // we don't need to patch StackSpace()
|
||||
return;
|
||||
|
||||
// open connection to "InterfaceLib"
|
||||
err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag,
|
||||
&connID, &interfaceLibAddr, errMessage);
|
||||
PR_ASSERT(err == noErr);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
// get symbol GetOSTrapAddress
|
||||
err = FindSymbol(connID, "\pGetOSTrapAddress", &(Ptr)getOSTrapAddressProc, &symClass);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
// get symbol SetOSTrapAddress
|
||||
err = FindSymbol(connID, "\pSetOSTrapAddress", &(Ptr)setOSTrapAddressProc, &symClass);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
// get symbol NewRoutineDescriptor
|
||||
err = FindSymbol(connID, "\pNewRoutineDescriptor", &(Ptr)newRoutineDescriptorProc, &symClass);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
// get symbol CallOSTrapUniversalProc
|
||||
err = FindSymbol(connID, "\pCallOSTrapUniversalProc", &(Ptr)gCallOSTrapUniversalProc, &symClass);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
// get and set trap address for StackSpace (A065)
|
||||
gStackSpacePatchCallThru = getOSTrapAddressProc(0x0065);
|
||||
if (gStackSpacePatchCallThru)
|
||||
{
|
||||
gStackSpacePatchUPP =
|
||||
(StackSpacePatchUPP)newRoutineDescriptorProc((ProcPtr)(StackSpacePatch), uppStackSpaceProcInfo, GetCurrentArchitecture());
|
||||
setOSTrapAddressProc(gStackSpacePatchUPP, 0x0065);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
StackSpace();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark ENVIRONMENT VARIABLES
|
||||
|
||||
|
||||
typedef struct EnvVariable EnvVariable;
|
||||
|
||||
struct EnvVariable {
|
||||
char *variable;
|
||||
char *value;
|
||||
EnvVariable *next;
|
||||
};
|
||||
|
||||
EnvVariable *gEnvironmentVariables = NULL;
|
||||
|
||||
char *_MD_GetEnv(const char *name)
|
||||
{
|
||||
EnvVariable *currentVariable = gEnvironmentVariables;
|
||||
|
||||
while (currentVariable) {
|
||||
if (!strcmp(currentVariable->variable, name))
|
||||
return currentVariable->value;
|
||||
|
||||
currentVariable = currentVariable->next;
|
||||
}
|
||||
|
||||
return getenv(name);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(int)
|
||||
_MD_PutEnv(const char *string)
|
||||
{
|
||||
EnvVariable *currentVariable = gEnvironmentVariables;
|
||||
char *variableCopy,
|
||||
*value,
|
||||
*current;
|
||||
|
||||
variableCopy = strdup(string);
|
||||
PR_ASSERT(variableCopy != NULL);
|
||||
|
||||
current = variableCopy;
|
||||
while (*current != '=')
|
||||
current++;
|
||||
|
||||
*current = 0;
|
||||
current++;
|
||||
|
||||
value = current;
|
||||
|
||||
while (currentVariable) {
|
||||
if (!strcmp(currentVariable->variable, variableCopy))
|
||||
break;
|
||||
|
||||
currentVariable = currentVariable->next;
|
||||
}
|
||||
|
||||
if (currentVariable == NULL) {
|
||||
currentVariable = PR_NEW(EnvVariable);
|
||||
|
||||
if (currentVariable == NULL) {
|
||||
PR_DELETE(variableCopy);
|
||||
return -1;
|
||||
}
|
||||
|
||||
currentVariable->variable = strdup(variableCopy);
|
||||
currentVariable->value = strdup(value);
|
||||
currentVariable->next = gEnvironmentVariables;
|
||||
gEnvironmentVariables = currentVariable;
|
||||
}
|
||||
|
||||
else {
|
||||
PR_DELETE(currentVariable->value);
|
||||
currentVariable->value = strdup(current);
|
||||
|
||||
/* This is a temporary hack. Working on a real fix, remove this when done. */
|
||||
/* OK, there are two ways to access the */
|
||||
/* library path, getenv() and PR_GetLibraryPath(). Take a look at PR_GetLibraryPath(). */
|
||||
/* You'll see that we keep the path in a global which is intialized at startup from */
|
||||
/* a call to getenv(). From then on, they have nothing in common. */
|
||||
/* We need to keep them in synch. */
|
||||
if (strcmp(currentVariable->variable, "LD_LIBRARY_PATH") == 0)
|
||||
PR_SetLibraryPath(currentVariable->value);
|
||||
}
|
||||
|
||||
PR_DELETE(variableCopy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark MISCELLANEOUS
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
if (isCurrent) {
|
||||
(void) setjmp(t->md.jb);
|
||||
}
|
||||
*np = sizeof(t->md.jb) / sizeof(PRUint32);
|
||||
return (PRWord*) (t->md.jb);
|
||||
}
|
||||
|
||||
void _MD_GetRegisters(PRUint32 *to)
|
||||
{
|
||||
(void) setjmp((void*) to);
|
||||
}
|
||||
|
||||
void _MD_EarlyInit()
|
||||
{
|
||||
Handle environmentVariables;
|
||||
|
||||
GetCurrentProcess(&gApplicationProcess);
|
||||
|
||||
INIT_CRITICAL_REGION();
|
||||
InitIdleSemaphore();
|
||||
|
||||
#if !defined(MAC_NSPR_STANDALONE)
|
||||
// MacintoshInitializeMemory(); Moved to mdmacmem.c: AllocateRawMemory(Size blockSize)
|
||||
#else
|
||||
MacintoshInitializeMemory();
|
||||
#endif
|
||||
MacintoshInitializeTime();
|
||||
|
||||
// Install resource-controlled environment variables.
|
||||
|
||||
environmentVariables = GetResource('Envi', 128);
|
||||
if (environmentVariables != NULL) {
|
||||
|
||||
Size resourceSize;
|
||||
char *currentPutEnvString = (char *)*environmentVariables,
|
||||
*currentScanChar = currentPutEnvString;
|
||||
|
||||
resourceSize = GetHandleSize(environmentVariables);
|
||||
DetachResource(environmentVariables);
|
||||
HLock(environmentVariables);
|
||||
|
||||
while (resourceSize--) {
|
||||
|
||||
if ((*currentScanChar == '\n') || (*currentScanChar == '\r')) {
|
||||
*currentScanChar = 0;
|
||||
_MD_PutEnv (currentPutEnvString);
|
||||
currentPutEnvString = currentScanChar + 1;
|
||||
}
|
||||
|
||||
currentScanChar++;
|
||||
|
||||
}
|
||||
|
||||
DisposeHandle(environmentVariables);
|
||||
|
||||
}
|
||||
|
||||
#ifdef PR_INTERNAL_LOGGING
|
||||
_MD_PutEnv ("NSPR_LOG_MODULES=clock:6,cmon:6,io:6,mon:6,linker:6,cvar:6,sched:6,thread:6");
|
||||
#endif
|
||||
|
||||
InstallStackSpacePatch();
|
||||
}
|
||||
|
||||
void _MD_FinalInit()
|
||||
{
|
||||
_MD_InitNetAccess();
|
||||
}
|
||||
|
||||
void PR_InitMemory(void) {
|
||||
#ifndef NSPR_AS_SHARED_LIB
|
||||
// Needed for Mac browsers without Java. We don't want them calling PR_INIT, since it
|
||||
// brings in all of the thread support. But we do need to allow them to initialize
|
||||
// the NSPR memory package.
|
||||
// This should go away when all clients of the NSPR want threads AND memory.
|
||||
MacintoshInitializeMemory();
|
||||
#endif
|
||||
}
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark TERMINATION
|
||||
|
||||
|
||||
// THIS IS *** VERY *** IMPORTANT... our CFM Termination proc.
|
||||
// This allows us to deactivate our Time Mananger task even
|
||||
// if we are not totally gracefully exited. If this is not
|
||||
// done then we will randomly crash at later times when the
|
||||
// task is called after the app heap is gone.
|
||||
|
||||
#if TARGET_CARBON
|
||||
extern OTClientContextPtr clientContext;
|
||||
#define CLOSE_OPEN_TRANSPORT() CloseOpenTransportInContext(clientContext)
|
||||
|
||||
#else
|
||||
|
||||
#define CLOSE_OPEN_TRANSPORT() CloseOpenTransport()
|
||||
#endif /* TARGET_CARBON */
|
||||
|
||||
extern pascal void __NSTerminate(void);
|
||||
|
||||
void CleanupTermProc(void)
|
||||
{
|
||||
_MD_StopInterrupts(); // deactive Time Manager task
|
||||
|
||||
CLOSE_OPEN_TRANSPORT();
|
||||
TermIdleSemaphore();
|
||||
TERM_CRITICAL_REGION();
|
||||
|
||||
__NSTerminate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark STRING OPERATIONS
|
||||
|
||||
#if !defined(MAC_NSPR_STANDALONE)
|
||||
|
||||
// PStrFromCStr converts the source C string to a destination
|
||||
// pascal string as it copies. The dest string will
|
||||
// be truncated to fit into an Str255 if necessary.
|
||||
// If the C String pointer is NULL, the pascal string's length is set to zero
|
||||
//
|
||||
void
|
||||
PStrFromCStr(const char* src, Str255 dst)
|
||||
{
|
||||
short length = 0;
|
||||
|
||||
// handle case of overlapping strings
|
||||
if ( (void*)src == (void*)dst )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
unsigned char thisChar;
|
||||
|
||||
thisChar = *(const unsigned char*)src++;
|
||||
while ( thisChar != '\0' )
|
||||
{
|
||||
unsigned char nextChar;
|
||||
|
||||
// use nextChar so we don't overwrite what we are about to read
|
||||
nextChar = *(const unsigned char*)src++;
|
||||
*curdst++ = thisChar;
|
||||
thisChar = nextChar;
|
||||
|
||||
if ( ++length >= 255 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( src != NULL )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
short overflow = 255; // count down so test it loop is faster
|
||||
register char temp;
|
||||
|
||||
// Can't do the K&R C thing of "while (*s++ = *t++)" because it will copy trailing zero
|
||||
// which might overrun pascal buffer. Instead we use a temp variable.
|
||||
while ( (temp = *src++) != 0 )
|
||||
{
|
||||
*(char*)curdst++ = temp;
|
||||
|
||||
if ( --overflow <= 0 )
|
||||
break;
|
||||
}
|
||||
length = 255 - overflow;
|
||||
}
|
||||
dst[0] = length;
|
||||
}
|
||||
|
||||
|
||||
void CStrFromPStr(ConstStr255Param pString, char **cString)
|
||||
{
|
||||
// Allocates a cString and copies a Pascal string into it.
|
||||
unsigned int len;
|
||||
|
||||
len = pString[0];
|
||||
*cString = malloc(len+1);
|
||||
|
||||
if (*cString != NULL) {
|
||||
strncpy(*cString, (char *)&pString[1], len);
|
||||
(*cString)[len] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dprintf(const char *format, ...)
|
||||
{
|
||||
#if DEBUG
|
||||
va_list ap;
|
||||
Str255 buffer;
|
||||
|
||||
va_start(ap, format);
|
||||
buffer[0] = PR_vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
DebugStr(buffer);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void debugstr(const char *debuggerMsg)
|
||||
{
|
||||
Str255 pStr;
|
||||
|
||||
PStrFromCStr(debuggerMsg, pStr);
|
||||
DebugStr(pStr);
|
||||
}
|
||||
|
||||
|
||||
char *strdup(const char *source)
|
||||
{
|
||||
char *newAllocation;
|
||||
size_t stringLength;
|
||||
|
||||
PR_ASSERT(source);
|
||||
|
||||
stringLength = strlen(source) + 1;
|
||||
|
||||
newAllocation = (char *)PR_MALLOC(stringLength);
|
||||
if (newAllocation == NULL)
|
||||
return NULL;
|
||||
BlockMoveData(source, newAllocation, stringLength);
|
||||
return newAllocation;
|
||||
}
|
||||
|
||||
// PStrFromCStr converts the source C string to a destination
|
||||
// pascal string as it copies. The dest string will
|
||||
// be truncated to fit into an Str255 if necessary.
|
||||
// If the C String pointer is NULL, the pascal string's length is set to zero
|
||||
//
|
||||
void PStrFromCStr(const char* src, Str255 dst)
|
||||
{
|
||||
short length = 0;
|
||||
|
||||
// handle case of overlapping strings
|
||||
if ( (void*)src == (void*)dst )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
unsigned char thisChar;
|
||||
|
||||
thisChar = *(const unsigned char*)src++;
|
||||
while ( thisChar != '\0' )
|
||||
{
|
||||
unsigned char nextChar;
|
||||
|
||||
// use nextChar so we don't overwrite what we are about to read
|
||||
nextChar = *(const unsigned char*)src++;
|
||||
*curdst++ = thisChar;
|
||||
thisChar = nextChar;
|
||||
|
||||
if ( ++length >= 255 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( src != NULL )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
short overflow = 255; // count down so test it loop is faster
|
||||
register char temp;
|
||||
|
||||
// Can't do the K&R C thing of "while (*s++ = *t++)" because it will copy trailing zero
|
||||
// which might overrun pascal buffer. Instead we use a temp variable.
|
||||
while ( (temp = *src++) != 0 )
|
||||
{
|
||||
*(char*)curdst++ = temp;
|
||||
|
||||
if ( --overflow <= 0 )
|
||||
break;
|
||||
}
|
||||
length = 255 - overflow;
|
||||
}
|
||||
dst[0] = length;
|
||||
}
|
||||
|
||||
|
||||
void CStrFromPStr(ConstStr255Param pString, char **cString)
|
||||
{
|
||||
// Allocates a cString and copies a Pascal string into it.
|
||||
unsigned int len;
|
||||
|
||||
len = pString[0];
|
||||
*cString = PR_MALLOC(len+1);
|
||||
|
||||
if (*cString != NULL) {
|
||||
strncpy(*cString, (char *)&pString[1], len);
|
||||
(*cString)[len] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t strlen(const char *source)
|
||||
{
|
||||
size_t currentLength = 0;
|
||||
|
||||
if (source == NULL)
|
||||
return currentLength;
|
||||
|
||||
while (*source++ != '\0')
|
||||
currentLength++;
|
||||
|
||||
return currentLength;
|
||||
}
|
||||
|
||||
int strcmpcore(const char *str1, const char *str2, int caseSensitive)
|
||||
{
|
||||
char currentChar1, currentChar2;
|
||||
|
||||
while (1) {
|
||||
|
||||
currentChar1 = *str1;
|
||||
currentChar2 = *str2;
|
||||
|
||||
if (!caseSensitive) {
|
||||
|
||||
if ((currentChar1 >= 'a') && (currentChar1 <= 'z'))
|
||||
currentChar1 += ('A' - 'a');
|
||||
|
||||
if ((currentChar2 >= 'a') && (currentChar2 <= 'z'))
|
||||
currentChar2 += ('A' - 'a');
|
||||
|
||||
}
|
||||
|
||||
if (currentChar1 == '\0')
|
||||
break;
|
||||
|
||||
if (currentChar1 != currentChar2)
|
||||
return currentChar1 - currentChar2;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return currentChar1 - currentChar2;
|
||||
}
|
||||
|
||||
int strcmp(const char *str1, const char *str2)
|
||||
{
|
||||
return strcmpcore(str1, str2, true);
|
||||
}
|
||||
|
||||
int strcasecmp(const char *str1, const char *str2)
|
||||
{
|
||||
return strcmpcore(str1, str2, false);
|
||||
}
|
||||
|
||||
|
||||
void *memcpy(void *to, const void *from, size_t size)
|
||||
{
|
||||
if (size != 0) {
|
||||
#if DEBUG
|
||||
if ((UInt32)to < 0x1000)
|
||||
DebugStr("\pmemcpy has illegal to argument");
|
||||
if ((UInt32)from < 0x1000)
|
||||
DebugStr("\pmemcpy has illegal from argument");
|
||||
#endif
|
||||
BlockMoveData(from, to, size);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
void dprintf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *buffer;
|
||||
|
||||
va_start(ap, format);
|
||||
buffer = (char *)PR_vsmprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
debugstr(buffer);
|
||||
PR_DELETE(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
exit(int result)
|
||||
{
|
||||
#pragma unused (result)
|
||||
|
||||
ExitToShell();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark FLUSHING THE GARBAGE COLLECTOR
|
||||
|
||||
#if !defined(MAC_NSPR_STANDALONE)
|
||||
|
||||
unsigned char GarbageCollectorCacheFlusher(PRUint32)
|
||||
{
|
||||
|
||||
PRIntn is;
|
||||
|
||||
UInt32 oldPriority;
|
||||
|
||||
// If java wasn't completely initialized, then bail
|
||||
// harmlessly.
|
||||
|
||||
if (PR_GetGCInfo()->lock == NULL)
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
if (_MD_GET_INTSOFF() == 1)
|
||||
DebugStr("\pGarbageCollectorCacheFlusher at interrupt time!");
|
||||
#endif
|
||||
|
||||
// The synchronization here is very tricky. We really
|
||||
// don't want any other threads to run while we are
|
||||
// cleaning up the gc heap... they could call malloc,
|
||||
// and then we would be in trouble in a big way. So,
|
||||
// we jack up our priority and that of the finalizer
|
||||
// so that we won't yield to other threads.
|
||||
// dkc 5/17/96
|
||||
|
||||
oldPriority = PR_GetThreadPriority(PR_GetCurrentThread());
|
||||
_PR_INTSOFF(is);
|
||||
_PR_SetThreadPriority(PR_GetCurrentThread(), (PRThreadPriority)30);
|
||||
_PR_INTSON(is);
|
||||
|
||||
// Garbage collect twice. This will finalize any
|
||||
// dangling AWT resources (images, components), and
|
||||
// then free up their GC space, too.
|
||||
// dkc 2/15/96
|
||||
// interrupts must be on during PR_GC
|
||||
|
||||
PR_GC();
|
||||
|
||||
// By setting the finalizer priority to 31, then we
|
||||
// ensure it will run before us. When it finishes
|
||||
// its list of finalizations, it returns to us
|
||||
// for the second garbage collection.
|
||||
|
||||
PR_Yield();
|
||||
|
||||
PR_GC();
|
||||
|
||||
// Restore our old priorities.
|
||||
|
||||
_PR_INTSOFF(is);
|
||||
_PR_SetThreadPriority(PR_GetCurrentThread(), (PRThreadPriority)oldPriority);
|
||||
_PR_INTSON(is);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//##############################################################################
|
||||
//##############################################################################
|
||||
#pragma mark -
|
||||
#pragma mark MISCELLANEOUS-HACKS
|
||||
|
||||
|
||||
//
|
||||
// ***** HACK FIX THESE ****
|
||||
//
|
||||
extern long _MD_GetOSName(char *buf, long count)
|
||||
{
|
||||
long len;
|
||||
|
||||
len = PR_snprintf(buf, count, "Mac OS");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern long _MD_GetOSVersion(char *buf, long count)
|
||||
{
|
||||
long len;
|
||||
|
||||
len = PR_snprintf(buf, count, "7.5");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern long _MD_GetArchitecture(char *buf, long count)
|
||||
{
|
||||
long len;
|
||||
|
||||
#if defined(TARGET_CPU_PPC) && TARGET_CPU_PPC
|
||||
len = PR_snprintf(buf, count, "PowerPC");
|
||||
#else
|
||||
len = PR_snprintf(buf, count, "Motorola68k");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#ifndef mdmac_h__
|
||||
#define mdmac_h__
|
||||
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
void PStrFromCStr(const char* src, Str255 dst);
|
||||
void CStrFromPStr(ConstStr255Param pString, char **cString);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
|
||||
#endif /* mdmac_h__ */
|
||||
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nspr_cpucfg___
|
||||
#define nspr_cpucfg___
|
||||
|
||||
#ifndef XP_MAC
|
||||
#define XP_MAC
|
||||
#endif
|
||||
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define HAVE_LONG_LONG
|
||||
|
||||
#define PR_AF_INET6 30 /* same as AF_INET6 */
|
||||
|
||||
#define PR_BYTES_PER_BYTE 1L
|
||||
#define PR_BYTES_PER_SHORT 2L
|
||||
#define PR_BYTES_PER_INT 4L
|
||||
#define PR_BYTES_PER_INT64 8L
|
||||
#define PR_BYTES_PER_LONG 4L
|
||||
#define PR_BYTES_PER_FLOAT 4L
|
||||
#define PR_BYTES_PER_DOUBLE 8L
|
||||
#define PR_BYTES_PER_WORD 4L
|
||||
#define PR_BYTES_PER_DWORD 8L
|
||||
|
||||
#define PR_BITS_PER_BYTE 8L
|
||||
#define PR_BITS_PER_SHORT 16L
|
||||
#define PR_BITS_PER_INT 32L
|
||||
#define PR_BITS_PER_INT64 64L
|
||||
#define PR_BITS_PER_LONG 32L
|
||||
#define PR_BITS_PER_FLOAT 32L
|
||||
#define PR_BITS_PER_DOUBLE 64L
|
||||
#define PR_BITS_PER_WORD 32L
|
||||
|
||||
#define PR_BITS_PER_BYTE_LOG2 3L
|
||||
#define PR_BITS_PER_SHORT_LOG2 4L
|
||||
#define PR_BITS_PER_INT_LOG2 5L
|
||||
#define PR_BITS_PER_INT64_LOG2 6L
|
||||
#define PR_BITS_PER_LONG_LOG2 5L
|
||||
#define PR_BITS_PER_FLOAT_LOG2 5L
|
||||
#define PR_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define PR_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define PR_ALIGN_OF_SHORT 2L
|
||||
#define PR_ALIGN_OF_INT 4L
|
||||
#define PR_ALIGN_OF_LONG 4L
|
||||
#define PR_ALIGN_OF_INT64 2L
|
||||
#define PR_ALIGN_OF_FLOAT 4L
|
||||
#define PR_ALIGN_OF_DOUBLE 4L
|
||||
#define PR_ALIGN_OF_POINTER 4L
|
||||
#define PR_ALIGN_OF_WORD 4L
|
||||
|
||||
#define PR_BYTES_PER_WORD_LOG2 2L
|
||||
#define PR_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
#ifndef NO_NSPR_10_SUPPORT
|
||||
#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
|
||||
#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
|
||||
#define BYTES_PER_INT PR_BYTES_PER_INT
|
||||
#define BYTES_PER_INT64 PR_BYTES_PER_INT64
|
||||
#define BYTES_PER_LONG PR_BYTES_PER_LONG
|
||||
#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
|
||||
#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
|
||||
#define BYTES_PER_WORD PR_BYTES_PER_WORD
|
||||
#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
|
||||
|
||||
#define BITS_PER_BYTE PR_BITS_PER_BYTE
|
||||
#define BITS_PER_SHORT PR_BITS_PER_SHORT
|
||||
#define BITS_PER_INT PR_BITS_PER_INT
|
||||
#define BITS_PER_INT64 PR_BITS_PER_INT64
|
||||
#define BITS_PER_LONG PR_BITS_PER_LONG
|
||||
#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
|
||||
#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
|
||||
#define BITS_PER_WORD PR_BITS_PER_WORD
|
||||
|
||||
#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
|
||||
#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
|
||||
#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
|
||||
#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
|
||||
#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
|
||||
#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
|
||||
#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
|
||||
#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
|
||||
|
||||
#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
|
||||
#define ALIGN_OF_INT PR_ALIGN_OF_INT
|
||||
#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
|
||||
#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
|
||||
#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
|
||||
#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
|
||||
#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
|
||||
#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
|
||||
|
||||
#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
|
||||
#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
|
||||
#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
|
||||
#endif /* NO_NSPR_10_SUPPORT */
|
||||
|
||||
#endif /* nspr_cpucfg___ */
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,18 @@
|
||||
/.cvsignore/1.2/Sat May 12 06:11:46 2001//
|
||||
/Makefile.in/1.16/Sun Apr 25 15:00:59 2004//
|
||||
/objs.mk/1.7/Sun Apr 25 15:00:59 2004//
|
||||
/os2_errors.c/3.9/Sun Apr 25 15:00:59 2004//
|
||||
/os2cv.c/3.14/Sun Apr 25 15:00:59 2004//
|
||||
/os2emx.s/1.3/Mon Jan 9 17:43:52 2006//
|
||||
/os2gc.c/3.7/Sun Apr 25 15:00:59 2004//
|
||||
/os2inrval.c/3.10/Tue Jan 25 22:24:12 2005//
|
||||
/os2io.c/3.17/Fri Apr 22 21:14:03 2005//
|
||||
/os2misc.c/3.24/Mon Nov 22 21:06:12 2004//
|
||||
/os2poll.c/3.14/Sun Apr 25 15:00:59 2004//
|
||||
/os2rng.c/1.6/Sun Apr 25 15:00:59 2004//
|
||||
/os2sem.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/os2sock.c/3.17/Fri Apr 22 21:14:03 2005//
|
||||
/os2thred.c/3.17/Sun Apr 25 15:00:59 2004//
|
||||
/os2vaclegacy.s/3.1/Tue Sep 16 01:57:42 2003//
|
||||
/os2vacpp.asm/1.7/Mon Jan 9 17:43:52 2006//
|
||||
D
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md/os2
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
ifeq ($(OS_TARGET), OS2)
|
||||
CSRCS = \
|
||||
os2misc.c \
|
||||
os2sem.c \
|
||||
os2inrval.c \
|
||||
os2gc.c \
|
||||
os2thred.c \
|
||||
os2io.c \
|
||||
os2cv.c \
|
||||
os2sock.c \
|
||||
os2_errors.c \
|
||||
os2poll.c \
|
||||
os2rng.c \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
ASFILES = os2vacpp.asm
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),EMX)
|
||||
ASFILES = os2emx.s os2vaclegacy.s
|
||||
endif
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
|
||||
|
||||
DEFINES += -D_NSPR_BUILD_
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# This makefile appends to the variable OBJS the platform-dependent
|
||||
# object modules that will be part of the nspr20 library.
|
||||
|
||||
CSRCS = \
|
||||
os2io.c \
|
||||
os2sock.c \
|
||||
os2thred.c \
|
||||
os2cv.c \
|
||||
os2gc.c \
|
||||
os2misc.c \
|
||||
os2inrval.c \
|
||||
os2sem.c \
|
||||
os2_errors.c \
|
||||
os2poll.c \
|
||||
os2rng.c \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),VACPP)
|
||||
ASFILES = os2vacpp.asm
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_OS2_TOOLS),EMX)
|
||||
ASFILES = os2emx.s os2vaclegacy.s
|
||||
endif
|
||||
|
||||
OBJS += $(addprefix md/os2/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix md/os2/$(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)))
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,432 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* os2cv.c -- OS/2 Machine-Dependent Code for Condition Variables
|
||||
*
|
||||
* We implement our own condition variable wait queue. Each thread
|
||||
* has a semaphore object (thread->md.blocked_sema) to block on while
|
||||
* waiting on a condition variable.
|
||||
*
|
||||
* We use a deferred condition notify algorithm. When PR_NotifyCondVar
|
||||
* or PR_NotifyAllCondVar is called, the condition notifies are simply
|
||||
* recorded in the _MDLock structure. We defer the condition notifies
|
||||
* until right after we unlock the lock. This way the awakened threads
|
||||
* have a better chance to reaquire the lock.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#ifdef USE_RAMSEM
|
||||
ULONG _Far16 _Pascal Dos16GetInfoSeg(PSEL pselGlobal, PSEL pselLocal);
|
||||
|
||||
#ifdef XP_OS2_EMX
|
||||
typedef unsigned short BOOL16;
|
||||
#endif
|
||||
|
||||
typedef struct _LINFOSEG
|
||||
{
|
||||
USHORT pidCurrent;
|
||||
USHORT pidParent;
|
||||
USHORT prtyCurrent;
|
||||
USHORT tidCurrent;
|
||||
USHORT sgCurrent;
|
||||
UCHAR rfProcStatus;
|
||||
UCHAR dummy1;
|
||||
BOOL16 fForeground;
|
||||
UCHAR typProcess;
|
||||
UCHAR dummy2;
|
||||
SEL selEnvironment;
|
||||
USHORT offCmdLine;
|
||||
USHORT cbDataSegment;
|
||||
USHORT cbStack;
|
||||
USHORT cbHeap;
|
||||
USHORT hmod;
|
||||
SEL selDS;
|
||||
SEL selPack;
|
||||
SEL selPackShr;
|
||||
SEL selPackPck;
|
||||
ULONG ulReserved;
|
||||
} LINFOSEG;
|
||||
typedef LINFOSEG FAR *PLINFOSEG;
|
||||
|
||||
PLINFOSEG plisCurrent = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AddThreadToCVWaitQueueInternal --
|
||||
*
|
||||
* Add the thread to the end of the condition variable's wait queue.
|
||||
* The CV's lock must be locked when this function is called.
|
||||
*/
|
||||
|
||||
static void
|
||||
AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv)
|
||||
{
|
||||
PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
|
||||
|| (cv->waitTail == NULL && cv->waitHead == NULL));
|
||||
cv->nwait += 1;
|
||||
thred->md.inCVWaitQueue = PR_TRUE;
|
||||
thred->md.next = NULL;
|
||||
thred->md.prev = cv->waitTail;
|
||||
if (cv->waitHead == NULL) {
|
||||
cv->waitHead = thred;
|
||||
} else {
|
||||
cv->waitTail->md.next = thred;
|
||||
}
|
||||
cv->waitTail = thred;
|
||||
}
|
||||
|
||||
/*
|
||||
* md_UnlockAndPostNotifies --
|
||||
*
|
||||
* Unlock the lock, and then do the deferred condition notifies.
|
||||
* If waitThred and waitCV are not NULL, waitThred is added to
|
||||
* the wait queue of waitCV before the lock is unlocked.
|
||||
*
|
||||
* This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK,
|
||||
* the two places where a lock is unlocked.
|
||||
*/
|
||||
void
|
||||
md_UnlockAndPostNotifies(
|
||||
_MDLock *lock,
|
||||
PRThread *waitThred,
|
||||
_MDCVar *waitCV)
|
||||
{
|
||||
PRIntn index;
|
||||
_MDNotified post;
|
||||
_MDNotified *notified, *prev = NULL;
|
||||
|
||||
/*
|
||||
* Time to actually notify any conditions that were affected
|
||||
* while the lock was held. Get a copy of the list that's in
|
||||
* the lock structure and then zero the original. If it's
|
||||
* linked to other such structures, we own that storage.
|
||||
*/
|
||||
post = lock->notified; /* a safe copy; we own the lock */
|
||||
|
||||
#if defined(DEBUG)
|
||||
memset(&lock->notified, 0, sizeof(_MDNotified)); /* reset */
|
||||
#else
|
||||
lock->notified.length = 0; /* these are really sufficient */
|
||||
lock->notified.link = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Figure out how many threads we need to wake up.
|
||||
*/
|
||||
notified = &post; /* this is where we start */
|
||||
do {
|
||||
for (index = 0; index < notified->length; ++index) {
|
||||
_MDCVar *cv = notified->cv[index].cv;
|
||||
PRThread *thred;
|
||||
int i;
|
||||
|
||||
/* Fast special case: no waiting threads */
|
||||
if (cv->waitHead == NULL) {
|
||||
notified->cv[index].notifyHead = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* General case */
|
||||
if (-1 == notified->cv[index].times) {
|
||||
/* broadcast */
|
||||
thred = cv->waitHead;
|
||||
while (thred != NULL) {
|
||||
thred->md.inCVWaitQueue = PR_FALSE;
|
||||
thred = thred->md.next;
|
||||
}
|
||||
notified->cv[index].notifyHead = cv->waitHead;
|
||||
cv->waitHead = cv->waitTail = NULL;
|
||||
cv->nwait = 0;
|
||||
} else {
|
||||
thred = cv->waitHead;
|
||||
i = notified->cv[index].times;
|
||||
while (thred != NULL && i > 0) {
|
||||
thred->md.inCVWaitQueue = PR_FALSE;
|
||||
thred = thred->md.next;
|
||||
i--;
|
||||
}
|
||||
notified->cv[index].notifyHead = cv->waitHead;
|
||||
cv->waitHead = thred;
|
||||
if (cv->waitHead == NULL) {
|
||||
cv->waitTail = NULL;
|
||||
} else {
|
||||
if (cv->waitHead->md.prev != NULL) {
|
||||
cv->waitHead->md.prev->md.next = NULL;
|
||||
cv->waitHead->md.prev = NULL;
|
||||
}
|
||||
}
|
||||
cv->nwait -= notified->cv[index].times - i;
|
||||
}
|
||||
}
|
||||
notified = notified->link;
|
||||
} while (NULL != notified);
|
||||
|
||||
if (waitThred) {
|
||||
AddThreadToCVWaitQueueInternal(waitThred, waitCV);
|
||||
}
|
||||
|
||||
/* Release the lock before notifying */
|
||||
#ifdef USE_RAMSEM
|
||||
SemReleasex86(&lock->mutex, 0);
|
||||
#else
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#endif
|
||||
|
||||
notified = &post; /* this is where we start */
|
||||
do {
|
||||
for (index = 0; index < notified->length; ++index) {
|
||||
PRThread *thred;
|
||||
PRThread *next;
|
||||
|
||||
thred = notified->cv[index].notifyHead;
|
||||
while (thred != NULL) {
|
||||
BOOL rv;
|
||||
|
||||
next = thred->md.next;
|
||||
thred->md.prev = thred->md.next = NULL;
|
||||
rv = DosPostEventSem(thred->md.blocked_sema);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
thred = next;
|
||||
}
|
||||
}
|
||||
prev = notified;
|
||||
notified = notified->link;
|
||||
if (&post != prev) PR_DELETE(prev);
|
||||
} while (NULL != notified);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notifies just get posted to the protecting mutex. The
|
||||
* actual notification is done when the lock is released so that
|
||||
* MP systems don't contend for a lock that they can't have.
|
||||
*/
|
||||
static void md_PostNotifyToCvar(_MDCVar *cvar, _MDLock *lock,
|
||||
PRBool broadcast)
|
||||
{
|
||||
PRIntn index = 0;
|
||||
_MDNotified *notified = &lock->notified;
|
||||
|
||||
while (1) {
|
||||
for (index = 0; index < notified->length; ++index) {
|
||||
if (notified->cv[index].cv == cvar) {
|
||||
if (broadcast) {
|
||||
notified->cv[index].times = -1;
|
||||
} else if (-1 != notified->cv[index].times) {
|
||||
notified->cv[index].times += 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* if not full, enter new CV in this array */
|
||||
if (notified->length < _MD_CV_NOTIFIED_LENGTH) break;
|
||||
|
||||
/* if there's no link, create an empty array and link it */
|
||||
if (NULL == notified->link) {
|
||||
notified->link = PR_NEWZAP(_MDNotified);
|
||||
}
|
||||
|
||||
notified = notified->link;
|
||||
}
|
||||
|
||||
/* A brand new entry in the array */
|
||||
notified->cv[index].times = (broadcast) ? -1 : 1;
|
||||
notified->cv[index].cv = cvar;
|
||||
notified->length += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _PR_MD_NEW_CV() -- Creating new condition variable
|
||||
* ... Solaris uses cond_init() in similar function.
|
||||
*
|
||||
* returns: -1 on failure
|
||||
* 0 when it succeeds.
|
||||
*
|
||||
*/
|
||||
PRInt32
|
||||
_PR_MD_NEW_CV(_MDCVar *cv)
|
||||
{
|
||||
cv->magic = _MD_MAGIC_CV;
|
||||
/*
|
||||
* The waitHead, waitTail, and nwait fields are zeroed
|
||||
* when the PRCondVar structure is created.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _PR_MD_FREE_CV(_MDCVar *cv)
|
||||
{
|
||||
cv->magic = (PRUint32)-1;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* _PR_MD_WAIT_CV() -- Wait on condition variable
|
||||
*/
|
||||
void
|
||||
_PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
|
||||
{
|
||||
PRThread *thred = _PR_MD_CURRENT_THREAD();
|
||||
ULONG rv, count;
|
||||
ULONG msecs = (timeout == PR_INTERVAL_NO_TIMEOUT) ?
|
||||
SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(timeout);
|
||||
|
||||
/*
|
||||
* If we have pending notifies, post them now.
|
||||
*/
|
||||
if (0 != lock->notified.length) {
|
||||
md_UnlockAndPostNotifies(lock, thred, cv);
|
||||
} else {
|
||||
AddThreadToCVWaitQueueInternal(thred, cv);
|
||||
#ifdef USE_RAMSEM
|
||||
SemReleasex86( &lock->mutex, 0 );
|
||||
#else
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait for notification or timeout; don't really care which */
|
||||
rv = DosWaitEventSem(thred->md.blocked_sema, msecs);
|
||||
if (rv == NO_ERROR) {
|
||||
DosResetEventSem(thred->md.blocked_sema, &count);
|
||||
}
|
||||
|
||||
#ifdef USE_RAMSEM
|
||||
SemRequest486(&(lock->mutex), -1);
|
||||
#else
|
||||
DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT);
|
||||
#endif
|
||||
|
||||
PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT);
|
||||
|
||||
if(rv == ERROR_TIMEOUT)
|
||||
{
|
||||
if (thred->md.inCVWaitQueue) {
|
||||
PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
|
||||
|| (cv->waitTail == NULL && cv->waitHead == NULL));
|
||||
cv->nwait -= 1;
|
||||
thred->md.inCVWaitQueue = PR_FALSE;
|
||||
if (cv->waitHead == thred) {
|
||||
cv->waitHead = thred->md.next;
|
||||
if (cv->waitHead == NULL) {
|
||||
cv->waitTail = NULL;
|
||||
} else {
|
||||
cv->waitHead->md.prev = NULL;
|
||||
}
|
||||
} else {
|
||||
PR_ASSERT(thred->md.prev != NULL);
|
||||
thred->md.prev->md.next = thred->md.next;
|
||||
if (thred->md.next != NULL) {
|
||||
thred->md.next->md.prev = thred->md.prev;
|
||||
} else {
|
||||
PR_ASSERT(cv->waitTail == thred);
|
||||
cv->waitTail = thred->md.prev;
|
||||
}
|
||||
}
|
||||
thred->md.next = thred->md.prev = NULL;
|
||||
} else {
|
||||
/*
|
||||
* This thread must have been notified, but the
|
||||
* SemRelease call happens after SemRequest
|
||||
* times out. Wait on the semaphore again to make it
|
||||
* non-signaled. We assume this wait won't take long.
|
||||
*/
|
||||
rv = DosWaitEventSem(thred->md.blocked_sema, SEM_INDEFINITE_WAIT);
|
||||
if (rv == NO_ERROR) {
|
||||
DosResetEventSem(thred->md.blocked_sema, &count);
|
||||
}
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
}
|
||||
PR_ASSERT(thred->md.inCVWaitQueue == PR_FALSE);
|
||||
return;
|
||||
} /* --- end _PR_MD_WAIT_CV() --- */
|
||||
|
||||
void
|
||||
_PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock)
|
||||
{
|
||||
md_PostNotifyToCvar(cv, lock, PR_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_NEW_LOCK(_MDLock *lock)
|
||||
{
|
||||
#ifdef USE_RAMSEM
|
||||
// It's better if this API traps when pCriticalSect is not a valid
|
||||
// pointer, because we can't return an error code and if we just return
|
||||
// the API caller will have nasty bugs that are hard to find.
|
||||
|
||||
PRAMSEM pramsem = (PRAMSEM)(&(lock->mutex));
|
||||
/* First time, set up addresses of processor specific functions
|
||||
*/
|
||||
if (plisCurrent == NULL)
|
||||
{
|
||||
SEL selGlobal = 0, selLocal = 0;
|
||||
|
||||
/* Convert 16 bit global information segment to 32 bit address
|
||||
* by performing CRMA on the 16 bit address: "shift" operation
|
||||
* to convert sel to flat, "and" operation to mask the address
|
||||
* to 32-bit
|
||||
*/
|
||||
Dos16GetInfoSeg(&selGlobal, &selLocal);
|
||||
plisCurrent = (PLINFOSEG)(((ULONG)selLocal << 13) &
|
||||
(ULONG)0x1fff0000);
|
||||
|
||||
}
|
||||
|
||||
memset(pramsem, 0, sizeof(pramsem));
|
||||
DosCreateEventSem(0, &pramsem->hevSem, DC_SEM_SHARED, 0);
|
||||
|
||||
lock->notified.length=0;
|
||||
lock->notified.link=NULL;
|
||||
return PR_SUCCESS;
|
||||
#else
|
||||
DosCreateMutexSem(0, &(lock->mutex), 0, 0);
|
||||
(lock)->notified.length=0;
|
||||
(lock)->notified.link=NULL;
|
||||
return PR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock)
|
||||
{
|
||||
md_PostNotifyToCvar(cv, lock, PR_TRUE);
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public
|
||||
/ License Version 1.1 (the "License"); you may not use this file
|
||||
/ except in compliance with the License. You may obtain a copy of
|
||||
/ the License at http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS
|
||||
/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
/ implied. See the License for the specific language governing
|
||||
/ rights and limitations under the License.
|
||||
/
|
||||
/ The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
/
|
||||
/ The Initial Developer of the Original Code is Netscape
|
||||
/ Communications Corporation. Portions created by Netscape are
|
||||
/ Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
/ Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/
|
||||
|
||||
/ PRInt32 __PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
|
||||
/
|
||||
/ Atomically increment the integer pointed to by 'val' and return
|
||||
/ the result of the increment.
|
||||
/
|
||||
.text
|
||||
.globl __PR_MD_ATOMIC_INCREMENT
|
||||
.align 4
|
||||
__PR_MD_ATOMIC_INCREMENT:
|
||||
movl 4(%esp), %ecx
|
||||
movl $1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
incl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 __PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
|
||||
/
|
||||
/ Atomically decrement the integer pointed to by 'val' and return
|
||||
/ the result of the decrement.
|
||||
/
|
||||
.text
|
||||
.globl __PR_MD_ATOMIC_DECREMENT
|
||||
.align 4
|
||||
__PR_MD_ATOMIC_DECREMENT:
|
||||
movl 4(%esp), %ecx
|
||||
movl $-1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
decl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 __PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
|
||||
/
|
||||
/ Atomically set the integer pointed to by 'val' to the new
|
||||
/ value 'newval' and return the old value.
|
||||
/
|
||||
/ An alternative implementation:
|
||||
/ .text
|
||||
/ .globl __PR_MD_ATOMIC_SET
|
||||
/ .align 4
|
||||
/__PR_MD_ATOMIC_SET:
|
||||
/ movl 4(%esp), %ecx
|
||||
/ movl 8(%esp), %edx
|
||||
/ movl (%ecx), %eax
|
||||
/retry:
|
||||
/ lock
|
||||
/ cmpxchgl %edx, (%ecx)
|
||||
/ jne retry
|
||||
/ ret
|
||||
/
|
||||
.text
|
||||
.globl __PR_MD_ATOMIC_SET
|
||||
.align 4
|
||||
__PR_MD_ATOMIC_SET:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
xchgl %eax, (%ecx)
|
||||
ret
|
||||
|
||||
/ PRInt32 __PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
|
||||
/
|
||||
/ Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
/ and return the result of the addition.
|
||||
/
|
||||
.text
|
||||
.globl __PR_MD_ATOMIC_ADD
|
||||
.align 4
|
||||
__PR_MD_ATOMIC_ADD:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
movl %eax, %edx
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
addl %edx, %eax
|
||||
ret
|
||||
@@ -0,0 +1,90 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* GC related routines
|
||||
*
|
||||
*/
|
||||
#include "primpl.h"
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
CONTEXTRECORD context;
|
||||
context.ContextFlags = CONTEXT_INTEGER;
|
||||
|
||||
if (_PR_IS_NATIVE_THREAD(t)) {
|
||||
context.ContextFlags |= CONTEXT_CONTROL;
|
||||
if (QueryThreadContext(t->md.handle, CONTEXT_CONTROL, &context)) {
|
||||
t->md.gcContext[0] = context.ctx_RegEax;
|
||||
t->md.gcContext[1] = context.ctx_RegEbx;
|
||||
t->md.gcContext[2] = context.ctx_RegEcx;
|
||||
t->md.gcContext[3] = context.ctx_RegEdx;
|
||||
t->md.gcContext[4] = context.ctx_RegEsi;
|
||||
t->md.gcContext[5] = context.ctx_RegEdi;
|
||||
t->md.gcContext[6] = context.ctx_RegEsp;
|
||||
t->md.gcContext[7] = context.ctx_RegEbp;
|
||||
*np = PR_NUM_GCREGS;
|
||||
} else {
|
||||
PR_ASSERT(0);/* XXX */
|
||||
}
|
||||
}
|
||||
return (PRWord *)&t->md.gcContext;
|
||||
}
|
||||
|
||||
/* This function is not used right now, but is left as a reference.
|
||||
* If you ever need to get the fiberID from the currently running fiber,
|
||||
* this is it.
|
||||
*/
|
||||
void *
|
||||
GetMyFiberID()
|
||||
{
|
||||
void *fiberData = 0;
|
||||
|
||||
/* A pointer to our tib entry is found at FS:[18]
|
||||
* At offset 10h is the fiberData pointer. The context of the
|
||||
* fiber is stored in there.
|
||||
*/
|
||||
#ifdef HAVE_ASM
|
||||
__asm {
|
||||
mov EDX, FS:[18h]
|
||||
mov EAX, DWORD PTR [EDX+10h]
|
||||
mov [fiberData], EAX
|
||||
}
|
||||
#endif
|
||||
|
||||
return fiberData;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* OS/2 interval timers
|
||||
*
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
static PRBool useHighResTimer = PR_FALSE;
|
||||
PRIntervalTime _os2_ticksPerSec = -1;
|
||||
PRIntn _os2_bitShift = 0;
|
||||
PRInt32 _os2_highMask = 0;
|
||||
|
||||
void
|
||||
_PR_MD_INTERVAL_INIT()
|
||||
{
|
||||
char *envp;
|
||||
ULONG timerFreq;
|
||||
APIRET rc;
|
||||
|
||||
if ((envp = getenv("NSPR_OS2_NO_HIRES_TIMER")) != NULL) {
|
||||
if (atoi(envp) == 1)
|
||||
return;
|
||||
}
|
||||
|
||||
timerFreq = 0; /* OS/2 high-resolution timer frequency in Hz */
|
||||
rc = DosTmrQueryFreq(&timerFreq);
|
||||
if (NO_ERROR == rc) {
|
||||
useHighResTimer = PR_TRUE;
|
||||
PR_ASSERT(timerFreq != 0);
|
||||
while (timerFreq > PR_INTERVAL_MAX) {
|
||||
timerFreq >>= 1;
|
||||
_os2_bitShift++;
|
||||
_os2_highMask = (_os2_highMask << 1)+1;
|
||||
}
|
||||
|
||||
_os2_ticksPerSec = timerFreq;
|
||||
PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_PR_MD_GET_INTERVAL()
|
||||
{
|
||||
if (useHighResTimer) {
|
||||
QWORD timestamp;
|
||||
PRInt32 top;
|
||||
APIRET rc = DosTmrQueryTime(×tamp);
|
||||
if (NO_ERROR != rc) {
|
||||
return -1;
|
||||
}
|
||||
/* Sadly, nspr requires the interval to range from 1000 ticks per
|
||||
* second to only 100000 ticks per second. DosTmrQueryTime is too
|
||||
* high resolution...
|
||||
*/
|
||||
top = timestamp.ulHi & _os2_highMask;
|
||||
top = top << (32 - _os2_bitShift);
|
||||
timestamp.ulLo = timestamp.ulLo >> _os2_bitShift;
|
||||
timestamp.ulLo = timestamp.ulLo + top;
|
||||
return (PRUint32)timestamp.ulLo;
|
||||
} else {
|
||||
ULONG msCount = -1;
|
||||
DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount));
|
||||
return msCount;
|
||||
}
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_PR_MD_INTERVAL_PER_SEC()
|
||||
{
|
||||
if (useHighResTimer) {
|
||||
return _os2_ticksPerSec;
|
||||
} else {
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,983 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/*
|
||||
* This Original Code has been modified by IBM Corporation.
|
||||
* Modifications made by IBM described herein are
|
||||
* Copyright (c) International Business Machines
|
||||
* Corporation, 2000
|
||||
*
|
||||
* Modifications to Mozilla code or documentation
|
||||
* identified per MPL Section 3.3
|
||||
*
|
||||
* Date Modified by Description of modification
|
||||
* 03/23/2000 IBM Corp. Changed write() to DosWrite(). EMX i/o
|
||||
* calls cannot be intermixed with DosXXX
|
||||
* calls since EMX remaps file/socket
|
||||
* handles.
|
||||
* 04/27/2000 IBM Corp. Changed open file to be more like NT and
|
||||
* better handle PR_TRUNCATE | PR_CREATE_FILE
|
||||
* and also fixed _PR_MD_SET_FD_INHERITABLE
|
||||
*/
|
||||
|
||||
/* OS2 IO module
|
||||
*
|
||||
* Assumes synchronous I/O.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
#include "prio.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#ifdef XP_OS2_VACPP
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
struct _MDLock _pr_ioq_lock;
|
||||
|
||||
static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */
|
||||
|
||||
typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction,
|
||||
LONGLONG cbFile, ULONG ulAttribute,
|
||||
ULONG fsOpenFlags, ULONG fsOpenMode,
|
||||
PEAOP2 peaop2);
|
||||
|
||||
typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock,
|
||||
PFILELOCKL pflLock, ULONG timeout,
|
||||
ULONG flags);
|
||||
|
||||
typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method,
|
||||
PLONGLONG ibActual);
|
||||
|
||||
DosOpenLType myDosOpenL;
|
||||
DosSetFileLocksLType myDosSetFileLocksL;
|
||||
DosSetFilePtrLType myDosSetFilePtrL;
|
||||
|
||||
void
|
||||
_PR_MD_INIT_IO()
|
||||
{
|
||||
APIRET rc;
|
||||
HMODULE module;
|
||||
|
||||
sock_init();
|
||||
|
||||
rc = DosLoadModule(NULL, 0, "DOSCALL1", &module);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isWSEB = PR_TRUE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
|
||||
{
|
||||
PRInt32 rv;
|
||||
ULONG count;
|
||||
|
||||
PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
|
||||
SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
|
||||
rv = DosWaitEventSem(thread->md.blocked_sema, msecs);
|
||||
DosResetEventSem(thread->md.blocked_sema, &count);
|
||||
switch(rv)
|
||||
{
|
||||
case NO_ERROR:
|
||||
return PR_SUCCESS;
|
||||
break;
|
||||
case ERROR_TIMEOUT:
|
||||
_PR_THREAD_LOCK(thread);
|
||||
if (thread->state == _PR_IO_WAIT) {
|
||||
;
|
||||
} else {
|
||||
if (thread->wait.cvar != NULL) {
|
||||
thread->wait.cvar = NULL;
|
||||
_PR_THREAD_UNLOCK(thread);
|
||||
} else {
|
||||
/* The CVAR was notified just as the timeout
|
||||
* occurred. This led to us being notified twice.
|
||||
* call SemRequest() to clear the semaphore.
|
||||
*/
|
||||
_PR_THREAD_UNLOCK(thread);
|
||||
rv = DosWaitEventSem(thread->md.blocked_sema, 0);
|
||||
DosResetEventSem(thread->md.blocked_sema, &count);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return PR_FAILURE;
|
||||
}
|
||||
PRStatus
|
||||
_PR_MD_WAKEUP_WAITER(PRThread *thread)
|
||||
{
|
||||
if ( _PR_IS_NATIVE_THREAD(thread) )
|
||||
{
|
||||
if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR)
|
||||
return PR_FAILURE;
|
||||
else
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* --- FILE IO ----------------------------------------------------------- */
|
||||
/*
|
||||
* _PR_MD_OPEN() -- Open a file
|
||||
*
|
||||
* returns: a fileHandle
|
||||
*
|
||||
* The NSPR open flags (osflags) are translated into flags for OS/2
|
||||
*
|
||||
* Mode seems to be passed in as a unix style file permissions argument
|
||||
* as in 0666, in the case of opening the logFile.
|
||||
*
|
||||
*/
|
||||
PRInt32
|
||||
_PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
|
||||
{
|
||||
HFILE file;
|
||||
PRInt32 access = OPEN_SHARE_DENYNONE;
|
||||
PRInt32 flags = 0L;
|
||||
APIRET rc = 0;
|
||||
PRUword actionTaken;
|
||||
|
||||
if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH;
|
||||
|
||||
if (osflags & PR_RDONLY)
|
||||
access |= OPEN_ACCESS_READONLY;
|
||||
else if (osflags & PR_WRONLY)
|
||||
access |= OPEN_ACCESS_WRITEONLY;
|
||||
else if(osflags & PR_RDWR)
|
||||
access |= OPEN_ACCESS_READWRITE;
|
||||
|
||||
if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
|
||||
{
|
||||
flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
|
||||
}
|
||||
else if (osflags & PR_CREATE_FILE)
|
||||
{
|
||||
if (osflags & PR_TRUNCATE)
|
||||
flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
|
||||
else
|
||||
flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (osflags & PR_TRUNCATE)
|
||||
flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
|
||||
else
|
||||
flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
|
||||
}
|
||||
|
||||
do {
|
||||
if (isWSEB)
|
||||
{
|
||||
rc = myDosOpenL((char*)name,
|
||||
&file, /* file handle if successful */
|
||||
&actionTaken, /* reason for failure */
|
||||
0, /* initial size of new file */
|
||||
FILE_NORMAL, /* file system attributes */
|
||||
flags, /* Open flags */
|
||||
access, /* Open mode and rights */
|
||||
0); /* OS/2 Extended Attributes */
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = DosOpen((char*)name,
|
||||
&file, /* file handle if successful */
|
||||
&actionTaken, /* reason for failure */
|
||||
0, /* initial size of new file */
|
||||
FILE_NORMAL, /* file system attributes */
|
||||
flags, /* Open flags */
|
||||
access, /* Open mode and rights */
|
||||
0); /* OS/2 Extended Attributes */
|
||||
};
|
||||
if (rc == ERROR_TOO_MANY_OPEN_FILES) {
|
||||
ULONG CurMaxFH = 0;
|
||||
LONG ReqCount = 20;
|
||||
APIRET rc2;
|
||||
rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
|
||||
if (rc2 != NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (rc == ERROR_TOO_MANY_OPEN_FILES);
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
_PR_MD_MAP_OPEN_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (PRInt32)file;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
|
||||
{
|
||||
ULONG bytes;
|
||||
int rv;
|
||||
|
||||
rv = DosRead((HFILE)fd->secret->md.osfd,
|
||||
(PVOID)buf,
|
||||
len,
|
||||
&bytes);
|
||||
|
||||
if (rv != NO_ERROR)
|
||||
{
|
||||
/* ERROR_HANDLE_EOF can only be returned by async io */
|
||||
PR_ASSERT(rv != ERROR_HANDLE_EOF);
|
||||
if (rv == ERROR_BROKEN_PIPE)
|
||||
return 0;
|
||||
else {
|
||||
_PR_MD_MAP_READ_ERROR(rv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (PRInt32)bytes;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
|
||||
{
|
||||
PRInt32 bytes;
|
||||
int rv;
|
||||
|
||||
rv = DosWrite((HFILE)fd->secret->md.osfd,
|
||||
(PVOID)buf,
|
||||
len,
|
||||
(PULONG)&bytes);
|
||||
|
||||
if (rv != NO_ERROR)
|
||||
{
|
||||
_PR_MD_MAP_WRITE_ERROR(rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len != bytes) {
|
||||
rv = ERROR_DISK_FULL;
|
||||
_PR_MD_MAP_WRITE_ERROR(rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
} /* --- end _PR_MD_WRITE() --- */
|
||||
|
||||
PRInt32
|
||||
_PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
|
||||
{
|
||||
PRInt32 rv;
|
||||
PRUword newLocation;
|
||||
|
||||
rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation);
|
||||
|
||||
if (rv != NO_ERROR) {
|
||||
_PR_MD_MAP_LSEEK_ERROR(rv);
|
||||
return -1;
|
||||
} else
|
||||
return newLocation;
|
||||
}
|
||||
|
||||
PRInt64
|
||||
_PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
|
||||
{
|
||||
#ifdef NO_LONG_LONG
|
||||
PRInt64 result;
|
||||
PRInt32 rv, low = offset.lo, hi = offset.hi;
|
||||
PRUword newLocation;
|
||||
|
||||
rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation);
|
||||
rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation);
|
||||
|
||||
if (rv != NO_ERROR) {
|
||||
_PR_MD_MAP_LSEEK_ERROR(rv);
|
||||
hi = newLocation = -1;
|
||||
}
|
||||
|
||||
result.lo = newLocation;
|
||||
result.hi = hi;
|
||||
return result;
|
||||
|
||||
#else
|
||||
PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
|
||||
PRUint64 rv;
|
||||
PRUint32 newLocation, uhi;
|
||||
PRUint64 newLocationL;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case PR_SEEK_SET:
|
||||
where = FILE_BEGIN;
|
||||
break;
|
||||
case PR_SEEK_CUR:
|
||||
where = FILE_CURRENT;
|
||||
break;
|
||||
case PR_SEEK_END:
|
||||
where = FILE_END;
|
||||
break;
|
||||
default:
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
if (isWSEB)
|
||||
{
|
||||
rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation);
|
||||
}
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
_PR_MD_MAP_LSEEK_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (isWSEB)
|
||||
{
|
||||
return newLocationL;
|
||||
}
|
||||
|
||||
uhi = (PRUint32)hi;
|
||||
PR_ASSERT((PRInt32)uhi >= 0);
|
||||
rv = uhi;
|
||||
PR_ASSERT((PRInt64)rv >= 0);
|
||||
rv = (rv << 32);
|
||||
PR_ASSERT((PRInt64)rv >= 0);
|
||||
rv += newLocation;
|
||||
PR_ASSERT((PRInt64)rv >= 0);
|
||||
return (PRInt64)rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_FSYNC(PRFileDesc *fd)
|
||||
{
|
||||
PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd);
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
if (rc != ERROR_ACCESS_DENIED) {
|
||||
_PR_MD_MAP_FSYNC_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_CloseFile(PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
rv = DosClose((HFILE)osfd);
|
||||
if (rv != NO_ERROR)
|
||||
_PR_MD_MAP_CLOSE_ERROR(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* --- DIR IO ------------------------------------------------------------ */
|
||||
#define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName)
|
||||
#define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile)
|
||||
|
||||
void FlipSlashes(char *cp, int len)
|
||||
{
|
||||
while (--len >= 0) {
|
||||
if (cp[0] == '/') {
|
||||
cp[0] = PR_DIRECTORY_SEPARATOR;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Local implementations of standard Unix RTL functions which are not provided
|
||||
** by the VAC RTL.
|
||||
**
|
||||
*/
|
||||
|
||||
PRInt32
|
||||
_PR_MD_CLOSE_DIR(_MDDir *d)
|
||||
{
|
||||
PRInt32 rc;
|
||||
|
||||
if ( d ) {
|
||||
rc = DosFindClose(d->d_hdl);
|
||||
if(rc == NO_ERROR){
|
||||
d->magic = (PRUint32)-1;
|
||||
return PR_SUCCESS;
|
||||
} else {
|
||||
_PR_MD_MAP_CLOSEDIR_ERROR(rc);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
PRStatus
|
||||
_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
|
||||
{
|
||||
char filename[ CCHMAXPATH ];
|
||||
PRUword numEntries, rc;
|
||||
|
||||
numEntries = 1;
|
||||
|
||||
PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
|
||||
name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
|
||||
FlipSlashes( filename, strlen(filename) );
|
||||
|
||||
d->d_hdl = HDIR_CREATE;
|
||||
|
||||
if (isWSEB)
|
||||
{
|
||||
rc = DosFindFirst( filename,
|
||||
&d->d_hdl,
|
||||
FILE_DIRECTORY | FILE_HIDDEN,
|
||||
&(d->d_entry.large),
|
||||
sizeof(d->d_entry.large),
|
||||
&numEntries,
|
||||
FIL_STANDARDL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = DosFindFirst( filename,
|
||||
&d->d_hdl,
|
||||
FILE_DIRECTORY | FILE_HIDDEN,
|
||||
&(d->d_entry.small),
|
||||
sizeof(d->d_entry.small),
|
||||
&numEntries,
|
||||
FIL_STANDARD);
|
||||
}
|
||||
if ( rc != NO_ERROR ) {
|
||||
_PR_MD_MAP_OPENDIR_ERROR(rc);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
d->firstEntry = PR_TRUE;
|
||||
d->magic = _MD_MAGIC_DIR;
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
char *
|
||||
_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
|
||||
{
|
||||
PRUword numFiles = 1;
|
||||
BOOL rv;
|
||||
char *fileName;
|
||||
USHORT fileAttr;
|
||||
|
||||
if ( d ) {
|
||||
while (1) {
|
||||
if (d->firstEntry) {
|
||||
d->firstEntry = PR_FALSE;
|
||||
rv = NO_ERROR;
|
||||
} else {
|
||||
rv = DosFindNext(d->d_hdl,
|
||||
&(d->d_entry),
|
||||
sizeof(d->d_entry),
|
||||
&numFiles);
|
||||
}
|
||||
if (rv != NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
fileName = GetFileFromDIR(d);
|
||||
fileAttr = GetFileAttr(d);
|
||||
if ( (flags & PR_SKIP_DOT) &&
|
||||
(fileName[0] == '.') && (fileName[1] == '\0'))
|
||||
continue;
|
||||
if ( (flags & PR_SKIP_DOT_DOT) &&
|
||||
(fileName[0] == '.') && (fileName[1] == '.') &&
|
||||
(fileName[2] == '\0'))
|
||||
continue;
|
||||
/*
|
||||
* XXX
|
||||
* Is this the correct definition of a hidden file on OS/2?
|
||||
*/
|
||||
if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN))
|
||||
return fileName;
|
||||
else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN))
|
||||
continue;
|
||||
return fileName;
|
||||
}
|
||||
PR_ASSERT(NO_ERROR != rv);
|
||||
_PR_MD_MAP_READDIR_ERROR(rv);
|
||||
return NULL;
|
||||
}
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_DELETE(const char *name)
|
||||
{
|
||||
PRInt32 rc = DosDelete((char*)name);
|
||||
if(rc == NO_ERROR) {
|
||||
return 0;
|
||||
} else {
|
||||
_PR_MD_MAP_DELETE_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_STAT(const char *fn, struct stat *info)
|
||||
{
|
||||
PRInt32 rv;
|
||||
char filename[CCHMAXPATH];
|
||||
|
||||
PR_snprintf(filename, CCHMAXPATH, "%s", fn);
|
||||
FlipSlashes(filename, strlen(filename));
|
||||
|
||||
rv = _stat((char*)filename, info);
|
||||
if (-1 == rv) {
|
||||
/*
|
||||
* Check for MSVC runtime library _stat() bug.
|
||||
* (It's really a bug in FindFirstFile().)
|
||||
* If a pathname ends in a backslash or slash,
|
||||
* e.g., c:\temp\ or c:/temp/, _stat() will fail.
|
||||
* Note: a pathname ending in a slash (e.g., c:/temp/)
|
||||
* can be handled by _stat() on NT but not on Win95.
|
||||
*
|
||||
* We remove the backslash or slash at the end and
|
||||
* try again.
|
||||
*
|
||||
* Not sure if this happens on OS/2 or not,
|
||||
* but it doesn't hurt to be careful.
|
||||
*/
|
||||
|
||||
int len = strlen(fn);
|
||||
if (len > 0 && len <= _MAX_PATH
|
||||
&& (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
|
||||
char newfn[_MAX_PATH + 1];
|
||||
|
||||
strcpy(newfn, fn);
|
||||
newfn[len - 1] = '\0';
|
||||
rv = _stat(newfn, info);
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 == rv) {
|
||||
_PR_MD_MAP_STAT_ERROR(errno);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt32 rv;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) {
|
||||
if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE ;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
info->size = sb.st_size;
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
|
||||
{
|
||||
PRFileInfo info32;
|
||||
PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
|
||||
if (rv != 0)
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
info->type = info32.type;
|
||||
LL_UI2L(info->size,info32.size);
|
||||
info->modifyTime = info32.modifyTime;
|
||||
info->creationTime = info32.creationTime;
|
||||
|
||||
if (isWSEB)
|
||||
{
|
||||
APIRET rc ;
|
||||
FILESTATUS3L fstatus;
|
||||
|
||||
rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus));
|
||||
|
||||
if (NO_ERROR != rc)
|
||||
{
|
||||
_PR_MD_MAP_OPEN_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! (fstatus.attrFile & FILE_DIRECTORY))
|
||||
{
|
||||
info->size = fstatus.cbFile;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
|
||||
{
|
||||
/* For once, the VAC compiler/library did a nice thing.
|
||||
* The file handle used by the C runtime is the same one
|
||||
* returned by the OS when you call DosOpen(). This means
|
||||
* that you can take an OS HFILE and use it with C file
|
||||
* functions. The only caveat is that you have to call
|
||||
* _setmode() first to initialize some junk. This is
|
||||
* immensely useful because I did not have a clue how to
|
||||
* implement this function otherwise. The windows folks
|
||||
* took the source from the Microsoft C library source, but
|
||||
* IBM wasn't kind enough to ship the source with VAC.
|
||||
* On second thought, the needed function could probably
|
||||
* be gotten from the OS/2 GNU library source, but the
|
||||
* point is now moot.
|
||||
*/
|
||||
struct stat hinfo;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
_setmode(fd->secret->md.osfd, O_BINARY);
|
||||
if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) {
|
||||
_PR_MD_MAP_FSTAT_ERROR(errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hinfo.st_mode & S_IFDIR)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_FILE;
|
||||
|
||||
info->size = hinfo.st_size;
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_I2L(s, hinfo.st_mtime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, hinfo.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
|
||||
{
|
||||
PRFileInfo info32;
|
||||
PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
|
||||
if (0 == rv)
|
||||
{
|
||||
info->type = info32.type;
|
||||
LL_UI2L(info->size,info32.size);
|
||||
|
||||
info->modifyTime = info32.modifyTime;
|
||||
info->creationTime = info32.creationTime;
|
||||
}
|
||||
|
||||
if (isWSEB)
|
||||
{
|
||||
APIRET rc ;
|
||||
FILESTATUS3L fstatus;
|
||||
|
||||
rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus));
|
||||
|
||||
if (NO_ERROR != rc)
|
||||
{
|
||||
_PR_MD_MAP_OPEN_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! (fstatus.attrFile & FILE_DIRECTORY))
|
||||
{
|
||||
info->size = fstatus.cbFile;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
_PR_MD_RENAME(const char *from, const char *to)
|
||||
{
|
||||
PRInt32 rc;
|
||||
/* Does this work with dot-relative pathnames? */
|
||||
if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) {
|
||||
return 0;
|
||||
} else {
|
||||
_PR_MD_MAP_RENAME_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_ACCESS(const char *name, PRAccessHow how)
|
||||
{
|
||||
PRInt32 rv;
|
||||
switch (how) {
|
||||
case PR_ACCESS_WRITE_OK:
|
||||
rv = access(name, 02);
|
||||
break;
|
||||
case PR_ACCESS_READ_OK:
|
||||
rv = access(name, 04);
|
||||
break;
|
||||
case PR_ACCESS_EXISTS:
|
||||
return access(name, 00);
|
||||
break;
|
||||
default:
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
if (rv < 0)
|
||||
_PR_MD_MAP_ACCESS_ERROR(errno);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_MKDIR(const char *name, PRIntn mode)
|
||||
{
|
||||
PRInt32 rc;
|
||||
/* XXXMB - how to translate the "mode"??? */
|
||||
if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) {
|
||||
return 0;
|
||||
} else {
|
||||
_PR_MD_MAP_MKDIR_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_RMDIR(const char *name)
|
||||
{
|
||||
PRInt32 rc;
|
||||
if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
|
||||
return 0;
|
||||
} else {
|
||||
_PR_MD_MAP_RMDIR_ERROR(rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_LOCKFILE(PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
FILELOCK lock, unlock;
|
||||
FILELOCKL lockL, unlockL;
|
||||
|
||||
lock.lOffset = 0;
|
||||
lockL.lOffset = 0;
|
||||
lock.lRange = 0xffffffff;
|
||||
lockL.lRange = 0xffffffffffffffff;
|
||||
unlock.lOffset = 0;
|
||||
unlock.lRange = 0;
|
||||
unlockL.lOffset = 0;
|
||||
unlockL.lRange = 0;
|
||||
|
||||
/*
|
||||
* loop trying to DosSetFileLocks(),
|
||||
* pause for a few miliseconds when can't get the lock
|
||||
* and try again
|
||||
*/
|
||||
for( rv = FALSE; rv == FALSE; /* do nothing */ )
|
||||
{
|
||||
if (isWSEB)
|
||||
{
|
||||
rv = myDosSetFileLocksL( (HFILE) f,
|
||||
&unlockL, &lockL,
|
||||
0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = DosSetFileLocks( (HFILE) f,
|
||||
&unlock, &lock,
|
||||
0, 0);
|
||||
}
|
||||
if ( rv != NO_ERROR )
|
||||
{
|
||||
DosSleep( 50 ); /* Sleep() a few milisecs and try again. */
|
||||
}
|
||||
} /* end for() */
|
||||
return PR_SUCCESS;
|
||||
} /* end _PR_MD_LOCKFILE() */
|
||||
|
||||
PRStatus
|
||||
_PR_MD_TLOCKFILE(PRInt32 f)
|
||||
{
|
||||
return _PR_MD_LOCKFILE(f);
|
||||
} /* end _PR_MD_TLOCKFILE() */
|
||||
|
||||
|
||||
PRStatus
|
||||
_PR_MD_UNLOCKFILE(PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
FILELOCK lock, unlock;
|
||||
FILELOCKL lockL, unlockL;
|
||||
|
||||
lock.lOffset = 0;
|
||||
lockL.lOffset = 0;
|
||||
lock.lRange = 0;
|
||||
lockL.lRange = 0;
|
||||
unlock.lOffset = 0;
|
||||
unlockL.lOffset = 0;
|
||||
unlock.lRange = 0xffffffff;
|
||||
unlockL.lRange = 0xffffffffffffffff;
|
||||
|
||||
if (isWSEB)
|
||||
{
|
||||
rv = myDosSetFileLocksL( (HFILE) f,
|
||||
&unlockL, &lockL,
|
||||
0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = DosSetFileLocks( (HFILE) f,
|
||||
&unlock, &lock,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
if ( rv != NO_ERROR )
|
||||
{
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
} /* end _PR_MD_UNLOCKFILE() */
|
||||
|
||||
PRStatus
|
||||
_PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
|
||||
{
|
||||
APIRET rc = 0;
|
||||
ULONG flags;
|
||||
switch (fd->methods->file_type)
|
||||
{
|
||||
case PR_DESC_PIPE:
|
||||
case PR_DESC_FILE:
|
||||
rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags);
|
||||
if (rc != NO_ERROR) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
if (inheritable)
|
||||
flags &= ~OPEN_FLAGS_NOINHERIT;
|
||||
else
|
||||
flags |= OPEN_FLAGS_NOINHERIT;
|
||||
|
||||
/* Mask off flags DosSetFHState don't want. */
|
||||
flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
|
||||
rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags);
|
||||
if (rc != NO_ERROR) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PR_DESC_LAYERED:
|
||||
/* what to do here? */
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/);
|
||||
return PR_FAILURE;
|
||||
|
||||
case PR_DESC_SOCKET_TCP:
|
||||
case PR_DESC_SOCKET_UDP:
|
||||
/* These are global on OS/2. */
|
||||
break;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
|
||||
{
|
||||
/* XXX this function needs to be implemented */
|
||||
fd->secret->inheritable = _PR_TRI_UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
|
||||
{
|
||||
/* XXX this function needs to be reviewed */
|
||||
ULONG flags;
|
||||
|
||||
PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
|
||||
if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) {
|
||||
if (flags & OPEN_FLAGS_NOINHERIT) {
|
||||
fd->secret->inheritable = _PR_TRI_FALSE;
|
||||
} else {
|
||||
fd->secret->inheritable = _PR_TRI_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Davide Bresolin <davide@teamos2.it>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* os2misc.c
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "primpl.h"
|
||||
|
||||
extern int _CRT_init(void);
|
||||
extern void _CRT_term(void);
|
||||
extern void __ctordtorInit(int flag);
|
||||
extern void __ctordtorTerm(int flag);
|
||||
|
||||
char *
|
||||
_PR_MD_GET_ENV(const char *name)
|
||||
{
|
||||
return getenv(name);
|
||||
}
|
||||
|
||||
PRIntn
|
||||
_PR_MD_PUT_ENV(const char *name)
|
||||
{
|
||||
return putenv(name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
**
|
||||
** Date and time routines
|
||||
**
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/timeb.h>
|
||||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
* PR_Now --
|
||||
*
|
||||
* Returns the current time in microseconds since the epoch.
|
||||
* The epoch is midnight January 1, 1970 GMT.
|
||||
* The implementation is machine dependent. This is the
|
||||
* implementation for OS/2.
|
||||
* Cf. time_t time(time_t *tp)
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(PRTime)
|
||||
PR_Now(void)
|
||||
{
|
||||
PRInt64 s, ms, ms2us, s2us;
|
||||
struct timeb b;
|
||||
|
||||
ftime(&b);
|
||||
LL_I2L(ms2us, PR_USEC_PER_MSEC);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_I2L(s, b.time);
|
||||
LL_I2L(ms, b.millitm);
|
||||
LL_MUL(ms, ms, ms2us);
|
||||
LL_MUL(s, s, s2us);
|
||||
LL_ADD(s, s, ms);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
***********************************************************************
|
||||
*
|
||||
* Process creation routines
|
||||
*
|
||||
***********************************************************************
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assemble the command line by concatenating the argv array.
|
||||
* On success, this function returns 0 and the resulting command
|
||||
* line is returned in *cmdLine. On failure, it returns -1.
|
||||
*/
|
||||
static int assembleCmdLine(char *const *argv, char **cmdLine)
|
||||
{
|
||||
char *const *arg;
|
||||
int cmdLineSize;
|
||||
|
||||
/*
|
||||
* Find out how large the command line buffer should be.
|
||||
*/
|
||||
cmdLineSize = 1; /* final null */
|
||||
for (arg = argv+1; *arg; arg++) {
|
||||
cmdLineSize += strlen(*arg) + 1; /* space in between */
|
||||
}
|
||||
*cmdLine = PR_MALLOC(cmdLineSize);
|
||||
if (*cmdLine == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*cmdLine)[0] = '\0';
|
||||
|
||||
for (arg = argv+1; *arg; arg++) {
|
||||
if (arg > argv +1) {
|
||||
strcat(*cmdLine, " ");
|
||||
}
|
||||
strcat(*cmdLine, *arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assemble the environment block by concatenating the envp array
|
||||
* (preserving the terminating null byte in each array element)
|
||||
* and adding a null byte at the end.
|
||||
*
|
||||
* Returns 0 on success. The resulting environment block is returned
|
||||
* in *envBlock. Note that if envp is NULL, a NULL pointer is returned
|
||||
* in *envBlock. Returns -1 on failure.
|
||||
*/
|
||||
static int assembleEnvBlock(char **envp, char **envBlock)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
char **env;
|
||||
char *curEnv;
|
||||
char *cwdStart, *cwdEnd;
|
||||
int envBlockSize;
|
||||
|
||||
PPIB ppib = NULL;
|
||||
PTIB ptib = NULL;
|
||||
|
||||
if (envp == NULL) {
|
||||
*envBlock = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR)
|
||||
return -1;
|
||||
|
||||
curEnv = ppib->pib_pchenv;
|
||||
|
||||
cwdStart = curEnv;
|
||||
while (*cwdStart) {
|
||||
if (cwdStart[0] == '=' && cwdStart[1] != '\0'
|
||||
&& cwdStart[2] == ':' && cwdStart[3] == '=') {
|
||||
break;
|
||||
}
|
||||
cwdStart += strlen(cwdStart) + 1;
|
||||
}
|
||||
cwdEnd = cwdStart;
|
||||
if (*cwdEnd) {
|
||||
cwdEnd += strlen(cwdEnd) + 1;
|
||||
while (*cwdEnd) {
|
||||
if (cwdEnd[0] != '=' || cwdEnd[1] == '\0'
|
||||
|| cwdEnd[2] != ':' || cwdEnd[3] != '=') {
|
||||
break;
|
||||
}
|
||||
cwdEnd += strlen(cwdEnd) + 1;
|
||||
}
|
||||
}
|
||||
envBlockSize = cwdEnd - cwdStart;
|
||||
|
||||
for (env = envp; *env; env++) {
|
||||
envBlockSize += strlen(*env) + 1;
|
||||
}
|
||||
envBlockSize++;
|
||||
|
||||
p = *envBlock = PR_MALLOC(envBlockSize);
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
q = cwdStart;
|
||||
while (q < cwdEnd) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
|
||||
for (env = envp; *env; env++) {
|
||||
q = *env;
|
||||
while (*q) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
*p++ = '\0';
|
||||
}
|
||||
*p = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For qsort. We sort (case-insensitive) the environment strings
|
||||
* before generating the environment block.
|
||||
*/
|
||||
static int compare(const void *arg1, const void *arg2)
|
||||
{
|
||||
return stricmp(* (char**)arg1, * (char**)arg2);
|
||||
}
|
||||
|
||||
PRProcess * _PR_CreateOS2Process(
|
||||
const char *path,
|
||||
char *const *argv,
|
||||
char *const *envp,
|
||||
const PRProcessAttr *attr)
|
||||
{
|
||||
PRProcess *proc = NULL;
|
||||
char *cmdLine = NULL;
|
||||
char **newEnvp = NULL;
|
||||
char *envBlock = NULL;
|
||||
|
||||
STARTDATA startData = {0};
|
||||
APIRET rc;
|
||||
ULONG ulAppType = 0;
|
||||
PID pid = 0;
|
||||
char *pEnvWPS = NULL;
|
||||
char *pszComSpec;
|
||||
char pszEXEName[CCHMAXPATH] = "";
|
||||
char pszFormatString[CCHMAXPATH];
|
||||
char pszObjectBuffer[CCHMAXPATH];
|
||||
char *pszFormatResult = NULL;
|
||||
|
||||
/*
|
||||
* Variables for DosExecPgm
|
||||
*/
|
||||
char szFailed[CCHMAXPATH];
|
||||
char *pszCmdLine = NULL;
|
||||
RESULTCODES procInfo;
|
||||
HFILE hStdIn = 0,
|
||||
hStdOut = 0,
|
||||
hStdErr = 0;
|
||||
HFILE hStdInSave = -1,
|
||||
hStdOutSave = -1,
|
||||
hStdErrSave = -1;
|
||||
|
||||
proc = PR_NEW(PRProcess);
|
||||
if (!proc) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (assembleCmdLine(argv, &cmdLine) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (envp == NULL) {
|
||||
newEnvp = NULL;
|
||||
} else {
|
||||
int i;
|
||||
int numEnv = 0;
|
||||
while (envp[numEnv]) {
|
||||
numEnv++;
|
||||
}
|
||||
newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *));
|
||||
for (i = 0; i <= numEnv; i++) {
|
||||
newEnvp[i] = envp[i];
|
||||
}
|
||||
qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
|
||||
}
|
||||
if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
rc = DosQueryAppType(path, &ulAppType);
|
||||
if (rc != NO_ERROR) {
|
||||
char *pszDot = strrchr(path, '.');
|
||||
if (pszDot) {
|
||||
/* If it is a CMD file, launch the users command processor */
|
||||
if (!stricmp(pszDot, ".cmd")) {
|
||||
rc = DosScanEnv("COMSPEC", &pszComSpec);
|
||||
if (!rc) {
|
||||
strcpy(pszFormatString, "/C %s %s");
|
||||
strcpy(pszEXEName, pszComSpec);
|
||||
ulAppType = FAPPTYP_WINDOWCOMPAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ulAppType == 0) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) {
|
||||
startData.SessionType = SSF_TYPE_PM;
|
||||
}
|
||||
else if (ulAppType & FAPPTYP_WINDOWCOMPAT) {
|
||||
startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
|
||||
}
|
||||
else {
|
||||
startData.SessionType = SSF_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL))
|
||||
{
|
||||
strcpy(pszEXEName, "WINOS2.COM");
|
||||
startData.SessionType = PROG_31_STDSEAMLESSVDM;
|
||||
strcpy(pszFormatString, "/3 %s %s");
|
||||
}
|
||||
|
||||
startData.InheritOpt = SSF_INHERTOPT_SHELL;
|
||||
|
||||
if (pszEXEName[0]) {
|
||||
pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine));
|
||||
sprintf(pszFormatResult, pszFormatString, path, cmdLine);
|
||||
startData.PgmInputs = pszFormatResult;
|
||||
} else {
|
||||
strcpy(pszEXEName, path);
|
||||
startData.PgmInputs = cmdLine;
|
||||
}
|
||||
startData.PgmName = pszEXEName;
|
||||
|
||||
startData.Length = sizeof(startData);
|
||||
startData.Related = SSF_RELATED_INDEPENDENT;
|
||||
startData.ObjectBuffer = pszObjectBuffer;
|
||||
startData.ObjectBuffLen = CCHMAXPATH;
|
||||
startData.Environment = envBlock;
|
||||
|
||||
if (attr) {
|
||||
/* On OS/2, there is really no way to pass file handles for stdin,
|
||||
* stdout, and stderr to a new process. Instead, we can make it
|
||||
* a child process and make the given file handles a copy of our
|
||||
* stdin, stdout, and stderr. The child process then inherits
|
||||
* ours, and we set ours back. Twisted and gross I know. If you
|
||||
* know a better way, please use it.
|
||||
*/
|
||||
if (attr->stdinFd) {
|
||||
hStdIn = 0;
|
||||
DosDupHandle(hStdIn, &hStdInSave);
|
||||
DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn);
|
||||
}
|
||||
|
||||
if (attr->stdoutFd) {
|
||||
hStdOut = 1;
|
||||
DosDupHandle(hStdOut, &hStdOutSave);
|
||||
DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut);
|
||||
}
|
||||
|
||||
if (attr->stderrFd) {
|
||||
hStdErr = 2;
|
||||
DosDupHandle(hStdErr, &hStdErrSave);
|
||||
DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr);
|
||||
}
|
||||
/*
|
||||
* Build up the Command Line for DosExecPgm
|
||||
*/
|
||||
pszCmdLine = PR_MALLOC(strlen(pszEXEName) +
|
||||
strlen(startData.PgmInputs) + 3);
|
||||
sprintf(pszCmdLine, "%s%c%s%c", pszEXEName, '\0',
|
||||
startData.PgmInputs, '\0');
|
||||
rc = DosExecPgm(szFailed,
|
||||
CCHMAXPATH,
|
||||
EXEC_ASYNCRESULT,
|
||||
pszCmdLine,
|
||||
envBlock,
|
||||
&procInfo,
|
||||
pszEXEName);
|
||||
PR_DELETE(pszCmdLine);
|
||||
|
||||
/* Restore our old values. Hope this works */
|
||||
if (hStdInSave != -1) {
|
||||
DosDupHandle(hStdInSave, &hStdIn);
|
||||
DosClose(hStdInSave);
|
||||
}
|
||||
|
||||
if (hStdOutSave != -1) {
|
||||
DosDupHandle(hStdOutSave, &hStdOut);
|
||||
DosClose(hStdOutSave);
|
||||
}
|
||||
|
||||
if (hStdErrSave != -1) {
|
||||
DosDupHandle(hStdErrSave, &hStdErr);
|
||||
DosClose(hStdErrSave);
|
||||
}
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
/* XXX what error code? */
|
||||
PR_SetError(PR_UNKNOWN_ERROR, rc);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
proc->md.pid = procInfo.codeTerminate;
|
||||
} else {
|
||||
/*
|
||||
* If no STDIN/STDOUT redirection is not needed, use DosStartSession
|
||||
* to create a new, independent session
|
||||
*/
|
||||
rc = DosStartSession(&startData, &ulAppType, &pid);
|
||||
|
||||
if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, rc);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
proc->md.pid = pid;
|
||||
}
|
||||
|
||||
if (pszFormatResult) {
|
||||
PR_DELETE(pszFormatResult);
|
||||
}
|
||||
|
||||
PR_DELETE(cmdLine);
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
return proc;
|
||||
|
||||
errorExit:
|
||||
if (cmdLine) {
|
||||
PR_DELETE(cmdLine);
|
||||
}
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
if (proc) {
|
||||
PR_DELETE(proc);
|
||||
}
|
||||
return NULL;
|
||||
} /* _PR_CreateOS2Process */
|
||||
|
||||
PRStatus _PR_DetachOS2Process(PRProcess *process)
|
||||
{
|
||||
/* On OS/2, a process is either created as a child or not.
|
||||
* You can't 'detach' it later on.
|
||||
*/
|
||||
PR_DELETE(process);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This will currently only work on a child process.
|
||||
*/
|
||||
PRStatus _PR_WaitOS2Process(PRProcess *process,
|
||||
PRInt32 *exitCode)
|
||||
{
|
||||
ULONG ulRetVal;
|
||||
RESULTCODES results;
|
||||
PID pidEnded = 0;
|
||||
|
||||
ulRetVal = DosWaitChild(DCWA_PROCESS, DCWW_WAIT,
|
||||
&results,
|
||||
&pidEnded, process->md.pid);
|
||||
|
||||
if (ulRetVal != NO_ERROR) {
|
||||
printf("\nDosWaitChild rc = %lu\n", ulRetVal);
|
||||
PR_SetError(PR_UNKNOWN_ERROR, ulRetVal);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
PR_DELETE(process);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRStatus _PR_KillOS2Process(PRProcess *process)
|
||||
{
|
||||
ULONG ulRetVal;
|
||||
if ((ulRetVal = DosKillProcess(DKP_PROCESS, process->md.pid)) == NO_ERROR) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
PR_SetError(PR_UNKNOWN_ERROR, ulRetVal);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen)
|
||||
{
|
||||
PRIntn rv;
|
||||
|
||||
rv = gethostname(name, (PRInt32) namelen);
|
||||
if (0 == rv) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
_PR_MD_MAP_GETHOSTNAME_ERROR(sock_errno());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_WAKEUP_CPUS( void )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* Memory-mapped files are not supported on OS/2 (or Win16).
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
|
||||
{
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRInt32 _MD_GetMemMapAlignment(void)
|
||||
{
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void * _MD_MemMap(
|
||||
PRFileMap *fmap,
|
||||
PROffset64 offset,
|
||||
PRUint32 len)
|
||||
{
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
|
||||
{
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus _MD_CloseFileMap(PRFileMap *fmap)
|
||||
{
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* This file implements _PR_MD_PR_POLL for OS/2.
|
||||
*/
|
||||
|
||||
#ifdef XP_OS2_EMX
|
||||
#include <sys/time.h> /* For timeval. */
|
||||
#endif
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#ifndef BSD_SELECT
|
||||
/* Utility functions called when using OS/2 select */
|
||||
|
||||
PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
|
||||
{
|
||||
int i;
|
||||
PRBool isSet = PR_FALSE;
|
||||
|
||||
for( i = start; i < start+count; i++ )
|
||||
{
|
||||
if( socks[i] == osfd )
|
||||
isSet = PR_TRUE;
|
||||
}
|
||||
|
||||
return isSet;
|
||||
}
|
||||
#endif
|
||||
|
||||
PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
|
||||
{
|
||||
#ifdef BSD_SELECT
|
||||
fd_set rd, wt, ex;
|
||||
#else
|
||||
int rd, wt, ex;
|
||||
int* socks;
|
||||
unsigned long msecs;
|
||||
int i, j;
|
||||
#endif
|
||||
PRFileDesc *bottom;
|
||||
PRPollDesc *pd, *epd;
|
||||
PRInt32 maxfd = -1, ready, err;
|
||||
PRIntervalTime remaining, elapsed, start;
|
||||
|
||||
#ifdef BSD_SELECT
|
||||
struct timeval tv, *tvp = NULL;
|
||||
|
||||
FD_ZERO(&rd);
|
||||
FD_ZERO(&wt);
|
||||
FD_ZERO(&ex);
|
||||
#else
|
||||
rd = 0;
|
||||
wt = 0;
|
||||
ex = 0;
|
||||
socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
|
||||
|
||||
if (!socks)
|
||||
{
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
PRInt16 in_flags_read = 0, in_flags_write = 0;
|
||||
PRInt16 out_flags_read = 0, out_flags_write = 0;
|
||||
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
if (pd->in_flags & PR_POLL_READ)
|
||||
{
|
||||
in_flags_read = (pd->fd->methods->poll)(
|
||||
pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
|
||||
}
|
||||
if (pd->in_flags & PR_POLL_WRITE)
|
||||
{
|
||||
in_flags_write = (pd->fd->methods->poll)(
|
||||
pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
|
||||
}
|
||||
if ((0 != (in_flags_read & out_flags_read)) ||
|
||||
(0 != (in_flags_write & out_flags_write)))
|
||||
{
|
||||
/* this one's ready right now */
|
||||
if (0 == ready)
|
||||
{
|
||||
/*
|
||||
* We will have to return without calling the
|
||||
* system poll/select function. So zero the
|
||||
* out_flags fields of all the poll descriptors
|
||||
* before this one.
|
||||
*/
|
||||
PRPollDesc *prev;
|
||||
for (prev = pds; prev < pd; prev++)
|
||||
{
|
||||
prev->out_flags = 0;
|
||||
}
|
||||
}
|
||||
ready += 1;
|
||||
pd->out_flags = out_flags_read | out_flags_write;
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->out_flags = 0; /* pre-condition */
|
||||
|
||||
/* make sure this is an NSPR supported stack */
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
PR_ASSERT(NULL != bottom); /* what to do about that? */
|
||||
if ((NULL != bottom) &&
|
||||
(_PR_FILEDESC_OPEN == bottom->secret->state))
|
||||
{
|
||||
if (0 == ready)
|
||||
{
|
||||
PRInt32 osfd = bottom->secret->md.osfd;
|
||||
if (osfd > maxfd)
|
||||
maxfd = osfd;
|
||||
if (in_flags_read & PR_POLL_READ)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_READ_SYS_READ;
|
||||
#ifdef BSD_SELECT
|
||||
FD_SET(osfd, &rd);
|
||||
#else
|
||||
socks[rd] = osfd;
|
||||
rd++;
|
||||
#endif
|
||||
}
|
||||
if (in_flags_read & PR_POLL_WRITE)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
|
||||
#ifdef BSD_SELECT
|
||||
FD_SET(osfd, &wt);
|
||||
#else
|
||||
socks[npds+wt] = osfd;
|
||||
wt++;
|
||||
#endif
|
||||
}
|
||||
if (in_flags_write & PR_POLL_READ)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
|
||||
#ifdef BSD_SELECT
|
||||
FD_SET(osfd, &rd);
|
||||
#else
|
||||
socks[rd] = osfd;
|
||||
rd++;
|
||||
#endif
|
||||
}
|
||||
if (in_flags_write & PR_POLL_WRITE)
|
||||
{
|
||||
pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
|
||||
#ifdef BSD_SELECT
|
||||
FD_SET(osfd, &wt);
|
||||
#else
|
||||
socks[npds+wt] = osfd;
|
||||
wt++;
|
||||
#endif
|
||||
}
|
||||
if (pd->in_flags & PR_POLL_EXCEPT)
|
||||
{
|
||||
#ifdef BSD_SELECT
|
||||
FD_SET(osfd, &ex);
|
||||
#else
|
||||
socks[npds*2+ex] = osfd;
|
||||
ex++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == ready)
|
||||
{
|
||||
PRPollDesc *prev;
|
||||
for (prev = pds; prev < pd; prev++)
|
||||
{
|
||||
prev->out_flags = 0;
|
||||
}
|
||||
}
|
||||
ready += 1; /* this will cause an abrupt return */
|
||||
pd->out_flags = PR_POLL_NVAL; /* bogii */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->out_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != ready)
|
||||
{
|
||||
#ifndef BSD_SELECT
|
||||
PR_Free(socks);
|
||||
#endif
|
||||
return ready; /* no need to block */
|
||||
}
|
||||
|
||||
remaining = timeout;
|
||||
start = PR_IntervalNow();
|
||||
|
||||
retry:
|
||||
#ifdef BSD_SELECT
|
||||
if (timeout != PR_INTERVAL_NO_TIMEOUT)
|
||||
{
|
||||
PRInt32 ticksPerSecond = PR_TicksPerSecond();
|
||||
tv.tv_sec = remaining / ticksPerSecond;
|
||||
tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
|
||||
#else
|
||||
switch (timeout)
|
||||
{
|
||||
case PR_INTERVAL_NO_WAIT:
|
||||
msecs = 0;
|
||||
break;
|
||||
case PR_INTERVAL_NO_TIMEOUT:
|
||||
msecs = -1;
|
||||
break;
|
||||
default:
|
||||
msecs = PR_IntervalToMilliseconds(remaining);
|
||||
}
|
||||
|
||||
/* compact array */
|
||||
for( i = rd, j = npds; j < npds+wt; i++,j++ )
|
||||
socks[i] = socks[j];
|
||||
for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
|
||||
socks[i] = socks[j];
|
||||
|
||||
ready = os2_select(socks, rd, wt, ex, msecs);
|
||||
#endif
|
||||
|
||||
if (ready == -1 && errno == EINTR)
|
||||
{
|
||||
if (timeout == PR_INTERVAL_NO_TIMEOUT)
|
||||
goto retry;
|
||||
else
|
||||
{
|
||||
elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
|
||||
if (elapsed > timeout)
|
||||
ready = 0; /* timed out */
|
||||
else
|
||||
{
|
||||
remaining = timeout - elapsed;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Now to unravel the select sets back into the client's poll
|
||||
** descriptor list. Is this possibly an area for pissing away
|
||||
** a few cycles or what?
|
||||
*/
|
||||
if (ready > 0)
|
||||
{
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
PRInt16 out_flags = 0;
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
PRInt32 osfd;
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
PR_ASSERT(NULL != bottom);
|
||||
|
||||
osfd = bottom->secret->md.osfd;
|
||||
|
||||
#ifdef BSD_SELECT
|
||||
if (FD_ISSET(osfd, &rd))
|
||||
#else
|
||||
if( IsSocketSet(osfd, socks, 0, rd) )
|
||||
#endif
|
||||
{
|
||||
if (pd->out_flags & _PR_POLL_READ_SYS_READ)
|
||||
out_flags |= PR_POLL_READ;
|
||||
if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
|
||||
out_flags |= PR_POLL_WRITE;
|
||||
}
|
||||
|
||||
#ifdef BSD_SELECT
|
||||
if (FD_ISSET(osfd, &wt))
|
||||
#else
|
||||
if( IsSocketSet(osfd, socks, rd, wt) )
|
||||
#endif
|
||||
{
|
||||
if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
|
||||
out_flags |= PR_POLL_READ;
|
||||
if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
|
||||
out_flags |= PR_POLL_WRITE;
|
||||
}
|
||||
|
||||
#ifdef BSD_SELECT
|
||||
if (FD_ISSET(osfd, &ex))
|
||||
#else
|
||||
if( IsSocketSet(osfd, socks, rd+wt, ex) )
|
||||
#endif
|
||||
{
|
||||
out_flags |= PR_POLL_EXCEPT;
|
||||
}
|
||||
}
|
||||
pd->out_flags = out_flags;
|
||||
if (out_flags) ready++;
|
||||
}
|
||||
PR_ASSERT(ready > 0);
|
||||
}
|
||||
else if (ready < 0)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
if (err == EBADF)
|
||||
{
|
||||
/* Find the bad fds */
|
||||
int optval;
|
||||
int optlen = sizeof(optval);
|
||||
ready = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++)
|
||||
{
|
||||
pd->out_flags = 0;
|
||||
if ((NULL != pd->fd) && (0 != pd->in_flags))
|
||||
{
|
||||
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
|
||||
if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
|
||||
SO_TYPE, (char *) &optval, &optlen) == -1)
|
||||
{
|
||||
PR_ASSERT(sock_errno() == ENOTSOCK);
|
||||
if (sock_errno() == ENOTSOCK)
|
||||
{
|
||||
pd->out_flags = PR_POLL_NVAL;
|
||||
ready++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PR_ASSERT(ready > 0);
|
||||
}
|
||||
else
|
||||
_PR_MD_MAP_SELECT_ERROR(err);
|
||||
}
|
||||
|
||||
#ifndef BSD_SELECT
|
||||
PR_Free(socks);
|
||||
#endif
|
||||
return ready;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "primpl.h"
|
||||
|
||||
static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
|
||||
{
|
||||
APIRET rc = NO_ERROR;
|
||||
QWORD qword = {0,0};
|
||||
|
||||
rc = DosTmrQueryTime(&qword);
|
||||
if (rc != NO_ERROR)
|
||||
return FALSE;
|
||||
|
||||
*phigh = qword.ulHi;
|
||||
*plow = qword.ulLo;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern PRSize _PR_MD_GetRandomNoise(void *buf, PRSize size )
|
||||
{
|
||||
unsigned long high = 0;
|
||||
unsigned long low = 0;
|
||||
clock_t val = 0;
|
||||
int n = 0;
|
||||
int nBytes = 0;
|
||||
time_t sTime;
|
||||
|
||||
if (size <= 0)
|
||||
return 0;
|
||||
|
||||
clockTickTime(&high, &low);
|
||||
|
||||
/* get the maximally changing bits first */
|
||||
nBytes = sizeof(low) > size ? size : sizeof(low);
|
||||
memcpy(buf, &low, nBytes);
|
||||
n += nBytes;
|
||||
size -= nBytes;
|
||||
|
||||
if (size <= 0)
|
||||
return n;
|
||||
|
||||
nBytes = sizeof(high) > size ? size : sizeof(high);
|
||||
memcpy(((char *)buf) + n, &high, nBytes);
|
||||
n += nBytes;
|
||||
size -= nBytes;
|
||||
|
||||
if (size <= 0)
|
||||
return n;
|
||||
|
||||
/* get the number of milliseconds that have elapsed since application started */
|
||||
val = clock();
|
||||
|
||||
nBytes = sizeof(val) > size ? size : sizeof(val);
|
||||
memcpy(((char *)buf) + n, &val, nBytes);
|
||||
n += nBytes;
|
||||
size -= nBytes;
|
||||
|
||||
if (size <= 0)
|
||||
return n;
|
||||
|
||||
/* get the time in seconds since midnight Jan 1, 1970 */
|
||||
time(&sTime);
|
||||
nBytes = sizeof(sTime) > size ? size : sizeof(sTime);
|
||||
memcpy(((char *)buf) + n, &sTime, nBytes);
|
||||
n += nBytes;
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* OS/2-specific semaphore handling code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
|
||||
void
|
||||
_PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value)
|
||||
{
|
||||
int rv;
|
||||
|
||||
/* Our Sems don't support a value > 1 */
|
||||
PR_ASSERT(value <= 1);
|
||||
|
||||
rv = DosCreateEventSem(NULL, &md->sem, 0, 0);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_DESTROY_SEM(_MDSemaphore *md)
|
||||
{
|
||||
int rv;
|
||||
rv = DosCloseEventSem(md->sem);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_TIMED_WAIT_SEM(_MDSemaphore *md, PRIntervalTime ticks)
|
||||
{
|
||||
int rv;
|
||||
rv = DosWaitEventSem(md->sem, PR_IntervalToMilliseconds(ticks));
|
||||
|
||||
if (rv == NO_ERROR)
|
||||
return PR_SUCCESS;
|
||||
else
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_WAIT_SEM(_MDSemaphore *md)
|
||||
{
|
||||
return _PR_MD_TIMED_WAIT_SEM(md, PR_INTERVAL_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_POST_SEM(_MDSemaphore *md)
|
||||
{
|
||||
int rv;
|
||||
rv = DosPostEventSem(md->sem);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,684 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* OS/2 Sockets module
|
||||
*
|
||||
*/
|
||||
|
||||
/*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */
|
||||
/*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */
|
||||
/*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
|
||||
/*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */
|
||||
/*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#ifdef XP_OS2_EMX
|
||||
#include <sys/time.h> /* For timeval. */
|
||||
#endif
|
||||
|
||||
#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
|
||||
#define READ_FD 1
|
||||
#define WRITE_FD 2
|
||||
|
||||
#ifdef XP_OS2_VACPP
|
||||
#define _OS2_WRITEV writev
|
||||
#define _OS2_IOCTL ioctl
|
||||
#else
|
||||
#define _OS2_WRITEV so_writev
|
||||
#define _OS2_IOCTL so_ioctl
|
||||
#endif
|
||||
|
||||
/* --- SOCKET IO --------------------------------------------------------- */
|
||||
|
||||
|
||||
PRInt32
|
||||
_PR_MD_SOCKET(int domain, int type, int flags)
|
||||
{
|
||||
PRInt32 osfd, err;
|
||||
|
||||
osfd = socket(domain, type, flags);
|
||||
|
||||
if (osfd == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_SOCKET_ERROR(err);
|
||||
}
|
||||
|
||||
return(osfd);
|
||||
}
|
||||
|
||||
/*
|
||||
** _MD_CloseSocket() -- Close a socket
|
||||
**
|
||||
*/
|
||||
PRInt32
|
||||
_MD_CloseSocket(PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = soclose(osfd);
|
||||
if (rv == -1) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_CLOSE_ERROR(err);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_SocketAvailable(PRFileDesc *fd)
|
||||
{
|
||||
PRInt32 result;
|
||||
|
||||
if (_OS2_IOCTL(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
|
||||
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
|
||||
{
|
||||
PRInt32 rv = -1;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRIntervalTime epoch, now, elapsed, remaining;
|
||||
PRBool wait_for_remaining;
|
||||
PRInt32 syserror;
|
||||
#ifdef BSD_SELECT
|
||||
struct timeval tv;
|
||||
fd_set rd_wr;
|
||||
#else
|
||||
int socks[1];
|
||||
long lTimeout;
|
||||
#endif
|
||||
|
||||
switch (timeout) {
|
||||
case PR_INTERVAL_NO_WAIT:
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
break;
|
||||
case PR_INTERVAL_NO_TIMEOUT:
|
||||
/*
|
||||
* This is a special case of the 'default' case below.
|
||||
* Please see the comments there.
|
||||
*/
|
||||
#ifdef BSD_SELECT
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rd_wr);
|
||||
do {
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
|
||||
else
|
||||
rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
|
||||
#else
|
||||
lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
|
||||
do {
|
||||
socks[0] = osfd;
|
||||
if (fd_type == READ_FD)
|
||||
rv = os2_select(socks, 1, 0, 0, lTimeout);
|
||||
else
|
||||
rv = os2_select(socks, 0, 1, 0, lTimeout);
|
||||
#endif
|
||||
if (rv == -1 && (syserror = sock_errno()) != EINTR) {
|
||||
_PR_MD_MAP_SELECT_ERROR(syserror);
|
||||
break;
|
||||
}
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
default:
|
||||
now = epoch = PR_IntervalNow();
|
||||
remaining = timeout;
|
||||
#ifdef BSD_SELECT
|
||||
FD_ZERO(&rd_wr);
|
||||
#endif
|
||||
do {
|
||||
/*
|
||||
* We block in select for at most
|
||||
* _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
|
||||
* so that there is an upper limit on the delay
|
||||
* before the interrupt bit is checked.
|
||||
*/
|
||||
#ifdef BSD_SELECT
|
||||
wait_for_remaining = PR_TRUE;
|
||||
tv.tv_sec = PR_IntervalToSeconds(remaining);
|
||||
if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
|
||||
wait_for_remaining = PR_FALSE;
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
} else {
|
||||
tv.tv_usec = PR_IntervalToMicroseconds(
|
||||
remaining -
|
||||
PR_SecondsToInterval(tv.tv_sec));
|
||||
}
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
|
||||
else
|
||||
rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
|
||||
#else
|
||||
wait_for_remaining = PR_TRUE;
|
||||
lTimeout = PR_IntervalToMilliseconds(remaining);
|
||||
if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
|
||||
wait_for_remaining = PR_FALSE;
|
||||
lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
|
||||
}
|
||||
socks[0] = osfd;
|
||||
if (fd_type == READ_FD)
|
||||
rv = os2_select(socks, 1, 0, 0, lTimeout);
|
||||
else
|
||||
rv = os2_select(socks, 0, 1, 0, lTimeout);
|
||||
#endif
|
||||
/*
|
||||
* we don't consider EINTR a real error
|
||||
*/
|
||||
if (rv == -1 && (syserror = sock_errno()) != EINTR) {
|
||||
_PR_MD_MAP_SELECT_ERROR(syserror);
|
||||
break;
|
||||
}
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We loop again if select timed out or got interrupted
|
||||
* by a signal, and the timeout deadline has not passed yet.
|
||||
*/
|
||||
if (rv == 0 || (rv == -1 && syserror == EINTR)) {
|
||||
/*
|
||||
* If select timed out, we know how much time
|
||||
* we spent in blocking, so we can avoid a
|
||||
* PR_IntervalNow() call.
|
||||
*/
|
||||
if (rv == 0) {
|
||||
if (wait_for_remaining) {
|
||||
now += remaining;
|
||||
} else {
|
||||
#ifdef BSD_SELECT
|
||||
now += PR_SecondsToInterval(tv.tv_sec)
|
||||
+ PR_MicrosecondsToInterval(tv.tv_usec);
|
||||
#else
|
||||
now += PR_MillisecondsToInterval(lTimeout);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
now = PR_IntervalNow();
|
||||
}
|
||||
elapsed = (PRIntervalTime) (now - epoch);
|
||||
if (elapsed >= timeout) {
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
} else {
|
||||
remaining = timeout - elapsed;
|
||||
}
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_Accept(PRFileDesc *fd, PRNetAddr *addr,
|
||||
PRUint32 *addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK) || (err == ECONNABORTED))
|
||||
{
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_ACCEPT_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect
|
||||
* modifies the sockaddr structure.
|
||||
* See Bugzilla bug 100776. */
|
||||
|
||||
/*
|
||||
* We initiate the connection setup by making a nonblocking connect()
|
||||
* call. If the connect() call fails, there are two cases we handle
|
||||
* specially:
|
||||
* 1. The connect() call was interrupted by a signal. In this case
|
||||
* we simply retry connect().
|
||||
* 2. The NSPR socket is nonblocking and connect() fails with
|
||||
* EINPROGRESS. We first wait until the socket becomes writable.
|
||||
* Then we try to find out whether the connection setup succeeded
|
||||
* or failed.
|
||||
*/
|
||||
|
||||
retry:
|
||||
if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
|
||||
if (err == EINTR) {
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!fd->secret->nonblocking && (err == EINPROGRESS))
|
||||
{
|
||||
/*
|
||||
* socket_io_wait() may return -1 or 1.
|
||||
*/
|
||||
|
||||
rv = socket_io_wait(osfd, WRITE_FD, timeout);
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PR_ASSERT(rv == 1);
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
err = _MD_os2_get_nonblocking_connect_error(osfd);
|
||||
if (err != 0) {
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
}
|
||||
|
||||
return rv;
|
||||
} /* _MD_connect */
|
||||
|
||||
PRInt32
|
||||
_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_BIND_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
rv = listen(fd->secret->md.osfd, backlog);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_DEFAULT_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = recv(osfd,buf,amount,flags)) == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECV_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = send(osfd,buf,amount,flags)) == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* optimization; if bytes sent is less than "amount" call
|
||||
* select before returning. This is because it is likely that
|
||||
* the next send() call will return EWOULDBLOCK.
|
||||
*/
|
||||
if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
|
||||
&& (timeout != PR_INTERVAL_NO_WAIT))
|
||||
{
|
||||
if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
|
||||
rv = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SEND_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
|
||||
const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
while ((rv = sendto(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr, addrlen)) == -1)
|
||||
{
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK))
|
||||
{
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SENDTO_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
|
||||
PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while( (*addrlen = PR_NETADDR_SIZE(addr)),
|
||||
((rv = recvfrom(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr, (int *)addrlen)) == -1))
|
||||
{
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECVFROM_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRInt32 index, amount = 0;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
/*
|
||||
* Calculate the total number of bytes to be sent; needed for
|
||||
* optimization later.
|
||||
* We could avoid this if this number was passed in; but it is
|
||||
* probably not a big deal because iov_size is usually small (less than
|
||||
* 3)
|
||||
*/
|
||||
if (!fd->secret->nonblocking) {
|
||||
for (index=0; index<iov_size; index++) {
|
||||
amount += iov[index].iov_len;
|
||||
}
|
||||
}
|
||||
|
||||
while ((rv = _OS2_WRITEV(osfd, (const struct iovec*)iov, iov_size)) == -1) {
|
||||
err = sock_errno();
|
||||
if ((err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* optimization; if bytes sent is less than "amount" call
|
||||
* select before returning. This is because it is likely that
|
||||
* the next writev() call will return EWOULDBLOCK.
|
||||
*/
|
||||
if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
|
||||
&& (timeout != PR_INTERVAL_NO_WAIT)) {
|
||||
if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
|
||||
rv = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_WRITEV_ERROR(err);
|
||||
}
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
rv = shutdown(fd->secret->md.osfd, how);
|
||||
if (rv < 0)
|
||||
_PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifndef XP_OS2_VACPP
|
||||
PRInt32
|
||||
_PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = socketpair(af, type, flags, osfd);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SOCKETPAIR_ERROR(err);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
PRStatus
|
||||
_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockname(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (int *)addrlen);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_GETSOCKNAME_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getpeername(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (int *)addrlen);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_GETPEERNAME_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
|
||||
char* optval, PRInt32* optlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_GETSOCKOPT_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
|
||||
const char* optval, PRInt32 optlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
|
||||
if (rv < 0) {
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_SETSOCKOPT_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
_MD_MakeNonblock(PRFileDesc *fd)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 err;
|
||||
PRUint32 one = 1;
|
||||
|
||||
if (osfd <= 2) {
|
||||
/* Don't mess around with stdin, stdout or stderr */
|
||||
return;
|
||||
}
|
||||
|
||||
err = _OS2_IOCTL( osfd, FIONBIO, (char *) &one, sizeof(one));
|
||||
if ( err != 0 )
|
||||
{
|
||||
err = sock_errno();
|
||||
_PR_MD_MAP_SOCKET_ERROR(err);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
#include <process.h> /* for _beginthread() */
|
||||
|
||||
#ifdef XP_OS2_VACPP
|
||||
#include <time.h> /* for _tzset() */
|
||||
#endif
|
||||
|
||||
#ifdef XP_OS2_EMX
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
|
||||
/* --- globals ------------------------------------------------ */
|
||||
_NSPR_TLS* pThreadLocalStorage = 0;
|
||||
_PRInterruptTable _pr_interruptTable[] = { { 0 } };
|
||||
APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
|
||||
|
||||
void
|
||||
_PR_MD_ENSURE_TLS(void)
|
||||
{
|
||||
if(!pThreadLocalStorage)
|
||||
{
|
||||
/* Allocate thread local storage (TLS). Note, that only 32 bytes can
|
||||
* be allocated at a time.
|
||||
*/
|
||||
int rc = DosAllocThreadLocalMemory(sizeof(_NSPR_TLS) / 4, (PULONG*)&pThreadLocalStorage);
|
||||
PR_ASSERT(rc == NO_ERROR);
|
||||
memset(pThreadLocalStorage, 0, sizeof(_NSPR_TLS));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_EARLY_INIT()
|
||||
{
|
||||
HMODULE hmod;
|
||||
|
||||
if (DosLoadModule(NULL, 0, "DOSCALL1", &hmod) == 0)
|
||||
DosQueryProcAddr(hmod, 877, "DOSQUERYTHREADCONTEXT",
|
||||
(PFN *)&QueryThreadContext);
|
||||
|
||||
#ifdef XP_OS2_VACPP
|
||||
_tzset();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
_pr_SetThreadMDHandle(PRThread *thread)
|
||||
{
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
PRUword rc;
|
||||
|
||||
rc = DosGetInfoBlocks(&ptib, &ppib);
|
||||
|
||||
thread->md.handle = ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
|
||||
/* On OS/2, some system function calls seem to change the FPU control word,
|
||||
* such that we crash with a floating underflow exception. The FIX_FPU() call
|
||||
* in jsnum.c does not always work, as sometimes FIX_FPU() is called BEFORE the
|
||||
* OS/2 system call that horks the FPU control word. So, we set an exception
|
||||
* handler that covers any floating point exceptions and resets the FPU CW to
|
||||
* the required value.
|
||||
*/
|
||||
static ULONG
|
||||
_System OS2_FloatExcpHandler(PEXCEPTIONREPORTRECORD p1,
|
||||
PEXCEPTIONREGISTRATIONRECORD p2,
|
||||
PCONTEXTRECORD p3,
|
||||
PVOID pv)
|
||||
{
|
||||
#ifdef DEBUG_pedemonte
|
||||
printf("Entering exception handler; ExceptionNum = %x\n", p1->ExceptionNum);
|
||||
switch(p1->ExceptionNum) {
|
||||
case XCPT_FLOAT_DENORMAL_OPERAND:
|
||||
printf("got XCPT_FLOAT_DENORMAL_OPERAND\n");
|
||||
break;
|
||||
case XCPT_FLOAT_DIVIDE_BY_ZERO:
|
||||
printf("got XCPT_FLOAT_DIVIDE_BY_ZERO\n");
|
||||
break;
|
||||
case XCPT_FLOAT_INEXACT_RESULT:
|
||||
printf("got XCPT_FLOAT_INEXACT_RESULT\n");
|
||||
break;
|
||||
case XCPT_FLOAT_INVALID_OPERATION:
|
||||
printf("got XCPT_FLOAT_INVALID_OPERATION\n");
|
||||
break;
|
||||
case XCPT_FLOAT_OVERFLOW:
|
||||
printf("got XCPT_FLOAT_OVERFLOW\n");
|
||||
break;
|
||||
case XCPT_FLOAT_STACK_CHECK:
|
||||
printf("got XCPT_FLOAT_STACK_CHECK\n");
|
||||
break;
|
||||
case XCPT_FLOAT_UNDERFLOW:
|
||||
printf("got XCPT_FLOAT_UNDERFLOW\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(p1->ExceptionNum) {
|
||||
case XCPT_FLOAT_DENORMAL_OPERAND:
|
||||
case XCPT_FLOAT_DIVIDE_BY_ZERO:
|
||||
case XCPT_FLOAT_INEXACT_RESULT:
|
||||
case XCPT_FLOAT_INVALID_OPERATION:
|
||||
case XCPT_FLOAT_OVERFLOW:
|
||||
case XCPT_FLOAT_STACK_CHECK:
|
||||
case XCPT_FLOAT_UNDERFLOW:
|
||||
{
|
||||
unsigned cw = p3->ctx_env[0];
|
||||
if ((cw & MCW_EM) != MCW_EM) {
|
||||
/* Mask out all floating point exceptions */
|
||||
p3->ctx_env[0] |= MCW_EM;
|
||||
/* Following two lines set precision to 53 bit mantissa. See jsnum.c */
|
||||
p3->ctx_env[0] &= ~MCW_PC;
|
||||
p3->ctx_env[0] |= PC_53;
|
||||
return XCPT_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
return XCPT_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
|
||||
{
|
||||
/* setup the exception handler for the thread */
|
||||
APIRET rv;
|
||||
excpreg->ExceptionHandler = OS2_FloatExcpHandler;
|
||||
excpreg->prev_structure = NULL;
|
||||
rv = DosSetExceptionHandler(excpreg);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
|
||||
{
|
||||
/* unset exception handler */
|
||||
APIRET rv = DosUnsetExceptionHandler(excpreg);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_INIT_THREAD(PRThread *thread)
|
||||
{
|
||||
APIRET rv;
|
||||
|
||||
if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
|
||||
_pr_SetThreadMDHandle(thread);
|
||||
}
|
||||
|
||||
/* Create the blocking IO semaphore */
|
||||
rv = DosCreateEventSem(NULL, &(thread->md.blocked_sema), 0, 0);
|
||||
return (rv == NO_ERROR) ? PR_SUCCESS : PR_FAILURE;
|
||||
}
|
||||
|
||||
typedef struct param_store
|
||||
{
|
||||
void (*start)(void *);
|
||||
PRThread* thread;
|
||||
} PARAMSTORE;
|
||||
|
||||
/* This is a small intermediate function that sets/unsets the exception
|
||||
handler before calling the initial thread function */
|
||||
static void
|
||||
ExcpStartFunc(void* arg)
|
||||
{
|
||||
EXCEPTIONREGISTRATIONRECORD excpreg;
|
||||
PARAMSTORE params, *pParams = arg;
|
||||
|
||||
PR_OS2_SetFloatExcpHandler(&excpreg);
|
||||
|
||||
params = *pParams;
|
||||
PR_Free(pParams);
|
||||
params.start(params.thread);
|
||||
|
||||
PR_OS2_UnsetFloatExcpHandler(&excpreg);
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_PR_MD_CREATE_THREAD(PRThread *thread,
|
||||
void (*start)(void *),
|
||||
PRThreadPriority priority,
|
||||
PRThreadScope scope,
|
||||
PRThreadState state,
|
||||
PRUint32 stackSize)
|
||||
{
|
||||
PARAMSTORE* params = PR_Malloc(sizeof(PARAMSTORE));
|
||||
params->start = start;
|
||||
params->thread = thread;
|
||||
#ifdef XP_OS2_VACPP /* No exception handler for VACPP */
|
||||
thread->md.handle = thread->id = (TID) _beginthread(
|
||||
(void(* _Optlink)(void*))start,
|
||||
NULL,
|
||||
thread->stack->stackSize,
|
||||
thread);
|
||||
#else
|
||||
thread->md.handle = thread->id = (TID) _beginthread(ExcpStartFunc,
|
||||
NULL,
|
||||
thread->stack->stackSize,
|
||||
params);
|
||||
#endif
|
||||
if(thread->md.handle == -1) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* On OS/2, a thread is created with a thread priority of
|
||||
* THREAD_PRIORITY_NORMAL
|
||||
*/
|
||||
|
||||
if (priority != PR_PRIORITY_NORMAL) {
|
||||
_PR_MD_SET_PRIORITY(&(thread->md), priority);
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_YIELD(void)
|
||||
{
|
||||
/* Isn't there some problem with DosSleep(0) on OS/2? */
|
||||
DosSleep(0);
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
|
||||
{
|
||||
int nativePri;
|
||||
BOOL rv;
|
||||
|
||||
if (newPri < PR_PRIORITY_FIRST) {
|
||||
newPri = PR_PRIORITY_FIRST;
|
||||
} else if (newPri > PR_PRIORITY_LAST) {
|
||||
newPri = PR_PRIORITY_LAST;
|
||||
}
|
||||
switch (newPri) {
|
||||
case PR_PRIORITY_LOW:
|
||||
nativePri = PRTYC_IDLETIME;
|
||||
break;
|
||||
case PR_PRIORITY_NORMAL:
|
||||
nativePri = PRTYC_REGULAR;
|
||||
break;
|
||||
case PR_PRIORITY_HIGH:
|
||||
nativePri = PRTYC_FOREGROUNDSERVER;
|
||||
break;
|
||||
case PR_PRIORITY_URGENT:
|
||||
nativePri = PRTYC_TIMECRITICAL;
|
||||
}
|
||||
rv = DosSetPriority(PRTYS_THREAD, nativePri, 0, thread->handle);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
if (rv != NO_ERROR) {
|
||||
PR_LOG(_pr_thread_lm, PR_LOG_MIN,
|
||||
("PR_SetThreadPriority: can't set thread priority\n"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_CLEAN_THREAD(PRThread *thread)
|
||||
{
|
||||
APIRET rv;
|
||||
|
||||
if (thread->md.blocked_sema) {
|
||||
rv = DosCloseEventSem(thread->md.blocked_sema);
|
||||
PR_ASSERT(rv == NO_ERROR);
|
||||
thread->md.blocked_sema = 0;
|
||||
}
|
||||
|
||||
if (thread->md.handle) {
|
||||
thread->md.handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_EXIT_THREAD(PRThread *thread)
|
||||
{
|
||||
_PR_MD_CLEAN_THREAD(thread);
|
||||
_PR_MD_SET_CURRENT_THREAD(NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_PR_MD_EXIT(PRIntn status)
|
||||
{
|
||||
_exit(status);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREAD_AFFINITY
|
||||
PR_EXTERN(PRInt32)
|
||||
_PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
|
||||
{
|
||||
/* Can we do this on OS/2? Only on SMP versions? */
|
||||
PR_ASSERT(!"Not implemented");
|
||||
return 0;
|
||||
|
||||
/* This is what windows does:
|
||||
int rv;
|
||||
|
||||
rv = SetThreadAffinityMask(thread->md.handle, mask);
|
||||
|
||||
return rv?0:-1;
|
||||
*/
|
||||
}
|
||||
|
||||
PR_EXTERN(PRInt32)
|
||||
_PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
|
||||
{
|
||||
/* Can we do this on OS/2? Only on SMP versions? */
|
||||
PR_ASSERT(!"Not implemented");
|
||||
return 0;
|
||||
|
||||
/* This is what windows does:
|
||||
PRInt32 rv, system_mask;
|
||||
|
||||
rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
|
||||
|
||||
return rv?0:-1;
|
||||
*/
|
||||
}
|
||||
#endif /* HAVE_THREAD_AFFINITY */
|
||||
|
||||
void
|
||||
_PR_MD_SUSPEND_CPU(_PRCPU *cpu)
|
||||
{
|
||||
_PR_MD_SUSPEND_THREAD(cpu->thread);
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_RESUME_CPU(_PRCPU *cpu)
|
||||
{
|
||||
_PR_MD_RESUME_THREAD(cpu->thread);
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_SUSPEND_THREAD(PRThread *thread)
|
||||
{
|
||||
if (_PR_IS_NATIVE_THREAD(thread)) {
|
||||
APIRET rc;
|
||||
|
||||
/* XXXMB - DosSuspendThread() is not a blocking call; how do we
|
||||
* know when the thread is *REALLY* suspended?
|
||||
*/
|
||||
rc = DosSuspendThread(thread->md.handle);
|
||||
PR_ASSERT(rc == NO_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_RESUME_THREAD(PRThread *thread)
|
||||
{
|
||||
if (_PR_IS_NATIVE_THREAD(thread)) {
|
||||
DosResumeThread(thread->md.handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PRThread*
|
||||
_MD_CURRENT_THREAD(void)
|
||||
{
|
||||
PRThread *thread;
|
||||
|
||||
thread = _MD_GET_ATTACHED_THREAD();
|
||||
|
||||
if (NULL == thread) {
|
||||
thread = _PRI_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
|
||||
}
|
||||
|
||||
PR_ASSERT(thread != NULL);
|
||||
return thread;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public
|
||||
/ License Version 1.1 (the "License"); you may not use this file
|
||||
/ except in compliance with the License. You may obtain a copy of
|
||||
/ the License at http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS
|
||||
/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
/ implied. See the License for the specific language governing
|
||||
/ rights and limitations under the License.
|
||||
/
|
||||
/ The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
/
|
||||
/ The Initial Developer of the Original Code is InnoTek
|
||||
/ Systemberatung GmbH.
|
||||
/ Portions created by the Initial Developer are Copyright (C) 2003
|
||||
/ the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/ InnoTek Systemberatung GmbH / Knut St. Osmundsen
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl PR_NewMonitor
|
||||
PR_NewMonitor:
|
||||
jmp _PR_NewMonitor
|
||||
|
||||
.align 4
|
||||
.globl PR_EnterMonitor
|
||||
PR_EnterMonitor:
|
||||
mov %eax, 4(%esp)
|
||||
jmp _PR_EnterMonitor
|
||||
|
||||
.align 4
|
||||
.globl PR_ExitMonitor
|
||||
PR_ExitMonitor:
|
||||
mov %eax, 4(%esp)
|
||||
jmp _PR_ExitMonitor
|
||||
|
||||
|
||||
|
||||
.align 4
|
||||
.globl PR_AttachThread
|
||||
PR_AttachThread:
|
||||
mov %eax, 4(%esp)
|
||||
mov %edx, 8(%esp)
|
||||
mov %ecx, 12(%esp)
|
||||
jmp _PR_AttachThread
|
||||
|
||||
.align 4
|
||||
.globl PR_DetachThread
|
||||
PR_DetachThread:
|
||||
jmp _PR_DetachThread
|
||||
|
||||
.align 4
|
||||
.globl PR_GetCurrentThread
|
||||
PR_GetCurrentThread:
|
||||
jmp _PR_GetCurrentThread
|
||||
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
; -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
|
||||
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; IBM Corporation.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2001
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
; Windows uses inline assembly for their atomic functions, so we have
|
||||
; created an assembly file for VACPP on OS/2.
|
||||
;
|
||||
; This assembly file also contains an implementation of RAM semaphores.
|
||||
;
|
||||
; Notes:
|
||||
; The ulTIDPID element of the RAMSEM structure is overloaded in the 386
|
||||
; implementation to hold the TID:PID in the lower 31 bits and the lock
|
||||
; bit in the high bit
|
||||
|
||||
page ,132
|
||||
|
||||
.486P
|
||||
ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT
|
||||
|
||||
EXTRN Dos32PostEventSem:PROC
|
||||
EXTRN Dos32WaitEventSem:PROC
|
||||
EXTRN Dos32ResetEventSem:PROC
|
||||
|
||||
ramsem STRUC
|
||||
ramsem_ulTIDPID DD ?
|
||||
ramsem_hevSem DD ?
|
||||
ramsem_cLocks DD ?
|
||||
ramsem_cWaiting DW ?
|
||||
ramsem_cPosts DW ?
|
||||
ramsem ENDS
|
||||
|
||||
ERROR_SEM_TIMEOUT equ 121
|
||||
ERROR_NOT_OWNER equ 288
|
||||
SEM_RELEASE_UNOWNED equ 1
|
||||
SEM_RELEASE_ALL equ 2
|
||||
TS_LOCKBIT equ 31
|
||||
|
||||
|
||||
DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
|
||||
|
||||
EXTRN plisCurrent:DWORD
|
||||
|
||||
DATA ENDS
|
||||
|
||||
CODE32 SEGMENT USE32 PUBLIC 'CODE'
|
||||
|
||||
PUBLIC SemRequest486
|
||||
PUBLIC SemReleasex86
|
||||
|
||||
PUBLIC _PR_MD_ATOMIC_SET
|
||||
PUBLIC _PR_MD_ATOMIC_ADD
|
||||
PUBLIC _PR_MD_ATOMIC_INCREMENT
|
||||
PUBLIC _PR_MD_ATOMIC_DECREMENT
|
||||
|
||||
;;;---------------------------------------------------------------------------
|
||||
;;; APIRET _Optlink SemRequest(PRAMSEM pramsem, ULONG ulTimeout);
|
||||
;;;
|
||||
;;; Registers:
|
||||
;;; EAX - packed TID:PID word
|
||||
;;; ECX - address of RAMSEM structure
|
||||
;;; EDX - length of timeout in milli-seconds
|
||||
;;;---------------------------------------------------------------------------
|
||||
|
||||
ALIGN 10H
|
||||
SemRequest486 PROC
|
||||
push ebx ; Save ebx (volatile)
|
||||
mov ecx, eax ; PRAMSEM must be in ecx,
|
||||
; not eax, for cmpxchg
|
||||
|
||||
mov ebx, dword ptr [plisCurrent]
|
||||
mov eax, dword ptr [ebx+4] ; Place thread id in high
|
||||
; word, process id in low
|
||||
mov ax, word ptr [ebx] ; word
|
||||
mov ebx,eax
|
||||
|
||||
req486_test:
|
||||
xor eax,eax
|
||||
cmp (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx ; If we own the sem, just
|
||||
jz short req486_inc_exit ; increment the use count
|
||||
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag
|
||||
|
||||
; lock ; Uncomment for SMP
|
||||
DB 0F0h
|
||||
; cmpxchg (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx
|
||||
; (byte 3 is the offset of ulProcessThread into the RAMSEM structure)
|
||||
DB 00Fh
|
||||
DB 0B1h
|
||||
DB 019h
|
||||
jnz short req486_sleep
|
||||
|
||||
req486_inc_exit:
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cLocks
|
||||
|
||||
req486_exit:
|
||||
pop ebx ; Restore ebx
|
||||
ret
|
||||
|
||||
req486_sleep:
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
push edx ; timeout
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32WaitEventSem
|
||||
add esp, 8
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
or eax, eax
|
||||
jne req486_exit ; Exit, if error
|
||||
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
sub esp, 4 ; Use stack space for
|
||||
push esp ; dummy pulPostCt
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32ResetEventSem
|
||||
add esp, 12
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
jmp req486_test ; Retry the semaphore
|
||||
|
||||
SemRequest486 ENDP
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; APIRET _Optlink SemReleasex86(PRAMSEM pramsem, ULONG flFlags);
|
||||
;;;
|
||||
;;; Registers:
|
||||
;;; EAX - address of RAMSEM structure
|
||||
;;; ECX - temporary variable
|
||||
;;; EDX - flags
|
||||
;;;---------------------------------------------------------------------
|
||||
|
||||
ALIGN 10H
|
||||
SemReleasex86 PROC
|
||||
test edx, SEM_RELEASE_UNOWNED ; If set, don't bother
|
||||
jnz short rel_ownerok ; getting/checking PID/TID
|
||||
|
||||
push ebx ; Save ebx (volatile)
|
||||
mov ebx, dword ptr [plisCurrent]
|
||||
mov ecx, dword ptr [ebx+4] ; Place thread id in high
|
||||
; word, process id in low
|
||||
mov cx, word ptr [ebx] ; word
|
||||
pop ebx ; Restore ebx
|
||||
|
||||
sub ecx, (ramsem PTR [eax]).ramsem_ulTIDPID ; This thread the owner?
|
||||
shl ecx,1 ; Don't compare top bit
|
||||
jnz short rel_notowner
|
||||
|
||||
rel_ownerok:
|
||||
test edx, SEM_RELEASE_ALL
|
||||
jnz short rel_clear
|
||||
|
||||
lock dec (ramsem PTR [eax]).ramsem_cLocks
|
||||
jnz short rel_exit
|
||||
|
||||
rel_disown:
|
||||
mov (ramsem PTR [eax]).ramsem_ulTIDPID, 0
|
||||
|
||||
lock inc (ramsem PTR [eax]).ramsem_cPosts
|
||||
mov cx, (ramsem PTR [eax]).ramsem_cWaiting
|
||||
cmp (ramsem PTR [eax]).ramsem_cPosts, cx
|
||||
jne short rel_post
|
||||
|
||||
rel_exit:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
rel_clear:
|
||||
lock mov (ramsem PTR [eax]).ramsem_cLocks,0
|
||||
jmp rel_disown
|
||||
|
||||
rel_notowner:
|
||||
mov eax, ERROR_NOT_OWNER
|
||||
ret
|
||||
|
||||
rel_post:
|
||||
mov (ramsem PTR [eax]).ramsem_cPosts, cx
|
||||
push (ramsem PTR [eax]).ramsem_hevSem
|
||||
call Dos32PostEventSem
|
||||
add esp,4
|
||||
xor eax,eax
|
||||
ret
|
||||
SemReleasex86 ENDP
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval)
|
||||
;;;---------------------------------------------------------------------
|
||||
ALIGN 10H
|
||||
_PR_MD_ATOMIC_SET proc
|
||||
xchg dword ptr [eax],edx
|
||||
mov eax, edx;
|
||||
ret
|
||||
_PR_MD_ATOMIC_SET endp
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val)
|
||||
;;;---------------------------------------------------------------------
|
||||
ALIGN 10H
|
||||
_PR_MD_ATOMIC_ADD proc
|
||||
mov ecx, edx
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
add eax, ecx
|
||||
ret
|
||||
_PR_MD_ATOMIC_ADD endp
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val)
|
||||
;;;---------------------------------------------------------------------
|
||||
ALIGN 10H
|
||||
_PR_MD_ATOMIC_INCREMENT proc
|
||||
mov edx, 1
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
inc eax
|
||||
ret
|
||||
_PR_MD_ATOMIC_INCREMENT endp
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val)
|
||||
;;;---------------------------------------------------------------------
|
||||
ALIGN 10H
|
||||
_PR_MD_ATOMIC_DECREMENT proc
|
||||
mov edx, 0ffffffffh
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
dec eax
|
||||
ret
|
||||
_PR_MD_ATOMIC_DECREMENT endp
|
||||
|
||||
CODE32 ENDS
|
||||
END
|
||||
@@ -0,0 +1,115 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prbit.h"
|
||||
#include "prsystem.h"
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef SUNOS4
|
||||
#include "md/sunos4.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifdef XP_BEOS
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
PRInt32 _pr_pageShift;
|
||||
PRInt32 _pr_pageSize;
|
||||
|
||||
/*
|
||||
** Get system page size
|
||||
*/
|
||||
static void GetPageSize(void)
|
||||
{
|
||||
PRInt32 pageSize;
|
||||
|
||||
/* Get page size */
|
||||
#ifdef XP_UNIX
|
||||
#if defined SUNOS4 || defined BSDI || defined AIX \
|
||||
|| defined LINUX || defined __GNU__ || defined __GLIBC__ \
|
||||
|| defined FREEBSD || defined NETBSD || defined OPENBSD \
|
||||
|| defined DARWIN || defined NEXTSTEP
|
||||
_pr_pageSize = getpagesize();
|
||||
#elif defined(HPUX)
|
||||
/* I have no idea. Don't get me started. --Rob */
|
||||
_pr_pageSize = sysconf(_SC_PAGE_SIZE);
|
||||
#else
|
||||
_pr_pageSize = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
#ifdef XP_MAC
|
||||
_pr_pageSize = 4096;
|
||||
#endif /* XP_MAC */
|
||||
|
||||
#ifdef XP_BEOS
|
||||
_pr_pageSize = B_PAGE_SIZE;
|
||||
#endif
|
||||
|
||||
#ifdef XP_PC
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
_pr_pageSize = info.dwPageSize;
|
||||
#else
|
||||
_pr_pageSize = 4096;
|
||||
#endif
|
||||
#endif /* XP_PC */
|
||||
|
||||
pageSize = _pr_pageSize;
|
||||
PR_CEILING_LOG2(_pr_pageShift, pageSize);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRInt32) PR_GetPageShift(void)
|
||||
{
|
||||
if (!_pr_pageSize) {
|
||||
GetPageSize();
|
||||
}
|
||||
return _pr_pageShift;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRInt32) PR_GetPageSize(void)
|
||||
{
|
||||
if (!_pr_pageSize) {
|
||||
GetPageSize();
|
||||
}
|
||||
return _pr_pageSize;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,54 @@
|
||||
/.cvsignore/1.2/Sat May 12 04:29:27 2001//
|
||||
/Makefile.in/1.26/Sun Apr 25 15:00:59 2004//
|
||||
/aix.c/3.11/Sun Apr 25 15:00:59 2004//
|
||||
/aixwrap.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/bsdi.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/darwin.c/3.11/Sun Apr 25 15:00:59 2004//
|
||||
/dgux.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/freebsd.c/3.7/Sun Apr 25 15:00:59 2004//
|
||||
/hpux.c/3.7/Sun Apr 25 15:00:59 2004//
|
||||
/irix.c/3.14/Sun Apr 25 15:00:59 2004//
|
||||
/linux.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/ncr.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/nec.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/netbsd.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/nextstep.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/nto.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/objs.mk/3.34/Sun Apr 25 15:00:59 2004//
|
||||
/openbsd.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/openvms.c/1.9/Sun Apr 25 15:00:59 2004//
|
||||
/os_AIX.s/3.5/Tue Jun 20 21:32:22 2000//
|
||||
/os_BSD_386_2.s/3.5/Tue Jun 20 21:32:26 2000//
|
||||
/os_Darwin_ppc.s/3.1/Sat Feb 22 15:00:13 2003//
|
||||
/os_Darwin_x86.s/1.1/Mon Jan 9 18:38:54 2006//
|
||||
/os_HPUX.s/1.3/Tue Jun 20 21:32:29 2000//
|
||||
/os_HPUX_ia64.s/1.2/Mon Nov 21 22:49:19 2005//
|
||||
/os_Irix.s/3.5/Tue Jun 20 21:32:31 2000//
|
||||
/os_Linux_ia64.s/3.5/Mon Nov 21 22:49:19 2005//
|
||||
/os_Linux_x86.s/3.8/Mon Jan 9 17:43:52 2006//
|
||||
/os_Linux_x86_64.s/1.2/Mon Jan 9 17:43:52 2006//
|
||||
/os_ReliantUNIX.s/3.5/Tue Jun 20 21:32:36 2000//
|
||||
/os_SunOS.s/3.6/Tue Jun 20 21:32:39 2000//
|
||||
/os_SunOS_sparcv9.s/3.1/Sun Jun 24 01:39:51 2001//
|
||||
/os_SunOS_ultrasparc.s/3.8/Tue Jun 20 21:32:43 2000//
|
||||
/os_SunOS_x86.s/3.10/Mon Jan 9 17:43:52 2006//
|
||||
/os_SunOS_x86_64.s/1.2/Mon Jan 9 17:43:52 2006//
|
||||
/osf1.c/3.7/Sun Apr 25 15:00:59 2004//
|
||||
/pthreads_user.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/qnx.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/reliantunix.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/rhapsody.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/riscos.c/3.1/Fri Jul 1 22:26:36 2005//
|
||||
/scoos.c/3.6/Sun Apr 25 15:00:59 2004//
|
||||
/solaris.c/3.16/Sun Apr 25 15:00:59 2004//
|
||||
/sony.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/sunos4.c/3.5/Sun Apr 25 15:00:59 2004//
|
||||
/unix.c/3.52/Sat Dec 24 08:25:29 2005//
|
||||
/unix_errors.c/3.26/Wed Mar 9 22:57:05 2005//
|
||||
/unixware.c/3.8/Sun Apr 25 15:00:59 2004//
|
||||
/uxpoll.c/3.11/Sun Apr 25 15:00:59 2004//
|
||||
/uxproces.c/3.20/Sat Dec 24 08:25:29 2005//
|
||||
/uxrng.c/1.19/Sat Dec 24 08:25:29 2005//
|
||||
/uxshm.c/3.11/Sun Apr 25 15:00:59 2004//
|
||||
/uxwrap.c/3.15/Sat Apr 30 00:19:33 2005//
|
||||
D
|
||||
@@ -0,0 +1 @@
|
||||
mozilla/nsprpub/pr/src/md/unix
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -0,0 +1,135 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
MOD_DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(MOD_DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
CSRCS = \
|
||||
unix.c \
|
||||
unix_errors.c \
|
||||
uxproces.c \
|
||||
uxrng.c \
|
||||
uxshm.c \
|
||||
uxwrap.c \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(USE_PTHREADS),1)
|
||||
CSRCS += uxpoll.c
|
||||
endif
|
||||
|
||||
ifeq ($(PTHREADS_USER),1)
|
||||
CSRCS += pthreads_user.c
|
||||
endif
|
||||
|
||||
CSRCS += $(PR_MD_CSRCS)
|
||||
ASFILES += $(PR_MD_ASFILES)
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifneq ($(OS_RELEASE),4.1.3_U1)
|
||||
ifeq ($(OS_TEST),sun4u)
|
||||
ifdef USE_64
|
||||
ULTRASPARC_ASFILES = os_SunOS_sparcv9.s
|
||||
ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
|
||||
else
|
||||
LIBRARY_NAME = $(ULTRASPARC_LIBRARY)
|
||||
LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
|
||||
ULTRASPARC_ASFILES = os_SunOS_ultrasparc.s
|
||||
ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
|
||||
TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY)
|
||||
RELEASE_LIBS = $(SHARED_LIBRARY)
|
||||
RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)/cpu/sparcv8plus
|
||||
lib_subdir = cpu/sparcv8plus
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
|
||||
|
||||
DEFINES += -D_NSPR_BUILD_
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
ifneq ($(OS_RELEASE),4.1.3_U1)
|
||||
ifeq ($(OS_TEST),sun4u)
|
||||
|
||||
ifdef USE_64
|
||||
$(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES)
|
||||
/usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v9 $<
|
||||
else
|
||||
$(SHARED_LIBRARY): $(ULTRASPARC_ASOBJS)
|
||||
$(LD) -G -z text -z endfiltee -o $@ $(ULTRASPARC_ASOBJS)
|
||||
$(INSTALL) -m 444 $@ $(dist_libdir)/cpu/sparcv8plus
|
||||
$(INSTALL) -m 444 $@ $(dist_bindir)/cpu/sparcv8plus
|
||||
#
|
||||
# The -f $(ORIGIN)/... linker flag uses the real file, after symbolic links
|
||||
# are resolved, as the origin. If NSDISTMODE is not "copy", libnspr4.so
|
||||
# will be installed as a symbolic link in $(dist_libdir), pointing to the
|
||||
# real libnspr4.so file in pr/src. Therefore we need to install an
|
||||
# additional copy of libnspr_flt4.so in pr/src/cpu/sparcv8plus.
|
||||
#
|
||||
ifneq ($(NSDISTMODE),copy)
|
||||
$(INSTALL) -m 444 $@ ../../cpu/sparcv8plus
|
||||
endif
|
||||
|
||||
ifneq ($(NSDISTMODE),copy)
|
||||
clobber realclean clobber_all distclean::
|
||||
rm -rf ../../cpu
|
||||
endif
|
||||
|
||||
$(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES)
|
||||
/usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v8plus $<
|
||||
|
||||
clean::
|
||||
rm -rf $(ULTRASPARC_ASOBJS)
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,333 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#ifdef AIX_HAVE_ATOMIC_OP_H
|
||||
#include <sys/atomic_op.h>
|
||||
|
||||
PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
{
|
||||
PRIntn oldval;
|
||||
boolean_t stored;
|
||||
oldval = fetch_and_add((atomic_p)val, 0);
|
||||
do
|
||||
{
|
||||
stored = compare_and_swap((atomic_p)val, &oldval, newval);
|
||||
} while (!stored);
|
||||
return oldval;
|
||||
} /* _AIX_AtomicSet */
|
||||
#endif /* AIX_HAVE_ATOMIC_OP_H */
|
||||
|
||||
#if defined(AIX_TIMERS)
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
static PRUint32 _aix_baseline_epoch;
|
||||
|
||||
static void _MD_AixIntervalInit(void)
|
||||
{
|
||||
timebasestruct_t real_time;
|
||||
read_real_time(&real_time, TIMEBASE_SZ);
|
||||
(void)time_base_to_time(&real_time, TIMEBASE_SZ);
|
||||
_aix_baseline_epoch = real_time.tb_high;
|
||||
} /* _MD_AixIntervalInit */
|
||||
|
||||
PRIntervalTime _MD_AixGetInterval(void)
|
||||
{
|
||||
PRIntn rv;
|
||||
PRUint64 temp;
|
||||
timebasestruct_t real_time;
|
||||
read_real_time(&real_time, TIMEBASE_SZ);
|
||||
(void)time_base_to_time(&real_time, TIMEBASE_SZ);
|
||||
/* tb_high is in seconds, tb_low in 10(-9)seconds */
|
||||
temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch);
|
||||
temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */
|
||||
temp >>= 16; /* now it's something way different */
|
||||
return (PRIntervalTime)temp;
|
||||
} /* _MD_AixGetInterval */
|
||||
|
||||
PRIntervalTime _MD_AixIntervalPerSec(void)
|
||||
{
|
||||
return 1000000000ULL >> 16; /* that's 15258, I think */
|
||||
} /* _MD_AixIntervalPerSec */
|
||||
|
||||
#endif /* defined(AIX_TIMERS) */
|
||||
|
||||
#if !defined(PTHREADS_USER)
|
||||
|
||||
#if defined(_PR_PTHREADS)
|
||||
|
||||
/*
|
||||
* AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield().
|
||||
* So we look up the appropriate function pointer at run time.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
int (*_PT_aix_yield_fcn)() = NULL;
|
||||
int _pr_aix_send_file_use_disabled = 0;
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
void *main_app_handle;
|
||||
char *evp;
|
||||
|
||||
main_app_handle = dlopen(NULL, RTLD_NOW);
|
||||
PR_ASSERT(NULL != main_app_handle);
|
||||
|
||||
_PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield");
|
||||
if (!_PT_aix_yield_fcn) {
|
||||
_PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield");
|
||||
PR_ASSERT(NULL != _PT_aix_yield_fcn);
|
||||
}
|
||||
dlclose(main_app_handle);
|
||||
|
||||
if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) {
|
||||
if (1 == atoi(evp))
|
||||
_pr_aix_send_file_use_disabled = 1;
|
||||
}
|
||||
|
||||
#if defined(AIX_TIMERS)
|
||||
_MD_AixIntervalInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* _PR_PTHREADS */
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
#if defined(AIX_TIMERS)
|
||||
_MD_AixIntervalInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _PR_PTHREADS */
|
||||
|
||||
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
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_InitializeThread(PRThread *thread)
|
||||
{
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
|
||||
{
|
||||
PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
|
||||
_PR_MD_SWITCH_CONTEXT(thread);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(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 AIX */
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(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 AIX.");
|
||||
}
|
||||
#endif /* _PR_PTHREADS */
|
||||
#endif /* PTHREADS_USER */
|
||||
|
||||
/*
|
||||
* NSPR 2.0 overrides the system select() and poll() functions.
|
||||
* On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
|
||||
* at the original system select() and poll() functions.
|
||||
*/
|
||||
|
||||
#if !defined(AIX_RENAME_SELECT)
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/poll.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static int (*aix_select_fcn)() = NULL;
|
||||
static int (*aix_poll_fcn)() = NULL;
|
||||
|
||||
int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (!aix_select_fcn) {
|
||||
void *aix_handle;
|
||||
|
||||
aix_handle = dlopen("/unix", RTLD_NOW);
|
||||
if (!aix_handle) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
|
||||
dlclose(aix_handle);
|
||||
if (!aix_select_fcn) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rv = (*aix_select_fcn)(width, r, w, e, t);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (!aix_poll_fcn) {
|
||||
void *aix_handle;
|
||||
|
||||
aix_handle = dlopen("/unix", RTLD_NOW);
|
||||
if (!aix_handle) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
|
||||
dlclose(aix_handle);
|
||||
if (!aix_poll_fcn) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rv = (*aix_poll_fcn)(listptr, nfds, timeout);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* In AIX versions prior to 4.2, we use the two-step rename/link trick.
|
||||
* The binary must contain at least one "poll" symbol for linker's rename
|
||||
* to work. So we must have this dummy function that references poll().
|
||||
*/
|
||||
#include <sys/poll.h>
|
||||
void _pr_aix_dummy()
|
||||
{
|
||||
poll(0,0,0);
|
||||
}
|
||||
|
||||
#endif /* !defined(AIX_RENAME_SELECT) */
|
||||
|
||||
#ifdef _PR_HAVE_ATOMIC_CAS
|
||||
|
||||
#include "pratom.h"
|
||||
|
||||
#define _PR_AIX_ATOMIC_LOCK -1
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
|
||||
{
|
||||
PRStackElem *addr;
|
||||
boolean_t locked = TRUE;
|
||||
|
||||
/* Is it safe to cast a pointer to an int? */
|
||||
PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
|
||||
do {
|
||||
while ((addr = stack->prstk_head.prstk_elem_next) ==
|
||||
(PRStackElem *)_PR_AIX_ATOMIC_LOCK)
|
||||
;
|
||||
locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
|
||||
(int) addr, _PR_AIX_ATOMIC_LOCK);
|
||||
} while (locked == TRUE);
|
||||
stack_elem->prstk_elem_next = addr;
|
||||
_clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem);
|
||||
return;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStackElem *)
|
||||
PR_StackPop(PRStack *stack)
|
||||
{
|
||||
PRStackElem *element;
|
||||
boolean_t locked = TRUE;
|
||||
|
||||
/* Is it safe to cast a pointer to an int? */
|
||||
PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
|
||||
do {
|
||||
while ((element = stack->prstk_head.prstk_elem_next) ==
|
||||
(PRStackElem *) _PR_AIX_ATOMIC_LOCK)
|
||||
;
|
||||
locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
|
||||
(int)element, _PR_AIX_ATOMIC_LOCK);
|
||||
} while (locked == TRUE);
|
||||
|
||||
if (element == NULL) {
|
||||
_clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL);
|
||||
} else {
|
||||
_clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
|
||||
(int) element->prstk_elem_next);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
#endif /* _PR_HAVE_ATOMIC_CAS */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* File: aixwrap.c
|
||||
* Description:
|
||||
* This file contains a single function, _MD_SELECT(), which simply
|
||||
* invokes the select() function. This file is used in an ugly
|
||||
* hack to override the system select() function on AIX releases
|
||||
* prior to 4.2. (On AIX 4.2, we use a different mechanism to
|
||||
* override select().)
|
||||
*/
|
||||
|
||||
#ifndef AIX_RENAME_SELECT
|
||||
#error aixwrap.c should only be used on AIX 3.2 or 4.1
|
||||
#else
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
|
||||
{
|
||||
return select(width, r, w, e, t);
|
||||
}
|
||||
|
||||
int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
|
||||
{
|
||||
return poll(listptr, nfds, timeout);
|
||||
}
|
||||
|
||||
#endif /* AIX_RENAME_SELECT */
|
||||
@@ -0,0 +1,119 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
/*
|
||||
* Ignore FPE because coercion of a NaN to an int causes SIGFPE
|
||||
* to be raised.
|
||||
*/
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction(SIGFPE, &act, 0);
|
||||
}
|
||||
|
||||
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 BSDI */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for BSDI.");
|
||||
}
|
||||
|
||||
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 BSDI.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
#if !defined(_PR_PTHREADS)
|
||||
if (isCurrent) {
|
||||
(void) setjmp(CONTEXT(t));
|
||||
}
|
||||
*np = sizeof(CONTEXT(t)) / sizeof(PRWord);
|
||||
return (PRWord *) CONTEXT(t);
|
||||
#else
|
||||
*np = 0;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_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 Darwin */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for Darwin.");
|
||||
}
|
||||
|
||||
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 Darwin.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
|
||||
/* darwin.c */
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
* using only NSPR threads here
|
||||
*
|
||||
* Copied from the UnixWare implementation. Should be kept in sync
|
||||
* with ../../../include/md/_dgux.h.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
if (isCurrent) {
|
||||
(void) setjmp(CONTEXT(t));
|
||||
}
|
||||
*np = sizeof(CONTEXT(t)) / sizeof(PRWord);
|
||||
return (PRWord *) CONTEXT(t);
|
||||
}
|
||||
|
||||
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 DG/UX */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for DG/UX.");
|
||||
}
|
||||
|
||||
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 DG/UX.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
/*
|
||||
* Ignore FPE because coercion of a NaN to an int causes SIGFPE
|
||||
* to be raised.
|
||||
*/
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction(SIGFPE, &act, 0);
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
#ifndef _PR_PTHREADS
|
||||
if (isCurrent) {
|
||||
(void) sigsetjmp(CONTEXT(t), 1);
|
||||
}
|
||||
*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 FreeBSD */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for FreeBSD.");
|
||||
}
|
||||
|
||||
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 FreeBSD.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
#if defined(HPUX_LW_TIMER)
|
||||
|
||||
#include <machine/inline.h>
|
||||
#include <machine/clock.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/pstat.h>
|
||||
|
||||
int __lw_get_thread_times(int which, int64_t *sample, int64_t *time);
|
||||
|
||||
static double msecond_per_itick;
|
||||
|
||||
void _PR_HPUX_LW_IntervalInit(void)
|
||||
{
|
||||
struct pst_processor psp;
|
||||
int iticksperclktick, clk_tck;
|
||||
int rv;
|
||||
|
||||
rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0);
|
||||
PR_ASSERT(rv != -1);
|
||||
|
||||
iticksperclktick = psp.psp_iticksperclktick;
|
||||
clk_tck = sysconf(_SC_CLK_TCK);
|
||||
msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck);
|
||||
}
|
||||
|
||||
PRIntervalTime _PR_HPUX_LW_GetInterval(void)
|
||||
{
|
||||
int64_t time, sample;
|
||||
|
||||
__lw_get_thread_times(1, &sample, &time);
|
||||
/*
|
||||
* Division is slower than float multiplication.
|
||||
* return (time / iticks_per_msecond);
|
||||
*/
|
||||
return (time * msecond_per_itick);
|
||||
}
|
||||
#endif /* HPUX_LW_TIMER */
|
||||
|
||||
#if !defined(PTHREADS_USER)
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
#ifndef _PR_PTHREADS
|
||||
/*
|
||||
* The following piece of code is taken from ns/nspr/src/md_HP-UX.c.
|
||||
* In the comment for revision 1.6, dated 1995/09/11 23:33:34,
|
||||
* robm says:
|
||||
* This version has some problems which need to be addressed.
|
||||
* First, intercept all system calls and prevent them from
|
||||
* executing the library code which performs stack switches
|
||||
* before normal system call invocation. In order for library
|
||||
* calls which make system calls to work (like stdio), however,
|
||||
* we must also allocate our own stack and switch the primordial
|
||||
* stack to use it. This isn't so bad, except that I fudged the
|
||||
* backtrace length when copying the old stack to the new one.
|
||||
*
|
||||
* This is the original comment of robm in the code:
|
||||
* XXXrobm Horrific. To avoid a problem with HP's system call
|
||||
* code, we allocate a new stack for the primordial thread and
|
||||
* use it. However, we don't know how far back the original stack
|
||||
* goes. We should create a routine that performs a backtrace and
|
||||
* finds out just how much we need to copy. As a temporary measure,
|
||||
* I just copy an arbitrary guess.
|
||||
*
|
||||
* In an email to servereng dated 2 Jan 1997, Mike Patnode (mikep)
|
||||
* suggests that this only needs to be done for HP-UX 9.
|
||||
*/
|
||||
#ifdef HPUX9
|
||||
#define PIDOOMA_STACK_SIZE 524288
|
||||
#define BACKTRACE_SIZE 8192
|
||||
{
|
||||
jmp_buf jb;
|
||||
char *newstack;
|
||||
char *oldstack;
|
||||
|
||||
if(!setjmp(jb)) {
|
||||
newstack = (char *) PR_MALLOC(PIDOOMA_STACK_SIZE);
|
||||
oldstack = (char *) (*(((int *) jb) + 1) - BACKTRACE_SIZE);
|
||||
memcpy(newstack, oldstack, BACKTRACE_SIZE);
|
||||
*(((int *) jb) + 1) = (int) (newstack + BACKTRACE_SIZE);
|
||||
longjmp(jb, 1);
|
||||
}
|
||||
}
|
||||
#endif /* HPUX9 */
|
||||
#endif /* !_PR_PTHREADS */
|
||||
}
|
||||
|
||||
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 HP-UX */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX.");
|
||||
}
|
||||
|
||||
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 HP-UX.");
|
||||
}
|
||||
#endif /* _PR_PTHREADS */
|
||||
|
||||
void
|
||||
_MD_suspend_thread(PRThread *thread)
|
||||
{
|
||||
#ifdef _PR_PTHREADS
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_MD_resume_thread(PRThread *thread)
|
||||
{
|
||||
#ifdef _PR_PTHREADS
|
||||
#endif
|
||||
}
|
||||
#endif /* PTHREADS_USER */
|
||||
|
||||
/*
|
||||
* The HP version of strchr is buggy. It looks past the end of the
|
||||
* string and causes a segmentation fault when our (NSPR) version
|
||||
* of malloc is used.
|
||||
*
|
||||
* A better solution might be to put a cushion in our malloc just in
|
||||
* case HP's version of strchr somehow gets used instead of this one.
|
||||
*/
|
||||
char *
|
||||
strchr(const char *s, int c)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch = (char) c;
|
||||
|
||||
while ((*s) && ((*s) != ch)) {
|
||||
s++;
|
||||
}
|
||||
|
||||
if ((*s) == ch) {
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implemementation of memcmp in HP-UX (verified on releases A.09.03,
|
||||
* A.09.07, and B.10.10) dumps core if called with:
|
||||
* 1. First operand with address = 1(mod 4).
|
||||
* 2. Size = 1(mod 4)
|
||||
* 3. Last byte of the second operand is the last byte of the page and
|
||||
* next page is not accessible(not mapped or protected)
|
||||
* Thus, using the following naive version (tons of optimizations are
|
||||
* possible;^)
|
||||
*/
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
register unsigned char *p1 = (unsigned char *) s1,
|
||||
*p2 = (unsigned char *) s2;
|
||||
|
||||
while (n-- > 0) {
|
||||
register int r = ((int) ((unsigned int) *p1))
|
||||
- ((int) ((unsigned int) *p2));
|
||||
if (r) return r;
|
||||
p1++; p2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
#ifdef _PR_PTHREADS
|
||||
|
||||
extern void _MD_unix_terminate_waitpid_daemon(void);
|
||||
|
||||
void _MD_CleanupBeforeExit(void)
|
||||
{
|
||||
_MD_unix_terminate_waitpid_daemon();
|
||||
}
|
||||
|
||||
#else /* ! _PR_PTHREADS */
|
||||
|
||||
void
|
||||
_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_InitializeThread(PRThread *thread)
|
||||
{
|
||||
/*
|
||||
* set the pointers to the stack-pointer and frame-pointer words in the
|
||||
* context structure; this is for debugging use.
|
||||
*/
|
||||
thread->md.sp = _MD_GET_SP_PTR(thread);
|
||||
thread->md.fp = _MD_GET_FP_PTR(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 Linux */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for Linux.");
|
||||
}
|
||||
|
||||
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 Linux.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
@@ -0,0 +1,395 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* NCR 3.0 - cloned from UnixWare by ruslan
|
||||
*/
|
||||
#include "primpl.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
if (isCurrent) {
|
||||
(void) setjmp(CONTEXT(t));
|
||||
}
|
||||
*np = sizeof(CONTEXT(t)) / sizeof(PRWord);
|
||||
return (PRWord *) CONTEXT(t);
|
||||
}
|
||||
|
||||
#ifdef ALARMS_BREAK_TCP /* I don't think they do */
|
||||
|
||||
PRInt32 _MD_connect(PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
_MD_BLOCK_CLOCK_INTERRUPTS();
|
||||
rv = _connect(osfd,addr,addrlen);
|
||||
_MD_UNBLOCK_CLOCK_INTERRUPTS();
|
||||
}
|
||||
|
||||
PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
_MD_BLOCK_CLOCK_INTERRUPTS();
|
||||
rv = _accept(osfd,addr,addrlen);
|
||||
_MD_UNBLOCK_CLOCK_INTERRUPTS();
|
||||
return(rv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are also implemented in pratom.c using NSPR locks. Any reason
|
||||
* this might be better or worse? If you like this better, define
|
||||
* _PR_HAVE_ATOMIC_OPS in include/md/unixware.h
|
||||
*/
|
||||
#ifdef _PR_HAVE_ATOMIC_OPS
|
||||
/* Atomic operations */
|
||||
#include <stdio.h>
|
||||
static FILE *_uw_semf;
|
||||
|
||||
void
|
||||
_MD_INIT_ATOMIC(void)
|
||||
{
|
||||
/* Sigh. Sure wish SYSV semaphores weren't such a pain to use */
|
||||
if ((_uw_semf = tmpfile()) == NULL)
|
||||
PR_ASSERT(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_MD_ATOMIC_INCREMENT(PRInt32 *val)
|
||||
{
|
||||
flockfile(_uw_semf);
|
||||
(*val)++;
|
||||
unflockfile(_uw_semf);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
|
||||
{
|
||||
flockfile(_uw_semf);
|
||||
(*ptr) += val;
|
||||
unflockfile(_uw_semf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_MD_ATOMIC_DECREMENT(PRInt32 *val)
|
||||
{
|
||||
flockfile(_uw_semf);
|
||||
(*val)--;
|
||||
unflockfile(_uw_semf);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
|
||||
{
|
||||
flockfile(_uw_semf);
|
||||
*val = newval;
|
||||
unflockfile(_uw_semf);
|
||||
}
|
||||
#endif
|
||||
|
||||
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 Unixware */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for Unixware.");
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_CREATE_THREAD(
|
||||
PRThread *thread,
|
||||
void (*start) (void *),
|
||||
PRUintn priority,
|
||||
PRThreadScope scope,
|
||||
PRThreadState state,
|
||||
PRUint32 stackSize)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
This is temp. replacement for localtime_r. Normally PR_ExplodeTime should
|
||||
be used as to my understanding
|
||||
*/
|
||||
|
||||
/*
|
||||
** $$$$$ THEN WHY ARE WE DOING THIS? - AOF $$$$$
|
||||
*/
|
||||
|
||||
#define NEED_LOCALTIME_R
|
||||
#define NEED_GMTIME_R
|
||||
#define NEED_ASCTIME_R
|
||||
#define NEED_STRTOK_R
|
||||
#define NEED_CTIME_R
|
||||
|
||||
#if defined (NEED_LOCALTIME_R) || defined (NEED_CTIME_R) || defined (NEED_ASCTIME_R) || defined (NEED_GMTIME_R) || defined (NEED_STRTOK_R)
|
||||
#include "prlock.h"
|
||||
#endif
|
||||
|
||||
#if defined (NEED_LOCALTIME_R)
|
||||
|
||||
static PRLock *localtime_r_monitor = NULL;
|
||||
|
||||
struct tm *localtime_r (const time_t *clock, struct tm *result)
|
||||
{
|
||||
struct tm *tmPtr;
|
||||
int needLock = PR_Initialized(); /* We need to use a lock to protect
|
||||
* against NSPR threads only when the
|
||||
* NSPR thread system is activated. */
|
||||
|
||||
if (needLock) {
|
||||
if (localtime_r_monitor == NULL) {
|
||||
|
||||
localtime_r_monitor = PR_NewLock();
|
||||
}
|
||||
PR_Lock(localtime_r_monitor);
|
||||
}
|
||||
|
||||
/*
|
||||
* On Windows, localtime() returns a NULL pointer if 'clock'
|
||||
* represents a time before midnight January 1, 1970. In
|
||||
* that case, we also return a NULL pointer and the struct tm
|
||||
* object pointed to by 'result' is not modified.
|
||||
*/
|
||||
|
||||
tmPtr = localtime(clock);
|
||||
if (tmPtr) {
|
||||
*result = *tmPtr;
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
if (needLock) PR_Unlock(localtime_r_monitor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (NEED_GMTIME_R)
|
||||
|
||||
static PRLock *gmtime_r_monitor = NULL;
|
||||
|
||||
struct tm *gmtime_r (const time_t *clock, struct tm *result)
|
||||
{
|
||||
struct tm *tmPtr;
|
||||
int needLock = PR_Initialized(); /* We need to use a lock to protect
|
||||
* against NSPR threads only when the
|
||||
* NSPR thread system is activated. */
|
||||
|
||||
if (needLock) {
|
||||
if (gmtime_r_monitor == NULL) {
|
||||
gmtime_r_monitor = PR_NewLock();
|
||||
}
|
||||
PR_Lock(gmtime_r_monitor);
|
||||
}
|
||||
|
||||
tmPtr = gmtime(clock);
|
||||
if (tmPtr) {
|
||||
*result = *tmPtr;
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
if (needLock) PR_Unlock(gmtime_r_monitor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (NEED_CTIME_R)
|
||||
|
||||
static PRLock *ctime_r_monitor = NULL;
|
||||
|
||||
char *ctime_r (const time_t *clock, char *buf, int buflen)
|
||||
{
|
||||
char *cbuf;
|
||||
int needLock = PR_Initialized(); /* We need to use a lock to protect
|
||||
* against NSPR threads only when the
|
||||
* NSPR thread system is activated. */
|
||||
|
||||
if (needLock) {
|
||||
|
||||
if (ctime_r_monitor == NULL) {
|
||||
ctime_r_monitor = PR_NewLock();
|
||||
}
|
||||
PR_Lock(ctime_r_monitor);
|
||||
}
|
||||
|
||||
cbuf = ctime (clock);
|
||||
if (cbuf) {
|
||||
strncpy (buf, cbuf, buflen - 1);
|
||||
buf[buflen - 1] = 0;
|
||||
}
|
||||
|
||||
if (needLock) PR_Unlock(ctime_r_monitor);
|
||||
|
||||
return cbuf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (NEED_ASCTIME_R)
|
||||
|
||||
static PRLock *asctime_r_monitor = NULL;
|
||||
|
||||
|
||||
char *asctime_r (const struct tm *tm, char *buf, int buflen)
|
||||
{
|
||||
char *cbuf;
|
||||
int needLock = PR_Initialized(); /* We need to use a lock to protect
|
||||
* against NSPR threads only when the
|
||||
* NSPR thread system is activated. */
|
||||
|
||||
if (needLock) {
|
||||
if (asctime_r_monitor == NULL) {
|
||||
asctime_r_monitor = PR_NewLock();
|
||||
}
|
||||
PR_Lock(asctime_r_monitor);
|
||||
}
|
||||
|
||||
cbuf = asctime (tm);
|
||||
if (cbuf) {
|
||||
strncpy (buf, cbuf, buflen - 1);
|
||||
buf[buflen - 1] = 0;
|
||||
}
|
||||
|
||||
if (needLock) PR_Unlock(asctime_r_monitor);
|
||||
|
||||
return cbuf;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (NEED_STRTOK_R)
|
||||
|
||||
char *
|
||||
strtok_r (s, delim, last)
|
||||
register char *s;
|
||||
register const char *delim;
|
||||
register char **last;
|
||||
{
|
||||
register char *spanp;
|
||||
register int c, sc;
|
||||
char *tok;
|
||||
|
||||
|
||||
if (s == NULL && (s = *last) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||
*/
|
||||
cont:
|
||||
|
||||
c = *s++;
|
||||
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
|
||||
if (c == sc)
|
||||
goto cont;
|
||||
}
|
||||
|
||||
if (c == 0) { /* no non-delimiter characters */
|
||||
*last = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
tok = s - 1;
|
||||
|
||||
/*
|
||||
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||
* Note that delim must have one NUL; we stop if we see that, too.
|
||||
*/
|
||||
for (;;) {
|
||||
c = *s++;
|
||||
spanp = (char *)delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
|
||||
else
|
||||
s[-1] = 0;
|
||||
*last = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
if (isCurrent) {
|
||||
(void) setjmp(CONTEXT(t));
|
||||
}
|
||||
*np = sizeof(CONTEXT(t)) / sizeof(PRWord);
|
||||
return (PRWord *) CONTEXT(t);
|
||||
}
|
||||
|
||||
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 NEC */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for NEC.");
|
||||
}
|
||||
|
||||
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 NEC.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
/*
|
||||
* Ignore FPE because coercion of a NaN to an int causes SIGFPE
|
||||
* to be raised.
|
||||
*/
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction(SIGFPE, &act, 0);
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
#ifndef _PR_PTHREADS
|
||||
if (isCurrent) {
|
||||
(void) sigsetjmp(CONTEXT(t), 1);
|
||||
}
|
||||
*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 NetBSD */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for NetBSD.");
|
||||
}
|
||||
|
||||
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 NetBSD.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
@@ -0,0 +1,284 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#import <mach/mach.h>
|
||||
#import <mach/mach_error.h>
|
||||
#import <mach-o/dyld.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <syscall.h>
|
||||
|
||||
|
||||
|
||||
/* These functions are hidden in NEXTSTEP, but beacuse they have syscall()
|
||||
** entries I can wrap these into their corresponding missing function.
|
||||
*/
|
||||
caddr_t
|
||||
mmap(caddr_t addr, size_t len, int prot, int flags,
|
||||
int fildes, off_t off)
|
||||
{
|
||||
return (caddr_t) syscall (SYS_mmap, addr, len, prot, flags, fildes, off);
|
||||
}
|
||||
|
||||
int
|
||||
munmap(caddr_t addr, size_t len)
|
||||
{
|
||||
return syscall (SYS_munmap, addr, len);
|
||||
}
|
||||
|
||||
int
|
||||
mprotect(caddr_t addr, size_t len, int prot)
|
||||
{
|
||||
return syscall (SYS_mprotect, addr, len, prot);
|
||||
}
|
||||
|
||||
|
||||
/* If found the brk() symbol in the sahred libraries but no syscall() entry ...
|
||||
** I don't know whether it will work ...
|
||||
int brk(void *endds)
|
||||
{
|
||||
return syscall ();
|
||||
}
|
||||
*/
|
||||
|
||||
void *sbrk(int incr)
|
||||
{
|
||||
return (void *) syscall (SYS_sbrk, incr);
|
||||
}
|
||||
|
||||
/* These are my mach based versions, untested and probably bad ...
|
||||
*/
|
||||
caddr_t my_mmap(caddr_t addr, size_t len, int prot, int flags,
|
||||
int fildes, off_t off)
|
||||
{
|
||||
kern_return_t ret_val;
|
||||
|
||||
/* First map ...
|
||||
*/
|
||||
ret_val = map_fd ( fildes, /* fd */
|
||||
(vm_offset_t) off, /* offset */
|
||||
(vm_offset_t*)&addr, /* address */
|
||||
TRUE, /* find_space */
|
||||
(vm_size_t) len); /* size */
|
||||
|
||||
if (ret_val != KERN_SUCCESS) {
|
||||
mach_error("Error calling map_fd() in mmap", ret_val );
|
||||
return (caddr_t)0;
|
||||
}
|
||||
|
||||
/* ... then protect (this is probably bad)
|
||||
*/
|
||||
ret_val = vm_protect( task_self(), /* target_task */
|
||||
(vm_address_t)addr, /* address */
|
||||
(vm_size_t) len, /* size */
|
||||
FALSE, /* set_maximum */
|
||||
(vm_prot_t) prot); /* new_protection */
|
||||
if (ret_val != KERN_SUCCESS) {
|
||||
mach_error("vm_protect in mmap()", ret_val );
|
||||
return (caddr_t)0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
int my_munmap(caddr_t addr, size_t len)
|
||||
{
|
||||
kern_return_t ret_val;
|
||||
|
||||
ret_val = vm_deallocate(task_self(),
|
||||
(vm_address_t) addr,
|
||||
(vm_size_t) len);
|
||||
|
||||
if (ret_val != KERN_SUCCESS) {
|
||||
mach_error("vm_deallocate in munmap()", ret_val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_mprotect(caddr_t addr, size_t len, int prot)
|
||||
{
|
||||
vm_prot_t mach_prot;
|
||||
kern_return_t ret_val;
|
||||
|
||||
switch (prot) {
|
||||
case PROT_READ: mach_prot = VM_PROT_READ; break;
|
||||
case PROT_WRITE: mach_prot = VM_PROT_WRITE; break;
|
||||
case PROT_EXEC: mach_prot = VM_PROT_EXECUTE; break;
|
||||
case PROT_NONE: mach_prot = VM_PROT_NONE; break;
|
||||
}
|
||||
|
||||
ret_val = vm_protect(task_self(), /* target_task */
|
||||
(vm_address_t)addr, /* address */
|
||||
(vm_size_t) len, /* size */
|
||||
FALSE, /* set_maximum */
|
||||
(vm_prot_t) prot); /* new_protection */
|
||||
|
||||
if (ret_val != KERN_SUCCESS) {
|
||||
mach_error("vm_protect in mprotect()", ret_val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strdup(const char *s1)
|
||||
{
|
||||
int len = strlen (s1);
|
||||
char *copy = (char*) malloc (len+1);
|
||||
|
||||
if (copy == (char*)0)
|
||||
return (char*)0;
|
||||
|
||||
strcpy (copy, s1);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Stub rld functions
|
||||
*/
|
||||
extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
|
||||
const char *pathName,
|
||||
NSObjectFileImage *objectFileImage)
|
||||
{
|
||||
return NSObjectFileImageFailure;
|
||||
}
|
||||
|
||||
extern void * NSAddressOfSymbol(
|
||||
NSSymbol symbol)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern NSModule NSLinkModule(
|
||||
NSObjectFileImage objectFileImage,
|
||||
const char *moduleName, /* can be NULL */
|
||||
enum bool bindNow)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern NSSymbol NSLookupAndBindSymbol(
|
||||
const char *symbolName)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern enum bool NSUnLinkModule(
|
||||
NSModule module,
|
||||
enum bool keepMemoryMapped)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
#ifndef _PR_PTHREADS
|
||||
if (isCurrent) {
|
||||
(void) sigsetjmp(CONTEXT(t), 1);
|
||||
}
|
||||
*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 NEXTSTEP */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for NEXTSTEP.");
|
||||
}
|
||||
|
||||
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 NEXTSTEP.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
/* Fake this out */
|
||||
int socketpair (int foo, int foo2, int foo3, int sv[2])
|
||||
{
|
||||
printf("error in socketpair\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# This makefile appends to the variable OBJS the platform-dependent
|
||||
# object modules that will be part of the nspr20 library.
|
||||
|
||||
CSRCS = \
|
||||
unix.c \
|
||||
unix_errors.c \
|
||||
uxproces.c \
|
||||
uxrng.c \
|
||||
uxshm.c \
|
||||
uxwrap.c \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(USE_PTHREADS),1)
|
||||
CSRCS += uxpoll.c
|
||||
endif
|
||||
|
||||
ifeq ($(PTHREADS_USER),1)
|
||||
CSRCS += pthreads_user.c
|
||||
endif
|
||||
|
||||
CSRCS += $(PR_MD_CSRCS)
|
||||
ASFILES += $(PR_MD_ASFILES)
|
||||
|
||||
OBJS += $(addprefix md/unix/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix md/unix/$(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX)))
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
void _MD_EarlyInit(void)
|
||||
{
|
||||
/*
|
||||
* Ignore FPE because coercion of a NaN to an int causes SIGFPE
|
||||
* to be raised.
|
||||
*/
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction(SIGFPE, &act, 0);
|
||||
}
|
||||
|
||||
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
||||
{
|
||||
#ifndef _PR_PTHREADS
|
||||
if (isCurrent) {
|
||||
(void) sigsetjmp(CONTEXT(t), 1);
|
||||
}
|
||||
*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 OpenBSD */
|
||||
void
|
||||
_MD_YIELD(void)
|
||||
{
|
||||
PR_NOT_REACHED("_MD_YIELD should not be called for OpenBSD.");
|
||||
}
|
||||
|
||||
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 OpenBSD.");
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* ! _PR_PTHREADS */
|
||||
@@ -0,0 +1,286 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#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,®s[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;
|
||||
}
|
||||
|
||||
/*
|
||||
** Stubs for nspr_symvec.opt
|
||||
**
|
||||
** PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended
|
||||
** (defined in ptthread.c) used to be exported by mistake
|
||||
** (because they look like public functions). They have been
|
||||
** converted into static functions.
|
||||
**
|
||||
** There is an existing third-party binary that uses NSPR: the
|
||||
** Java plugin for Mozilla. Because it is part of the Java
|
||||
** SDK, we have no control over its releases. So we need these
|
||||
** stub functions to occupy the slots that used to be occupied
|
||||
** by PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended
|
||||
** in the symbol vector so that LIBNSPR4 is backward compatible.
|
||||
**
|
||||
** The Java plugin was also using PR_CreateThread which we didn't
|
||||
** realise and hadn't "nailed down". So we now need to nail it down
|
||||
** to its Mozilla 1.1 position and have to insert 51 additional stubs
|
||||
** in order to achive this (stubs 4-54).
|
||||
**
|
||||
** Over time some of these stubs will get reused by new symbols.
|
||||
** - Stub54 is replaced by LL_MaxUint
|
||||
*/
|
||||
|
||||
void PR_VMS_Stub1(void) { }
|
||||
void PR_VMS_Stub2(void) { }
|
||||
void PR_VMS_Stub3(void) { }
|
||||
void PR_VMS_Stub4(void) { }
|
||||
void PR_VMS_Stub5(void) { }
|
||||
void PR_VMS_Stub6(void) { }
|
||||
void PR_VMS_Stub7(void) { }
|
||||
void PR_VMS_Stub8(void) { }
|
||||
void PR_VMS_Stub9(void) { }
|
||||
void PR_VMS_Stub10(void) { }
|
||||
void PR_VMS_Stub11(void) { }
|
||||
void PR_VMS_Stub12(void) { }
|
||||
void PR_VMS_Stub13(void) { }
|
||||
void PR_VMS_Stub14(void) { }
|
||||
void PR_VMS_Stub15(void) { }
|
||||
void PR_VMS_Stub16(void) { }
|
||||
void PR_VMS_Stub17(void) { }
|
||||
void PR_VMS_Stub18(void) { }
|
||||
void PR_VMS_Stub19(void) { }
|
||||
void PR_VMS_Stub20(void) { }
|
||||
void PR_VMS_Stub21(void) { }
|
||||
void PR_VMS_Stub22(void) { }
|
||||
void PR_VMS_Stub23(void) { }
|
||||
void PR_VMS_Stub24(void) { }
|
||||
void PR_VMS_Stub25(void) { }
|
||||
void PR_VMS_Stub26(void) { }
|
||||
void PR_VMS_Stub27(void) { }
|
||||
void PR_VMS_Stub28(void) { }
|
||||
void PR_VMS_Stub29(void) { }
|
||||
void PR_VMS_Stub30(void) { }
|
||||
void PR_VMS_Stub31(void) { }
|
||||
void PR_VMS_Stub32(void) { }
|
||||
void PR_VMS_Stub33(void) { }
|
||||
void PR_VMS_Stub34(void) { }
|
||||
void PR_VMS_Stub35(void) { }
|
||||
void PR_VMS_Stub36(void) { }
|
||||
void PR_VMS_Stub37(void) { }
|
||||
void PR_VMS_Stub38(void) { }
|
||||
void PR_VMS_Stub39(void) { }
|
||||
void PR_VMS_Stub40(void) { }
|
||||
void PR_VMS_Stub41(void) { }
|
||||
void PR_VMS_Stub42(void) { }
|
||||
void PR_VMS_Stub43(void) { }
|
||||
void PR_VMS_Stub44(void) { }
|
||||
void PR_VMS_Stub45(void) { }
|
||||
void PR_VMS_Stub46(void) { }
|
||||
void PR_VMS_Stub47(void) { }
|
||||
void PR_VMS_Stub48(void) { }
|
||||
void PR_VMS_Stub49(void) { }
|
||||
void PR_VMS_Stub50(void) { }
|
||||
void PR_VMS_Stub51(void) { }
|
||||
void PR_VMS_Stub52(void) { }
|
||||
void PR_VMS_Stub53(void) { }
|
||||
@@ -0,0 +1,119 @@
|
||||
# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4
|
||||
.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
|
||||
.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
|
||||
.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
|
||||
.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
|
||||
.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
|
||||
.set r30,30; .set r31,31
|
||||
|
||||
|
||||
.rename H.10.NO_SYMBOL{PR},""
|
||||
.rename H.18.longjmp{TC},"longjmp"
|
||||
|
||||
.lglobl H.10.NO_SYMBOL{PR}
|
||||
.globl .longjmp
|
||||
.globl longjmp{DS}
|
||||
.extern .sigcleanup
|
||||
.extern .jmprestfpr
|
||||
|
||||
# .text section
|
||||
|
||||
.csect H.10.NO_SYMBOL{PR}
|
||||
.longjmp:
|
||||
mr r13,r3
|
||||
mr r14,r4
|
||||
stu SP,-56(SP)
|
||||
bl .sigcleanup
|
||||
l RTOC,0x14(SP)
|
||||
cal SP,0x38(SP)
|
||||
mr r3,r13
|
||||
mr r4,r14
|
||||
l r5,0x8(r3)
|
||||
l SP,0xc(r3)
|
||||
l r7,0xf8(r3)
|
||||
st r7,0x0(SP)
|
||||
l RTOC,0x10(r3)
|
||||
bl .jmprestfpr
|
||||
# 1 == cr0 in disassembly
|
||||
cmpi 1,r4,0x0
|
||||
mtlr r5
|
||||
lm r13,0x14(r3)
|
||||
l r5,0x60(r3)
|
||||
mtcrf 0x38,r5
|
||||
mr r3,r4
|
||||
bne __L1
|
||||
lil r3,0x1
|
||||
__L1:
|
||||
br
|
||||
|
||||
# traceback table
|
||||
.long 0x00000000
|
||||
.byte 0x00 # VERSION=0
|
||||
.byte 0x00 # LANG=TB_C
|
||||
.byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1
|
||||
# INT_PROC=0,HAS_CTL=0,TOCLESS=0
|
||||
# FP_PRESENT=0,LOG_ABORT=0
|
||||
.byte 0x40 # INT_HNDL=0,NAME_PRESENT=1
|
||||
# USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND
|
||||
# SAVES_CR=0,SAVES_LR=0
|
||||
.byte 0x80 # STORES_BC=1,FPR_SAVED=0
|
||||
.byte 0x00 # GPR_SAVED=0
|
||||
.byte 0x02 # FIXEDPARMS=2
|
||||
.byte 0x01 # FLOATPARMS=0,PARMSONSTK=1
|
||||
.long 0x00000000 #
|
||||
.long 0x00000014 # TB_OFFSET
|
||||
.short 7 # NAME_LEN
|
||||
.byte "longjmp"
|
||||
.byte 0 # padding
|
||||
.byte 0 # padding
|
||||
.byte 0 # padding
|
||||
# End of traceback table
|
||||
.long 0x00000000 # "\0\0\0\0"
|
||||
|
||||
# .data section
|
||||
|
||||
.toc # 0x00000038
|
||||
T.18.longjmp:
|
||||
.tc H.18.longjmp{TC},longjmp{DS}
|
||||
|
||||
.csect longjmp{DS}
|
||||
.long .longjmp # "\0\0\0\0"
|
||||
.long TOC{TC0} # "\0\0\0008"
|
||||
.long 0x00000000 # "\0\0\0\0"
|
||||
# End csect longjmp{DS}
|
||||
|
||||
# .bss section
|
||||
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* os_BSD_386_2.s
|
||||
* We need to define our own setjmp/longjmp on BSDI 2.x because libc's
|
||||
* implementation does some sanity checking that defeats user level threads.
|
||||
* This should no longer be necessary in BSDI 3.0.
|
||||
*/
|
||||
|
||||
.globl _setjmp
|
||||
.align 2
|
||||
_setjmp:
|
||||
movl 4(%esp),%eax
|
||||
movl 0(%esp),%edx
|
||||
movl %edx, 0(%eax) /* rta */
|
||||
movl %ebx, 4(%eax)
|
||||
movl %esp, 8(%eax)
|
||||
movl %ebp,12(%eax)
|
||||
movl %esi,16(%eax)
|
||||
movl %edi,20(%eax)
|
||||
movl $0,%eax
|
||||
ret
|
||||
|
||||
.globl _longjmp
|
||||
.align 2
|
||||
_longjmp:
|
||||
movl 4(%esp),%edx
|
||||
movl 8(%esp),%eax
|
||||
movl 0(%edx),%ecx
|
||||
movl 4(%edx),%ebx
|
||||
movl 8(%edx),%esp
|
||||
movl 12(%edx),%ebp
|
||||
movl 16(%edx),%esi
|
||||
movl 20(%edx),%edi
|
||||
cmpl $0,%eax
|
||||
jne 1f
|
||||
movl $1,%eax
|
||||
1: movl %ecx,0(%esp)
|
||||
ret
|
||||
@@ -0,0 +1,92 @@
|
||||
# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2003 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#
|
||||
# Based on the programming examples in The PowerPC Architecture:
|
||||
# A Specification for A New Family of RISC Processors, 2nd Ed.,
|
||||
# Book I, Section E.1, "Synchronization," pp. 249-256, May 1994.
|
||||
#
|
||||
|
||||
.text
|
||||
|
||||
#
|
||||
# PRInt32 __PR_DarwinPPC_AtomicIncrement(PRInt32 *val);
|
||||
#
|
||||
.align 2
|
||||
.globl __PR_DarwinPPC_AtomicIncrement
|
||||
__PR_DarwinPPC_AtomicIncrement:
|
||||
lwarx r4,0,r3
|
||||
addi r0,r4,1
|
||||
stwcx. r0,0,r3
|
||||
bne- __PR_DarwinPPC_AtomicIncrement
|
||||
mr r3,r0
|
||||
blr
|
||||
|
||||
#
|
||||
# PRInt32 __PR_DarwinPPC_AtomicDecrement(PRInt32 *val);
|
||||
#
|
||||
.align 2
|
||||
.globl __PR_DarwinPPC_AtomicDecrement
|
||||
__PR_DarwinPPC_AtomicDecrement:
|
||||
lwarx r4,0,r3
|
||||
addi r0,r4,-1
|
||||
stwcx. r0,0,r3
|
||||
bne- __PR_DarwinPPC_AtomicDecrement
|
||||
mr r3,r0
|
||||
blr
|
||||
|
||||
#
|
||||
# PRInt32 __PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval);
|
||||
#
|
||||
.align 2
|
||||
.globl __PR_DarwinPPC_AtomicSet
|
||||
__PR_DarwinPPC_AtomicSet:
|
||||
lwarx r5,0,r3
|
||||
stwcx. r4,0,r3
|
||||
bne- __PR_DarwinPPC_AtomicSet
|
||||
mr r3,r5
|
||||
blr
|
||||
|
||||
#
|
||||
# PRInt32 __PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val);
|
||||
#
|
||||
.align 2
|
||||
.globl __PR_DarwinPPC_AtomicAdd
|
||||
__PR_DarwinPPC_AtomicAdd:
|
||||
lwarx r5,0,r3
|
||||
add r0,r4,r5
|
||||
stwcx. r0,0,r3
|
||||
bne- __PR_DarwinPPC_AtomicAdd
|
||||
mr r3,r0
|
||||
blr
|
||||
@@ -0,0 +1,105 @@
|
||||
# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 2003 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Josh Aas <josh@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU General Public License Version 2 or later (the
|
||||
# "GPL"), in which case the provisions of the GPL are applicable
|
||||
# instead of those above. If you wish to allow use of your
|
||||
# version of this file only under the terms of the GPL and not to
|
||||
# allow others to use your version of this file under the MPL,
|
||||
# indicate your decision by deleting the provisions above and
|
||||
# replace them with the notice and other provisions required by
|
||||
# the GPL. If you do not delete the provisions above, a recipient
|
||||
# may use your version of this file under either the MPL or the
|
||||
# GPL.
|
||||
#
|
||||
|
||||
#
|
||||
# Based on os_Linux_x86.s
|
||||
#
|
||||
|
||||
#
|
||||
# PRInt32 __PR_Darwin_x86_AtomicIncrement(PRInt32 *val);
|
||||
#
|
||||
# Atomically increment the integer pointed to by 'val' and return
|
||||
# the result of the increment.
|
||||
#
|
||||
.text
|
||||
.globl __PR_Darwin_x86_AtomicIncrement
|
||||
.align 4
|
||||
__PR_Darwin_x86_AtomicIncrement:
|
||||
movl 4(%esp), %ecx
|
||||
movl $1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
incl %eax
|
||||
ret
|
||||
|
||||
#
|
||||
# PRInt32 __PR_Darwin_x86_AtomicDecrement(PRInt32 *val);
|
||||
#
|
||||
# Atomically decrement the integer pointed to by 'val' and return
|
||||
# the result of the decrement.
|
||||
#
|
||||
.text
|
||||
.globl __PR_Darwin_x86_AtomicDecrement
|
||||
.align 4
|
||||
__PR_Darwin_x86_AtomicDecrement:
|
||||
movl 4(%esp), %ecx
|
||||
movl $-1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
decl %eax
|
||||
ret
|
||||
|
||||
#
|
||||
# PRInt32 __PR_Darwin_x86_AtomicSet(PRInt32 *val, PRInt32 newval);
|
||||
#
|
||||
# Atomically set the integer pointed to by 'val' to the new
|
||||
# value 'newval' and return the old value.
|
||||
#
|
||||
.text
|
||||
.globl __PR_Darwin_x86_AtomicSet
|
||||
.align 4
|
||||
__PR_Darwin_x86_AtomicSet:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
xchgl %eax, (%ecx)
|
||||
ret
|
||||
|
||||
#
|
||||
# PRInt32 __PR_Darwin_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val);
|
||||
#
|
||||
# Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
# and return the result of the addition.
|
||||
#
|
||||
.text
|
||||
.globl __PR_Darwin_x86_AtomicAdd
|
||||
.align 4
|
||||
__PR_Darwin_x86_AtomicAdd:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
movl %eax, %edx
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
addl %edx, %eax
|
||||
ret
|
||||
@@ -0,0 +1,54 @@
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public
|
||||
; License Version 1.1 (the "License"); you may not use this file
|
||||
; except in compliance with the License. You may obtain a copy of
|
||||
; the License at http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS
|
||||
; IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
; implied. See the License for the specific language governing
|
||||
; rights and limitations under the License.
|
||||
;
|
||||
; The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
;
|
||||
; The Initial Developer of the Original Code is Netscape
|
||||
; Communications Corporation. Portions created by Netscape are
|
||||
; Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
; Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the
|
||||
; terms of the GNU General Public License Version 2 or later (the
|
||||
; "GPL"), in which case the provisions of the GPL are applicable
|
||||
; instead of those above. If you wish to allow use of your
|
||||
; version of this file only under the terms of the GPL and not to
|
||||
; allow others to use your version of this file under the MPL,
|
||||
; indicate your decision by deleting the provisions above and
|
||||
; replace them with the notice and other provisions required by
|
||||
; the GPL. If you do not delete the provisions above, a recipient
|
||||
; may use your version of this file under either the MPL or the
|
||||
; GPL.
|
||||
;
|
||||
|
||||
#ifdef __LP64__
|
||||
.LEVEL 2.0W
|
||||
#else
|
||||
.LEVEL 1.1
|
||||
#endif
|
||||
|
||||
.CODE ; equivalent to the following two lines
|
||||
; .SPACE $TEXT$,SORT=8
|
||||
; .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
|
||||
|
||||
ret_cr16
|
||||
.PROC
|
||||
.CALLINFO FRAME=0, NO_CALLS
|
||||
.EXPORT ret_cr16,ENTRY
|
||||
.ENTER
|
||||
; BV %r0(%rp)
|
||||
BV 0(%rp)
|
||||
MFCTL %cr16,%ret0
|
||||
.LEAVE
|
||||
.PROCEND
|
||||
.END
|
||||
@@ -0,0 +1,108 @@
|
||||
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public
|
||||
// License Version 1.1 (the "License"); you may not use this file
|
||||
// except in compliance with the License. You may obtain a copy of
|
||||
// the License at http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS
|
||||
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// rights and limitations under the License.
|
||||
//
|
||||
// The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
//
|
||||
// The Initial Developer of the Original Code is Netscape
|
||||
// Communications Corporation. Portions created by Netscape are
|
||||
// Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
// Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the
|
||||
// terms of the GNU General Public License Version 2 or later (the
|
||||
// "GPL"), in which case the provisions of the GPL are applicable
|
||||
// instead of those above. If you wish to allow use of your
|
||||
// version of this file only under the terms of the GPL and not to
|
||||
// allow others to use your version of this file under the MPL,
|
||||
// indicate your decision by deleting the provisions above and
|
||||
// replace them with the notice and other provisions required by
|
||||
// the GPL. If you do not delete the provisions above, a recipient
|
||||
// may use your version of this file under either the MPL or the
|
||||
// GPL.
|
||||
//
|
||||
|
||||
.text
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val)
|
||||
//
|
||||
// Atomically increment the integer pointed to by 'val' and return
|
||||
// the result of the increment.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicIncrement#
|
||||
.proc _PR_ia64_AtomicIncrement#
|
||||
_PR_ia64_AtomicIncrement:
|
||||
#ifndef _LP64
|
||||
addp4 r32 = 0, r32 ;;
|
||||
#endif
|
||||
fetchadd4.acq r8 = [r32], 1 ;;
|
||||
adds r8 = 1, r8
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicIncrement#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val)
|
||||
//
|
||||
// Atomically decrement the integer pointed to by 'val' and return
|
||||
// the result of the decrement.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicDecrement#
|
||||
.proc _PR_ia64_AtomicDecrement#
|
||||
_PR_ia64_AtomicDecrement:
|
||||
#ifndef _LP64
|
||||
addp4 r32 = 0, r32 ;;
|
||||
#endif
|
||||
fetchadd4.rel r8 = [r32], -1 ;;
|
||||
adds r8 = -1, r8
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicDecrement#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
|
||||
//
|
||||
// Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
// and return the result of the addition.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicAdd#
|
||||
.proc _PR_ia64_AtomicAdd#
|
||||
_PR_ia64_AtomicAdd:
|
||||
#ifndef _LP64
|
||||
addp4 r32 = 0, r32 ;;
|
||||
#endif
|
||||
ld4 r15 = [r32] ;;
|
||||
.L3:
|
||||
mov r14 = r15
|
||||
mov ar.ccv = r15
|
||||
add r8 = r15, r33 ;;
|
||||
cmpxchg4.acq r15 = [r32], r8, ar.ccv ;;
|
||||
cmp4.ne p6, p7 = r15, r14
|
||||
(p6) br.cond.dptk .L3
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicAdd#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
//
|
||||
// Atomically set the integer pointed to by 'val' to the new
|
||||
// value 'newval' and return the old value.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicSet#
|
||||
.proc _PR_ia64_AtomicSet#
|
||||
_PR_ia64_AtomicSet:
|
||||
#ifndef _LP64
|
||||
addp4 r32 = 0, r32 ;;
|
||||
#endif
|
||||
xchg4 r8 = [r32], r33
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicSet#
|
||||
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Atomically add a new element to the top of the stack
|
||||
*
|
||||
* usage : PR_StackPush(listp, elementp);
|
||||
* -----------------------
|
||||
*/
|
||||
|
||||
#include "md/_irix.h"
|
||||
#ifdef _PR_HAVE_ATOMIC_CAS
|
||||
|
||||
#include <sys/asm.h>
|
||||
#include <sys/regdef.h>
|
||||
|
||||
LEAF(PR_StackPush)
|
||||
|
||||
retry_push:
|
||||
.set noreorder
|
||||
lw v0,0(a0)
|
||||
li t1,1
|
||||
beq v0,t1,retry_push
|
||||
move t0,a1
|
||||
|
||||
ll v0,0(a0)
|
||||
beq v0,t1,retry_push
|
||||
nop
|
||||
sc t1,0(a0)
|
||||
beq t1,0,retry_push
|
||||
nop
|
||||
sw v0,0(a1)
|
||||
sync
|
||||
sw t0,0(a0)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jr ra
|
||||
nop
|
||||
|
||||
END(PR_StackPush)
|
||||
|
||||
/*
|
||||
*
|
||||
* Atomically remove the element at the top of the stack
|
||||
*
|
||||
* usage : elemep = PR_StackPop(listp);
|
||||
*
|
||||
*/
|
||||
|
||||
LEAF(PR_StackPop)
|
||||
retry_pop:
|
||||
.set noreorder
|
||||
|
||||
|
||||
lw v0,0(a0)
|
||||
li t1,1
|
||||
beq v0,0,done
|
||||
nop
|
||||
beq v0,t1,retry_pop
|
||||
nop
|
||||
|
||||
ll v0,0(a0)
|
||||
beq v0,0,done
|
||||
nop
|
||||
beq v0,t1,retry_pop
|
||||
nop
|
||||
sc t1,0(a0)
|
||||
beq t1,0,retry_pop
|
||||
nop
|
||||
lw t0,0(v0)
|
||||
sw t0,0(a0)
|
||||
done:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jr ra
|
||||
nop
|
||||
|
||||
END(PR_StackPop)
|
||||
|
||||
#endif /* _PR_HAVE_ATOMIC_CAS */
|
||||
@@ -0,0 +1,99 @@
|
||||
// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
//
|
||||
// The contents of this file are subject to the Mozilla Public
|
||||
// License Version 1.1 (the "License"); you may not use this file
|
||||
// except in compliance with the License. You may obtain a copy of
|
||||
// the License at http://www.mozilla.org/MPL/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS
|
||||
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// rights and limitations under the License.
|
||||
//
|
||||
// The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
//
|
||||
// The Initial Developer of the Original Code is Netscape
|
||||
// Communications Corporation. Portions created by Netscape are
|
||||
// Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
// Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the
|
||||
// terms of the GNU General Public License Version 2 or later (the
|
||||
// "GPL"), in which case the provisions of the GPL are applicable
|
||||
// instead of those above. If you wish to allow use of your
|
||||
// version of this file only under the terms of the GPL and not to
|
||||
// allow others to use your version of this file under the MPL,
|
||||
// indicate your decision by deleting the provisions above and
|
||||
// replace them with the notice and other provisions required by
|
||||
// the GPL. If you do not delete the provisions above, a recipient
|
||||
// may use your version of this file under either the MPL or the
|
||||
// GPL.
|
||||
//
|
||||
|
||||
.text
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val)
|
||||
//
|
||||
// Atomically increment the integer pointed to by 'val' and return
|
||||
// the result of the increment.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicIncrement#
|
||||
.proc _PR_ia64_AtomicIncrement#
|
||||
_PR_ia64_AtomicIncrement:
|
||||
fetchadd4.acq r8 = [r32], 1 ;;
|
||||
adds r8 = 1, r8
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicIncrement#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val)
|
||||
//
|
||||
// Atomically decrement the integer pointed to by 'val' and return
|
||||
// the result of the decrement.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicDecrement#
|
||||
.proc _PR_ia64_AtomicDecrement#
|
||||
_PR_ia64_AtomicDecrement:
|
||||
fetchadd4.rel r8 = [r32], -1 ;;
|
||||
adds r8 = -1, r8
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicDecrement#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
|
||||
//
|
||||
// Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
// and return the result of the addition.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicAdd#
|
||||
.proc _PR_ia64_AtomicAdd#
|
||||
_PR_ia64_AtomicAdd:
|
||||
ld4 r15 = [r32] ;;
|
||||
.L3:
|
||||
mov r14 = r15
|
||||
mov ar.ccv = r15
|
||||
add r8 = r15, r33 ;;
|
||||
cmpxchg4.acq r15 = [r32], r8, ar.ccv ;;
|
||||
cmp4.ne p6, p7 = r15, r14
|
||||
(p6) br.cond.dptk .L3
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicAdd#
|
||||
|
||||
// PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
//
|
||||
// Atomically set the integer pointed to by 'val' to the new
|
||||
// value 'newval' and return the old value.
|
||||
//
|
||||
.align 16
|
||||
.global _PR_ia64_AtomicSet#
|
||||
.proc _PR_ia64_AtomicSet#
|
||||
_PR_ia64_AtomicSet:
|
||||
xchg4 r8 = [r32], r33
|
||||
br.ret.sptk.many b0
|
||||
.endp _PR_ia64_AtomicSet#
|
||||
|
||||
// Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack, "", @progbits ; .previous
|
||||
@@ -0,0 +1,113 @@
|
||||
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public
|
||||
/ License Version 1.1 (the "License"); you may not use this file
|
||||
/ except in compliance with the License. You may obtain a copy of
|
||||
/ the License at http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS
|
||||
/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
/ implied. See the License for the specific language governing
|
||||
/ rights and limitations under the License.
|
||||
/
|
||||
/ The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
/
|
||||
/ The Initial Developer of the Original Code is Netscape
|
||||
/ Communications Corporation. Portions created by Netscape are
|
||||
/ Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
/ Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/
|
||||
|
||||
/ PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val)
|
||||
/
|
||||
/ Atomically increment the integer pointed to by 'val' and return
|
||||
/ the result of the increment.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_AtomicIncrement
|
||||
.align 4
|
||||
_PR_x86_AtomicIncrement:
|
||||
movl 4(%esp), %ecx
|
||||
movl $1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
incl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val)
|
||||
/
|
||||
/ Atomically decrement the integer pointed to by 'val' and return
|
||||
/ the result of the decrement.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_AtomicDecrement
|
||||
.align 4
|
||||
_PR_x86_AtomicDecrement:
|
||||
movl 4(%esp), %ecx
|
||||
movl $-1, %eax
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
decl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
/
|
||||
/ Atomically set the integer pointed to by 'val' to the new
|
||||
/ value 'newval' and return the old value.
|
||||
/
|
||||
/ An alternative implementation:
|
||||
/ .text
|
||||
/ .globl _PR_x86_AtomicSet
|
||||
/ .align 4
|
||||
/_PR_x86_AtomicSet:
|
||||
/ movl 4(%esp), %ecx
|
||||
/ movl 8(%esp), %edx
|
||||
/ movl (%ecx), %eax
|
||||
/retry:
|
||||
/ lock
|
||||
/ cmpxchgl %edx, (%ecx)
|
||||
/ jne retry
|
||||
/ ret
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_AtomicSet
|
||||
.align 4
|
||||
_PR_x86_AtomicSet:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
xchgl %eax, (%ecx)
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val)
|
||||
/
|
||||
/ Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
/ and return the result of the addition.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_AtomicAdd
|
||||
.align 4
|
||||
_PR_x86_AtomicAdd:
|
||||
movl 4(%esp), %ecx
|
||||
movl 8(%esp), %eax
|
||||
movl %eax, %edx
|
||||
lock
|
||||
xaddl %eax, (%ecx)
|
||||
addl %edx, %eax
|
||||
ret
|
||||
|
||||
/ Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack, "", @progbits ; .previous
|
||||
@@ -0,0 +1,94 @@
|
||||
/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public
|
||||
/ License Version 1.1 (the "License"); you may not use this file
|
||||
/ except in compliance with the License. You may obtain a copy of
|
||||
/ the License at http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS
|
||||
/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
/ implied. See the License for the specific language governing
|
||||
/ rights and limitations under the License.
|
||||
/
|
||||
/ The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
/
|
||||
/ The Initial Developer of the Original Code is Netscape
|
||||
/ Communications Corporation. Portions created by Netscape are
|
||||
/ Copyright (C) 2004 Netscape Communications Corporation. All
|
||||
/ Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the
|
||||
/ terms of the GNU General Public License Version 2 or later (the
|
||||
/ "GPL"), in which case the provisions of the GPL are applicable
|
||||
/ instead of those above. If you wish to allow use of your
|
||||
/ version of this file only under the terms of the GPL and not to
|
||||
/ allow others to use your version of this file under the MPL,
|
||||
/ indicate your decision by deleting the provisions above and
|
||||
/ replace them with the notice and other provisions required by
|
||||
/ the GPL. If you do not delete the provisions above, a recipient
|
||||
/ may use your version of this file under either the MPL or the
|
||||
/ GPL.
|
||||
/
|
||||
|
||||
/ PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val)
|
||||
/
|
||||
/ Atomically increment the integer pointed to by 'val' and return
|
||||
/ the result of the increment.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_64_AtomicIncrement
|
||||
.align 4
|
||||
_PR_x86_64_AtomicIncrement:
|
||||
movl $1, %eax
|
||||
lock
|
||||
xaddl %eax, (%rdi)
|
||||
incl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val)
|
||||
/
|
||||
/ Atomically decrement the integer pointed to by 'val' and return
|
||||
/ the result of the decrement.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_64_AtomicDecrement
|
||||
.align 4
|
||||
_PR_x86_64_AtomicDecrement:
|
||||
movl $-1, %eax
|
||||
lock
|
||||
xaddl %eax, (%rdi)
|
||||
decl %eax
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval)
|
||||
/
|
||||
/ Atomically set the integer pointed to by 'val' to the new
|
||||
/ value 'newval' and return the old value.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_64_AtomicSet
|
||||
.align 4
|
||||
_PR_x86_64_AtomicSet:
|
||||
movl %esi, %eax
|
||||
xchgl %eax, (%rdi)
|
||||
ret
|
||||
|
||||
/ PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
|
||||
/
|
||||
/ Atomically add 'val' to the integer pointed to by 'ptr'
|
||||
/ and return the result of the addition.
|
||||
/
|
||||
.text
|
||||
.globl _PR_x86_64_AtomicAdd
|
||||
.align 4
|
||||
_PR_x86_64_AtomicAdd:
|
||||
movl %esi, %eax
|
||||
lock
|
||||
xaddl %eax, (%rdi)
|
||||
addl %esi, %eax
|
||||
ret
|
||||
|
||||
/ Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack, "", @progbits ; .previous
|
||||
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
/* We want position independent code */
|
||||
#define PIC
|
||||
|
||||
#include <sys/asm.h>
|
||||
#include <sys/regdef.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
.file 1 "os_ReliantUNIX.s"
|
||||
.option pic2
|
||||
.text
|
||||
|
||||
.align 2
|
||||
.globl getcxt
|
||||
.ent getcxt
|
||||
getcxt:
|
||||
.frame sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
|
||||
# saved integer regs
|
||||
sw ra,180(a0) # gpregs[CXT_EPC]
|
||||
sw gp,152(a0) # gpregs[CXT_GP]
|
||||
sw sp,156(a0) # gpregs[CXT_SP]
|
||||
sw s8,160(a0) # gpregs[CXT_S8]
|
||||
sw s0,104(a0) # gpregs[CXT_S0]
|
||||
sw s1,108(a0) # gpregs[CXT_S1]
|
||||
sw s2,112(a0) # gpregs[CXT_S2]
|
||||
sw s3,116(a0) # gpregs[CXT_S3]
|
||||
sw s4,120(a0) # gpregs[CXT_S4]
|
||||
sw s5,124(a0) # gpregs[CXT_S5]
|
||||
sw s6,128(a0) # gpregs[CXT_S6]
|
||||
sw s7,132(a0) # gpregs[CXT_S7]
|
||||
# csr
|
||||
cfc1 v0,$31
|
||||
# saved float regs
|
||||
s.d $f20,264(a0) # fpregs.fp_r.fp_dregs[10]
|
||||
s.d $f22,272(a0) # fpregs.fp_r.fp_dregs[11]
|
||||
s.d $f24,280(a0) # fpregs.fp_r.fp_dregs[12]
|
||||
s.d $f26,288(a0) # fpregs.fp_r.fp_dregs[13]
|
||||
s.d $f28,296(a0) # fpregs.fp_r.fp_dregs[14]
|
||||
s.d $f30,304(a0) # fpregs.fp_r.fp_dregs[15]
|
||||
sw v0,312(a0) # fpregs.fp_csr
|
||||
|
||||
# give no illusions about the contents
|
||||
li v0,0x0c # UC_CPU | UC_MAU
|
||||
sw v0,0(a0) # uc_flags
|
||||
|
||||
move v0,zero
|
||||
j ra
|
||||
.end getcxt
|
||||
|
||||
.align 2
|
||||
.globl setcxt
|
||||
.ent setcxt
|
||||
setcxt:
|
||||
.frame sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
|
||||
lw v0,312(a0) # fpregs.fp_csr
|
||||
li v1,0xfffc0fff # mask out exception cause bits
|
||||
and v0,v0,v1
|
||||
# saved integer regs
|
||||
lw t9,180(a0) # gpregs[CXT_EPC]
|
||||
lw ra,180(a0) # gpregs[CXT_EPC]
|
||||
lw gp,152(a0) # gpregs[CXT_GP]
|
||||
lw sp,156(a0) # gpregs[CXT_SP]
|
||||
ctc1 v0,$31 # fp_csr
|
||||
lw s8,160(a0) # gpregs[CXT_S8]
|
||||
lw s0,104(a0) # gpregs[CXT_S0]
|
||||
lw s1,108(a0) # gpregs[CXT_S1]
|
||||
lw s2,112(a0) # gpregs[CXT_S2]
|
||||
lw s3,116(a0) # gpregs[CXT_S3]
|
||||
lw s4,120(a0) # gpregs[CXT_S4]
|
||||
lw s5,124(a0) # gpregs[CXT_S5]
|
||||
lw s6,128(a0) # gpregs[CXT_S6]
|
||||
lw s7,132(a0) # gpregs[CXT_S7]
|
||||
# saved float regs
|
||||
l.d $f20,264(a0) # fpregs.fp_r.fp_dregs[10]
|
||||
l.d $f22,272(a0) # fpregs.fp_r.fp_dregs[11]
|
||||
l.d $f24,280(a0) # fpregs.fp_r.fp_dregs[12]
|
||||
l.d $f26,288(a0) # fpregs.fp_r.fp_dregs[13]
|
||||
l.d $f28,296(a0) # fpregs.fp_r.fp_dregs[14]
|
||||
l.d $f30,304(a0) # fpregs.fp_r.fp_dregs[15]
|
||||
|
||||
# load these, too
|
||||
# they were not saved, but maybe the user modified them...
|
||||
lw v0,48(a0)
|
||||
lw v1,52(a0)
|
||||
lw a1,60(a0)
|
||||
lw a2,64(a0)
|
||||
lw a3,68(a0)
|
||||
lw a0,56(a0) # there is no way back
|
||||
|
||||
j ra
|
||||
|
||||
.end setcxt
|
||||
@@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* sol_getsp()
|
||||
*
|
||||
* Return the current sp (for debugging)
|
||||
*/
|
||||
.global sol_getsp
|
||||
sol_getsp:
|
||||
retl
|
||||
mov %sp, %o0
|
||||
|
||||
|
||||
/*
|
||||
* sol_curthread()
|
||||
*
|
||||
* Return a unique identifier for the currently active thread.
|
||||
*/
|
||||
.global sol_curthread
|
||||
sol_curthread:
|
||||
retl
|
||||
mov %g7, %o0
|
||||
|
||||
|
||||
.global __MD_FlushRegisterWindows
|
||||
.global _MD_FlushRegisterWindows
|
||||
|
||||
__MD_FlushRegisterWindows:
|
||||
_MD_FlushRegisterWindows:
|
||||
|
||||
ta 3
|
||||
ret
|
||||
restore
|
||||
|
||||
Loaded 100 of 1137 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user