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:
Brian West committed 2006-12-18 15:53:47 +00:00
1 parent 855c7b9a77
commit fff98f6316
1137 files changed
+386873

No files matched your search

+1
View File
@@ -0,0 +1 @@
Makefile
+4
View File
@@ -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////
+1
View File
@@ -0,0 +1 @@
mozilla/nsprpub/pr/src/md
+1
View File
@@ -0,0 +1 @@
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+64
View File
@@ -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
+1
View File
@@ -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)
+55
View File
@@ -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);
+264
View File
@@ -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
+902
View File
@@ -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;
}
+42
View File
@@ -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);
+123
View File
@@ -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;
}
+73
View File
@@ -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;
}
+929
View File
@@ -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 */
+237
View File
@@ -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;
}
+69
View File
@@ -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() */
+54
View File
@@ -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)
{
}
+54
View File
@@ -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)
+75
View File
@@ -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;
}
+43
View File
@@ -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))
+18
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+7
View File
@@ -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
+587
View File
@@ -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;
}
+57
View File
@@ -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
+51
View File
@@ -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__ */
+52
View File
@@ -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));
}
+238
View File
@@ -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
+721
View File
@@ -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);
}
}
+253
View File
@@ -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(&currentTime);
/*
* 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);
}
+51
View File
@@ -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___ */
+776
View File
@@ -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;
}
+51
View File
@@ -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__ */
+136
View File
@@ -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___ */
+1
View File
@@ -0,0 +1 @@
Makefile
+18
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+85
View File
@@ -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)
+65
View File
@@ -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
+432
View File
@@ -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;
}
+110
View File
@@ -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
+90
View File
@@ -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;
}
+112
View File
@@ -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(&timestamp);
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;
}
}
+983
View File
@@ -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;
}
}
}
+566
View File
@@ -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;
}
+382
View File
@@ -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;
}
+110
View File
@@ -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;
}
+93
View File
@@ -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);
}
+684
View File
@@ -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);
}
}
+407
View File
@@ -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
+266
View File
@@ -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
+115
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+135
View File
@@ -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
+333
View File
@@ -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 */
+65
View File
@@ -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 */
+119
View File
@@ -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 */
+110
View File
@@ -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 */
+109
View File
@@ -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.");
}
+119
View File
@@ -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 */
+261
View File
@@ -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
+123
View File
@@ -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 */
+395
View File
@@ -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
+100
View File
@@ -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;
}
+121
View File
@@ -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 */
+284
View File
@@ -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
+66
View File
@@ -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
}
+63
View File
@@ -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)))
+121
View File
@@ -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 */
+286
View File
@@ -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,&regs[0],0);
if (res==0)
thr_id->sp = (void *) regs[30];
thr_id->suspend |= PT_THREAD_SUSPENDED;
/* Always succeeds */
return 0;
}
int thread_resume(PRThread *thr_id) {
extern int pthread_resume_np(pthread_t thread);
int res;
res = pthread_resume_np (thr_id->id);
thr_id->suspend |= PT_THREAD_RESUMED;
return 0;
}
/*
** 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) { }
+119
View File
@@ -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
+54
View File
@@ -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#
+163
View File
@@ -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
+68
View File
@@ -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