mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-08 20:43:51 +00:00
add js to tree
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3693 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
855c7b9a77
commit
fff98f6316
1137 files changed
+386873
No files matched your search
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,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
|
||||
@@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 *) ⊤
|
||||
}
|
||||
#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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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() */
|
||||
@@ -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 */
|
||||
@@ -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() */
|
||||
@@ -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
@@ -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 */
|
||||
Reference in new issue
Block a user