Bug 1753127 - NSPR doc: Fix warnings and links r=kaie DONTBUILD

and remove the old doc
docs/nspr/porting_nspr_to_unix_platforms.rst

Differential Revision: https://phabricator.services.mozilla.com/D137979
This commit is contained in:
Sylvestre Ledru 2022-02-07 12:05:48 +00:00
parent e7eabe08f4
commit 909f96f128
4 changed files with 72 additions and 276 deletions

View File

@ -1,5 +1,5 @@
.. rubric:: NSPR 2.0: ``PR_Poll()`` and the layered I/O
:name: nspr-2.0-pr_poll-and-the-layered-io
PR_Poll() and the layered I/O
=============================
*[last edited by AOF 8 August 1998]*
This memo discusses some of the nuances of using PR_Poll() in
@ -7,30 +7,26 @@ conjunction with *layered I/O*. This is a relatively new feature in NSPR
2.0, not that it hasn't been in the source tree for a while, but in that
it has had no clients.
.. rubric:: Implementation
:name: implementation
Implementation
--------------
NSPR provides a public API function, PR_Poll() that is modeled after
UNIX' ``poll()`` system call.
The implementation of ``PR_Poll()`` is somewhat complicated. Not only
does it map the ``PRPollDesc`` array into structures needed by the
The implementation of :ref:`PR_Poll` is somewhat complicated. Not only
does it map the :ref:`PRPollDesc` array into structures needed by the
underlying OS, it also must deal with layered I/O. This is done despite
the fact that ``PR_Poll()`` itself is *not* layered. For every element
of the ``PRPollDesc`` array that has a non-NULL ``PRFileDesc`` and whose
the fact that :ref:`PR_Poll` itself is *not* layered. For every element
of the :ref:`PRPollDesc` array that has a non-NULL :ref:`PRFileDesc` and whose
``in_flags`` are not zero, it calls the file descriptor's
``poll() method``.
The ``poll()`` method is one of the vector contained in the
``PRIOMethods`` table. In the case of layered I/O, the elements (the
:ref:`PRIOMethods` table. In the case of layered I/O, the elements (the
methods) of the methods table may be overridden by the implementor of
that layer. The layers are then *stacked.* I/O using that *stack* will
call through the method at the top layer, and each layer may make
altering decisions regarding how the I/O operation should proceed.
| The signature for the ``poll()`` method is
The default implementation for this function is
The purpose of the ``poll()`` method is to allow a layer to modify the
flags that will ultimately be used in the call to the underlying OS'
``poll()`` (or equivalent) function. Such modification might be useful
@ -46,17 +42,17 @@ the number of bytes it is willing to receive (in the test code there are
no error conditions, so don't even ask).
The implication of the protocol is obvious. In order to do a
``PR_Send()`` operation, the layer must first do a *different* send and
:ref:`PR_Send` operation, the layer must first do a *different* send and
then *receive* a response. Doing this and keeping the *stack's* client
unaware is the goal. **It is not a goal of NSPR 2.0 to hide the nuances
of synchronous verses non-blocking I/O**\ *.*
of synchronous verses non-blocking I/O**.
.. rubric:: The layered methods
:name: the-layered-methods
The layered methods
-------------------
Each layer must implement a suitable function for *every* element of the
methods table. One can get a copy of default methods by calling
``PR_GetDefaultIOMethods().`` These methods simply pass all calls
:ref:`PR_GetDefaultIOMethods` These methods simply pass all calls
through the layer on to the next lower layer of the stack.
A layer implementor might copy the elements of the ``PRIOMethods``
@ -64,16 +60,17 @@ acquired from this function into a methods table of its own, then
override just those methods of interest. *Usually* (with only a single
exception) a layered method will perform its design duties and then call
the next lower layer's equivalent function.
.. rubric:: Layered ``poll()``
:name: layered-poll
Layered ``poll()``
------------------
One of the more interesting methods is the ``poll()``. It is called by
the runtime whenever the client calls ``PR_Poll()``. It may be called at
the runtime whenever the client calls :ref:`PR_Poll`. It may be called at
the *top* layer for *every* file descriptor in the poll descriptor. It
may be called zero or more times. The purpose of the ``poll()`` method
is to provide the layer an opportunity to adjust the polling bits as
needed. For instance, if a client (*i.e.*, top layer) is calling
``PR_Poll()`` for a particular file descriptor with a *read* poll
:ref:`PR_Poll` for a particular file descriptor with a *read* poll
request, a lower layer might decide that it must perform a *write*
first.
In that case, the layer's ``poll()`` method would be called with
@ -82,7 +79,7 @@ In that case, the layer's ``poll()`` method would be called with
with a ``PR_POLL_WRITE`` bit set. This process of re-assigning the poll
flags can happen as many times as there are layers in the stack. It is
the final value, the one returned to the caller of the top layer's
``poll()`` method (``PR_Poll()``) that will be used by the runtime when
``poll()`` method (:ref:`PR_Poll`) that will be used by the runtime when
calling the OS' ``poll()`` (or equivalent) system call.
It is expected that the modification of the polling bits propagate from
@ -115,7 +112,7 @@ still confirm with the OS that such an operation is permitted.
Since the ``poll()`` method may be called zero or more times it must
therefore be *idempotent* or at least *functional*. It will need to look
at the layer's state, but must not make modifications to that state that
would cause subsequent calls within the same ``PR_Poll()`` call to
would cause subsequent calls within the same :ref:`PR_Poll` call to
return a different answer. Since the ``poll()`` method may not be called
at all, so there is not guarantee that any modifications that would have
been performed by the routine will every happen.

View File

@ -1,5 +1,5 @@
.. rubric:: NSPR 2.0: Non-blocking layered I/O
:name: nspr-2.0-non-blocking-layered-io
Non-blocking layered I/O
========================
*[last edited by AOF 24 March 1998 14:15]*
I've recently been working on a long standing issue regarding NSPR's I/O
@ -13,19 +13,19 @@ This memo is some of what I think must be done in NSPR's I/O subsystem
to make layered, non-blocking protocols workable. It is just a proposal.
There is an API change.
.. rubric:: Layered I/O
:name: layered-io
Layered I/O
-----------
NSPR 2.0 defines a structure by which one may define I/O layers. Each
layer looks basically like any other in that it still uses a
**``PRFileDesc``** as a object identifier, complete with the
:ref:`PRFileDesc` as a object identifier, complete with the
**``IOMethods``** table of functions. However, each layer may override
default behavior of a particular operation to implement other services.
For instance, the experiment at hand is one that implements a little
reliable echo protocol; the client sends *n* bytes, and the same bytes
get echoed back by the server. In the non-layered design of this it is
straight forward.
The goal of the experiment  was to put a layer between the client and
The goal of the experiment was to put a layer between the client and
the network, and not have the client know about it. This additional
layer is one that, before sending the client's data, must ask permission
from the peer layer to send that many bytes. It imposes an additional
@ -37,43 +37,43 @@ that data to be sent, then actually receiving the data itself, which is
delivered to the client.
The synchronous form of the layer's operation is straight forward. A
call to receive (**``PR_Recv()``**) first receives the request to send,
sends (**``PR_Send()``**) the grant, then receives the actual data
(**``PR_Recv()``**). All the client of the layer sees is the data coming
call to receive (:ref:`PR_Recv`) first receives the request to send,
sends (:ref:`PR_Send`) the grant, then receives the actual data
(:ref:`PR_Recv`). All the client of the layer sees is the data coming
in. Similar behavior is observed on the sending side.
.. rubric:: Non-blocking layered I/O
:name: non-blocking-layered-io
Non-blocking layered
--------------------
The non-blocking method is not so simple. Any of the I/O operations
potentially result in an indication that no progress can be made. The
intermediate layers cannot act directly on this information, but must
store the state of the I/O operation until it can be resumed. The method
for determining that a I/O operation can make progress is to call
**``PR_Poll()``** and indicating what type of progress is desired,
:ref:`PR_Poll` and indicating what type of progress is desired,
either input or output (or some others). Therein lies the problem.
The intermediate layer is performing operations that the client is
unaware. So when the client calls send (**``PR_Send()``**) and is told
unaware. So when the client calls send (:ref:`PR_Send`) and is told
that the operation would block, it is possible that the layer below is
actually doing a receive (**``PR_Recv()``**). The problem is that the
flag bits passed to **``PR_Poll()``**\ are only reflective of the
actually doing a receive (:ref:`PR_Recv`). The problem is that the
flag bits passed to :ref:`PR_Poll` are only reflective of the
client's knowledge and desires. This is further complicated by the fact
that **``PR_Poll()``** is not layered. That is each layer does not have
that :ref:`PR_Poll` is not layered. That is each layer does not have
the opportunity to override the behavior. It operates, not on a single
file descriptor (**``PRFileDesc``**), but on an arbitrary collection of
file descriptor (:ref:`PRFileDesc`), but on an arbitrary collection of
file descriptors.
Into the picture comes another I/O method, **``poll()``**. Keep in mind
that all I/O methods are those that are part of the I/O methods table
structure (**``PRIOMethods``**). These functions are layered, and layers
structure (:ref:`PRIOMethods`). These functions are layered, and layers
may and sometimes must override their behavior by offering unique
implementations. The **``poll()``** method is used to provide two
modifying aspects to the semantics of **``PR_Poll()``**: redefining the
modifying aspects to the semantics of :ref:`PR_Poll`: redefining the
polling bits (i.e., what to poll for) and to indicate that a layer is
already able to make progress in the  manner suggested by the polling
already able to make progress in the manner suggested by the polling
bits.
The **``poll()``** method is called by **``PR_Poll()``** as the latter
The **``poll()``** method is called by :ref:`PR_Poll` as the latter
is building the structure to provide the operating system call. The
stack's top layer will be called first. Each layer's implementation is
responsible for performing appropriate operations and possibly calling
@ -92,5 +92,3 @@ the read bits in the **``out_flags``**. If that is the case, then it
should also suppress the calling of the next lower layer's
**``poll()``** method and return a value equal to that of
**``in_flags``**.
--------------

View File

@ -1,18 +1,17 @@
.. rubric:: NSPR: Build System and Supported Platforms
:name: nspr-build-system-and-supported-platforms
NSPR platforms
==============
**Note:** This was written in 1998. Platforms and releases have
changed since then. See the release notes for current data.
Build System and Supported Platforms
------------------------------------
|
| NSPR has been implemented on over 20 platforms. A platform may have
more than one implementation strategy of its multi threading and I/O
facilities. This article explains the NSPR build system and how to
specify a particular implementation strategy, compiler or compiler
switches, or the target OS for your build on each platform.
NSPR has been implemented on over 20 platforms. A platform may have
more than one implementation strategy of its multi threading and I/O
facilities. This article explains the NSPR build system and how to
specify a particular implementation strategy, compiler or compiler
switches, or the target OS for your build on each platform.
.. rubric:: Implementation Strategies
:name: implementation-strategies
Implementation Strategies
-------------------------
Threads are at the core of NSPR, and the I/O functions are tied to the
multi threading facilities because many I/O functions may block the
@ -50,43 +49,37 @@ both classic NSPR and pthreads. Consult
``mozilla/nsprpub/pr/src/Makefile`` for the definitive list of files
used by each implementation strategy (see the definition of the makefile
variable ``OBJS``).
.. rubric:: Compilers
:name: compilers
Compilers
---------
For ease of integration with third-party libraries, which may use native
threads, NSPR uses the native threads whenever possible. As a result,
native compilers are used to build NSPR on most platforms because they
have better debugging support for native threads. The only exception is
Solaris, where both cc and gcc are used.
.. rubric:: NSPR Build System
:name: nspr-build-system
On Unix and Win32, NSPR build system is based on GNU make. (GNU make can
be obtained by anonymous ftp from ``ftp://prep.ai.mit.edu/pub/gnu/``.)
On Mac, NSPR uses Metrowork's CodeWarrior Mac project files.
Inside Netscape, we use GNU make 3.74 on Unix, but our makefiles should
work fine under newer versions of GNU make. On Win32, we use an internal
Win32 port of GNU make 3.74 and a homegrown stripped-down version of
Bourne shell called ``shmsdos.exe``. Our own Win32 port of GNU make and
``shmsdos.exe`` are distributed with the NSPR source. Our makefiles also
work under the official Win32 port of GNU make (3.75 and above) and the
Korn shell ``sh.exe`` in MKS Toolkit.
NSPR Build System
-----------------
NSPR build system is based on GNU make.
We use GNU make 3.74 on Unix, but our makefiles should
work fine under newer versions of GNU make.
Every directory in NSPR has a makefile named ``Makefile``, which
includes the makefile fragments in ``mozilla/nsprpub/config``. NSPR
makefiles implement the common Netscape makefile targets such as
makefiles implement the common Makefile targets such as
``export``, ``libs``, and ``install``. However, some makefiles targets
are no-op in NSPR because they are not necessary for NSPR.
| To build NSPR, change directory to the root of our source tree
| ``cd mozilla/nsprpub``
| and then issue the command
| ``gmake``
| Make will recursively go into all the subdirectories and the right
things will happen.
To build NSPR, change directory to the root of our source tree
``cd mozilla/nsprpub``
and then issue the command
``gmake``
Make will recursively go into all the subdirectories and the right
things will happen.
| The table below lists the common NSPR makefile targets.
| ` <nspbuild.htm>`__ 
The table below lists the common NSPR makefile targets.
+-----------------------------------+-----------------------------------+
| ``all`` | The default target. Same as |
@ -113,9 +106,8 @@ are no-op in NSPR because they are not necessary for NSPR.
| ``clobber_all`` | Same as ``realclean``. |
+-----------------------------------+-----------------------------------+
| The table below lists common makefile variables that one can specify
on the command line to customize a build..
|  
The table below lists common makefile variables that one can specify
on the command line to customize a build..
+-----------------------------------+-----------------------------------+
| ``BUILD_OPT`` | Optimized build (default: debug |
@ -151,57 +143,3 @@ are no-op in NSPR because they are not necessary for NSPR.
| ``MOZILLA_CLIENT`` | Adjust NSPR build system for |
| | Netscape Client (mozilla). |
+-----------------------------------+-----------------------------------+
.. rubric:: Platforms
:name: platforms
Platforms supported by NSPR can be divided into three categories: Unix,
Windows, and Mac. At present, NSPR aims to support Netscape Communicator
5.0 and Server Suitespot 4.0. The platforms on which we build our binary
releases are listed below.
.. rubric:: Unix
:name: unix
AIX: 4.2.1
BSD/386: 3.0, 2.1
Digital Unix: V4.0B
FreeBSD: 2.2
HP-UX: B.10.10
HP-UX: B.11.00
Irix: 6.2
Linux: 2.0
MkLinux/PPC: 2.0
NCR: 3.0
NEC: 4.2
SCO_SV: 3.2
SINIX: 5.42
Solaris: 2.5.1 sparc, 2.5.1 x86
SunOS 4: 4.1.3_U1
UNIXWARE: 2.1
.. rubric:: Windows
:name: windows
Windows NT: 3.51, 4.0, Windows 2000
Windows 95, 98, Me
Windows 3.1 (16-bit Windows)
.. rubric:: Mac
:name: mac

View File

@ -1,137 +0,0 @@
Last modified 16 July 1998
<<< Under construction >>>
Unix platforms are probably the easiest platforms to port NetScape
Portable Runtime (NSPR) to. However, if you are not familiar with the
structure of the NSPR source tree and its build system, it may take you
extra time. Therefore I write this article to document the more
mechanical part of the Unix porting task. For certain more "standard"
Unix platforms, this may be all you have to do. On other platforms, you
may need to do extra work to deal with their idiosyncrasies.
.. _Porting_Instructions:
Porting Instructions
--------------------
You can use different threading packages to implement NSPR threads. NSPR
has a user-level threading library where thread context switches are
done by <tt>setjmp/longjmp</tt> or <tt>sigsetjmp/siglongjmp</tt>. This
is called the *local threads only* version of *classic NSPR*. You should
attempt to do a local threads only port first. The classic NSPR source
files are in <tt>mozilla/nsprpub/pr/src/threads</tt> and
<tt>mozilla/nsprpub/pr/src/io</tt>.
If the platform has pthreads, you can also use pthreads as an
implementation strategy. This is referred to as *pthreads NSPR*.
Pthreads NSPR has relatively orthogonal source code in the thread
management, thread synchronization, and I/O area. The pthreads source
files are in <tt>mozilla/nsprpub/pr/src/pthreads</tt>.
I use the NetBSD port I recently received as an example to illustrate
the mechanical part of the porting process.
There are a few new files you need to add:
<tt>mozilla/nsprpub/config/NetBSD.mk</tt> 
The name of this file is the return value of <tt>uname -s</tt> on the
platform, plus the file suffix <tt>.mk</tt>. If the return value of
<tt>uname -s</tt> is too long or ambiguous, you can modify it in
<tt>mozilla/nsprpub/config/arch.mk</tt> (the makefile variable
<tt>OS_ARCH</tt>).
<tt>mozilla/nsprpub/pr/include/md/_netbsd.cfg</tt> 
We have a program <tt>mozilla/nsprpub/pr/include/gencfg.c</tt> to
help you generate *part*\ of this file. You can build the
<tt>gencfg</tt> tool as follows:
.. code:: eval
cd mozilla/nsprpub/pr/include
gmake gencfg
gencfg > foo.bar
Then you use the macro values in <tt>foo.bar</tt> as a basis for the
<tt>_xxxos.cfg</tt> file.
- <tt>mozilla/nsprpub/pr/include/md/_netbsd.h</tt>: For local threads
only version, the main challenge is to figure out how to define the
three thread context switch macros. In particular, you need to figure
out which element in the <tt>jmp_buf</tt> is the stack pointer.
Usually <tt>jmp_buf</tt> is an array of integers, and some platforms
have a <tt>JB_SP</tt> macro that tells you which array element is the
stack pointer. If you can't find a <tt>JB_SP</tt> macro, you must
resort to brute-force experiments. I usually print out every element
in the <tt>jmp_buf</tt> and see which one is the closest to the
address of a local variable (local variables are allocated on the
stack). On some platforms, <tt>jmp_buf</tt> is a struct, then you
should look for a struct member named <tt>sp</tt> or something
similar.
- <tt>mozilla/nsprpub/pr/src/md/unix/netbsd.c</tt>
You need to modify the following existing files:
- <tt>mozilla/nsprpub/pr/include/md/Makefile</tt>
- <tt>mozilla/nsprpub/pr/include/md/_unixos.h</tt>: Just fix the
compiling errors, usually pointed out by the <tt>#error</tt>
preprocessor directives we inserted.
- <tt>mozilla/nsprpub/pr/include/md/prosdep.h</tt>
- <tt>mozilla/nsprpub/pr/src/md/prosdep.c</tt>
- <tt>mozilla/nsprpub/pr/src/md/unix/Makefile</tt>
- <tt>mozilla/nsprpub/pr/src/md/unix/objs.mk</tt>
- <tt>mozilla/nsprpub/pr/src/md/unix/unix.c</tt>: Just fix the
compiling errors, usually pointed out by the <tt>#error</tt>
preprocessor directives we inserted
For a pthreads port, you need to modify the following files:
- <tt>mozilla/nsprpub/pr/include/md/_pth.h</tt>
- Files in mozilla/nsprpub/pr/src/pthreads, most likely
<tt>ptthread.c</tt> and <tt>ptio.c</tt>
.. _Testing_Your_Port:
Testing Your Port
-----------------
We have some unit tests in <tt>mozilla/nsprpub/pr/tests</tt>. First a
warning: some of the tests are broken. Further, we don't have
documentation of our unit tests, so you often need to resort to read the
source code to understand what they do. Some of them respond to the
<tt>-h</tt> command line option and print a usage message. <strike>Henry
Sobotka of the OS/2 Mozilla porting project has a web page at
`http://www.axess.com/users/sobotka/n.../warpztjs.html <http://www.axess.com/users/sobotka/nsprtest/warpztjs.html>`__
with good documentation of the NSPR unit tests</strike>.
Here are my favorite tests.
For thread management and synchronization:
- <tt>cvar -d</tt>
- <tt>cvar2</tt>
- <tt>./join -d</tt>
- <tt>perf</tt>
- <tt>./switch -d</tt>
- <tt>intrupt -d</tt>
For I/O:
- <tt>cltsrv -d</tt>, <tt>cltsrv -Gd</tt>
- <tt>socket</tt>
- <tt>testfile -d</tt>
- <tt>tmocon -d</tt>
- '<tt>tmoacc -d</tt>' in conjunction with '<tt>writev -d</tt>'
Miscellaneous:
- <tt>dlltest -d</tt>
- <tt>forktest</tt>
.. _Original_Document_Information:
Original Document Information
-----------------------------
- Author: larryh@netscape.com
- Last Updated Date: 16 July 1998