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
+28
View File
@@ -0,0 +1,28 @@
/.cvsignore/1.2/Sat May 12 04:52:36 2001//
/Makefile.in/1.19/Mon Nov 8 02:52:56 2004//
/compile-et.pl/3.9/Sun Apr 25 15:01:01 2004//
/pralarm.c/3.8/Sun Apr 25 15:01:01 2004//
/pratom.c/3.18/Sun Apr 25 15:01:01 2004//
/prcountr.c/3.8/Sun Apr 25 15:01:01 2004//
/prdtoa.c/4.3/Fri Jul 1 01:19:30 2005//
/prenv.c/3.11/Sun Apr 25 15:01:01 2004//
/prerr.c/3.10/Sun Apr 25 15:01:01 2004//
/prerr.et/3.7/Wed Feb 2 22:27:58 2005//
/prerr.properties/3.7/Sun Apr 25 15:01:01 2004//
/prerror.c/3.10/Sun Apr 25 15:01:01 2004//
/prerrortable.c/3.8/Sun Apr 25 15:01:01 2004//
/prinit.c/3.44/Fri Oct 21 18:21:43 2005//
/prinrval.c/3.9/Sun Apr 25 15:01:01 2004//
/pripc.c/3.5/Sun Apr 25 15:01:01 2004//
/pripcsem.c/3.5/Sun Apr 25 15:01:01 2004//
/prlog2.c/3.5/Sun Apr 25 15:01:01 2004//
/prlong.c/3.6/Sun Apr 25 15:01:01 2004//
/prnetdb.c/3.48/Sat Dec 24 08:25:30 2005//
/prolock.c/3.8/Sun Apr 25 15:01:01 2004//
/prrng.c/1.7/Sun Apr 25 15:01:01 2004//
/prsystem.c/3.28/Thu Jan 19 22:11:59 2006//
/prthinfo.c/3.10/Mon Nov 7 22:39:01 2005//
/prtime.c/3.23/Mon Jan 9 22:48:25 2006//
/prtpool.c/3.9/Thu Apr 28 22:37:25 2005//
/prtrace.c/3.8/Sun Apr 25 15:01:01 2004//
D
@@ -0,0 +1 @@
mozilla/nsprpub/pr/src/misc
+1
View File
@@ -0,0 +1 @@
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+111
View File
@@ -0,0 +1,111 @@
#
# ***** 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
CSRCS = \
pralarm.c \
pratom.c \
prcountr.c \
prdtoa.c \
prenv.c \
prerr.c \
prerror.c \
prerrortable.c \
prinit.c \
prinrval.c \
pripc.c \
prlog2.c \
prlong.c \
prnetdb.c \
prolock.c \
prrng.c \
prsystem.c \
prtime.c \
prthinfo.c \
prtpool.c \
prtrace.c \
$(NULL)
ifndef USE_PTHREADS
CSRCS += \
pripcsem.c \
$(NULL)
endif
TARGETS = $(OBJS)
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
DEFINES += -D_NSPR_BUILD_
RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties
include $(topsrcdir)/config/rules.mk
# Prevent floating point errors caused by MSVC 6.0 Processor Pack
# optimizations (bug 207421). This disables optimizations that
# could change the precision of floating-point calculations for
# this single compilation unit.
ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
$(OBJDIR)/prdtoa.$(OBJ_SUFFIX): prdtoa.c
@$(MAKE_OBJDIR)
ifeq (,$(filter-out 1100 1200 1300 1310,$(MSC_VER)))
$(CC) -Fo$@ -c $(CFLAGS) -Op $(call abspath,$<)
else
$(CC) -Fo$@ -c $(CFLAGS) -fp:precise $(call abspath,$<)
endif
endif
#
# Generate prerr.h, prerr.c, and prerr.properties from prerr.et.
#
build_prerr:
cd $(srcdir); $(PERL) compile-et.pl prerr.et
export:: $(TARGETS)
+140
View File
@@ -0,0 +1,140 @@
#!/usr/bin/perl
# usage: compile-et input.et
#
# ***** 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 *****
sub header
{
local($filename, $comment) = @_;
<<EOF
$comment
$comment $filename
$comment This file is automatically generated; please do not edit it.
EOF
}
sub table_base
{
local($name) = @_;
local($base) = 0;
for ($i = 0; $i < length($name); $i++) {
$base *= 64;
$base += index("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", substr($name, $i, 1)) + 1;
}
$base -= 0x1000000 if ($base > 0x7fffff);
$base*256;
}
sub code {
local($macro, $text) = @_;
$code = $table_base + $table_item_count;
print H "\n";
print H "/* ", $text, " */\n";
printf H "#define %-40s (%dL)\n", $macro, $code;
print C "\t{\"", $macro, "\", \"", $text, "\"},\n";
print PROPERTIES $macro, "=", $text, "\n";
$table_item_count++;
}
$filename = $ARGV[0];
open(INPUT, "< $filename") || die "Can't read $filename: $!\n";
$base = "$filename";
$base =~ s/\.et$//;
$base =~ s#.*/##;
open(H, "> ${base}.h") || die "Can't write ${base}.h\n";
open(C, "> ${base}.c") || die "Can't write ${base}.c\n";
open(PROPERTIES, "> ${base}.properties") || die "Can't write ${base}.properties\n";
print H "/*\n", &header("${base}.h", " *"), " */\n";
print C "/*\n", &header("${base}.c", " *"), " */\n";
print PROPERTIES &header("${base}.properties", "#");
$skipone = 0;
while ($_ = <INPUT>) {
next if /^#/;
if (/^[ \t]*(error_table|et)[ \t]+([a-zA-Z][a-zA-Z0-9_]+) *(-?[0-9]*)/) {
$table_name = $2;
if ($3) {
$table_base = $3;
}
else {
$table_base = &table_base($table_name);
}
$table_item_count = 0;
print C "#include \"prerror.h\"\n";
print C "static const struct PRErrorMessage text[] = {\n";
}
elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*$/) {
$skipone = 1;
$macro = $2;
}
elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*"(.*)"[ \t]*$/) {
&code($2, $3);
}
elsif ($skipone && /^[ \t]*"(.*)"[ \t]*$/) {
&code($macro, $1);
}
}
print H "\n";
print H "extern void ", $table_name, "_InitializePRErrorTable","(void);\n";
printf H "#define ERROR_TABLE_BASE_%s (%dL)\n", $table_name, $table_base;
print C "\t{0, 0}\n";
print C "};\n\n";
printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n",
$base, $table_base, $table_item_count;
print C "\n";
print C "void ", $table_name, "_InitializePRErrorTable", "(void) {\n";
print C " PR_ErrorInstallTable(&et);\n";
print C "}\n";
0;
+282
View File
@@ -0,0 +1,282 @@
/* -*- 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"
/**********************************************************************/
/******************************* PRALARM ******************************/
/**********************************************************************/
#ifdef XP_MAC
#include "pralarm.h"
#else
#include "obsolete/pralarm.h"
#endif
struct PRAlarmID { /* typedef'd in pralarm.h */
PRCList list; /* circular list linkage */
PRAlarm *alarm; /* back pointer to owning alarm */
PRPeriodicAlarmFn function; /* function to call for notify */
void *clientData; /* opaque client context */
PRIntervalTime period; /* the client defined period */
PRUint32 rate; /* rate of notification */
PRUint32 accumulator; /* keeps track of # notifies */
PRIntervalTime epoch; /* when timer was started */
PRIntervalTime nextNotify; /* when we'll next do our thing */
PRIntervalTime lastNotify; /* when we last did our thing */
};
typedef enum {alarm_active, alarm_inactive} _AlarmState;
struct PRAlarm { /* typedef'd in pralarm.h */
PRCList timers; /* base of alarm ids list */
PRLock *lock; /* lock used to protect data */
PRCondVar *cond; /* condition that used to wait */
PRThread *notifier; /* thread to deliver notifies */
PRAlarmID *current; /* current alarm being served */
_AlarmState state; /* used to delete the alarm */
};
static PRAlarmID *pr_getNextAlarm(PRAlarm *alarm, PRAlarmID *id)
{
/*
* Puts 'id' back into the sorted list iff it's not NULL.
* Removes the first element from the list and returns it (or NULL).
* List is "assumed" to be short.
*
* NB: Caller is providing locking
*/
PRCList *timer;
PRAlarmID *result = id;
PRIntervalTime now = PR_IntervalNow();
if (!PR_CLIST_IS_EMPTY(&alarm->timers))
{
if (id != NULL) /* have to put this id back in */
{
PRIntervalTime idDelta = now - id->nextNotify;
timer = alarm->timers.next;
do
{
result = (PRAlarmID*)timer;
if ((PRIntervalTime)(now - result->nextNotify) > idDelta)
{
PR_INSERT_BEFORE(&id->list, &alarm->timers);
break;
}
timer = timer->next;
} while (timer != &alarm->timers);
}
result = (PRAlarmID*)(timer = PR_LIST_HEAD(&alarm->timers));
PR_REMOVE_LINK(timer); /* remove it from the list */
}
return result;
} /* pr_getNextAlarm */
static PRIntervalTime pr_PredictNextNotifyTime(PRAlarmID *id)
{
PRIntervalTime delta;
PRFloat64 baseRate = (PRFloat64)id->period / (PRFloat64)id->rate;
PRFloat64 offsetFromEpoch = (PRFloat64)id->accumulator * baseRate;
id->accumulator += 1; /* every call advances to next period */
id->lastNotify = id->nextNotify; /* just keeping track of things */
id->nextNotify = (PRIntervalTime)(offsetFromEpoch + 0.5);
delta = id->nextNotify - id->lastNotify;
return delta;
} /* pr_PredictNextNotifyTime */
static void PR_CALLBACK pr_alarmNotifier(void *arg)
{
/*
* This is the root of the notifier thread. There is one such thread
* for each PRAlarm. It may service an arbitrary (though assumed to be
* small) number of alarms using the same thread and structure. It
* continues to run until the alarm is destroyed.
*/
PRAlarmID *id = NULL;
PRAlarm *alarm = (PRAlarm*)arg;
enum {notify, abort, scan} why = scan;
while (why != abort)
{
PRIntervalTime pause;
PR_Lock(alarm->lock);
while (why == scan)
{
alarm->current = NULL; /* reset current id */
if (alarm->state == alarm_inactive) why = abort; /* we're toast */
else if (why == scan) /* the dominant case */
{
id = pr_getNextAlarm(alarm, id); /* even if it's the same */
if (id == NULL) /* there are no alarms set */
(void)PR_WaitCondVar(alarm->cond, PR_INTERVAL_NO_TIMEOUT);
else
{
pause = id->nextNotify - (PR_IntervalNow() - id->epoch);
if ((PRInt32)pause <= 0) /* is this one's time up? */
{
why = notify; /* set up to do our thing */
alarm->current = id; /* id we're about to schedule */
}
else
(void)PR_WaitCondVar(alarm->cond, pause); /* dally */
}
}
}
PR_Unlock(alarm->lock);
if (why == notify)
{
(void)pr_PredictNextNotifyTime(id);
if (!id->function(id, id->clientData, ~pause))
{
/*
* Notified function decided not to continue. Free
* the alarm id to make sure it doesn't get back on
* the list.
*/
PR_DELETE(id); /* free notifier object */
id = NULL; /* so it doesn't get back into the list */
}
why = scan; /* so we can cycle through the loop again */
}
}
} /* pr_alarm_notifier */
PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm(void)
{
PRAlarm *alarm = PR_NEWZAP(PRAlarm);
if (alarm != NULL)
{
if ((alarm->lock = PR_NewLock()) == NULL) goto done;
if ((alarm->cond = PR_NewCondVar(alarm->lock)) == NULL) goto done;
alarm->state = alarm_active;
PR_INIT_CLIST(&alarm->timers);
alarm->notifier = PR_CreateThread(
PR_USER_THREAD, pr_alarmNotifier, alarm,
PR_GetThreadPriority(PR_GetCurrentThread()),
PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
if (alarm->notifier == NULL) goto done;
}
return alarm;
done:
if (alarm->cond != NULL) PR_DestroyCondVar(alarm->cond);
if (alarm->lock != NULL) PR_DestroyLock(alarm->lock);
PR_DELETE(alarm);
return NULL;
} /* CreateAlarm */
PR_IMPLEMENT(PRStatus) PR_DestroyAlarm(PRAlarm *alarm)
{
PRStatus rv;
PR_Lock(alarm->lock);
alarm->state = alarm_inactive;
rv = PR_NotifyCondVar(alarm->cond);
PR_Unlock(alarm->lock);
if (rv == PR_SUCCESS)
rv = PR_JoinThread(alarm->notifier);
if (rv == PR_SUCCESS)
{
PR_DestroyCondVar(alarm->cond);
PR_DestroyLock(alarm->lock);
PR_DELETE(alarm);
}
return rv;
} /* PR_DestroyAlarm */
PR_IMPLEMENT(PRAlarmID*) PR_SetAlarm(
PRAlarm *alarm, PRIntervalTime period, PRUint32 rate,
PRPeriodicAlarmFn function, void *clientData)
{
/*
* Create a new periodic alarm an existing current structure.
* Set up the context and compute the first notify time (immediate).
* Link the new ID into the head of the list (since it's notifying
* immediately).
*/
PRAlarmID *id = PR_NEWZAP(PRAlarmID);
if (!id)
return NULL;
id->alarm = alarm;
PR_INIT_CLIST(&id->list);
id->function = function;
id->clientData = clientData;
id->period = period;
id->rate = rate;
id->epoch = id->nextNotify = PR_IntervalNow();
(void)pr_PredictNextNotifyTime(id);
PR_Lock(alarm->lock);
PR_INSERT_BEFORE(&id->list, &alarm->timers);
PR_NotifyCondVar(alarm->cond);
PR_Unlock(alarm->lock);
return id;
} /* PR_SetAlarm */
PR_IMPLEMENT(PRStatus) PR_ResetAlarm(
PRAlarmID *id, PRIntervalTime period, PRUint32 rate)
{
/*
* Can only be called from within the notify routine. Doesn't
* need locking because it can only be called from within the
* notify routine.
*/
if (id != id->alarm->current)
return PR_FAILURE;
id->period = period;
id->rate = rate;
id->accumulator = 1;
id->epoch = PR_IntervalNow();
(void)pr_PredictNextNotifyTime(id);
return PR_SUCCESS;
} /* PR_ResetAlarm */
+409
View File
@@ -0,0 +1,409 @@
/* -*- 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 ***** */
/*
** PR Atomic operations
*/
#include "pratom.h"
#include "primpl.h"
#include <string.h>
/*
* The following is a fallback implementation that emulates
* atomic operations for platforms without atomic operations.
* If a platform has atomic operations, it should define the
* macro _PR_HAVE_ATOMIC_OPS, and the following will not be
* compiled in.
*/
#if !defined(_PR_HAVE_ATOMIC_OPS)
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
/*
* PR_AtomicDecrement() is used in NSPR's thread-specific data
* destructor. Because thread-specific data destructors may be
* invoked after a PR_Cleanup() call, we need an implementation
* of the atomic routines that doesn't need NSPR to be initialized.
*/
/*
* We use a set of locks for all the emulated atomic operations.
* By hashing on the address of the integer to be locked the
* contention between multiple threads should be lessened.
*
* The number of atomic locks can be set by the environment variable
* NSPR_ATOMIC_HASH_LOCKS
*/
/*
* lock counts should be a power of 2
*/
#define DEFAULT_ATOMIC_LOCKS 16 /* should be in sync with the number of initializers
below */
#define MAX_ATOMIC_LOCKS (4 * 1024)
static pthread_mutex_t static_atomic_locks[DEFAULT_ATOMIC_LOCKS] = {
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
#ifdef DEBUG
static PRInt32 static_hash_lock_counts[DEFAULT_ATOMIC_LOCKS];
static PRInt32 *hash_lock_counts = static_hash_lock_counts;
#endif
static PRUint32 num_atomic_locks = DEFAULT_ATOMIC_LOCKS;
static pthread_mutex_t *atomic_locks = static_atomic_locks;
static PRUint32 atomic_hash_mask = DEFAULT_ATOMIC_LOCKS - 1;
#define _PR_HASH_FOR_LOCK(ptr) \
((PRUint32) (((PRUptrdiff) (ptr) >> 2) ^ \
((PRUptrdiff) (ptr) >> 8)) & \
atomic_hash_mask)
void _PR_MD_INIT_ATOMIC()
{
char *eval;
int index;
PR_ASSERT(PR_FloorLog2(MAX_ATOMIC_LOCKS) ==
PR_CeilingLog2(MAX_ATOMIC_LOCKS));
PR_ASSERT(PR_FloorLog2(DEFAULT_ATOMIC_LOCKS) ==
PR_CeilingLog2(DEFAULT_ATOMIC_LOCKS));
if (((eval = getenv("NSPR_ATOMIC_HASH_LOCKS")) != NULL) &&
((num_atomic_locks = atoi(eval)) != DEFAULT_ATOMIC_LOCKS)) {
if (num_atomic_locks > MAX_ATOMIC_LOCKS)
num_atomic_locks = MAX_ATOMIC_LOCKS;
else {
num_atomic_locks = PR_FloorLog2(num_atomic_locks);
num_atomic_locks = 1L << num_atomic_locks;
}
atomic_locks = (pthread_mutex_t *) PR_Malloc(sizeof(pthread_mutex_t) *
num_atomic_locks);
if (atomic_locks) {
for (index = 0; index < num_atomic_locks; index++) {
if (pthread_mutex_init(&atomic_locks[index], NULL)) {
PR_DELETE(atomic_locks);
atomic_locks = NULL;
break;
}
}
}
#ifdef DEBUG
if (atomic_locks) {
hash_lock_counts = PR_CALLOC(num_atomic_locks * sizeof(PRInt32));
if (hash_lock_counts == NULL) {
PR_DELETE(atomic_locks);
atomic_locks = NULL;
}
}
#endif
if (atomic_locks == NULL) {
/*
* Use statically allocated locks
*/
atomic_locks = static_atomic_locks;
num_atomic_locks = DEFAULT_ATOMIC_LOCKS;
#ifdef DEBUG
hash_lock_counts = static_hash_lock_counts;
#endif
}
atomic_hash_mask = num_atomic_locks - 1;
}
PR_ASSERT(PR_FloorLog2(num_atomic_locks) ==
PR_CeilingLog2(num_atomic_locks));
}
PRInt32
_PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
{
PRInt32 rv;
PRInt32 idx = _PR_HASH_FOR_LOCK(val);
pthread_mutex_lock(&atomic_locks[idx]);
rv = ++(*val);
#ifdef DEBUG
hash_lock_counts[idx]++;
#endif
pthread_mutex_unlock(&atomic_locks[idx]);
return rv;
}
PRInt32
_PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
{
PRInt32 rv;
PRInt32 idx = _PR_HASH_FOR_LOCK(ptr);
pthread_mutex_lock(&atomic_locks[idx]);
rv = ((*ptr) += val);
#ifdef DEBUG
hash_lock_counts[idx]++;
#endif
pthread_mutex_unlock(&atomic_locks[idx]);
return rv;
}
PRInt32
_PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
PRInt32 rv;
PRInt32 idx = _PR_HASH_FOR_LOCK(val);
pthread_mutex_lock(&atomic_locks[idx]);
rv = --(*val);
#ifdef DEBUG
hash_lock_counts[idx]++;
#endif
pthread_mutex_unlock(&atomic_locks[idx]);
return rv;
}
PRInt32
_PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
{
PRInt32 rv;
PRInt32 idx = _PR_HASH_FOR_LOCK(val);
pthread_mutex_lock(&atomic_locks[idx]);
rv = *val;
*val = newval;
#ifdef DEBUG
hash_lock_counts[idx]++;
#endif
pthread_mutex_unlock(&atomic_locks[idx]);
return rv;
}
#else /* _PR_PTHREADS && !_PR_DCETHREADS */
/*
* We use a single lock for all the emulated atomic operations.
* The lock contention should be acceptable.
*/
static PRLock *atomic_lock = NULL;
void _PR_MD_INIT_ATOMIC(void)
{
if (atomic_lock == NULL) {
atomic_lock = PR_NewLock();
}
}
PRInt32
_PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
{
PRInt32 rv;
if (!_pr_initialized) {
_PR_ImplicitInitialization();
}
PR_Lock(atomic_lock);
rv = ++(*val);
PR_Unlock(atomic_lock);
return rv;
}
PRInt32
_PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
{
PRInt32 rv;
if (!_pr_initialized) {
_PR_ImplicitInitialization();
}
PR_Lock(atomic_lock);
rv = ((*ptr) += val);
PR_Unlock(atomic_lock);
return rv;
}
PRInt32
_PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
PRInt32 rv;
if (!_pr_initialized) {
_PR_ImplicitInitialization();
}
PR_Lock(atomic_lock);
rv = --(*val);
PR_Unlock(atomic_lock);
return rv;
}
PRInt32
_PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
{
PRInt32 rv;
if (!_pr_initialized) {
_PR_ImplicitInitialization();
}
PR_Lock(atomic_lock);
rv = *val;
*val = newval;
PR_Unlock(atomic_lock);
return rv;
}
#endif /* _PR_PTHREADS && !_PR_DCETHREADS */
#endif /* !_PR_HAVE_ATOMIC_OPS */
void _PR_InitAtomic(void)
{
_PR_MD_INIT_ATOMIC();
}
PR_IMPLEMENT(PRInt32)
PR_AtomicIncrement(PRInt32 *val)
{
return _PR_MD_ATOMIC_INCREMENT(val);
}
PR_IMPLEMENT(PRInt32)
PR_AtomicDecrement(PRInt32 *val)
{
return _PR_MD_ATOMIC_DECREMENT(val);
}
PR_IMPLEMENT(PRInt32)
PR_AtomicSet(PRInt32 *val, PRInt32 newval)
{
return _PR_MD_ATOMIC_SET(val, newval);
}
PR_IMPLEMENT(PRInt32)
PR_AtomicAdd(PRInt32 *ptr, PRInt32 val)
{
return _PR_MD_ATOMIC_ADD(ptr, val);
}
/*
* For platforms, which don't support the CAS (compare-and-swap) instruction
* (or an equivalent), the stack operations are implemented by use of PRLock
*/
PR_IMPLEMENT(PRStack *)
PR_CreateStack(const char *stack_name)
{
PRStack *stack;
if (!_pr_initialized) {
_PR_ImplicitInitialization();
}
if ((stack = PR_NEW(PRStack)) == NULL) {
return NULL;
}
if (stack_name) {
stack->prstk_name = (char *) PR_Malloc(strlen(stack_name) + 1);
if (stack->prstk_name == NULL) {
PR_DELETE(stack);
return NULL;
}
strcpy(stack->prstk_name, stack_name);
} else
stack->prstk_name = NULL;
#ifndef _PR_HAVE_ATOMIC_CAS
stack->prstk_lock = PR_NewLock();
if (stack->prstk_lock == NULL) {
PR_Free(stack->prstk_name);
PR_DELETE(stack);
return NULL;
}
#endif /* !_PR_HAVE_ATOMIC_CAS */
stack->prstk_head.prstk_elem_next = NULL;
return stack;
}
PR_IMPLEMENT(PRStatus)
PR_DestroyStack(PRStack *stack)
{
if (stack->prstk_head.prstk_elem_next != NULL) {
PR_SetError(PR_INVALID_STATE_ERROR, 0);
return PR_FAILURE;
}
if (stack->prstk_name)
PR_Free(stack->prstk_name);
#ifndef _PR_HAVE_ATOMIC_CAS
PR_DestroyLock(stack->prstk_lock);
#endif /* !_PR_HAVE_ATOMIC_CAS */
PR_DELETE(stack);
return PR_SUCCESS;
}
#ifndef _PR_HAVE_ATOMIC_CAS
PR_IMPLEMENT(void)
PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
{
PR_Lock(stack->prstk_lock);
stack_elem->prstk_elem_next = stack->prstk_head.prstk_elem_next;
stack->prstk_head.prstk_elem_next = stack_elem;
PR_Unlock(stack->prstk_lock);
return;
}
PR_IMPLEMENT(PRStackElem *)
PR_StackPop(PRStack *stack)
{
PRStackElem *element;
PR_Lock(stack->prstk_lock);
element = stack->prstk_head.prstk_elem_next;
if (element != NULL) {
stack->prstk_head.prstk_elem_next = element->prstk_elem_next;
element->prstk_elem_next = NULL; /* debugging aid */
}
PR_Unlock(stack->prstk_lock);
return element;
}
#endif /* !_PR_HAVE_ATOMIC_CAS */
+506
View File
@@ -0,0 +1,506 @@
/* -*- 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 ***** */
/*
** prcountr.c -- NSPR Instrumentation Counters
**
** Implement the interface defined in prcountr.h
**
** Design Notes:
**
** The Counter Facility (CF) has a single anchor: qNameList.
** The anchor is a PRCList. qNameList is a list of links in QName
** structures. From qNameList any QName structure and its
** associated RName structure can be located.
**
** For each QName, a list of RName structures is anchored at
** rnLink in the QName structure.
**
** The counter itself is embedded in the RName structure.
**
** For manipulating the counter database, single lock is used to
** protect the entire list: counterLock.
**
** A PRCounterHandle, defined in prcountr.h, is really a pointer
** to a RName structure. References by PRCounterHandle are
** dead-reconed to the RName structure. The PRCounterHandle is
** "overloaded" for traversing the QName structures; only the
** function PR_FindNextQnameHandle() uses this overloading.
**
**
** ToDo (lth): decide on how to lock or atomically update
** individual counters. Candidates are: the global lock; a lock
** per RName structure; Atomic operations (Note that there are
** not adaquate atomic operations (yet) to achieve this goal). At
** this writing (6/19/98) , the update of the counter variable in
** a QName structure is unprotected.
**
*/
#include "prcountr.h"
#include "prclist.h"
#include "prlock.h"
#include "prlog.h"
#include "prmem.h"
#include <string.h>
/*
**
*/
typedef struct QName
{
PRCList link;
PRCList rNameList;
char name[PRCOUNTER_NAME_MAX+1];
} QName;
/*
**
*/
typedef struct RName
{
PRCList link;
QName *qName;
PRLock *lock;
volatile PRUint32 counter;
char name[PRCOUNTER_NAME_MAX+1];
char desc[PRCOUNTER_DESC_MAX+1];
} RName;
/*
** Define the Counter Facility database
*/
static PRLock *counterLock;
static PRCList qNameList;
static PRLogModuleInfo *lm;
/*
** _PR_CounterInitialize() -- Initialize the Counter Facility
**
*/
static void _PR_CounterInitialize( void )
{
/*
** This function should be called only once
*/
PR_ASSERT( counterLock == NULL );
counterLock = PR_NewLock();
PR_INIT_CLIST( &qNameList );
lm = PR_NewLogModule("counters");
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete"));
return;
} /* end _PR_CounterInitialize() */
/*
** PR_CreateCounter() -- Create a counter
**
** ValidateArguments
** Lock
** if (qName not already in database)
** NewQname
** if (rName already in database )
** Assert
** else NewRname
** NewCounter
** link 'em up
** Unlock
**
*/
PR_IMPLEMENT(PRCounterHandle)
PR_CreateCounter(
const char *qName,
const char *rName,
const char *description
)
{
QName *qnp;
RName *rnp;
PRBool matchQname = PR_FALSE;
/* Self initialize, if necessary */
if ( counterLock == NULL )
_PR_CounterInitialize();
/* Validate input arguments */
PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX );
PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX );
PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX );
/* Lock the Facility */
PR_Lock( counterLock );
/* Do we already have a matching QName? */
if (!PR_CLIST_IS_EMPTY( &qNameList ))
{
qnp = (QName *) PR_LIST_HEAD( &qNameList );
do {
if ( strcmp(qnp->name, qName) == 0)
{
matchQname = PR_TRUE;
break;
}
qnp = (QName *)PR_NEXT_LINK( &qnp->link );
} while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
}
/*
** If we did not find a matching QName,
** allocate one and initialize it.
** link it onto the qNameList.
**
*/
if ( matchQname != PR_TRUE )
{
qnp = PR_NEWZAP( QName );
PR_ASSERT( qnp != NULL );
PR_INIT_CLIST( &qnp->link );
PR_INIT_CLIST( &qnp->rNameList );
strcpy( qnp->name, qName );
PR_APPEND_LINK( &qnp->link, &qNameList );
}
/* Do we already have a matching RName? */
if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
{
rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
do {
/*
** No duplicate RNames are allowed within a QName
**
*/
PR_ASSERT( strcmp(rnp->name, rName));
rnp = (RName *)PR_NEXT_LINK( &rnp->link );
} while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
}
/* Get a new RName structure; initialize its members */
rnp = PR_NEWZAP( RName );
PR_ASSERT( rnp != NULL );
PR_INIT_CLIST( &rnp->link );
strcpy( rnp->name, rName );
strcpy( rnp->desc, description );
rnp->lock = PR_NewLock();
if ( rnp->lock == NULL )
{
PR_ASSERT(0);
}
PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
rnp->qName = qnp; /* point the RName to the QName */
/* Unlock the Facility */
PR_Unlock( counterLock );
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t",
qName, qnp, rName, rnp ));
return((PRCounterHandle)rnp);
} /* end PR_CreateCounter() */
/*
**
*/
PR_IMPLEMENT(void)
PR_DestroyCounter(
PRCounterHandle handle
)
{
RName *rnp = (RName *)handle;
QName *qnp = rnp->qName;
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s",
qnp->name, rnp->name));
/* Lock the Facility */
PR_Lock( counterLock );
/*
** Remove RName from the list of RNames in QName
** and free RName
*/
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p",
rnp->name, rnp));
PR_REMOVE_LINK( &rnp->link );
PR_Free( rnp->lock );
PR_DELETE( rnp );
/*
** If this is the last RName within QName
** remove QName from the qNameList and free it
*/
if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
{
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p",
qnp->name, qnp));
PR_REMOVE_LINK( &qnp->link );
PR_DELETE( qnp );
}
/* Unlock the Facility */
PR_Unlock( counterLock );
return;
} /* end PR_DestroyCounter() */
/*
**
*/
PR_IMPLEMENT(PRCounterHandle)
PR_GetCounterHandleFromName(
const char *qName,
const char *rName
)
{
const char *qn, *rn, *desc;
PRCounterHandle qh, rh = NULL;
RName *rnp = NULL;
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t"
"QName: %s, RName: %s", qName, rName ));
qh = PR_FindNextCounterQname( NULL );
while (qh != NULL)
{
rh = PR_FindNextCounterRname( NULL, qh );
while ( rh != NULL )
{
PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc );
if ( (strcmp( qName, qn ) == 0)
&& (strcmp( rName, rn ) == 0 ))
{
rnp = (RName *)rh;
goto foundIt;
}
rh = PR_FindNextCounterRname( rh, qh );
}
qh = PR_FindNextCounterQname( NULL );
}
foundIt:
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
return(rh);
} /* end PR_GetCounterHandleFromName() */
/*
**
*/
PR_IMPLEMENT(void)
PR_GetCounterNameFromHandle(
PRCounterHandle handle,
const char **qName,
const char **rName,
const char **description
)
{
RName *rnp = (RName *)handle;
QName *qnp = rnp->qName;
*qName = qnp->name;
*rName = rnp->name;
*description = rnp->desc;
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: "
"QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
qnp, rnp, qnp->name, rnp->name, rnp->desc ));
return;
} /* end PR_GetCounterNameFromHandle() */
/*
**
*/
PR_IMPLEMENT(void)
PR_IncrementCounter(
PRCounterHandle handle
)
{
PR_Lock(((RName *)handle)->lock);
((RName *)handle)->counter++;
PR_Unlock(((RName *)handle)->lock);
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld",
handle, ((RName *)handle)->counter ));
return;
} /* end PR_IncrementCounter() */
/*
**
*/
PR_IMPLEMENT(void)
PR_DecrementCounter(
PRCounterHandle handle
)
{
PR_Lock(((RName *)handle)->lock);
((RName *)handle)->counter--;
PR_Unlock(((RName *)handle)->lock);
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld",
handle, ((RName *)handle)->counter ));
return;
} /* end PR_DecrementCounter() */
/*
**
*/
PR_IMPLEMENT(void)
PR_AddToCounter(
PRCounterHandle handle,
PRUint32 value
)
{
PR_Lock(((RName *)handle)->lock);
((RName *)handle)->counter += value;
PR_Unlock(((RName *)handle)->lock);
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld",
handle, ((RName *)handle)->counter ));
return;
} /* end PR_AddToCounter() */
/*
**
*/
PR_IMPLEMENT(void)
PR_SubtractFromCounter(
PRCounterHandle handle,
PRUint32 value
)
{
PR_Lock(((RName *)handle)->lock);
((RName *)handle)->counter -= value;
PR_Unlock(((RName *)handle)->lock);
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld",
handle, ((RName *)handle)->counter ));
return;
} /* end PR_SubtractFromCounter() */
/*
**
*/
PR_IMPLEMENT(PRUint32)
PR_GetCounter(
PRCounterHandle handle
)
{
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld",
handle, ((RName *)handle)->counter ));
return(((RName *)handle)->counter);
} /* end PR_GetCounter() */
/*
**
*/
PR_IMPLEMENT(void)
PR_SetCounter(
PRCounterHandle handle,
PRUint32 value
)
{
((RName *)handle)->counter = value;
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld",
handle, ((RName *)handle)->counter ));
return;
} /* end PR_SetCounter() */
/*
**
*/
PR_IMPLEMENT(PRCounterHandle)
PR_FindNextCounterQname(
PRCounterHandle handle
)
{
QName *qnp = (QName *)handle;
if ( PR_CLIST_IS_EMPTY( &qNameList ))
qnp = NULL;
else if ( qnp == NULL )
qnp = (QName *)PR_LIST_HEAD( &qNameList );
else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
qnp = NULL;
else
qnp = (QName *)PR_NEXT_LINK( &qnp->link );
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p",
handle, qnp ));
return((PRCounterHandle)qnp);
} /* end PR_FindNextCounterQname() */
/*
**
*/
PR_IMPLEMENT(PRCounterHandle)
PR_FindNextCounterRname(
PRCounterHandle rhandle,
PRCounterHandle qhandle
)
{
RName *rnp = (RName *)rhandle;
QName *qnp = (QName *)qhandle;
if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
rnp = NULL;
else if ( rnp == NULL )
rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
rnp = NULL;
else
rnp = (RName *)PR_NEXT_LINK( &rnp->link );
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
rhandle, qhandle, rnp ));
return((PRCounterHandle)rnp);
} /* end PR_FindNextCounterRname() */
File diff suppressed because it is too large. Load diff
+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 <string.h>
#include "primpl.h"
/* Lock used to lock the environment */
#if defined(_PR_NO_PREEMPT)
#define _PR_NEW_LOCK_ENV()
#define _PR_DELETE_LOCK_ENV()
#define _PR_LOCK_ENV()
#define _PR_UNLOCK_ENV()
#elif defined(_PR_LOCAL_THREADS_ONLY)
extern _PRCPU * _pr_primordialCPU;
static PRIntn _is;
#define _PR_NEW_LOCK_ENV()
#define _PR_DELETE_LOCK_ENV()
#define _PR_LOCK_ENV() if (_pr_primordialCPU) _PR_INTSOFF(_is);
#define _PR_UNLOCK_ENV() if (_pr_primordialCPU) _PR_INTSON(_is);
#else
static PRLock *_pr_envLock = NULL;
#define _PR_NEW_LOCK_ENV() {_pr_envLock = PR_NewLock();}
#define _PR_DELETE_LOCK_ENV() \
{ if (_pr_envLock) { PR_DestroyLock(_pr_envLock); _pr_envLock = NULL; } }
#define _PR_LOCK_ENV() { if (_pr_envLock) PR_Lock(_pr_envLock); }
#define _PR_UNLOCK_ENV() { if (_pr_envLock) PR_Unlock(_pr_envLock); }
#endif
/************************************************************************/
void _PR_InitEnv(void)
{
_PR_NEW_LOCK_ENV();
}
void _PR_CleanupEnv(void)
{
_PR_DELETE_LOCK_ENV();
}
PR_IMPLEMENT(char*) PR_GetEnv(const char *var)
{
char *ev;
if (!_pr_initialized) _PR_ImplicitInitialization();
_PR_LOCK_ENV();
ev = _PR_MD_GET_ENV(var);
_PR_UNLOCK_ENV();
return ev;
}
PR_IMPLEMENT(PRStatus) PR_SetEnv(const char *string)
{
PRIntn result;
if (!_pr_initialized) _PR_ImplicitInitialization();
if ( !strchr(string, '=')) return(PR_FAILURE);
_PR_LOCK_ENV();
result = _PR_MD_PUT_ENV(string);
_PR_UNLOCK_ENV();
return (result)? PR_FAILURE : PR_SUCCESS;
}
/*
** DEPRECATED. Use PR_SetEnv() instead.
*/
#ifdef XP_MAC
PR_IMPLEMENT(PRIntn) PR_PutEnv(const char *string)
{
return (PR_SetEnv(string) == PR_SUCCESS) ? PR_TRUE : PR_FALSE;
}
#endif
+128
View File
@@ -0,0 +1,128 @@
/* -*- 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 ***** */
/*
*
* prerr.c
* This file is automatically generated; please do not edit it.
*/
#include "prerror.h"
static const struct PRErrorMessage text[] = {
{"PR_OUT_OF_MEMORY_ERROR", "Memory allocation attempt failed"},
{"PR_BAD_DESCRIPTOR_ERROR", "Invalid file descriptor"},
{"PR_WOULD_BLOCK_ERROR", "The operation would have blocked"},
{"PR_ACCESS_FAULT_ERROR", "Invalid memory address argument"},
{"PR_INVALID_METHOD_ERROR", "Invalid function for file type"},
{"PR_ILLEGAL_ACCESS_ERROR", "Invalid memory address argument"},
{"PR_UNKNOWN_ERROR", "Some unknown error has occurred"},
{"PR_PENDING_INTERRUPT_ERROR", "Operation interrupted by another thread"},
{"PR_NOT_IMPLEMENTED_ERROR", "function not implemented"},
{"PR_IO_ERROR", "I/O function error"},
{"PR_IO_TIMEOUT_ERROR", "I/O operation timed out"},
{"PR_IO_PENDING_ERROR", "I/O operation on busy file descriptor"},
{"PR_DIRECTORY_OPEN_ERROR", "The directory could not be opened"},
{"PR_INVALID_ARGUMENT_ERROR", "Invalid function argument"},
{"PR_ADDRESS_NOT_AVAILABLE_ERROR", "Network address not available (in use?)"},
{"PR_ADDRESS_NOT_SUPPORTED_ERROR", "Network address type not supported"},
{"PR_IS_CONNECTED_ERROR", "Already connected"},
{"PR_BAD_ADDRESS_ERROR", "Network address is invalid"},
{"PR_ADDRESS_IN_USE_ERROR", "Local Network address is in use"},
{"PR_CONNECT_REFUSED_ERROR", "Connection refused by peer"},
{"PR_NETWORK_UNREACHABLE_ERROR", "Network address is presently unreachable"},
{"PR_CONNECT_TIMEOUT_ERROR", "Connection attempt timed out"},
{"PR_NOT_CONNECTED_ERROR", "Network file descriptor is not connected"},
{"PR_LOAD_LIBRARY_ERROR", "Failure to load dynamic library"},
{"PR_UNLOAD_LIBRARY_ERROR", "Failure to unload dynamic library"},
{"PR_FIND_SYMBOL_ERROR", "Symbol not found in any of the loaded dynamic libraries"},
{"PR_INSUFFICIENT_RESOURCES_ERROR", "Insufficient system resources"},
{"PR_DIRECTORY_LOOKUP_ERROR", "A directory lookup on a network address has failed"},
{"PR_TPD_RANGE_ERROR", "Attempt to access a TPD key that is out of range"},
{"PR_PROC_DESC_TABLE_FULL_ERROR", "Process open FD table is full"},
{"PR_SYS_DESC_TABLE_FULL_ERROR", "System open FD table is full"},
{"PR_NOT_SOCKET_ERROR", "Network operation attempted on non-network file descriptor"},
{"PR_NOT_TCP_SOCKET_ERROR", "TCP-specific function attempted on a non-TCP file descriptor"},
{"PR_SOCKET_ADDRESS_IS_BOUND_ERROR", "TCP file descriptor is already bound"},
{"PR_NO_ACCESS_RIGHTS_ERROR", "Access Denied"},
{"PR_OPERATION_NOT_SUPPORTED_ERROR", "The requested operation is not supported by the platform"},
{"PR_PROTOCOL_NOT_SUPPORTED_ERROR", "The host operating system does not support the protocol requested"},
{"PR_REMOTE_FILE_ERROR", "Access to the remote file has been severed"},
{"PR_BUFFER_OVERFLOW_ERROR", "The value requested is too large to be stored in the data buffer provided"},
{"PR_CONNECT_RESET_ERROR", "TCP connection reset by peer"},
{"PR_RANGE_ERROR", "Unused"},
{"PR_DEADLOCK_ERROR", "The operation would have deadlocked"},
{"PR_FILE_IS_LOCKED_ERROR", "The file is already locked"},
{"PR_FILE_TOO_BIG_ERROR", "Write would result in file larger than the system allows"},
{"PR_NO_DEVICE_SPACE_ERROR", "The device for storing the file is full"},
{"PR_PIPE_ERROR", "Unused"},
{"PR_NO_SEEK_DEVICE_ERROR", "Unused"},
{"PR_IS_DIRECTORY_ERROR", "Cannot perform a normal file operation on a directory"},
{"PR_LOOP_ERROR", "Symbolic link loop"},
{"PR_NAME_TOO_LONG_ERROR", "File name is too long"},
{"PR_FILE_NOT_FOUND_ERROR", "File not found"},
{"PR_NOT_DIRECTORY_ERROR", "Cannot perform directory operation on a normal file"},
{"PR_READ_ONLY_FILESYSTEM_ERROR", "Cannot write to a read-only file system"},
{"PR_DIRECTORY_NOT_EMPTY_ERROR", "Cannot delete a directory that is not empty"},
{"PR_FILESYSTEM_MOUNTED_ERROR", "Cannot delete or rename a file object while the file system is busy"},
{"PR_NOT_SAME_DEVICE_ERROR", "Cannot rename a file to a file system on another device"},
{"PR_DIRECTORY_CORRUPTED_ERROR", "The directory object in the file system is corrupted"},
{"PR_FILE_EXISTS_ERROR", "Cannot create or rename a filename that already exists"},
{"PR_MAX_DIRECTORY_ENTRIES_ERROR", "Directory is full. No additional filenames may be added"},
{"PR_INVALID_DEVICE_STATE_ERROR", "The required device was in an invalid state"},
{"PR_DEVICE_IS_LOCKED_ERROR", "The device is locked"},
{"PR_NO_MORE_FILES_ERROR", "No more entries in the directory"},
{"PR_END_OF_FILE_ERROR", "Encountered end of file"},
{"PR_FILE_SEEK_ERROR", "Seek error"},
{"PR_FILE_IS_BUSY_ERROR", "The file is busy"},
{"PR_OPERATION_ABORTED_ERROR", "The I/O operation was aborted"},
{"PR_IN_PROGRESS_ERROR", "Operation is still in progress (probably a non-blocking connect)"},
{"PR_ALREADY_INITIATED_ERROR", "Operation has already been initiated (probably a non-blocking connect)"},
{"PR_GROUP_EMPTY_ERROR", "The wait group is empty"},
{"PR_INVALID_STATE_ERROR", "Object state improper for request"},
{"PR_NETWORK_DOWN_ERROR", "Network is down"},
{"PR_SOCKET_SHUTDOWN_ERROR", "Socket shutdown"},
{"PR_CONNECT_ABORTED_ERROR", "Connection aborted"},
{"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"},
{"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"},
{"PR_MAX_ERROR", "Placeholder for the end of the list"},
{0, 0}
};
static const struct PRErrorTable et = { text, "prerr", -6000L, 76 };
void nspr_InitializePRErrorTable(void) {
PR_ErrorInstallTable(&et);
}
+139
View File
@@ -0,0 +1,139 @@
#
# ***** 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 *****
et nspr -6000
ec PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed"
ec PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor"
ec PR_WOULD_BLOCK_ERROR, "The operation would have blocked"
ec PR_ACCESS_FAULT_ERROR, "Invalid memory address argument"
ec PR_INVALID_METHOD_ERROR, "Invalid function for file type"
ec PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument"
ec PR_UNKNOWN_ERROR, "Some unknown error has occurred"
ec PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread"
ec PR_NOT_IMPLEMENTED_ERROR, "function not implemented"
ec PR_IO_ERROR, "I/O function error"
ec PR_IO_TIMEOUT_ERROR, "I/O operation timed out"
ec PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor"
ec PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened"
ec PR_INVALID_ARGUMENT_ERROR, "Invalid function argument"
ec PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)"
ec PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported"
ec PR_IS_CONNECTED_ERROR, "Already connected"
ec PR_BAD_ADDRESS_ERROR, "Network address is invalid"
ec PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use"
ec PR_CONNECT_REFUSED_ERROR, "Connection refused by peer"
ec PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable"
ec PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out"
ec PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected"
ec PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library"
ec PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library"
ec PR_FIND_SYMBOL_ERROR,
"Symbol not found in any of the loaded dynamic libraries"
ec PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources"
ec PR_DIRECTORY_LOOKUP_ERROR,
"A directory lookup on a network address has failed"
ec PR_TPD_RANGE_ERROR,
"Attempt to access a TPD key that is out of range"
ec PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full"
ec PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full"
ec PR_NOT_SOCKET_ERROR,
"Network operation attempted on non-network file descriptor"
ec PR_NOT_TCP_SOCKET_ERROR,
"TCP-specific function attempted on a non-TCP file descriptor"
ec PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound"
ec PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied"
ec PR_OPERATION_NOT_SUPPORTED_ERROR,
"The requested operation is not supported by the platform"
ec PR_PROTOCOL_NOT_SUPPORTED_ERROR,
"The host operating system does not support the protocol requested"
ec PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed"
ec PR_BUFFER_OVERFLOW_ERROR,
"The value requested is too large to be stored in the data buffer provided"
ec PR_CONNECT_RESET_ERROR, "TCP connection reset by peer"
ec PR_RANGE_ERROR, "Unused"
ec PR_DEADLOCK_ERROR, "The operation would have deadlocked"
ec PR_FILE_IS_LOCKED_ERROR, "The file is already locked"
ec PR_FILE_TOO_BIG_ERROR,
"Write would result in file larger than the system allows"
ec PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full"
ec PR_PIPE_ERROR, "Unused"
ec PR_NO_SEEK_DEVICE_ERROR, "Unused"
ec PR_IS_DIRECTORY_ERROR,
"Cannot perform a normal file operation on a directory"
ec PR_LOOP_ERROR, "Symbolic link loop"
ec PR_NAME_TOO_LONG_ERROR, "File name is too long"
ec PR_FILE_NOT_FOUND_ERROR, "File not found"
ec PR_NOT_DIRECTORY_ERROR,
"Cannot perform directory operation on a normal file"
ec PR_READ_ONLY_FILESYSTEM_ERROR,
"Cannot write to a read-only file system"
ec PR_DIRECTORY_NOT_EMPTY_ERROR,
"Cannot delete a directory that is not empty"
ec PR_FILESYSTEM_MOUNTED_ERROR,
"Cannot delete or rename a file object while the file system is busy"
ec PR_NOT_SAME_DEVICE_ERROR,
"Cannot rename a file to a file system on another device"
ec PR_DIRECTORY_CORRUPTED_ERROR,
"The directory object in the file system is corrupted"
ec PR_FILE_EXISTS_ERROR,
"Cannot create or rename a filename that already exists"
ec PR_MAX_DIRECTORY_ENTRIES_ERROR,
"Directory is full. No additional filenames may be added"
ec PR_INVALID_DEVICE_STATE_ERROR,
"The required device was in an invalid state"
ec PR_DEVICE_IS_LOCKED_ERROR, "The device is locked"
ec PR_NO_MORE_FILES_ERROR, "No more entries in the directory"
ec PR_END_OF_FILE_ERROR, "Encountered end of file"
ec PR_FILE_SEEK_ERROR, "Seek error"
ec PR_FILE_IS_BUSY_ERROR, "The file is busy"
ec PR_OPERATION_ABORTED_ERROR, "The I/O operation was aborted"
ec PR_IN_PROGRESS_ERROR,
"Operation is still in progress (probably a non-blocking connect)"
ec PR_ALREADY_INITIATED_ERROR,
"Operation has already been initiated (probably a non-blocking connect)"
ec PR_GROUP_EMPTY_ERROR, "The wait group is empty"
ec PR_INVALID_STATE_ERROR, "Object state improper for request"
ec PR_NETWORK_DOWN_ERROR, "Network is down"
ec PR_SOCKET_SHUTDOWN_ERROR, "Socket shutdown"
ec PR_CONNECT_ABORTED_ERROR, "Connection aborted"
ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable"
ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded"
ec PR_MAX_ERROR, "Placeholder for the end of the list"
end
@@ -0,0 +1,116 @@
#
# ***** 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 *****
#
# prerr.properties
# This file is automatically generated; please do not edit it.
PR_OUT_OF_MEMORY_ERROR=Memory allocation attempt failed
PR_BAD_DESCRIPTOR_ERROR=Invalid file descriptor
PR_WOULD_BLOCK_ERROR=The operation would have blocked
PR_ACCESS_FAULT_ERROR=Invalid memory address argument
PR_INVALID_METHOD_ERROR=Invalid function for file type
PR_ILLEGAL_ACCESS_ERROR=Invalid memory address argument
PR_UNKNOWN_ERROR=Some unknown error has occurred
PR_PENDING_INTERRUPT_ERROR=Operation interrupted by another thread
PR_NOT_IMPLEMENTED_ERROR=function not implemented
PR_IO_ERROR=I/O function error
PR_IO_TIMEOUT_ERROR=I/O operation timed out
PR_IO_PENDING_ERROR=I/O operation on busy file descriptor
PR_DIRECTORY_OPEN_ERROR=The directory could not be opened
PR_INVALID_ARGUMENT_ERROR=Invalid function argument
PR_ADDRESS_NOT_AVAILABLE_ERROR=Network address not available (in use?)
PR_ADDRESS_NOT_SUPPORTED_ERROR=Network address type not supported
PR_IS_CONNECTED_ERROR=Already connected
PR_BAD_ADDRESS_ERROR=Network address is invalid
PR_ADDRESS_IN_USE_ERROR=Local Network address is in use
PR_CONNECT_REFUSED_ERROR=Connection refused by peer
PR_NETWORK_UNREACHABLE_ERROR=Network address is presently unreachable
PR_CONNECT_TIMEOUT_ERROR=Connection attempt timed out
PR_NOT_CONNECTED_ERROR=Network file descriptor is not connected
PR_LOAD_LIBRARY_ERROR=Failure to load dynamic library
PR_UNLOAD_LIBRARY_ERROR=Failure to unload dynamic library
PR_FIND_SYMBOL_ERROR=Symbol not found in any of the loaded dynamic libraries
PR_INSUFFICIENT_RESOURCES_ERROR=Insufficient system resources
PR_DIRECTORY_LOOKUP_ERROR=A directory lookup on a network address has failed
PR_TPD_RANGE_ERROR=Attempt to access a TPD key that is out of range
PR_PROC_DESC_TABLE_FULL_ERROR=Process open FD table is full
PR_SYS_DESC_TABLE_FULL_ERROR=System open FD table is full
PR_NOT_SOCKET_ERROR=Network operation attempted on non-network file descriptor
PR_NOT_TCP_SOCKET_ERROR=TCP-specific function attempted on a non-TCP file descriptor
PR_SOCKET_ADDRESS_IS_BOUND_ERROR=TCP file descriptor is already bound
PR_NO_ACCESS_RIGHTS_ERROR=Access Denied
PR_OPERATION_NOT_SUPPORTED_ERROR=The requested operation is not supported by the platform
PR_PROTOCOL_NOT_SUPPORTED_ERROR=The host operating system does not support the protocol requested
PR_REMOTE_FILE_ERROR=Access to the remote file has been severed
PR_BUFFER_OVERFLOW_ERROR=The value requested is too large to be stored in the data buffer provided
PR_CONNECT_RESET_ERROR=TCP connection reset by peer
PR_RANGE_ERROR=Unused
PR_DEADLOCK_ERROR=The operation would have deadlocked
PR_FILE_IS_LOCKED_ERROR=The file is already locked
PR_FILE_TOO_BIG_ERROR=Write would result in file larger than the system allows
PR_NO_DEVICE_SPACE_ERROR=The device for storing the file is full
PR_PIPE_ERROR=Unused
PR_NO_SEEK_DEVICE_ERROR=Unused
PR_IS_DIRECTORY_ERROR=Cannot perform a normal file operation on a directory
PR_LOOP_ERROR=Symbolic link loop
PR_NAME_TOO_LONG_ERROR=File name is too long
PR_FILE_NOT_FOUND_ERROR=File not found
PR_NOT_DIRECTORY_ERROR=Cannot perform directory operation on a normal file
PR_READ_ONLY_FILESYSTEM_ERROR=Cannot write to a read-only file system
PR_DIRECTORY_NOT_EMPTY_ERROR=Cannot delete a directory that is not empty
PR_FILESYSTEM_MOUNTED_ERROR=Cannot delete or rename a file object while the file system is busy
PR_NOT_SAME_DEVICE_ERROR=Cannot rename a file to a file system on another device
PR_DIRECTORY_CORRUPTED_ERROR=The directory object in the file system is corrupted
PR_FILE_EXISTS_ERROR=Cannot create or rename a filename that already exists
PR_MAX_DIRECTORY_ENTRIES_ERROR=Directory is full. No additional filenames may be added
PR_INVALID_DEVICE_STATE_ERROR=The required device was in an invalid state
PR_DEVICE_IS_LOCKED_ERROR=The device is locked
PR_NO_MORE_FILES_ERROR=No more entries in the directory
PR_END_OF_FILE_ERROR=Encountered end of file
PR_FILE_SEEK_ERROR=Seek error
PR_FILE_IS_BUSY_ERROR=The file is busy
PR_OPERATION_ABORTED_ERROR=The I/O operation was aborted
PR_IN_PROGRESS_ERROR=Operation is still in progress (probably a non-blocking connect)
PR_ALREADY_INITIATED_ERROR=Operation has already been initiated (probably a non-blocking connect)
PR_GROUP_EMPTY_ERROR=The wait group is empty
PR_INVALID_STATE_ERROR=Object state improper for request
PR_NETWORK_DOWN_ERROR=Network is down
PR_SOCKET_SHUTDOWN_ERROR=Socket shutdown
PR_CONNECT_ABORTED_ERROR=Connection aborted
PR_HOST_UNREACHABLE_ERROR=Host is unreachable
PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded
PR_MAX_ERROR=Placeholder for the end of the list
+107
View File
@@ -0,0 +1,107 @@
/* -*- 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 <stdlib.h>
PR_IMPLEMENT(PRErrorCode) PR_GetError(void)
{
PRThread *thread = PR_GetCurrentThread();
return thread->errorCode;
}
PR_IMPLEMENT(PRInt32) PR_GetOSError(void)
{
PRThread *thread = PR_GetCurrentThread();
return thread->osErrorCode;
}
PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr)
{
PRThread *thread = PR_GetCurrentThread();
thread->errorCode = code;
thread->osErrorCode = osErr;
thread->errorStringLength = 0;
}
PR_IMPLEMENT(void) PR_SetErrorText(PRIntn textLength, const char *text)
{
PRThread *thread = PR_GetCurrentThread();
if (0 == textLength)
{
if (NULL != thread->errorString)
PR_DELETE(thread->errorString);
thread->errorStringSize = 0;
}
else
{
PRIntn size = textLength + 31; /* actual length to allocate. Plus a little extra */
if (thread->errorStringSize < textLength+1) /* do we have room? */
{
if (NULL != thread->errorString)
PR_DELETE(thread->errorString);
thread->errorString = (char*)PR_MALLOC(size);
if ( NULL == thread->errorString ) {
thread->errorStringSize = 0;
thread->errorStringLength = 0;
return;
}
thread->errorStringSize = size;
}
memcpy(thread->errorString, text, textLength+1 );
}
thread->errorStringLength = textLength;
}
PR_IMPLEMENT(PRInt32) PR_GetErrorTextLength(void)
{
PRThread *thread = PR_GetCurrentThread();
return thread->errorStringLength;
} /* PR_GetErrorTextLength */
PR_IMPLEMENT(PRInt32) PR_GetErrorText(char *text)
{
PRThread *thread = PR_GetCurrentThread();
if (0 != thread->errorStringLength)
memcpy(text, thread->errorString, thread->errorStringLength+1);
return thread->errorStringLength;
} /* PR_GetErrorText */
+240
View File
@@ -0,0 +1,240 @@
/* ***** 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 ***** */
/*
Copyright 1987, 1988 by the Student Information Processing Board
of the Massachusetts Institute of Technology
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is
hereby granted, provided that the above copyright notice
appear in all copies and that both that copyright notice and
this permission notice appear in supporting documentation,
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
M.I.T. and the M.I.T. S.I.P.B. make no representations about
the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
*/
#include <string.h>
#ifdef SUNOS4
#include "md/sunos4.h" /* for strerror */
#endif
#include <assert.h>
#include <errno.h>
#include "prmem.h"
#include "prerror.h"
#define ERRCODE_RANGE 8 /* # of bits to shift table number */
#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
#ifdef NEED_SYS_ERRLIST
extern char const * const sys_errlist[];
extern const int sys_nerr;
#endif
/* List of error tables */
struct PRErrorTableList {
struct PRErrorTableList *next;
const struct PRErrorTable *table;
struct PRErrorCallbackTablePrivate *table_private;
};
static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL;
/* Supported languages */
static const char * default_languages[] = { "i-default", "en", 0 };
static const char * const * callback_languages = default_languages;
/* Callback info */
static struct PRErrorCallbackPrivate *callback_private = 0;
static PRErrorCallbackLookupFn *callback_lookup = 0;
static PRErrorCallbackNewTableFn *callback_newtable = 0;
static const char char_set[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
static const char *
error_table_name (PRErrorCode num)
{
static char buf[6]; /* only used if internal code problems exist */
long ch;
int i;
char *p;
/* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
p = buf;
num >>= ERRCODE_RANGE;
/* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
num &= 077777777;
/* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
for (i = 4; i >= 0; i--) {
ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
if (ch != 0)
*p++ = char_set[ch-1];
}
*p = '\0';
return(buf);
}
PR_IMPLEMENT(const char *)
PR_ErrorToString(PRErrorCode code, PRLanguageCode language)
{
/* static buffer only used if code is using inconsistent error message
* numbers, so just ignore the possible thread contention
*/
static char buffer[25];
const char *msg;
int offset;
PRErrorCode table_num;
struct PRErrorTableList *et;
int started = 0;
char *cp;
for (et = Table_List; et; et = et->next) {
if (et->table->base <= code &&
et->table->base + et->table->n_msgs > code) {
/* This is the right table */
if (callback_lookup) {
msg = callback_lookup(code, language, et->table,
callback_private, et->table_private);
if (msg) return msg;
}
return(et->table->msgs[code - et->table->base].en_text);
}
}
if (code >= 0 && code < 256) {
return strerror(code);
}
offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
table_num = code - offset;
strcpy (buffer, "Unknown code ");
if (table_num) {
strcat(buffer, error_table_name (table_num));
strcat(buffer, " ");
}
for (cp = buffer; *cp; cp++)
;
if (offset >= 100) {
*cp++ = (char)('0' + offset / 100);
offset %= 100;
started++;
}
if (started || offset >= 10) {
*cp++ = (char)('0' + offset / 10);
offset %= 10;
}
*cp++ = (char)('0' + offset);
*cp = '\0';
return(buffer);
}
PR_IMPLEMENT(const char *)
PR_ErrorToName(PRErrorCode code)
{
struct PRErrorTableList *et;
for (et = Table_List; et; et = et->next) {
if (et->table->base <= code &&
et->table->base + et->table->n_msgs > code) {
/* This is the right table */
return(et->table->msgs[code - et->table->base].name);
}
}
return 0;
}
PR_IMPLEMENT(const char * const *)
PR_ErrorLanguages(void)
{
return callback_languages;
}
PR_IMPLEMENT(PRErrorCode)
PR_ErrorInstallTable(const struct PRErrorTable *table)
{
struct PRErrorTableList * new_et;
new_et = (struct PRErrorTableList *)
PR_Malloc(sizeof(struct PRErrorTableList));
if (!new_et)
return errno; /* oops */
new_et->table = table;
if (callback_newtable) {
new_et->table_private = callback_newtable(table, callback_private);
} else {
new_et->table_private = 0;
}
new_et->next = Table_List;
Table_List = new_et;
return 0;
}
PR_IMPLEMENT(void)
PR_ErrorInstallCallback(const char * const * languages,
PRErrorCallbackLookupFn *lookup,
PRErrorCallbackNewTableFn *newtable,
struct PRErrorCallbackPrivate *cb_private)
{
struct PRErrorTableList *et;
assert(strcmp(languages[0], "i-default") == 0);
assert(strcmp(languages[1], "en") == 0);
callback_languages = languages;
callback_lookup = lookup;
callback_newtable = newtable;
callback_private = cb_private;
if (callback_newtable) {
for (et = Table_List; et; et = et->next) {
et->table_private = callback_newtable(et->table, callback_private);
}
}
}
+870
View File
@@ -0,0 +1,870 @@
/* -*- 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 <ctype.h>
#include <string.h>
PRLogModuleInfo *_pr_clock_lm;
PRLogModuleInfo *_pr_cmon_lm;
PRLogModuleInfo *_pr_io_lm;
PRLogModuleInfo *_pr_cvar_lm;
PRLogModuleInfo *_pr_mon_lm;
PRLogModuleInfo *_pr_linker_lm;
PRLogModuleInfo *_pr_sched_lm;
PRLogModuleInfo *_pr_thread_lm;
PRLogModuleInfo *_pr_gc_lm;
PRLogModuleInfo *_pr_shm_lm;
PRLogModuleInfo *_pr_shma_lm;
PRFileDesc *_pr_stdin;
PRFileDesc *_pr_stdout;
PRFileDesc *_pr_stderr;
#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
PRCList _pr_active_local_threadQ =
PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ);
PRCList _pr_active_global_threadQ =
PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ);
_MDLock _pr_cpuLock; /* lock for the CPU Q */
PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
PRUint32 _pr_utid;
PRInt32 _pr_userActive;
PRInt32 _pr_systemActive;
PRUintn _pr_maxPTDs;
#ifdef _PR_LOCAL_THREADS_ONLY
struct _PRCPU *_pr_currentCPU;
PRThread *_pr_currentThread;
PRThread *_pr_lastThread;
PRInt32 _pr_intsOff;
#endif /* _PR_LOCAL_THREADS_ONLY */
/* Lock protecting all "termination" condition variables of all threads */
PRLock *_pr_terminationCVLock;
#endif /* !defined(_PR_PTHREADS) */
PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */
static void _PR_InitCallOnce(void);
PRBool _pr_initialized = PR_FALSE;
PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
{
/*
** This is the secret handshake algorithm.
**
** This release has a simple version compatibility
** check algorithm. This release is not backward
** compatible with previous major releases. It is
** not compatible with future major, minor, or
** patch releases.
*/
int vmajor = 0, vminor = 0, vpatch = 0;
const char *ptr = importedVersion;
while (isdigit(*ptr)) {
vmajor = 10 * vmajor + *ptr - '0';
ptr++;
}
if (*ptr == '.') {
ptr++;
while (isdigit(*ptr)) {
vminor = 10 * vminor + *ptr - '0';
ptr++;
}
if (*ptr == '.') {
ptr++;
while (isdigit(*ptr)) {
vpatch = 10 * vpatch + *ptr - '0';
ptr++;
}
}
}
if (vmajor != PR_VMAJOR) {
return PR_FALSE;
}
if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
return PR_FALSE;
}
if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) {
return PR_FALSE;
}
return PR_TRUE;
} /* PR_VersionCheck */
PR_IMPLEMENT(PRBool) PR_Initialized(void)
{
return _pr_initialized;
}
PRInt32 _native_threads_only = 0;
#ifdef WINNT
static void _pr_SetNativeThreadsOnlyMode(void)
{
HMODULE mainExe;
PRBool *globalp;
char *envp;
mainExe = GetModuleHandle(NULL);
PR_ASSERT(NULL != mainExe);
globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only");
if (globalp) {
_native_threads_only = (*globalp != PR_FALSE);
} else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) {
_native_threads_only = (atoi(envp) == 1);
}
}
#endif
#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
extern PRStatus _pr_init_ipv6(void);
#endif
static void _PR_InitStuff(void)
{
if (_pr_initialized) return;
_pr_initialized = PR_TRUE;
#ifdef _PR_ZONE_ALLOCATOR
_PR_InitZones();
#endif
#ifdef WINNT
_pr_SetNativeThreadsOnlyMode();
#endif
(void) PR_GetPageSize();
_pr_clock_lm = PR_NewLogModule("clock");
_pr_cmon_lm = PR_NewLogModule("cmon");
_pr_io_lm = PR_NewLogModule("io");
_pr_mon_lm = PR_NewLogModule("mon");
_pr_linker_lm = PR_NewLogModule("linker");
_pr_cvar_lm = PR_NewLogModule("cvar");
_pr_sched_lm = PR_NewLogModule("sched");
_pr_thread_lm = PR_NewLogModule("thread");
_pr_gc_lm = PR_NewLogModule("gc");
_pr_shm_lm = PR_NewLogModule("shm");
_pr_shma_lm = PR_NewLogModule("shma");
/* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */
_PR_MD_EARLY_INIT();
_PR_InitLocks();
_PR_InitAtomic();
_PR_InitSegs();
_PR_InitStacks();
_PR_InitTPD();
_PR_InitEnv();
_PR_InitLayerCache();
_PR_InitClock();
_pr_sleeplock = PR_NewLock();
PR_ASSERT(NULL != _pr_sleeplock);
#ifdef GC_LEAK_DETECTOR
_PR_InitGarbageCollector();
#endif
_PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
#ifdef WIN16
{
PRInt32 top; /* artificial top of stack, win16 */
_pr_top_of_task_stack = (char *) &top;
}
#endif
#ifndef _PR_GLOBAL_THREADS_ONLY
_PR_InitCPUs();
#endif
/*
* XXX: call _PR_InitMem only on those platforms for which nspr implements
* malloc, for now.
*/
#ifdef _PR_OVERRIDE_MALLOC
_PR_InitMem();
#endif
_PR_InitCMon();
_PR_InitIO();
_PR_InitNet();
_PR_InitLog();
_PR_InitLinker();
_PR_InitCallOnce();
_PR_InitDtoa();
_PR_InitMW();
_PR_InitRWLocks();
nspr_InitializePRErrorTable();
#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
_pr_init_ipv6();
#endif
_PR_MD_FINAL_INIT();
}
void _PR_ImplicitInitialization(void)
{
_PR_InitStuff();
/* Enable interrupts */
#if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)
_PR_MD_START_INTERRUPTS();
#endif
}
PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
{
#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
if (!_pr_initialized) {
_PR_InitStuff();
} else {
_PR_MD_DISABLE_CLOCK_INTERRUPTS();
}
#endif
}
PR_IMPLEMENT(void) PR_EnableClockInterrupts(void)
{
#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
if (!_pr_initialized) {
_PR_InitStuff();
}
_PR_MD_ENABLE_CLOCK_INTERRUPTS();
#endif
}
PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
{
#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
_PR_MD_BLOCK_CLOCK_INTERRUPTS();
#endif
}
PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void)
{
#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
_PR_MD_UNBLOCK_CLOCK_INTERRUPTS();
#endif
}
PR_IMPLEMENT(void) PR_Init(
PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
{
#if defined(XP_MAC)
#pragma unused (type, priority, maxPTDs)
#endif
_PR_ImplicitInitialization();
}
PR_IMPLEMENT(PRIntn) PR_Initialize(
PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
{
#if defined(XP_MAC)
#pragma unused (maxPTDs)
#endif
PRIntn rv;
_PR_ImplicitInitialization();
rv = prmain(argc, argv);
PR_Cleanup();
return rv;
} /* PR_Initialize */
/*
*-----------------------------------------------------------------------
*
* _PR_CleanupBeforeExit --
*
* Perform the cleanup work before exiting the process.
* We first do the cleanup generic to all platforms. Then
* we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent
* cleanup is done. This function is used by PR_Cleanup().
*
* See also: PR_Cleanup().
*
*-----------------------------------------------------------------------
*/
#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
/* see ptthread.c */
#else
static void
_PR_CleanupBeforeExit(void)
{
/*
Do not make any calls here other than to destroy resources. For example,
do not make any calls that eventually may end up in PR_Lock. Because the
thread is destroyed, can not access current thread any more.
*/
_PR_CleanupTPD();
if (_pr_terminationCVLock)
/*
* In light of the comment above, this looks real suspicious.
* I'd go so far as to say it's just a problem waiting to happen.
*/
PR_DestroyLock(_pr_terminationCVLock);
_PR_MD_CLEANUP_BEFORE_EXIT();
}
#endif /* defined(_PR_PTHREADS) */
/*
*----------------------------------------------------------------------
*
* PR_Cleanup --
*
* Perform a graceful shutdown of the NSPR runtime. PR_Cleanup() may
* only be called from the primordial thread, typically at the
* end of the main() function. It returns when it has completed
* its platform-dependent duty and the process must not make any other
* NSPR library calls prior to exiting from main().
*
* PR_Cleanup() first blocks the primordial thread until all the
* other user (non-system) threads, if any, have terminated.
* Then it performs cleanup in preparation for exiting the process.
* PR_Cleanup() does not exit the primordial thread (which would
* in turn exit the process).
*
* PR_Cleanup() only responds when it is called by the primordial
* thread. Calls by any other thread are silently ignored.
*
* See also: PR_ExitProcess()
*
*----------------------------------------------------------------------
*/
#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
/* see ptthread.c */
#else
PR_IMPLEMENT(PRStatus) PR_Cleanup()
{
PRThread *me = PR_GetCurrentThread();
PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL));
if ((NULL != me) && (me->flags & _PR_PRIMORDIAL))
{
PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
/*
* No more recycling of threads
*/
_pr_recycleThreads = 0;
/*
* Wait for all other user (non-system/daemon) threads
* to terminate.
*/
PR_Lock(_pr_activeLock);
while (_pr_userActive > _pr_primordialExitCount) {
PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT);
}
PR_Unlock(_pr_activeLock);
#ifdef IRIX
_PR_MD_PRE_CLEANUP(me);
/*
* The primordial thread must now be running on the primordial cpu
*/
PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0));
#endif
_PR_CleanupMW();
_PR_CleanupDtoa();
_PR_CleanupCallOnce();
_PR_ShutdownLinker();
/* Release the primordial thread's private data, etc. */
_PR_CleanupThread(me);
_PR_MD_STOP_INTERRUPTS();
PR_LOG(_pr_thread_lm, PR_LOG_MIN,
("PR_Cleanup: clean up before destroying thread"));
_PR_LogCleanup();
/*
* This part should look like the end of _PR_NativeRunThread
* and _PR_UserRunThread.
*/
if (_PR_IS_NATIVE_THREAD(me)) {
_PR_MD_EXIT_THREAD(me);
_PR_NativeDestroyThread(me);
} else {
_PR_UserDestroyThread(me);
PR_DELETE(me->stack);
PR_DELETE(me);
}
/*
* XXX: We are freeing the heap memory here so that Purify won't
* complain, but we should also free other kinds of resources
* that are allocated by the _PR_InitXXX() functions.
* Ideally, for each _PR_InitXXX(), there should be a corresponding
* _PR_XXXCleanup() that we can call here.
*/
_PR_CleanupNet();
_PR_CleanupIO();
#ifdef WINNT
_PR_CleanupCPUs();
#endif
_PR_CleanupThreads();
PR_DestroyLock(_pr_sleeplock);
_pr_sleeplock = NULL;
_PR_CleanupLayerCache();
_PR_CleanupEnv();
_PR_CleanupStacks();
_PR_CleanupBeforeExit();
_pr_initialized = PR_FALSE;
return PR_SUCCESS;
}
return PR_FAILURE;
}
#endif /* defined(_PR_PTHREADS) */
/*
*------------------------------------------------------------------------
* PR_ProcessExit --
*
* Cause an immediate, nongraceful, forced termination of the process.
* It takes a PRIntn argument, which is the exit status code of the
* process.
*
* See also: PR_Cleanup()
*
*------------------------------------------------------------------------
*/
#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
/* see ptthread.c */
#else
PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
{
_PR_MD_EXIT(status);
}
#endif /* defined(_PR_PTHREADS) */
PR_IMPLEMENT(PRProcessAttr *)
PR_NewProcessAttr(void)
{
PRProcessAttr *attr;
attr = PR_NEWZAP(PRProcessAttr);
if (!attr) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
}
return attr;
}
PR_IMPLEMENT(void)
PR_ResetProcessAttr(PRProcessAttr *attr)
{
PR_FREEIF(attr->currentDirectory);
PR_FREEIF(attr->fdInheritBuffer);
memset(attr, 0, sizeof(*attr));
}
PR_IMPLEMENT(void)
PR_DestroyProcessAttr(PRProcessAttr *attr)
{
PR_FREEIF(attr->currentDirectory);
PR_FREEIF(attr->fdInheritBuffer);
PR_DELETE(attr);
}
PR_IMPLEMENT(void)
PR_ProcessAttrSetStdioRedirect(
PRProcessAttr *attr,
PRSpecialFD stdioFd,
PRFileDesc *redirectFd)
{
switch (stdioFd) {
case PR_StandardInput:
attr->stdinFd = redirectFd;
break;
case PR_StandardOutput:
attr->stdoutFd = redirectFd;
break;
case PR_StandardError:
attr->stderrFd = redirectFd;
break;
default:
PR_ASSERT(0);
}
}
/*
* OBSOLETE
*/
PR_IMPLEMENT(void)
PR_SetStdioRedirect(
PRProcessAttr *attr,
PRSpecialFD stdioFd,
PRFileDesc *redirectFd)
{
#if defined(DEBUG)
static PRBool warn = PR_TRUE;
if (warn) {
warn = _PR_Obsolete("PR_SetStdioRedirect()",
"PR_ProcessAttrSetStdioRedirect()");
}
#endif
PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
}
PR_IMPLEMENT(PRStatus)
PR_ProcessAttrSetCurrentDirectory(
PRProcessAttr *attr,
const char *dir)
{
PR_FREEIF(attr->currentDirectory);
attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1);
if (!attr->currentDirectory) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return PR_FAILURE;
}
strcpy(attr->currentDirectory, dir);
return PR_SUCCESS;
}
PR_IMPLEMENT(PRStatus)
PR_ProcessAttrSetInheritableFD(
PRProcessAttr *attr,
PRFileDesc *fd,
const char *name)
{
/* We malloc the fd inherit buffer in multiples of this number. */
#define FD_INHERIT_BUFFER_INCR 128
/* The length of "NSPR_INHERIT_FDS=" */
#define NSPR_INHERIT_FDS_STRLEN 17
/* The length of osfd (PROsfd) printed in hexadecimal with 0x prefix */
#ifdef _WIN64
#define OSFD_STRLEN 18
#else
#define OSFD_STRLEN 10
#endif
/* The length of fd type (PRDescType) printed in decimal */
#define FD_TYPE_STRLEN 1
PRSize newSize;
int remainder;
char *newBuffer;
int nwritten;
char *cur;
int freeSize;
if (fd->identity != PR_NSPR_IO_LAYER) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
if (fd->secret->inheritable == _PR_TRI_UNKNOWN) {
_PR_MD_QUERY_FD_INHERITABLE(fd);
}
if (fd->secret->inheritable != _PR_TRI_TRUE) {
PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
return PR_FAILURE;
}
/*
* We also need to account for the : separators and the
* terminating null byte.
*/
if (NULL == attr->fdInheritBuffer) {
/* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */
newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name)
+ FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1;
} else {
/* At other times, we print ":<name>:<type>:<val>" */
newSize = attr->fdInheritBufferUsed + strlen(name)
+ FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1;
}
if (newSize > attr->fdInheritBufferSize) {
/* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */
remainder = newSize % FD_INHERIT_BUFFER_INCR;
if (remainder != 0) {
newSize += (FD_INHERIT_BUFFER_INCR - remainder);
}
if (NULL == attr->fdInheritBuffer) {
newBuffer = (char *) PR_MALLOC(newSize);
} else {
newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize);
}
if (NULL == newBuffer) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return PR_FAILURE;
}
attr->fdInheritBuffer = newBuffer;
attr->fdInheritBufferSize = newSize;
}
cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed;
freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed;
if (0 == attr->fdInheritBufferUsed) {
nwritten = PR_snprintf(cur, freeSize,
"NSPR_INHERIT_FDS=%s:%d:0x%" PR_PRIxOSFD,
name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
} else {
nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%" PR_PRIxOSFD,
name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
}
attr->fdInheritBufferUsed += nwritten;
return PR_SUCCESS;
}
PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
const char *name)
{
PRFileDesc *fd;
const char *envVar;
const char *ptr;
int len = strlen(name);
PROsfd osfd;
int nColons;
PRIntn fileType;
envVar = PR_GetEnv("NSPR_INHERIT_FDS");
if (NULL == envVar || '\0' == envVar[0]) {
PR_SetError(PR_UNKNOWN_ERROR, 0);
return NULL;
}
ptr = envVar;
while (1) {
if ((ptr[len] == ':') && (strncmp(ptr, name, len) == 0)) {
ptr += len + 1;
PR_sscanf(ptr, "%d:0x%" PR_SCNxOSFD, &fileType, &osfd);
switch ((PRDescType)fileType) {
case PR_DESC_FILE:
fd = PR_ImportFile(osfd);
break;
case PR_DESC_PIPE:
fd = PR_ImportPipe(osfd);
break;
case PR_DESC_SOCKET_TCP:
fd = PR_ImportTCPSocket(osfd);
break;
case PR_DESC_SOCKET_UDP:
fd = PR_ImportUDPSocket(osfd);
break;
default:
PR_ASSERT(0);
PR_SetError(PR_UNKNOWN_ERROR, 0);
fd = NULL;
break;
}
if (fd) {
/*
* An inherited FD is inheritable by default.
* The child process needs to call PR_SetFDInheritable
* to make it non-inheritable if so desired.
*/
fd->secret->inheritable = _PR_TRI_TRUE;
}
return fd;
}
/* Skip three colons */
nColons = 0;
while (*ptr) {
if (*ptr == ':') {
if (++nColons == 3) {
break;
}
}
ptr++;
}
if (*ptr == '\0') {
PR_SetError(PR_UNKNOWN_ERROR, 0);
return NULL;
}
ptr++;
}
}
PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
const char *path,
char *const *argv,
char *const *envp,
const PRProcessAttr *attr)
{
return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
} /* PR_CreateProcess */
PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
const char *path,
char *const *argv,
char *const *envp,
const PRProcessAttr *attr)
{
PRProcess *process;
PRStatus rv;
process = PR_CreateProcess(path, argv, envp, attr);
if (NULL == process) {
return PR_FAILURE;
}
rv = PR_DetachProcess(process);
PR_ASSERT(PR_SUCCESS == rv);
if (rv == PR_FAILURE) {
PR_DELETE(process);
return PR_FAILURE;
}
return PR_SUCCESS;
}
PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
{
return _PR_MD_DETACH_PROCESS(process);
}
PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
{
return _PR_MD_WAIT_PROCESS(process, exitCode);
} /* PR_WaitProcess */
PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
{
return _PR_MD_KILL_PROCESS(process);
}
/*
********************************************************************
*
* Module initialization
*
********************************************************************
*/
static struct {
PRLock *ml;
PRCondVar *cv;
} mod_init;
static void _PR_InitCallOnce(void) {
mod_init.ml = PR_NewLock();
PR_ASSERT(NULL != mod_init.ml);
mod_init.cv = PR_NewCondVar(mod_init.ml);
PR_ASSERT(NULL != mod_init.cv);
}
void _PR_CleanupCallOnce()
{
PR_DestroyLock(mod_init.ml);
mod_init.ml = NULL;
PR_DestroyCondVar(mod_init.cv);
mod_init.cv = NULL;
}
PR_IMPLEMENT(PRStatus) PR_CallOnce(
PRCallOnceType *once,
PRCallOnceFN func)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
if (!once->initialized) {
if (PR_AtomicSet(&once->inProgress, 1) == 0) {
once->status = (*func)();
PR_Lock(mod_init.ml);
once->initialized = 1;
PR_NotifyAllCondVar(mod_init.cv);
PR_Unlock(mod_init.ml);
} else {
PR_Lock(mod_init.ml);
while (!once->initialized) {
PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
}
PR_Unlock(mod_init.ml);
}
}
return once->status;
}
PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
PRCallOnceType *once,
PRCallOnceWithArgFN func,
void *arg)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
if (!once->initialized) {
if (PR_AtomicSet(&once->inProgress, 1) == 0) {
once->status = (*func)(arg);
PR_Lock(mod_init.ml);
once->initialized = 1;
PR_NotifyAllCondVar(mod_init.cv);
PR_Unlock(mod_init.ml);
} else {
PR_Lock(mod_init.ml);
while (!once->initialized) {
PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
}
PR_Unlock(mod_init.ml);
}
}
return once->status;
}
PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
{
#if defined(DEBUG)
#ifndef XP_MAC
PR_fprintf(
PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
obsolete, (NULL == preferred) ? "something else" : preferred);
#else
#pragma unused (obsolete, preferred)
#endif
#endif
return PR_FALSE;
} /* _PR_Obsolete */
/* prinit.c */
+157
View File
@@ -0,0 +1,157 @@
/* -*- 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: prinrval.c
* description: implementation for the kernel interval timing functions
*/
#include "primpl.h"
/*
*-----------------------------------------------------------------------
*
* _PR_InitClock --
*
*
*-----------------------------------------------------------------------
*/
void _PR_InitClock(void)
{
_PR_MD_INTERVAL_INIT();
#ifdef DEBUG
{
PRIntervalTime ticksPerSec = PR_TicksPerSecond();
PR_ASSERT(ticksPerSec >= PR_INTERVAL_MIN);
PR_ASSERT(ticksPerSec <= PR_INTERVAL_MAX);
}
#endif /* DEBUG */
}
/*
* This version of interval times is based on the time of day
* capability offered by system. This isn't valid for two reasons:
* 1) The time of day is neither linear nor montonically increasing
* 2) The units here are milliseconds. That's not appropriate for our use.
*/
PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
return _PR_MD_GET_INTERVAL();
} /* PR_IntervalNow */
PR_EXTERN(PRUint32) PR_TicksPerSecond(void)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
return _PR_MD_INTERVAL_PER_SEC();
} /* PR_TicksPerSecond */
PR_IMPLEMENT(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds)
{
return seconds * PR_TicksPerSecond();
} /* PR_SecondsToInterval */
PR_IMPLEMENT(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli)
{
PRIntervalTime ticks;
PRUint64 tock, tps, msecPerSec, rounding;
LL_UI2L(tock, milli);
LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
LL_I2L(rounding, (PR_MSEC_PER_SEC >> 1));
LL_I2L(tps, PR_TicksPerSecond());
LL_MUL(tock, tock, tps);
LL_ADD(tock, tock, rounding);
LL_DIV(tock, tock, msecPerSec);
LL_L2UI(ticks, tock);
return ticks;
} /* PR_MillisecondsToInterval */
PR_IMPLEMENT(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro)
{
PRIntervalTime ticks;
PRUint64 tock, tps, usecPerSec, rounding;
LL_UI2L(tock, micro);
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_I2L(rounding, (PR_USEC_PER_SEC >> 1));
LL_I2L(tps, PR_TicksPerSecond());
LL_MUL(tock, tock, tps);
LL_ADD(tock, tock, rounding);
LL_DIV(tock, tock, usecPerSec);
LL_L2UI(ticks, tock);
return ticks;
} /* PR_MicrosecondsToInterval */
PR_IMPLEMENT(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks)
{
return ticks / PR_TicksPerSecond();
} /* PR_IntervalToSeconds */
PR_IMPLEMENT(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks)
{
PRUint32 milli;
PRUint64 tock, tps, msecPerSec, rounding;
LL_UI2L(tock, ticks);
LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
LL_I2L(tps, PR_TicksPerSecond());
LL_USHR(rounding, tps, 1);
LL_MUL(tock, tock, msecPerSec);
LL_ADD(tock, tock, rounding);
LL_DIV(tock, tock, tps);
LL_L2UI(milli, tock);
return milli;
} /* PR_IntervalToMilliseconds */
PR_IMPLEMENT(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks)
{
PRUint32 micro;
PRUint64 tock, tps, usecPerSec, rounding;
LL_UI2L(tock, ticks);
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
LL_I2L(tps, PR_TicksPerSecond());
LL_USHR(rounding, tps, 1);
LL_MUL(tock, tock, usecPerSec);
LL_ADD(tock, tock, rounding);
LL_DIV(tock, tock, tps);
LL_L2UI(micro, tock);
return micro;
} /* PR_IntervalToMicroseconds */
/* prinrval.c */
+132
View File
@@ -0,0 +1,132 @@
/* -*- 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 ***** */
/*
* File: pripc.c
*
* Description: functions for IPC support
*/
#include "primpl.h"
#include <string.h>
/*
* A POSIX IPC name must begin with a '/'.
* A POSIX IPC name on Solaris cannot contain any '/' except
* the required leading '/'.
* A POSIX IPC name on HP-UX and OSF1 must be a valid pathname
* in the file system.
*
* The ftok() function for System V IPC requires a valid pathname
* in the file system.
*
* A Win32 IPC name cannot contain '\'.
*/
static void _pr_ConvertSemName(char *result)
{
#ifdef _PR_HAVE_POSIX_SEMAPHORES
#if defined(SOLARIS)
char *p;
/* Convert '/' to '_' except for the leading '/' */
for (p = result+1; *p; p++) {
if (*p == '/') {
*p = '_';
}
}
return;
#else
return;
#endif
#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
return;
#elif defined(WIN32)
return;
#endif
}
static void _pr_ConvertShmName(char *result)
{
#if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY)
#if defined(SOLARIS)
char *p;
/* Convert '/' to '_' except for the leading '/' */
for (p = result+1; *p; p++) {
if (*p == '/') {
*p = '_';
}
}
return;
#else
return;
#endif
#elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY)
return;
#elif defined(WIN32)
return;
#else
return;
#endif
}
PRStatus _PR_MakeNativeIPCName(
const char *name,
char *result,
PRIntn size,
_PRIPCType type)
{
if (strlen(name) >= (PRSize)size) {
PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
return PR_FAILURE;
}
strcpy(result, name);
switch (type) {
case _PRIPCSem:
_pr_ConvertSemName(result);
break;
case _PRIPCShm:
_pr_ConvertShmName(result);
break;
default:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
return PR_SUCCESS;
}
+130
View File
@@ -0,0 +1,130 @@
/* -*- 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 ***** */
/*
* File: pripcsem.c
*
* Description: implements the named semaphores API in prsemipc.h
* for classic NSPR. If _PR_HAVE_NAMED_SEMAPHORES is not defined,
* the named semaphore functions all fail with the error code
* PR_NOT_IMPLEMENTED_ERROR.
*/
#include "primpl.h"
#ifdef _PR_PTHREADS
#error "This file should not be compiled for the pthreads version"
#else
#ifndef _PR_HAVE_NAMED_SEMAPHORES
PRSem * _PR_MD_OPEN_SEMAPHORE(
const char *osname, PRIntn flags, PRIntn mode, PRUintn value)
{
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return NULL;
}
PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem)
{
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return PR_FAILURE;
}
PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem)
{
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return PR_FAILURE;
}
PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem)
{
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return PR_FAILURE;
}
PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname)
{
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return PR_FAILURE;
}
#endif /* !_PR_HAVE_NAMED_SEMAPHORES */
PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
const char *name, PRIntn flags, PRIntn mode, PRUintn value)
{
char osname[PR_IPC_NAME_SIZE];
if (!_pr_initialized) _PR_ImplicitInitialization();
if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
== PR_FAILURE) {
return NULL;
}
return _PR_MD_OPEN_SEMAPHORE(osname, flags, mode, value);
}
PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
{
return _PR_MD_WAIT_SEMAPHORE(sem);
}
PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
{
return _PR_MD_POST_SEMAPHORE(sem);
}
PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
{
return _PR_MD_CLOSE_SEMAPHORE(sem);
}
PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
{
char osname[PR_IPC_NAME_SIZE];
if (!_pr_initialized) _PR_ImplicitInitialization();
if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
== PR_FAILURE) {
return PR_FAILURE;
}
return _PR_MD_DELETE_SEMAPHORE(osname);
}
#endif /* _PR_PTHREADS */
+81
View File
@@ -0,0 +1,81 @@
/* -*- 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"
/*
** Compute the log of the least power of 2 greater than or equal to n
*/
PR_IMPLEMENT(PRIntn) PR_CeilingLog2(PRUint32 n)
{
PRIntn log2 = 0;
if (n & (n-1))
log2++;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}
/*
** Compute the log of the greatest power of 2 less than or equal to n.
** This really just finds the highest set bit in the word.
*/
PR_IMPLEMENT(PRIntn) PR_FloorLog2(PRUint32 n)
{
PRIntn log2 = 0;
if (n >> 16)
log2 += 16, n >>= 16;
if (n >> 8)
log2 += 8, n >>= 8;
if (n >> 4)
log2 += 4, n >>= 4;
if (n >> 2)
log2 += 2, n >>= 2;
if (n >> 1)
log2++;
return log2;
}
+282
View File
@@ -0,0 +1,282 @@
/* -*- 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"
static PRInt64 ll_zero = LL_INIT( 0x00000000,0x00000000 );
static PRInt64 ll_maxint = LL_INIT( 0x7fffffff, 0xffffffff );
static PRInt64 ll_minint = LL_INIT( 0x80000000, 0x00000000 );
static PRUint64 ll_maxuint = LL_INIT( 0xffffffff, 0xffffffff );
#if defined(HAVE_WATCOM_BUG_2)
PRInt64 __pascal __loadds __export
LL_Zero(void) { return ll_zero; }
PRInt64 __pascal __loadds __export
LL_MaxInt(void) { return ll_maxint; }
PRInt64 __pascal __loadds __export
LL_MinInt(void) { return ll_minint; }
PRUint64 __pascal __loadds __export
LL_MaxUint(void) { return ll_maxuint; }
#else
PR_IMPLEMENT(PRInt64) LL_Zero(void) { return ll_zero; }
PR_IMPLEMENT(PRInt64) LL_MaxInt(void) { return ll_maxint; }
PR_IMPLEMENT(PRInt64) LL_MinInt(void) { return ll_minint; }
PR_IMPLEMENT(PRUint64) LL_MaxUint(void) { return ll_maxuint; }
#endif
#ifndef HAVE_LONG_LONG
/*
** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1.
*/
static void norm_udivmod32(PRUint32 *qp, PRUint32 *rp, PRUint64 a, PRUint32 b)
{
PRUint32 d1, d0, q1, q0;
PRUint32 r1, r0, m;
d1 = _hi16(b);
d0 = _lo16(b);
r1 = a.hi % d1;
q1 = a.hi / d1;
m = q1 * d0;
r1 = (r1 << 16) | _hi16(a.lo);
if (r1 < m) {
q1--, r1 += b;
if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */
&& r1 < m) {
q1--, r1 += b;
}
}
r1 -= m;
r0 = r1 % d1;
q0 = r1 / d1;
m = q0 * d0;
r0 = (r0 << 16) | _lo16(a.lo);
if (r0 < m) {
q0--, r0 += b;
if (r0 >= b
&& r0 < m) {
q0--, r0 += b;
}
}
*qp = (q1 << 16) | q0;
*rp = r0 - m;
}
static PRUint32 CountLeadingZeros(PRUint32 a)
{
PRUint32 t;
PRUint32 r = 32;
if ((t = a >> 16) != 0)
r -= 16, a = t;
if ((t = a >> 8) != 0)
r -= 8, a = t;
if ((t = a >> 4) != 0)
r -= 4, a = t;
if ((t = a >> 2) != 0)
r -= 2, a = t;
if ((t = a >> 1) != 0)
r -= 1, a = t;
if (a & 1)
r--;
return r;
}
PR_IMPLEMENT(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b)
{
PRUint32 n0, n1, n2;
PRUint32 q0, q1;
PRUint32 rsh, lsh;
n0 = a.lo;
n1 = a.hi;
if (b.hi == 0) {
if (b.lo > n1) {
/* (0 q0) = (n1 n0) / (0 D0) */
lsh = CountLeadingZeros(b.lo);
if (lsh) {
/*
* Normalize, i.e. make the most significant bit of the
* denominator be set.
*/
b.lo = b.lo << lsh;
n1 = (n1 << lsh) | (n0 >> (32 - lsh));
n0 = n0 << lsh;
}
a.lo = n0, a.hi = n1;
norm_udivmod32(&q0, &n0, a, b.lo);
q1 = 0;
/* remainder is in n0 >> lsh */
} else {
/* (q1 q0) = (n1 n0) / (0 d0) */
if (b.lo == 0) /* user wants to divide by zero! */
b.lo = 1 / b.lo; /* so go ahead and crash */
lsh = CountLeadingZeros(b.lo);
if (lsh == 0) {
/*
* From (n1 >= b.lo)
* && (the most significant bit of b.lo is set),
* conclude that
* (the most significant bit of n1 is set)
* && (the leading quotient digit q1 = 1).
*
* This special case is necessary, not an optimization
* (Shifts counts of 32 are undefined).
*/
n1 -= b.lo;
q1 = 1;
} else {
/*
* Normalize.
*/
rsh = 32 - lsh;
b.lo = b.lo << lsh;
n2 = n1 >> rsh;
n1 = (n1 << lsh) | (n0 >> rsh);
n0 = n0 << lsh;
a.lo = n1, a.hi = n2;
norm_udivmod32(&q1, &n1, a, b.lo);
}
/* n1 != b.lo... */
a.lo = n0, a.hi = n1;
norm_udivmod32(&q0, &n0, a, b.lo);
/* remainder in n0 >> lsh */
}
if (rp) {
rp->lo = n0 >> lsh;
rp->hi = 0;
}
} else {
if (b.hi > n1) {
/* (0 0) = (n1 n0) / (D1 d0) */
q0 = 0;
q1 = 0;
/* remainder in (n1 n0) */
if (rp) {
rp->lo = n0;
rp->hi = n1;
}
} else {
/* (0 q0) = (n1 n0) / (d1 d0) */
lsh = CountLeadingZeros(b.hi);
if (lsh == 0) {
/*
* From (n1 >= b.hi)
* && (the most significant bit of b.hi is set),
* conclude that
* (the most significant bit of n1 is set)
* && (the quotient digit q0 = 0 or 1).
*
* This special case is necessary, not an optimization.
*/
/*
* The condition on the next line takes advantage of that
* n1 >= b.hi (true due to control flow).
*/
if (n1 > b.hi || n0 >= b.lo) {
q0 = 1;
a.lo = n0, a.hi = n1;
LL_SUB(a, a, b);
} else {
q0 = 0;
}
q1 = 0;
if (rp) {
rp->lo = n0;
rp->hi = n1;
}
} else {
PRInt64 m;
/*
* Normalize.
*/
rsh = 32 - lsh;
b.hi = (b.hi << lsh) | (b.lo >> rsh);
b.lo = b.lo << lsh;
n2 = n1 >> rsh;
n1 = (n1 << lsh) | (n0 >> rsh);
n0 = n0 << lsh;
a.lo = n1, a.hi = n2;
norm_udivmod32(&q0, &n1, a, b.hi);
LL_MUL32(m, q0, b.lo);
if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) {
q0--;
LL_SUB(m, m, b);
}
q1 = 0;
/* Remainder is ((n1 n0) - (m1 m0)) >> lsh */
if (rp) {
a.lo = n0, a.hi = n1;
LL_SUB(a, a, m);
rp->lo = (a.hi << rsh) | (a.lo >> lsh);
rp->hi = a.hi >> lsh;
}
}
}
}
if (qp) {
qp->lo = q0;
qp->hi = q1;
}
}
#endif /* !HAVE_LONG_LONG */
File diff suppressed because it is too large. Load diff
+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 ***** */
/*
** prolock.c -- NSPR Ordered Lock
**
** Implement the API defined in prolock.h
**
*/
#include "prolock.h"
#include "prlog.h"
#include "prerror.h"
PR_IMPLEMENT(PROrderedLock *)
PR_CreateOrderedLock(
PRInt32 order,
const char *name
)
{
#ifdef XP_MAC
#pragma unused( order, name )
#endif
PR_ASSERT(!"Not implemented"); /* Not implemented yet */
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return NULL;
} /* end PR_CreateOrderedLock() */
PR_IMPLEMENT(void)
PR_DestroyOrderedLock(
PROrderedLock *lock
)
{
#ifdef XP_MAC
#pragma unused( lock )
#endif
PR_ASSERT(!"Not implemented"); /* Not implemented yet */
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
} /* end PR_DestroyOrderedLock() */
PR_IMPLEMENT(void)
PR_LockOrderedLock(
PROrderedLock *lock
)
{
#ifdef XP_MAC
#pragma unused( lock )
#endif
PR_ASSERT(!"Not implemented"); /* Not implemented yet */
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
} /* end PR_LockOrderedLock() */
PR_IMPLEMENT(PRStatus)
PR_UnlockOrderedLock(
PROrderedLock *lock
)
{
#ifdef XP_MAC
#pragma unused( lock )
#endif
PR_ASSERT(!"Not implemented"); /* Not implemented yet */
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return PR_FAILURE;
} /* end PR_UnlockOrderedLock() */
+76
View File
@@ -0,0 +1,76 @@
/* -*- 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"
/*
* We were not including <string.h> in optimized builds. On AIX this
* caused libnspr4.so to export memcpy and some binaries linked with
* libnspr4.so resolved their memcpy references with libnspr4.so. To
* be backward compatible with old libnspr4.so binaries, we do not
* include <string.h> in optimized builds for AIX. (bug 200561)
*/
#if !(defined(AIX) && !defined(DEBUG))
#include <string.h>
#endif
PRSize _pr_CopyLowBits(
void *dst,
PRSize dstlen,
void *src,
PRSize srclen )
{
if (srclen <= dstlen) {
memcpy(dst, src, srclen);
return srclen;
}
#if defined IS_BIG_ENDIAN
memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
#else
memcpy(dst, src, dstlen);
#endif
return dstlen;
}
PR_IMPLEMENT(PRSize) PR_GetRandomNoise(
void *buf,
PRSize size
)
{
return( _PR_MD_GET_RANDOM_NOISE( buf, size ));
} /* end PR_GetRandomNoise() */
/* end prrng.c */
+366
View File
@@ -0,0 +1,366 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; 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 "prsystem.h"
#include "prprf.h"
#include "prlong.h"
#if defined(BEOS)
#include <kernel/OS.h>
#endif
#if defined(OS2)
#define INCL_DOS
#define INCL_DOSMISC
#include <os2.h>
/* define the required constant if it is not already defined in the headers */
#ifndef QSV_NUMPROCESSORS
#define QSV_NUMPROCESSORS 26
#endif
#endif
/* BSD-derived systems use sysctl() to get the number of processors */
#if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
|| defined(OPENBSD) || defined(DARWIN)
#define _PR_HAVE_SYSCTL
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#if defined(DARWIN)
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#endif
#if defined(HPUX)
#include <sys/mpctl.h>
#include <sys/pstat.h>
#endif
#if defined(XP_UNIX)
#include <unistd.h>
#include <sys/utsname.h>
#endif
#if defined(AIX)
#include <cf.h>
#include <sys/cfgodm.h>
#endif
#if defined(WIN32)
/* This struct is not present in VC6 headers, so declare it here */
typedef struct {
DWORD dwLength;
DWORD dwMemoryLoad;
DWORDLONG ullTotalPhys;
DWORDLONG ullAvailPhys;
DWORDLONG ullToalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
} PR_MEMORYSTATUSEX;
/* Typedef for dynamic lookup of GlobalMemoryStatusEx(). */
typedef BOOL (WINAPI *GlobalMemoryStatusExFn)(PR_MEMORYSTATUSEX *);
#endif
PR_IMPLEMENT(char) PR_GetDirectorySeparator(void)
{
return PR_DIRECTORY_SEPARATOR;
} /* PR_GetDirectorySeparator */
/*
** OBSOLETE -- the function name is misspelled.
*/
PR_IMPLEMENT(char) PR_GetDirectorySepartor(void)
{
#if defined(DEBUG)
static PRBool warn = PR_TRUE;
if (warn) {
warn = _PR_Obsolete("PR_GetDirectorySepartor()",
"PR_GetDirectorySeparator()");
}
#endif
return PR_GetDirectorySeparator();
} /* PR_GetDirectorySepartor */
PR_IMPLEMENT(char) PR_GetPathSeparator(void)
{
return PR_PATH_SEPARATOR;
} /* PR_GetPathSeparator */
PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen)
{
PRUintn len = 0;
if (!_pr_initialized) _PR_ImplicitInitialization();
switch(cmd)
{
case PR_SI_HOSTNAME:
case PR_SI_HOSTNAME_UNTRUNCATED:
if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen))
return PR_FAILURE;
if (cmd == PR_SI_HOSTNAME_UNTRUNCATED)
break;
/*
* On some platforms a system does not have a hostname and
* its IP address is returned instead. The following code
* should be skipped on those platforms.
*/
#ifndef _PR_GET_HOST_ADDR_AS_NAME
/* Return the unqualified hostname */
while (buf[len] && (len < buflen)) {
if (buf[len] == '.') {
buf[len] = '\0';
break;
}
len += 1;
}
#endif
break;
case PR_SI_SYSNAME:
/* Return the operating system name */
#if defined(XP_UNIX) || defined(WIN32)
if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
return PR_FAILURE;
#else
(void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME);
#endif
break;
case PR_SI_RELEASE:
/* Return the version of the operating system */
#if defined(XP_UNIX) || defined(WIN32)
if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
return PR_FAILURE;
#endif
#if defined(XP_OS2)
{
ULONG os2ver[2] = {0};
DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION,
&os2ver, sizeof(os2ver));
/* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially,
Warp 4 is version 2.40.00, WSeB 2.45.00 */
if (os2ver[0] < 30)
(void)PR_snprintf(buf, buflen, "%s%lu",
"2.", os2ver[0]);
else if (os2ver[0] < 45)
(void)PR_snprintf(buf, buflen, "%lu%s%lu",
os2ver[0]/10, ".", os2ver[1]);
else
(void)PR_snprintf(buf, buflen, "%.1f",
os2ver[0]/10.0);
}
#endif /* OS2 */
break;
case PR_SI_ARCHITECTURE:
/* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/
(void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE);
break;
default:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
return PR_SUCCESS;
}
/*
** PR_GetNumberOfProcessors()
**
** Implementation notes:
** Every platform does it a bit different.
** numCpus is the returned value.
** for each platform's "if defined" section
** declare your local variable
** do your thing, assign to numCpus
** order of the if defined()s may be important,
** especially for unix variants. Do platform
** specific implementations before XP_UNIX.
**
*/
PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void )
{
PRInt32 numCpus;
#if defined(WIN32)
SYSTEM_INFO info;
GetSystemInfo( &info );
numCpus = info.dwNumberOfProcessors;
#elif defined(XP_MAC)
/* Hard-code the number of processors to 1 on the Mac
** MacOS/9 will always be 1. The MPProcessors() call is for
** MacOS/X, when issued. Leave it commented out for now. */
/* numCpus = MPProcessors(); */
numCpus = 1;
#elif defined(BEOS)
system_info sysInfo;
get_system_info(&sysInfo);
numCpus = sysInfo.cpu_count;
#elif defined(OS2)
DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus));
#elif defined(_PR_HAVE_SYSCTL)
int mib[2];
int rc;
size_t len = sizeof(numCpus);
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 );
if ( -1 == rc ) {
numCpus = -1; /* set to -1 for return value on error */
_PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
}
#elif defined(HPUX)
numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 );
if ( numCpus < 1 ) {
numCpus = -1; /* set to -1 for return value on error */
_PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
}
#elif defined(IRIX)
numCpus = sysconf( _SC_NPROC_ONLN );
#elif defined(RISCOS)
numCpus = 1;
#elif defined(XP_UNIX)
numCpus = sysconf( _SC_NPROCESSORS_ONLN );
#else
#error "An implementation is required"
#endif
return(numCpus);
} /* end PR_GetNumberOfProcessors() */
/*
** PR_GetPhysicalMemorySize()
**
** Implementation notes:
** Every platform does it a bit different.
** bytes is the returned value.
** for each platform's "if defined" section
** declare your local variable
** do your thing, assign to bytes.
**
*/
PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void)
{
PRUint64 bytes = 0;
#if defined(LINUX) || defined(SOLARIS)
long pageSize = sysconf(_SC_PAGESIZE);
long pageCount = sysconf(_SC_PHYS_PAGES);
bytes = (PRUint64) pageSize * pageCount;
#elif defined(HPUX)
struct pst_static info;
int result = pstat_getstatic(&info, sizeof(info), 1, 0);
if (result == 1)
bytes = (PRUint64) info.physical_memory * info.page_size;
#elif defined(DARWIN)
struct host_basic_info hInfo;
mach_msg_type_number_t count;
int result = host_info(mach_host_self(),
HOST_BASIC_INFO,
(host_info_t) &hInfo,
&count);
if (result == KERN_SUCCESS)
bytes = hInfo.memory_size;
#elif defined(WIN32)
/* Try to use the newer GlobalMemoryStatusEx API for Windows 2000+. */
GlobalMemoryStatusExFn globalMemory = (GlobalMemoryStatusExFn) NULL;
HMODULE module = GetModuleHandle("kernel32.dll");
if (module) {
globalMemory = (GlobalMemoryStatusExFn)GetProcAddress(module, "GlobalMemoryStatusEx");
if (globalMemory) {
PR_MEMORYSTATUSEX memStat;
memStat.dwLength = sizeof(memStat);
if (globalMemory(&memStat))
bytes = memStat.ullTotalPhys;
}
}
if (!bytes) {
/* Fall back to the older API. */
MEMORYSTATUS memStat;
memset(&memStat, 0, sizeof(memStat));
GlobalMemoryStatus(&memStat);
bytes = memStat.dwTotalPhys;
}
#elif defined(OS2)
ULONG ulPhysMem;
DosQuerySysInfo(QSV_TOTPHYSMEM,
QSV_TOTPHYSMEM,
&ulPhysMem,
sizeof(ulPhysMem));
bytes = ulPhysMem;
#elif defined(AIX)
if (odm_initialize() == 0) {
int how_many;
struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many);
if (obj != NULL) {
bytes = (PRUint64) atoi(obj->value) * 1024;
free(obj);
}
odm_terminate();
}
#else
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
#endif
return bytes;
} /* end PR_GetPhysicalMemorySize() */
+247
View File
@@ -0,0 +1,247 @@
/* -*- 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 "prlog.h"
#include "prthread.h"
#ifdef XP_MAC
#include "pprthred.h"
#else
#include "private/pprthred.h"
#endif
#include "primpl.h"
PR_IMPLEMENT(PRWord *)
PR_GetGCRegisters(PRThread *t, int isCurrent, int *np)
{
return _MD_HomeGCRegisters(t, isCurrent, np);
}
PR_IMPLEMENT(PRStatus)
PR_ThreadScanStackPointers(PRThread* t,
PRScanStackFun scanFun, void* scanClosure)
{
PRThread* current = PR_GetCurrentThread();
PRWord *sp, *esp, *p0;
int n;
void **ptd;
PRStatus status;
PRUint32 index;
int stack_end;
/*
** Store the thread's registers in the thread structure so the GC
** can scan them. Then scan them.
*/
p0 = _MD_HomeGCRegisters(t, t == current, &n);
status = scanFun(t, (void**)p0, n, scanClosure);
if (status != PR_SUCCESS)
return status;
/* Scan the C stack for pointers into the GC heap */
#if defined(XP_PC) && defined(WIN16)
/*
** Under WIN16, the stack of the current thread is always mapped into
** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
** the "task stack". Otherwise, scan the "cached stack" of the inactive
** thread...
*/
if (t == current) {
sp = (PRWord*) &stack_end;
esp = (PRWord*) _pr_top_of_task_stack;
PR_ASSERT(sp <= esp);
} else {
sp = (PRWord*) PR_GetSP(t);
esp = (PRWord*) t->stack->stackTop;
PR_ASSERT((t->stack->stackSize == 0) ||
((sp > (PRWord*)t->stack->stackBottom) &&
(sp <= (PRWord*)t->stack->stackTop)));
}
#else /* ! WIN16 */
#ifdef HAVE_STACK_GROWING_UP
if (t == current) {
esp = (PRWord*) &stack_end;
} else {
esp = (PRWord*) PR_GetSP(t);
}
sp = (PRWord*) t->stack->stackTop;
if (t->stack->stackSize) {
PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
(esp < (PRWord*)t->stack->stackBottom));
}
#else /* ! HAVE_STACK_GROWING_UP */
if (t == current) {
sp = (PRWord*) &stack_end;
} else {
sp = (PRWord*) PR_GetSP(t);
}
esp = (PRWord*) t->stack->stackTop;
if (t->stack->stackSize) {
PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
(sp < (PRWord*)t->stack->stackTop));
}
#endif /* ! HAVE_STACK_GROWING_UP */
#endif /* ! WIN16 */
#if defined(WIN16)
{
prword_t scan;
prword_t limit;
scan = (prword_t) sp;
limit = (prword_t) esp;
while (scan < limit) {
prword_t *test;
test = *((prword_t **)scan);
status = scanFun(t, (void**)&test, 1, scanClosure);
if (status != PR_SUCCESS)
return status;
scan += sizeof(char);
}
}
#else
if (sp < esp) {
status = scanFun(t, (void**)sp, esp - sp, scanClosure);
if (status != PR_SUCCESS)
return status;
}
#endif
/*
** Mark all of the per-thread-data items attached to this thread
**
** The execution environment better be accounted for otherwise it
** will be collected
*/
status = scanFun(t, (void**)&t->environment, 1, scanClosure);
if (status != PR_SUCCESS)
return status;
#ifndef GC_LEAK_DETECTOR
/* if thread is not allocated on stack, this is redundant. */
ptd = t->privateData;
for (index = 0; index < t->tpdLength; index++, ptd++) {
status = scanFun(t, (void**)ptd, 1, scanClosure);
if (status != PR_SUCCESS)
return status;
}
#endif
return PR_SUCCESS;
}
/* transducer for PR_EnumerateThreads */
typedef struct PRScanStackData {
PRScanStackFun scanFun;
void* scanClosure;
} PRScanStackData;
static PRStatus PR_CALLBACK
pr_ScanStack(PRThread* t, int i, void* arg)
{
#if defined(XP_MAC)
#pragma unused (i)
#endif
PRScanStackData* data = (PRScanStackData*)arg;
return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure);
}
PR_IMPLEMENT(PRStatus)
PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure)
{
PRScanStackData data;
data.scanFun = scanFun;
data.scanClosure = scanClosure;
return PR_EnumerateThreads(pr_ScanStack, &data);
}
PR_IMPLEMENT(PRUword)
PR_GetStackSpaceLeft(PRThread* t)
{
PRThread *current = PR_GetCurrentThread();
PRWord *sp, *esp;
int stack_end;
#if defined(WIN16)
/*
** Under WIN16, the stack of the current thread is always mapped into
** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
** the "task stack". Otherwise, scan the "cached stack" of the inactive
** thread...
*/
if (t == current) {
sp = (PRWord*) &stack_end;
esp = (PRWord*) _pr_top_of_task_stack;
PR_ASSERT(sp <= esp);
} else {
sp = (PRWord*) PR_GetSP(t);
esp = (PRWord*) t->stack->stackTop;
PR_ASSERT((t->stack->stackSize == 0) ||
((sp > (PRWord*)t->stack->stackBottom) &&
(sp <= (PRWord*)t->stack->stackTop)));
}
#else /* ! WIN16 */
#ifdef HAVE_STACK_GROWING_UP
if (t == current) {
esp = (PRWord*) &stack_end;
} else {
esp = (PRWord*) PR_GetSP(t);
}
sp = (PRWord*) t->stack->stackTop;
if (t->stack->stackSize) {
PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
(esp < (PRWord*)t->stack->stackBottom));
}
#else /* ! HAVE_STACK_GROWING_UP */
if (t == current) {
sp = (PRWord*) &stack_end;
} else {
sp = (PRWord*) PR_GetSP(t);
}
esp = (PRWord*) t->stack->stackTop;
if (t->stack->stackSize) {
PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
(sp < (PRWord*)t->stack->stackTop));
}
#endif /* ! HAVE_STACK_GROWING_UP */
#endif /* ! WIN16 */
return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp);
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+922
View File
@@ -0,0 +1,922 @@
/* -*- 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 ***** */
/*
** prtrace.c -- NSPR Trace Instrumentation
**
** Implement the API defined in prtrace.h
**
**
**
*/
#include <string.h>
#include "prtrace.h"
#include "prclist.h"
#include "prlock.h"
#include "prcvar.h"
#include "prio.h"
#include "prlog.h"
#include "prenv.h"
#include "prmem.h"
#include "prerror.h"
#define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 )
#define DEFAULT_BUFFER_SEGMENTS 2
/*
** Enumerate states in a RName structure
*/
typedef enum TraceState
{
Running = 1,
Suspended = 2
} TraceState;
/*
** Define QName structure
*/
typedef struct QName
{
PRCList link;
PRCList rNameList;
char name[PRTRACE_NAME_MAX+1];
} QName;
/*
** Define RName structure
*/
typedef struct RName
{
PRCList link;
PRLock *lock;
QName *qName;
TraceState state;
char name[PRTRACE_NAME_MAX+1];
char desc[PRTRACE_DESC_MAX+1];
} RName;
/*
** The Trace Facility database
**
*/
static PRLogModuleInfo *lm;
static PRLock *traceLock; /* Facility Lock */
static PRCList qNameList; /* anchor to all QName structures */
static TraceState traceState = Running;
/*
** in-memory trace buffer controls
*/
static PRTraceEntry *tBuf; /* pointer to buffer */
static PRInt32 bufSize; /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */
static volatile PRInt32 next; /* index to next PRTraceEntry */
static PRInt32 last; /* index of highest numbered trace entry */
/*
** Real-time buffer capture controls
*/
static PRInt32 fetchLastSeen = 0;
static PRBool fetchLostData = PR_FALSE;
/*
** Buffer write-to-file controls
*/
static PRLock *logLock; /* Sync lock */
static PRCondVar *logCVar; /* Sync Condidtion Variable */
/*
** Inter-thread state communication.
** Controling thread writes to logOrder under protection of logCVar
** the logging thread reads logOrder and sets logState on Notify.
**
** logSegments, logCount, logLostData must be read and written under
** protection of logLock, logCVar.
**
*/
static enum LogState
{
LogNotRunning, /* Initial state */
LogReset, /* Causes logger to re-calc controls */
LogActive, /* Logging in progress, set only by log thread */
LogSuspend, /* Suspend Logging */
LogResume, /* Resume Logging => LogActive */
LogStop /* Stop the log thread */
} logOrder, logState, localState; /* controlling state variables */
static PRInt32 logSegments; /* Number of buffer segments */
static PRInt32 logEntries; /* number of Trace Entries in the buffer */
static PRInt32 logEntriesPerSegment; /* number of PRTraceEntries per buffer segment */
static PRInt32 logSegSize; /* size of buffer segment */
static PRInt32 logCount; /* number of segments pending output */
static PRInt32 logLostData; /* number of lost log buffer segments */
/*
** end Trace Database
**
*/
/*
** _PR_InitializeTrace() -- Initialize the trace facility
*/
static void NewTraceBuffer( PRInt32 size )
{
/*
** calculate the size of the buffer
** round down so that each segment has the same number of
** trace entries
*/
logSegments = DEFAULT_BUFFER_SEGMENTS;
logEntries = size / sizeof(PRTraceEntry);
logEntriesPerSegment = logEntries / logSegments;
logEntries = logSegments * logEntriesPerSegment;
bufSize = logEntries * sizeof(PRTraceEntry);
logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);
PR_ASSERT( bufSize != 0);
PR_LOG( lm, PR_LOG_ERROR,
("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",
logSegments, logEntries, logEntriesPerSegment, logSegSize ));
tBuf = PR_Malloc( bufSize );
if ( tBuf == NULL )
{
PR_LOG( lm, PR_LOG_ERROR,
("PRTrace: Failed to get trace buffer"));
PR_ASSERT( 0 );
}
else
{
PR_LOG( lm, PR_LOG_NOTICE,
("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));
}
next = 0;
last = logEntries -1;
logCount = 0;
logLostData = PR_TRUE; /* not really on first call */
logOrder = LogReset;
} /* end NewTraceBuffer() */
/*
** _PR_InitializeTrace() -- Initialize the trace facility
*/
static void _PR_InitializeTrace( void )
{
/* The lock pointer better be null on this call */
PR_ASSERT( traceLock == NULL );
traceLock = PR_NewLock();
PR_ASSERT( traceLock != NULL );
PR_Lock( traceLock );
PR_INIT_CLIST( &qNameList );
lm = PR_NewLogModule("trace");
bufSize = DEFAULT_TRACE_BUFSIZE;
NewTraceBuffer( bufSize );
/* Initialize logging controls */
logLock = PR_NewLock();
logCVar = PR_NewCondVar( logLock );
PR_Unlock( traceLock );
return;
} /* end _PR_InitializeTrace() */
/*
** Create a Trace Handle
*/
PR_IMPLEMENT(PRTraceHandle)
PR_CreateTrace(
const char *qName, /* QName for this trace handle */
const char *rName, /* RName for this trace handle */
const char *description /* description for this trace handle */
)
{
QName *qnp;
RName *rnp;
PRBool matchQname = PR_FALSE;
/* Self initialize, if necessary */
if ( traceLock == NULL )
_PR_InitializeTrace();
/* Validate input arguments */
PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );
PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );
PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );
PR_LOG( lm, PR_LOG_DEBUG,
("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));
/* Lock the Facility */
PR_Lock( traceLock );
/* Do we already have a matching QName? */
if (!PR_CLIST_IS_EMPTY( &qNameList ))
{
qnp = (QName *) PR_LIST_HEAD( &qNameList );
do {
if ( strcmp(qnp->name, qName) == 0)
{
matchQname = PR_TRUE;
break;
}
qnp = (QName *)PR_NEXT_LINK( &qnp->link );
} while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
}
/*
** If we did not find a matching QName,
** allocate one and initialize it.
** link it onto the qNameList.
**
*/
if ( matchQname != PR_TRUE )
{
qnp = PR_NEWZAP( QName );
PR_ASSERT( qnp != NULL );
PR_INIT_CLIST( &qnp->link );
PR_INIT_CLIST( &qnp->rNameList );
strcpy( qnp->name, qName );
PR_APPEND_LINK( &qnp->link, &qNameList );
}
/* Do we already have a matching RName? */
if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
{
rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
do {
/*
** No duplicate RNames are allowed within a QName
**
*/
PR_ASSERT( strcmp(rnp->name, rName));
rnp = (RName *)PR_NEXT_LINK( &rnp->link );
} while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
}
/* Get a new RName structure; initialize its members */
rnp = PR_NEWZAP( RName );
PR_ASSERT( rnp != NULL );
PR_INIT_CLIST( &rnp->link );
strcpy( rnp->name, rName );
strcpy( rnp->desc, description );
rnp->lock = PR_NewLock();
rnp->state = Running;
if ( rnp->lock == NULL )
{
PR_ASSERT(0);
}
PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
rnp->qName = qnp; /* point the RName to the QName */
/* Unlock the Facility */
PR_Unlock( traceLock );
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",
qName, qnp, rName, rnp ));
return((PRTraceHandle)rnp);
} /* end PR_CreateTrace() */
/*
**
*/
PR_IMPLEMENT(void)
PR_DestroyTrace(
PRTraceHandle handle /* Handle to be destroyed */
)
{
RName *rnp = (RName *)handle;
QName *qnp = rnp->qName;
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s",
qnp->name, rnp->name));
/* Lock the Facility */
PR_Lock( traceLock );
/*
** Remove RName from the list of RNames in QName
** and free RName
*/
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p",
rnp->name, rnp));
PR_REMOVE_LINK( &rnp->link );
PR_Free( rnp->lock );
PR_DELETE( rnp );
/*
** If this is the last RName within QName
** remove QName from the qNameList and free it
*/
if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
{
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p",
qnp->name, qnp));
PR_REMOVE_LINK( &qnp->link );
PR_DELETE( qnp );
}
/* Unlock the Facility */
PR_Unlock( traceLock );
return;
} /* end PR_DestroyTrace() */
/*
** Create a TraceEntry in the trace buffer
*/
PR_IMPLEMENT(void)
PR_Trace(
PRTraceHandle handle, /* use this trace handle */
PRUint32 userData0, /* User supplied data word 0 */
PRUint32 userData1, /* User supplied data word 1 */
PRUint32 userData2, /* User supplied data word 2 */
PRUint32 userData3, /* User supplied data word 3 */
PRUint32 userData4, /* User supplied data word 4 */
PRUint32 userData5, /* User supplied data word 5 */
PRUint32 userData6, /* User supplied data word 6 */
PRUint32 userData7 /* User supplied data word 7 */
)
{
PRTraceEntry *tep;
PRInt32 mark;
if ( (traceState == Suspended )
|| ( ((RName *)handle)->state == Suspended ))
return;
/*
** Get the next trace entry slot w/ minimum delay
*/
PR_Lock( traceLock );
tep = &tBuf[next++];
if ( next > last )
next = 0;
if ( fetchLostData == PR_FALSE && next == fetchLastSeen )
fetchLostData = PR_TRUE;
mark = next;
PR_Unlock( traceLock );
/*
** We have a trace entry. Fill it in.
*/
tep->thread = PR_GetCurrentThread();
tep->handle = handle;
tep->time = PR_Now();
tep->userData[0] = userData0;
tep->userData[1] = userData1;
tep->userData[2] = userData2;
tep->userData[3] = userData3;
tep->userData[4] = userData4;
tep->userData[5] = userData5;
tep->userData[6] = userData6;
tep->userData[7] = userData7;
/* When buffer segment is full, signal trace log thread to run */
if (( mark % logEntriesPerSegment) == 0 )
{
PR_Lock( logLock );
logCount++;
PR_NotifyCondVar( logCVar );
PR_Unlock( logLock );
/*
** Gh0D! This is awful!
** Anyway, to minimize lost trace data segments,
** I inserted the PR_Sleep(0) to cause a context switch
** so that the log thread could run.
** I know, it perturbs the universe and may cause
** funny things to happen in the optimized builds.
** Take it out, loose data; leave it in risk Heisenberg.
*/
/* PR_Sleep(0); */
}
return;
} /* end PR_Trace() */
/*
**
*/
PR_IMPLEMENT(void)
PR_SetTraceOption(
PRTraceOption command, /* One of the enumerated values */
void *value /* command value or NULL */
)
{
RName * rnp;
switch ( command )
{
case PRTraceBufSize :
PR_Lock( traceLock );
PR_Free( tBuf );
bufSize = *(PRInt32 *)value;
NewTraceBuffer( bufSize );
PR_Unlock( traceLock );
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));
break;
case PRTraceEnable :
rnp = *(RName **)value;
rnp->state = Running;
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceEnable: %p", rnp));
break;
case PRTraceDisable :
rnp = *(RName **)value;
rnp->state = Suspended;
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceDisable: %p", rnp));
break;
case PRTraceSuspend :
traceState = Suspended;
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceSuspend"));
break;
case PRTraceResume :
traceState = Running;
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceResume"));
break;
case PRTraceSuspendRecording :
PR_Lock( logLock );
logOrder = LogSuspend;
PR_NotifyCondVar( logCVar );
PR_Unlock( logLock );
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceSuspendRecording"));
break;
case PRTraceResumeRecording :
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceResumeRecording"));
if ( logState != LogSuspend )
break;
PR_Lock( logLock );
logOrder = LogResume;
PR_NotifyCondVar( logCVar );
PR_Unlock( logLock );
break;
case PRTraceStopRecording :
PR_Lock( logLock );
logOrder = LogStop;
PR_NotifyCondVar( logCVar );
PR_Unlock( logLock );
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceStopRecording"));
break;
case PRTraceLockHandles :
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceLockTraceHandles"));
PR_Lock( traceLock );
break;
case PRTraceUnLockHandles :
PR_LOG( lm, PR_LOG_DEBUG,
("PRSetTraceOption: PRTraceUnLockHandles"));
PR_Lock( traceLock );
break;
default:
PR_LOG( lm, PR_LOG_ERROR,
("PRSetTraceOption: Invalid command %ld", command ));
PR_ASSERT( 0 );
break;
} /* end switch() */
return;
} /* end PR_SetTraceOption() */
/*
**
*/
PR_IMPLEMENT(void)
PR_GetTraceOption(
PRTraceOption command, /* One of the enumerated values */
void *value /* command value or NULL */
)
{
switch ( command )
{
case PRTraceBufSize :
*((PRInt32 *)value) = bufSize;
PR_LOG( lm, PR_LOG_DEBUG,
("PRGetTraceOption: PRTraceBufSize: %ld", bufSize ));
break;
default:
PR_LOG( lm, PR_LOG_ERROR,
("PRGetTraceOption: Invalid command %ld", command ));
PR_ASSERT( 0 );
break;
} /* end switch() */
return;
} /* end PR_GetTraceOption() */
/*
**
*/
PR_IMPLEMENT(PRTraceHandle)
PR_GetTraceHandleFromName(
const char *qName, /* QName search argument */
const char *rName /* RName search argument */
)
{
const char *qn, *rn, *desc;
PRTraceHandle qh, rh = NULL;
RName *rnp = NULL;
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t"
"QName: %s, RName: %s", qName, rName ));
qh = PR_FindNextTraceQname( NULL );
while (qh != NULL)
{
rh = PR_FindNextTraceRname( NULL, qh );
while ( rh != NULL )
{
PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc );
if ( (strcmp( qName, qn ) == 0)
&& (strcmp( rName, rn ) == 0 ))
{
rnp = (RName *)rh;
goto foundIt;
}
rh = PR_FindNextTraceRname( rh, qh );
}
qh = PR_FindNextTraceQname( NULL );
}
foundIt:
PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
return(rh);
} /* end PR_GetTraceHandleFromName() */
/*
**
*/
PR_IMPLEMENT(void)
PR_GetTraceNameFromHandle(
PRTraceHandle handle, /* handle as search argument */
const char **qName, /* pointer to associated QName */
const char **rName, /* pointer to associated RName */
const char **description /* pointer to associated description */
)
{
RName *rnp = (RName *)handle;
QName *qnp = rnp->qName;
*qName = qnp->name;
*rName = rnp->name;
*description = rnp->desc;
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: "
"QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
qnp, rnp, qnp->name, rnp->name, rnp->desc ));
return;
} /* end PR_GetTraceNameFromHandle() */
/*
**
*/
PR_IMPLEMENT(PRTraceHandle)
PR_FindNextTraceQname(
PRTraceHandle handle
)
{
QName *qnp = (QName *)handle;
if ( PR_CLIST_IS_EMPTY( &qNameList ))
qnp = NULL;
else if ( qnp == NULL )
qnp = (QName *)PR_LIST_HEAD( &qNameList );
else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
qnp = NULL;
else
qnp = (QName *)PR_NEXT_LINK( &qnp->link );
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p",
handle, qnp ));
return((PRTraceHandle)qnp);
} /* end PR_FindNextTraceQname() */
/*
**
*/
PR_IMPLEMENT(PRTraceHandle)
PR_FindNextTraceRname(
PRTraceHandle rhandle,
PRTraceHandle qhandle
)
{
RName *rnp = (RName *)rhandle;
QName *qnp = (QName *)qhandle;
if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
rnp = NULL;
else if ( rnp == NULL )
rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
rnp = NULL;
else
rnp = (RName *)PR_NEXT_LINK( &rnp->link );
PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
rhandle, qhandle, rnp ));
return((PRTraceHandle)rnp);
} /* end PR_FindNextTraceRname() */
/*
**
*/
static PRFileDesc * InitializeRecording( void )
{
char *logFileName;
PRFileDesc *logFile;
/* Self initialize, if necessary */
if ( traceLock == NULL )
_PR_InitializeTrace();
PR_LOG( lm, PR_LOG_DEBUG,
("PR_RecordTraceEntries: begins"));
logLostData = 0; /* reset at entry */
logState = LogReset;
/* Get the filename for the logfile from the environment */
logFileName = PR_GetEnv( "NSPR_TRACE_LOG" );
if ( logFileName == NULL )
{
PR_LOG( lm, PR_LOG_ERROR,
("RecordTraceEntries: Environment variable not defined. Exiting"));
return NULL;
}
/* Open the logfile */
logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 );
if ( logFile == NULL )
{
PR_LOG( lm, PR_LOG_ERROR,
("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld",
logFileName, PR_GetOSError()));
return NULL;
}
return logFile;
} /* end InitializeRecording() */
/*
**
*/
static void ProcessOrders( void )
{
switch ( logOrder )
{
case LogReset :
logOrder = logState = localState;
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: LogReset"));
break;
case LogSuspend :
localState = logOrder = logState = LogSuspend;
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: LogSuspend"));
break;
case LogResume :
localState = logOrder = logState = LogActive;
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: LogResume"));
break;
case LogStop :
logOrder = logState = LogStop;
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: LogStop"));
break;
default :
PR_LOG( lm, PR_LOG_ERROR,
("RecordTraceEntries: Invalid logOrder: %ld", logOrder ));
PR_ASSERT( 0 );
break;
} /* end switch() */
return ;
} /* end ProcessOrders() */
/*
**
*/
static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount )
{
PRInt32 rc;
PR_LOG( lm, PR_LOG_ERROR,
("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount));
rc = PR_Write( logFile, buf , amount );
if ( rc == -1 )
PR_LOG( lm, PR_LOG_ERROR,
("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() ));
else if ( rc != amount )
PR_LOG( lm, PR_LOG_ERROR,
("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc));
else
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount));
return;
} /* end WriteTraceSegment() */
/*
**
*/
PR_IMPLEMENT(void)
PR_RecordTraceEntries(
void
)
{
PRFileDesc *logFile;
PRInt32 lostSegments;
PRInt32 currentSegment = 0;
void *buf;
PRBool doWrite;
logFile = InitializeRecording();
if ( logFile == NULL )
{
PR_LOG( lm, PR_LOG_DEBUG,
("PR_RecordTraceEntries: Failed to initialize"));
return;
}
/* Do this until told to stop */
while ( logState != LogStop )
{
PR_Lock( logLock );
while ( (logCount == 0) && ( logOrder == logState ) )
PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT );
/* Handle state transitions */
if ( logOrder != logState )
ProcessOrders();
/* recalculate local controls */
if ( logCount )
{
lostSegments = logCount - logSegments;
if ( lostSegments > 0 )
{
logLostData += ( logCount - logSegments );
logCount = (logCount % logSegments);
currentSegment = logCount;
PR_LOG( lm, PR_LOG_DEBUG,
("PR_RecordTraceEntries: LostData segments: %ld", logLostData));
}
else
{
logCount--;
}
buf = tBuf + ( logEntriesPerSegment * currentSegment );
if (++currentSegment >= logSegments )
currentSegment = 0;
doWrite = PR_TRUE;
}
else
doWrite = PR_FALSE;
PR_Unlock( logLock );
if ( doWrite == PR_TRUE )
{
if ( localState != LogSuspend )
WriteTraceSegment( logFile, buf, logSegSize );
else
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: PR_Write(): is suspended" ));
}
} /* end while(logState...) */
PR_Close( logFile );
PR_LOG( lm, PR_LOG_DEBUG,
("RecordTraceEntries: exiting"));
return;
} /* end PR_RecordTraceEntries() */
/*
**
*/
PR_IMPLEMENT(PRIntn)
PR_GetTraceEntries(
PRTraceEntry *buffer, /* where to write output */
PRInt32 count, /* number to get */
PRInt32 *found /* number you got */
)
{
PRInt32 rc;
PRInt32 copied = 0;
PR_Lock( traceLock );
/*
** Depending on where the LastSeen and Next indices are,
** copy the trace buffer in one or two pieces.
*/
PR_LOG( lm, PR_LOG_ERROR,
("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen));
if ( fetchLastSeen <= next )
{
while (( count-- > 0 ) && (fetchLastSeen < next ))
{
*(buffer + copied++) = *(tBuf + fetchLastSeen++);
}
PR_LOG( lm, PR_LOG_ERROR,
("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
}
else /* copy in 2 parts */
{
while ( count-- > 0 && fetchLastSeen <= last )
{
*(buffer + copied++) = *(tBuf + fetchLastSeen++);
}
fetchLastSeen = 0;
PR_LOG( lm, PR_LOG_ERROR,
("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
while ( count-- > 0 && fetchLastSeen < next )
{
*(buffer + copied++) = *(tBuf + fetchLastSeen++);
}
PR_LOG( lm, PR_LOG_ERROR,
("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
}
*found = copied;
rc = ( fetchLostData == PR_TRUE )? 1 : 0;
fetchLostData = PR_FALSE;
PR_Unlock( traceLock );
return rc;
} /* end PR_GetTraceEntries() */
/* end prtrace.c */