summaryrefslogtreecommitdiff
path: root/doc/developer
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developer')
-rw-r--r--doc/developer/.gitignore2
-rw-r--r--doc/developer/Makefile1
-rw-r--r--doc/developer/Makefile.in8
-rw-r--r--doc/developer/conf.py10
-rw-r--r--doc/developer/index.rst4
-rw-r--r--doc/developer/library.rst2
-rw-r--r--doc/developer/process-architecture.rst54
7 files changed, 70 insertions, 11 deletions
diff --git a/doc/developer/.gitignore b/doc/developer/.gitignore
index 0505537159..2e7d8573f1 100644
--- a/doc/developer/.gitignore
+++ b/doc/developer/.gitignore
@@ -1,3 +1,3 @@
/_templates
/_build
-!/Makefile
+!/Makefile.in
diff --git a/doc/developer/Makefile b/doc/developer/Makefile
deleted file mode 100644
index 9807a750bf..0000000000
--- a/doc/developer/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-include ../frr-sphinx.mk
diff --git a/doc/developer/Makefile.in b/doc/developer/Makefile.in
new file mode 100644
index 0000000000..76758f9242
--- /dev/null
+++ b/doc/developer/Makefile.in
@@ -0,0 +1,8 @@
+# This is necessary to support VPATH builds.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# This variable is used as the documentation source location in frr-sphinx.mk
+SOURCESDIR = @srcdir@
+
+include @srcdir@/../frr-sphinx.mk
diff --git a/doc/developer/conf.py b/doc/developer/conf.py
index a3968b60ff..61253c4b2f 100644
--- a/doc/developer/conf.py
+++ b/doc/developer/conf.py
@@ -342,6 +342,14 @@ texinfo_documents = [
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
+# contents of ../extra/frrlexer.py.
+# This is read here to support VPATH build. Since this section is execfile()'d
+# with the file location, we can safely use a relative path here to save the
+# contents of the lexer file for later use even if our relative path changes
+# due to VPATH.
+with open('../extra/frrlexer.py', 'rb') as lex:
+ frrlexerpy = lex.read()
+
# custom extensions here
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
@@ -357,5 +365,5 @@ def setup(app):
#
# frrlexer = pygments.lexers.load_lexer_from_file('../extra/frrlexer.py', lexername="FRRLexer")
custom_namespace = {}
- exec(open('../extra/frrlexer.py', 'rb').read(), custom_namespace)
+ exec(frrlexerpy, custom_namespace)
lexers['frr'] = custom_namespace['FRRLexer']()
diff --git a/doc/developer/index.rst b/doc/developer/index.rst
index 2f4b96bc1f..2c855ee880 100644
--- a/doc/developer/index.rst
+++ b/doc/developer/index.rst
@@ -1,5 +1,5 @@
-Welcome to FRR's documentation!
-===============================
+FRRouting Developer's Guide
+===========================
.. toctree::
:maxdepth: 2
diff --git a/doc/developer/library.rst b/doc/developer/library.rst
index c5ce1f5982..f6efa33051 100644
--- a/doc/developer/library.rst
+++ b/doc/developer/library.rst
@@ -1,3 +1,5 @@
+.. _libfrr:
+
***************************
Library Facilities (libfrr)
***************************
diff --git a/doc/developer/process-architecture.rst b/doc/developer/process-architecture.rst
index 514b5becdd..806afa644c 100644
--- a/doc/developer/process-architecture.rst
+++ b/doc/developer/process-architecture.rst
@@ -32,6 +32,8 @@ explicitly named, they will be formatted ``like this`` to differentiate from
the conceptual names. When speaking of kernel threads, the term used will be
"pthread" since FRR's kernel threading implementation is POSIX threads.
+.. This should be broken into its document under :ref:`libfrr`
+.. _event-architecture:
Event Architecture
------------------
@@ -67,7 +69,8 @@ are given by integer macros in :file:`thread.h` and are:
``THREAD_EVENT``
Generic task that executes with high priority and carries an arbitrary
- integer indicating the event type to its handler.
+ integer indicating the event type to its handler. These are commonly used to
+ implement the finite state machines typically found in routing protocols.
``THREAD_READY``
Type used internally for tasks on the ready queue.
@@ -110,6 +113,26 @@ highest priority, followed by expired timers and finally I/O tasks (type
arbitrary argument are provided. The task returned from ``thread_fetch()`` is
then executed with ``thread_call()``.
+The following diagram illustrates a simplified version of this infrastructure.
+
+.. todo: replace these with SVG
+.. figure:: ../figures/threadmaster-single.png
+ :align: center
+
+ Lifecycle of a program using a single threadmaster.
+
+The series of "task" boxes represents the current ready task queue. The various
+other queues for other types are not shown. The fetch-execute loop is
+illustrated at the bottom.
+
+Mapping the general names used in the figure to specific FRR functions:
+
+- ``task`` is ``struct thread *``
+- ``fetch`` is ``thread_fetch()``
+- ``exec()`` is ``thread_call``
+- ``cancel()`` is ``thread_cancel()``
+- ``schedule()`` is any of the various task-specific ``thread_add_*`` functions
+
Adding tasks is done with various task-specific function-like macros. These
macros wrap underlying functions in :file:`thread.c` to provide additional
information added at compile time, such as the line number the task was
@@ -134,10 +157,6 @@ There are some gotchas to keep in mind:
call is the responsibility of the caller.
-.. todo: include this when its more complete
-.. .. figure:: ../figures/threadmaster.svg
-
-
Kernel Thread Architecture
--------------------------
Efforts have begun to introduce kernel threads into FRR to improve performance
@@ -158,6 +177,27 @@ the currently existing task and context primitives. In this way the familiar
execution model of FRR gains the ability to execute tasks simultaneously while
preserving the existing model for concurrency.
+The following figure illustrates the architecture with multiple pthreads, each
+running their own ``threadmaster``-based event loop.
+
+.. todo: replace these with SVG
+.. figure:: ../figures/threadmaster-multiple.png
+ :align: center
+
+ Lifecycle of a program using multiple pthreads, each running their own
+ ``threadmaster``
+
+Each roundrect represents a single pthread running the same event loop
+described under :ref:`event-architecture`. Note the arrow from the ``exec()``
+box on the right to the ``schedule()`` box in the middle pthread. This
+illustrates code running in one pthread scheduling a task onto another
+pthread's threadmaster. A global lock for each ``threadmaster`` is used to
+synchronize these operations. The pthread names are examples.
+
+
+.. This should be broken into its document under :ref:`libfrr`
+.. _kernel-thread-wrapper:
+
Kernel Thread Wrapper
^^^^^^^^^^^^^^^^^^^^^
The basis for the integration of pthreads and the event system is a lightweight
@@ -184,7 +224,9 @@ passing, where the messages are the regular task events as used in the
event-driven model. The only difference is thread cancellation, which requires
calling ``thread_cancel_async()`` instead of ``thread_cancel`` to cancel a task
currently scheduled on a ``threadmaster`` belonging to a different pthread.
-This is necessary
+This is necessary to avoid race conditions in the specific case where one
+pthread wants to guarantee that a task on another pthread is cancelled before
+proceeding.
In addition, the existing commands to show statistics and other information for
tasks within the event driven model have been expanded to handle multiple