|
|
NSPR: Caveats
NSPR tries to provide a consistent level of service across the platforms
it supports. This has proven to be quite challenging, a challenge that
was met to a large degree, but there is always room for improvement. The
casual client may not encounter a need to know the details of the shortcomings
to the level described here, but if and when clients become more sophisticated,
these issues will certainly surface.
This memo is by no way complete.
Multiplatform
-
Do not call any blocking system call from a local thread. The only exception
to this rule is the select() and poll()
system calls on Unix, both of which NSPR has overridden to make sure they
are aware of the NSPR local threads.
-
In the combined (MxN) model, which includes NT, IRIX (sprocs), and pthreads-user,
the primordial thread is always a local thread. Therefore, if you
call a blocking system call from the primordial thread, it is going to
block more than just the primordial thread and the system may not function
correctly. On NT, this problem is especially obvious because the
idle thread, which is in charge of driving the asynch io completion port,
is also blocked. Do not call blocking system calls from the primordial
thread. Create a global thread and call the system call in that thread,
and have the primordial thread join that thread.
-
NSPR uses timer signals to implement thread preemption for local threads
on some platforms. If all the software linked into the application is not
ported to the NSPR API, the application may fail because of threads being
preempted during critical sections. To disable thread preemption call PR_DisableClockInterrupts()
during initialization.
-
Interrupting threads (via PR_Interrupt()) on threads blocked
in I/O functions is implemented to various degrees on different platforms.
The UNIX based platforms all implement the function though there may be
up to a 5 second delay in processing the request.
-
The mechanism used to implement PR_Interrupt() on the pthreads
versions of NSPR is flawed. No failure attributable to the flaw has shown
up in any tests or products - yet. The specific area surrounding pthread's
continuation thread has been both observed and empirically proven
faulty, and a correction identified.
Macintosh
-
The current port of NSPR for Macintosh will not be usable in its own right.
The implementation has dependencies on libraries that are implemented in
the Netscape Communicator. The work to undo this dependency has already
been started and the result will be made available soon.
-
Macintosh threads are not preemptable. As usual, it isn't that we couldn't
preempt them, but rather that the Macintosh libraries are not prepared
for such things to happen. NSPR does take advantage of Macintosh' asynchronous
I/O capability to perform scheduling during I/O. Still, there is no enforceable
mechanism to guarantee thread scheduling fairness.
-
Calendar time facilities are limited on Macintosh. One can only determine
the immediate setting of Daylight Savings Time, not what it would be at
some arbitrary time in the past or the future.
-
Initialization of NSPR may fail if the host is not connected to a network
of some kind.
WIN-16
The WIN-16 port is unique in the NSPR world in that it uses the WATCOM
development environment. This environment does bring along some of its
own special trappings.
-
Win16 uses co-operative non-preemptive dispatching for its own processes.
This means that when the application using NSPR is dispatched, a thread
within that application will run until that thread voluntarily gives up
control to another thread within the process. Further, the process in which
the threads are being emulated will run until it invokes some function
that gives control to Windows.
-
Windows 3.1 applications always run on a stack provided by Windows. This
means that NSPR threads use a shadow stack to preserve context across
a thread switch. At thread switch time, the stack of the current running
thread is copied to other storage associated with that thread and the about-to-be-dispatched
thread's stack data is copied back onto the Windows stack just before the
thread is given control. This has disastrous implications on the generally
accepted programming practice of taking the address of a stack variable
and giving that address to another thread.
Consider that the Windows stack is swapped in and out with each thread
switch. The thread that created a stack variable sees his own stack variables
correctly across thread switches. However, another thread does not see
the data as intended because the stack has been swapped out to the shadow
stack and the current thread's stack now occupies the Windows stack.
This can be difficult to diagnose.
For complete cross platform portability, do not take the address of
a stack variable and make that address available to another thread. For
more details, see the memo on Automatic Addresses.
-
Windows 3.1 does not support 64 bit file offsets. The NSPR 64 bit file
offset APIs map to Windows 3.1 32 bit file offset APIs. You may use NSPR's
64bit file offset APIs in your Windows 3.1 applications for cross platform
consistency, but do not expect to see real 64 bit file offset behavior.
On Windows 3.1, when NSPR detects a value in a 64 bit file offset greater
than 32bit significance, it terminates with an ASSERT.
-
The general rules of 16 bit Large Model memory restrictions apply to applications
using NSPR on Windows 3.1.
-
The NSPR Process Creation API functions return an error when invoked on
Windows 3.1.
-
Functions called in an application by a shared library require an additional
function prolog. The prolog is presented in the macro PR_CALLBACK.
For any function made available to any shared library (most likely passed
in as a function pointer), that function must have the PR_CALLBACK
qualifier.
-
NSPR functions are normally declared __cdecl. These declarations
are hidden in the PR_EXTERN() declarations in NSPR's header
files. NSPR functions returning floating point types and structs by value,
including the derived types PRInt64, are declared __PASCAL.
These different declarations are to accommodate restrictions in Watcom's
C/C++ version 11.0 and 11.0a compiler.
-
Windows 3.1 does not provide a non-blocking file I/O interface. NSPR's
file I/O is done using Windows 3.1's synchronous file I/O API. The NSPR
file I/O APIs may cause a thread switch even though the I/O is fully synchronous.
Do not depend on File I/O being synchronous.
-
Command line applications using the LIBC printf() and related APIs behave
funny on Windows 3.1. Read the fine print in the Windows SDK for the grizzly
details.
-
Watch out for PRIntn overflow on Win16. Make sure all possible values
of your PRIntn variables are within 2^16.
WIN-95
The WIN-95 version of NSPR should really be labeled WIN-32. The same library
will work on either WIN-NT or WIN-95.
-
WIN-95 NSPR uses native threads as NSPR threads. Generally speaking, the
native threads (on NT or '95) are quite functional. However, having lots
of them (100s or even 1000s) is unrealistic.
-
PR_Interrupt() is not implemented.
WIN-NT
The WIN-NT port of NSPR takes advantage of some of the features
of NT that are not available in WIN-95, such as fibers and asynch I/O.
The implementation is well suited for high performance application, such
as a server, but clients may find the WIN-95 version more suited (and adequate)
for interactive applications such as are prevalent on today's workstations.
-
The NT version implements a MxN threading model, using native NT threads
as the virtual processors and NT's fiber abstraction as the locally scheduled
threads. The fibers are nice because much of the NT API understands them.
But they are not really preemptable, and that can lead to problems, depending
on the needs of your application.
-
The mode (blocking or nonblocking) of a socket cannot be changed at will
once the socket has been used. Also, the new socket created by an
PR_Accept() call on a listening socket inherits the mode
of the listening socket, and cannot be changed.
-
A file descriptor is not usable after an IO operation on it fails with
either PR_IO_TIMEOUT_ERROR or PR_IO_INTERRUPT_ERROR.
The only thing you can do is to close the file descriptor. See the
FAQ article for more info. There is no current workaround. You must
write your program with this restriction in mind.
-
PR_Interrupt is implemented except for PR_Connect().
IRIX
-
The IRIX (classic) implementation has a known race condition in creating
new threads. If the spawned thread establishes and exits before the parent
thread is resumed, the parent will be left with an invalid pointer to the
child. The problem has a solution that will be available soon.
Digital Unix
-
Digital Unix (aka, OSF1) requires the latest patches for the pthreads library.
The changes are not evident until one tries to do thread suspension (PR_SuspendAll())
which is in preparation for garbage collection.
-
Digital Unix is the main platform used for NSPR's prototype use of IPv6.
There are some conflicts between the patches needed to use IPv6 and those
needed for pthreads. The IPv6 kit needs to be applied on a baseline configuration
of Digital Unix V4.0B.
Linux
-
The pthreads version of Linux (which is not the default) uses the same
signals that NSPR uses to suspend threads in preparation for garbage collection.
No solution in hand.
OS/2
-
The OS/2 port is not functional in its current state due to the requirement
to remove some files that could not be shipped under the NPL. This problem
has been resolved and an update will be appearing shortly.
Last updated: Tue Mar 10 10:31:39 PST
1998
Copyright © 1998 Netscape
Communications Corporation
|