On 11 December 2015 at 10:08, Bill Fischofer <bill.fischo...@linaro.org>
wrote:

> The problem is that this is documentation text (pseudocode) not code and
> yet some tools insist on trying to treat it as if it's a code patch.
> Checkpatch should not apply to documentation this way.
>

In this case then we need to turn all the other spaces to tabs becasue now
we have a mix.
I want to keep it consistent one way or the other or reviewing will be
difficult depending on the viewers tab setting.

+...thread init processing
+
+while (1) {
+        odp_event_t ev;   <-- only this one is newly tabbed
+       odp_queue_t which_q;
+       ev = odp_schedule(&which_q, <wait option>);
+       ...process the event
+}
+----


I honestly think it is just easier to not use tabs in the docs.



>
> On Fri, Dec 11, 2015 at 9:04 AM, Mike Holmes <mike.hol...@linaro.org>
> wrote:
>
>> Using patch:
>> lng-odp_PATCHv3_doc_userguide_add_application_programming_section.mbox
>>   Trying to apply patch
>>   Patch applied
>> Applying: doc: userguide: add application programming section
>> /home/mike/git/check-odp/build/odp-apply/.git/rebase-apply/patch:446:
>> indent with spaces.
>>         odp_event_t ev;
>> /home/mike/git/check-odp/build/odp-apply/.git/rebase-apply/patch:613:
>> indent with spaces.
>>         odp_init_local();
>> /home/mike/git/check-odp/build/odp-apply/.git/rebase-apply/patch:616:
>> indent with spaces.
>>         while (1) {
>> /home/mike/git/check-odp/build/odp-apply/.git/rebase-apply/patch:617:
>> indent with spaces.
>>        ev = odp_schedule(&which_q, ODP_SCHED_WAIT);
>> warning: 4 lines add whitespace errors.
>> 0001-doc-userguide-add-application-programming-section.patch: unified
>> diff output, UTF-8 Unicode text
>>
>> When I look at all these with git show I see a tab got in there rather
>> than a space which is inconsistent with the rest of the text.
>>
>> Do you have the .gitconfig whitespace =
>> trailing-space,space-before-tab,indent-with-non-tab,error-all if not you
>> may not be seeing some things.
>>
>>
>>
>>
>>
>> On 8 December 2015 at 17:36, Bill Fischofer <bill.fischo...@linaro.org>
>> wrote:
>>
>>> Complete the reformatting to standard asciidoc style, expand the
>>> ODP Application Programming section, and include a reorganized and
>>> expanded discussion of ODP queues.
>>>
>>> Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
>>> ---
>>>  doc/users-guide/users-guide.adoc | 451
>>> +++++++++++++++++++++++++++++++--------
>>>  1 file changed, 359 insertions(+), 92 deletions(-)
>>>
>>> diff --git a/doc/users-guide/users-guide.adoc
>>> b/doc/users-guide/users-guide.adoc
>>> index cf77fa0..d660fb8 100644
>>> --- a/doc/users-guide/users-guide.adoc
>>> +++ b/doc/users-guide/users-guide.adoc
>>> @@ -8,16 +8,19 @@ OpenDataPlane (ODP)  Users-Guide
>>>  Abstract
>>>  --------
>>>  This document is intended to guide a new ODP application developer.
>>> -Further details about ODP may be found at the http://opendataplane.org[ODP]
>>> home page.
>>> +Further details about ODP may be found at the http://opendataplane.org
>>> [ODP]
>>> +home page.
>>>
>>>  .Overview of a system running ODP applications
>>>  image::../images/overview.png[align="center"]
>>>
>>> -ODP is an API specification that allows many implementations to provide
>>> platform independence, automatic hardware acceleration and CPU scaling to
>>> high performance networking  applications.
>>> -This document describes how to write an application that can
>>> successfully take advantage of the API.
>>> +ODP is an API specification that allows many implementations to provide
>>> +platform independence, automatic hardware acceleration and CPU scaling
>>> to
>>> +high performance networking  applications. This document describes how
>>> to
>>> +write an application that can successfully take advantage of the API.
>>>
>>>  :numbered:
>>> -== Introduction ==
>>> +== Introduction
>>>  .OpenDataPlane Components
>>>  image::../images/odp_components.png[align="center"]
>>>
>>> @@ -42,7 +45,7 @@ ODP API specification--that is the responsibility of
>>> each ODP implementation.
>>>  * Application-centric.  Covers functional needs of data plane
>>> applications.
>>>  * Ensures portability by specifying the functional behavior of ODP.
>>>  * Defined jointly and openly by application writers and platform
>>> implementers.
>>> -* Archiected to be implementable on a wide range of platforms
>>> efficiently
>>> +* Architected to be implementable on a wide range of platforms
>>> efficiently
>>>  * Sponsored, governed, and maintained by the Linaro Networking Group
>>> (LNG)
>>>
>>>  .ODP Implementations
>>> @@ -68,7 +71,7 @@ where the application will run on a target platform
>>> chosen by someone else.
>>>  * One size does not fit all--supporting multiple implementations allows
>>> ODP
>>>  to adapt to widely differing internals among platforms.
>>>  * Anyone can create an ODP implementation tailored to their platform
>>> -* Distribution and mainteinance of each implementation is as owner
>>> wishes
>>> +* Distribution and maintenance of each implementation is as owner wishes
>>>    - Open source or closed source as business needs determine
>>>    - Have independent release cycles and service streams
>>>  * Allows HW and SW innovation in how ODP APIs are implemented on each
>>> platform.
>>> @@ -100,7 +103,7 @@ drivers supported by DPDK.
>>>  they are derived from a reference implementation.
>>>
>>>  .ODP Validation Test Suite
>>> -Third, to enure consistency between different ODP implementations, ODP
>>> +Third, to ensure consistency between different ODP implementations, ODP
>>>  consists of a validation suite that verifies that any given
>>> implementation of
>>>  ODP faithfully provides the specified functional behavior of each ODP
>>> API.
>>>  As a separate open source component, the validation suite may be used by
>>> @@ -115,16 +118,16 @@ ODP API specification.
>>>  * Key to ensuring application portability across all ODP implementations
>>>  * Tests that ODP implementations conform to the specified functional
>>> behavior
>>>  of ODP APIs.
>>> -* Can be run at any time by users and vendors to validat implementations
>>> -od ODP.
>>> +* Can be run at any time by users and vendors to validate
>>> implementations
>>> +of ODP.
>>>
>>> -=== ODP API Specification Versioning ===
>>> +=== ODP API Specification Versioning
>>>  As an evolving standard, the ODP API specification is released under an
>>>  incrementing version number, and corresponding implementations of ODP,
>>> as well
>>>  as the validation suite that verifies API conformance, are linked to
>>> this
>>> -version number. ODP versions are specified using a stanard three-level
>>> +version number. ODP versions are specified using a standard three-level
>>>  number (major.minor.fixlevel) that are incremented according to the
>>> degree of
>>> -change the level represents. Increments to the fixlevel represent
>>> clarification
>>> +change the level represents. Increments to the fix level represent
>>> clarification
>>>  of the specification or other minor changes that do not affect either
>>> the
>>>  syntax or semantics of the specification. Such changes in the API
>>> specification
>>>  are expected to be rare. Increments to the minor level
>>> @@ -136,26 +139,26 @@ the major level represent significant structural
>>> changes that most likely
>>>  require some level of application source code change, again as
>>> documented in
>>>  the release notes for that version.
>>>
>>> -=== ODP Implementation Versioning ===
>>> +=== ODP Implementation Versioning
>>>  ODP implementations are free to use whatever release naming/numbering
>>>  conventions they wish, as long as it is clear what level of the ODP API
>>> a given
>>>  release implements. A recommended convention is to use the same three
>>> level
>>>  numbering scheme where the major and minor numbers correspond to the
>>> ODP API
>>> -level and the fixlevel represents an implementation-defined service
>>> level
>>> +level and the fix level represents an implementation-defined service
>>> level
>>>  associated with that API level implementation. The LNG-supplied ODP
>>> reference
>>>  implementations follow this convention.
>>>
>>> -=== ODP Validation Test Suite Versioning ===
>>> +=== ODP Validation Test Suite Versioning
>>>  The ODP validation test suite follows these same naming conventions.
>>> The major
>>>  and minor release numbers correspond to the ODP API level that the suite
>>> -validates and the fixlevel represents the service level of the
>>> validation
>>> +validates and the fix level represents the service level of the
>>> validation
>>>  suite itself for that API level.
>>>
>>> -=== ODP Design Goals ===
>>> +=== ODP Design Goals
>>>  ODP has three primary goals that follow from its component structure.
>>> The first
>>>  is application portability across a wide range of platforms. These
>>> platforms
>>>  differ in terms of processor instruction set architecture, number and
>>> types of
>>> -application processing cores, memory oranization, as well as the number
>>> and
>>> +application processing cores, memory organization, as well as the
>>> number and
>>>  type of platform specific hardware acceleration and offload features
>>> that
>>>  are available. ODP applications can move from one conforming
>>> implementation
>>>  to another with at most a recompile.
>>> @@ -175,7 +178,7 @@ of processing cores that are available to realize
>>> application function. The
>>>  result is that an application written to this model does not require
>>> redesign
>>>  as it scales from 4, to 40, to 400 cores.
>>>
>>> -== Organization of this Document ==
>>> +== Organization of this Document
>>>  This document is organized into several sections. The first presents a
>>> high
>>>  level overview of the ODP API component areas and their associated
>>> abstract
>>>  data types. This section introduces ODP APIs at a conceptual level.
>>> @@ -190,14 +193,14 @@ full reference specification for each API. The
>>> latter is intended to be used
>>>  by ODP application programmers, as well as implementers, to understand
>>> the
>>>  precise syntax and semantics of each API.
>>>
>>> -== ODP API Concepts ==
>>> +== ODP API Concepts
>>>  ODP programs are built around several conceptual structures that every
>>> -appliation programmer needs to be familiar with to use ODP effectively.
>>> The
>>> +application programmer needs to be familiar with to use ODP
>>> effectively. The
>>>  main ODP concepts are:
>>>  Thread, Event, Queue, Pool, Shared Memory, Buffer, Packet, PktIO, Timer,
>>>  and Synchronizer.
>>>
>>> -=== Thread ===
>>> +=== Thread
>>>  The thread is the fundamental programming unit in ODP.  ODP
>>> applications are
>>>  organized into a collection of threads that perform the work that the
>>>  application is designed to do. ODP threads may or may not share memory
>>> with
>>> @@ -209,7 +212,7 @@ A control thread is a supervisory thread that
>>> organizes
>>>  the operation of worker threads. Worker threads, by contrast, exist to
>>>  perform the main processing logic of the application and employ a run to
>>>  completion model. Worker threads, in particular, are intended to
>>> operate on
>>> -dedicated processing cores, especially in many core proessing
>>> environments,
>>> +dedicated processing cores, especially in many core processing
>>> environments,
>>>  however a given implementation may multitask multiple threads on a
>>> single
>>>  core if desired (typically on smaller and lower performance target
>>>  environments).
>>> @@ -219,7 +222,7 @@ _thread mask_ and _scheduler group_ that determine
>>> where they can run and
>>>  the type of work that they can handle. These will be discussed in
>>> greater
>>>  detail later.
>>>
>>> -=== Event ===
>>> +=== Event
>>>  Events are what threads process to perform their work. Events can
>>> represent
>>>  new work, such as the arrival of a packet that needs to be processed,
>>> or they
>>>  can represent the completion of requests that have executed
>>> asynchronously.
>>> @@ -232,7 +235,7 @@ References to events are via handles of abstract
>>> type +odp_event_t+. Cast
>>>  functions are provided to convert these into specific handles of the
>>>  appropriate type represented by the event.
>>>
>>> -=== Queue ===
>>> +=== Queue
>>>  A queue is a message passing channel that holds events.  Events can be
>>>  added to a queue via enqueue operations or removed from a queue via
>>> dequeue
>>>  operations. The endpoints of a queue will vary depending on how it is
>>> used.
>>> @@ -244,7 +247,7 @@ stateful processing on events as well as stateless
>>> processing.
>>>
>>>  Queues are represented by handles of abstract type +odp_queue_t+.
>>>
>>> -=== Pool ===
>>> +=== Pool
>>>  A pool is a shared memory area from which elements may be drawn. Pools
>>>  represent the backing store for events, among other things. Pools are
>>>  typically created and destroyed by the application during
>>> initialization and
>>> @@ -256,32 +259,32 @@ are Buffer and Packet.
>>>
>>>  Pools are represented by handles of abstract type +odp_pool_t+.
>>>
>>> -=== Shared Memory ===
>>> +=== Shared Memory
>>>  Shared memory represents raw blocks of storage that are sharable between
>>>  threads. They are the building blocks of pools but can be used directly
>>> by
>>>  ODP applications if desired.
>>>
>>>  Shared memory is represented by handles of abstract type +odp_shm_t+.
>>>
>>> -=== Buffer ===
>>> +=== Buffer
>>>  A buffer is a fixed sized block of shared storage that is used by ODP
>>>  components and/or applications to realize their function. Buffers
>>> contain
>>>  zero or more bytes of application data as well as system maintained
>>>  metadata that provide information about the buffer, such as its size or
>>> the
>>>  pool it was allocated from. Metadata is an important ODP concept
>>> because it
>>>  allows for arbitrary amounts of side information to be associated with
>>> an
>>> -ODP object. Most ODP objects have assocaited metadata and this metadata
>>> is
>>> +ODP object. Most ODP objects have associated metadata and this metadata
>>> is
>>>  manipulated via accessor functions that act as getters and setters for
>>> -this information. Getter acces functions permit an application to read
>>> +this information. Getter access functions permit an application to read
>>>  a metadata item, while setter access functions permit an application to
>>> write
>>>  a metadata item. Note that some metadata is inherently read only and
>>> thus
>>>  no setter is provided to manipulate it.  When object have multiple
>>> metadata
>>>  items, each has its own associated getter and/or setter access function
>>> to
>>>  inspect or manipulate it.
>>>
>>> -Buffers are represened by handles of abstract type +odp_buffer_t+.
>>> +Buffers are represented by handles of abstract type +odp_buffer_t+.
>>>
>>> -=== Packet ===
>>> +=== Packet
>>>  Packets are received and transmitted via I/O interfaces and represent
>>>  the basic data that data plane applications manipulate.
>>>  Packets are drawn from pools of type +ODP_POOL_PACKET+.
>>> @@ -294,7 +297,7 @@ with each packet for its own use.
>>>
>>>  Packets are represented by handles of abstract type +odp_packet_t+.
>>>
>>> -=== PktIO ===
>>> +=== PktIO
>>>  PktIO is how ODP represents I/O interfaces. A pktio object is a logical
>>>  port capable of receiving and/or transmitting packets. This may be
>>> directly
>>>  supported by the underlying platform as an integrated feature,
>>> @@ -302,7 +305,7 @@ or may represent a device attached via a PCIE or
>>> other bus.
>>>
>>>  PktIOs are represented by handles of abstract type +odp_pktio_t+.
>>>
>>> -=== Timer ===
>>> +=== Timer
>>>  Timers are how ODP applications measure and respond to the passage of
>>> time.
>>>  Timers are drawn from specialized pools called timer pools that have
>>> their
>>>  own abstract type (+odp_timer_pool_t+). Applications may have many
>>> timers
>>> @@ -310,7 +313,7 @@ active at the same time and can set them to use
>>> either relative or absolute
>>>  time. When timers expire they create events of type +odp_timeout_t+,
>>> which
>>>  serve as notifications of timer expiration.
>>>
>>> -=== Synchronizer ===
>>> +=== Synchronizer
>>>  Multiple threads operating in parallel typically require various
>>>  synchronization services to permit them to operate in a reliable and
>>>  coordinated manner. ODP provides a rich set of locks, barriers, and
>>> similar
>>> @@ -325,7 +328,7 @@ flow of work through an ODP application. These
>>> include the Classifier,
>>>  Scheduler, and Traffic Manager.  These components relate to the three
>>>  main stages of packet processing: Receive, Process, and Transmit.
>>>
>>> -=== Classifier ===
>>> +=== Classifier
>>>  The *Classifier* provides a suite of APIs that control packet receive
>>> (RX)
>>>  processing.
>>>
>>> @@ -362,8 +365,8 @@ Note that the use of the classifier is optional.
>>> Applications may directly
>>>  receive packets from a corresponding PktIO input queue via direct
>>> polling
>>>  if they choose.
>>>
>>> -=== Scheduler ===
>>> -The *Scheduler* provides a suite of APIs that control scalabable event
>>> +=== Scheduler
>>> +The *Scheduler* provides a suite of APIs that control scalable event
>>>  processing.
>>>
>>>  .ODP Scheduler and Event Processing
>>> @@ -391,10 +394,10 @@ scheduled back to a thread to continue processing
>>> with the results of the
>>>  requested asynchronous operation.
>>>
>>>  Threads themselves can enqueue events to queues for downstream
>>> processing
>>> -by other threads, permitting flexibility in how applicaitions structure
>>> +by other threads, permitting flexibility in how applications structure
>>>  themselves to maximize concurrency.
>>>
>>> -=== Traffic Manager ===
>>> +=== Traffic Manager
>>>  The *Traffic Manager* provides a suite of APIs that control traffic
>>> shaping and
>>>  Quality of Service (QoS) processing for packet output.
>>>
>>> @@ -413,23 +416,33 @@ goals. Again, the advantage here is that on many
>>> platforms traffic management
>>>  functions are implemented in hardware, permitting transparent offload of
>>>  this work.
>>>
>>> -Glossary
>>> ---------
>>> -[glossary]
>>> -odp_worker::
>>> -    An opd_worker is a type of odp_thread. It will usually be isolated
>>> from the scheduling of any host operating system and is intended for
>>> fast-path processing with a low and predictable latency. Odp_workers will
>>> not generally receive interrupts and will run to completion.
>>> -odp_control::
>>> -    An odp_control is a type of odp_thread. It will be isolated from
>>> the host operating system house keeping tasks but will be scheduled by it
>>> and may receive interrupts.
>>> -odp_thread::
>>> -    An odp_thread is a flow of execution that in a Linux environment
>>> could be a Linux process or thread.
>>> -event::
>>> -    An event is a notification that can be placed in a queue.
>>> -
>>> -The include structure
>>> ----------------------
>>> -Applications only include the 'include/odp.h file which includes the
>>> 'platform/<implementation name>/include/plat' files to provide a complete
>>> definition of the API on that platform.
>>> -The doxygen documentation defining the behavior of the ODP API is all
>>> contained in the public API files, and the actual definitions for an
>>> implementation will be found in the per platform directories.
>>> -Per-platform data that might normally be a #define can be recovered via
>>> the appropriate access function if the #define is not directly visible to
>>> the application.
>>> +== ODP Application Programming
>>> +At the highest level, an *ODP Application* is a program that uses one
>>> or more
>>> +ODP APIs. Because ODP is a framework rather than a programming
>>> environment,
>>> +applications are free to also use other APIs that may or may not
>>> provide the
>>> +same portability characteristics as ODP APIs.
>>> +
>>> +ODP applications vary in terms of what they do and how they operate,
>>> but in
>>> +general all share the following characteristics:
>>> +
>>> +. They are organized into one or more _threads_ that execute in
>>> parallel.
>>> +. These threads communicate and coordinate their activities using
>>> various
>>> +_synchronization_ mechanisms.
>>> +. They receive packets from one or more _packet I/O interfaces_.
>>> +. They examine, transform, or otherwise process packets.
>>> +. They transmit packets to one or more _packet I/O interfaces_.
>>> +
>>> +ODP provides APIs to assist in each of these areas.
>>> +
>>> +=== The include structure
>>> +Applications only include the 'include/odp.h' file, which includes the
>>> +'platform/<implementation name>/include/odp' files to provide a complete
>>> +definition of the API on that platform. The doxygen documentation
>>> defining
>>> +the behavior of the ODP API is all contained in the public API files,
>>> and the
>>> +actual definitions for an implementation will be found in the per
>>> platform
>>> +directories. Per-platform data that might normally be a +#define+ can be
>>> +recovered via the appropriate access function if the #define is not
>>> directly
>>> +visible to the application.
>>>
>>>  .Users include structure
>>>  ----
>>> @@ -442,51 +455,305 @@ Per-platform data that might normally be a
>>> #define can be recovered via the appr
>>>  │   └── odp.h   This file should be the only file included by the
>>> application.
>>>  ----
>>>
>>> -Initialization
>>> ---------------
>>> -IMPORTANT: ODP depends on the application to perform a graceful
>>> shutdown, calling the terminate functions should only be done when the
>>> application is sure it has closed the ingress and subsequently drained all
>>> queues etc.
>>> +=== Initialization
>>> +IMPORTANT: ODP depends on the application to perform a graceful
>>> shutdown,
>>> +calling the terminate functions should only be done when the
>>> application is
>>> +sure it has closed the ingress and subsequently drained all queues, etc.
>>> +
>>> +=== Startup
>>> +The first API that must be called by an ODP application is
>>> 'odp_init_global()'.
>>> +This takes two pointers. The first, +odp_init_t+, contains ODP
>>> initialization
>>> +data that is platform independent and portable, while the second,
>>> ++odp_platform_init_t+, is passed unparsed to the implementation
>>> +to be used for platform specific data that is not yet, or may never be
>>> +suitable for the ODP API.
>>> +
>>> +Calling odp_init_global() establishes the ODP API framework and MUST be
>>> +called before any other ODP API may be called. Note that it is only
>>> called
>>> +once per application. Following global initialization, each thread in
>>> turn
>>> +calls 'odp_init_local()' is called. This establishes the local ODP
>>> thread
>>> +context for that thread and MUST be called before other ODP APIs may be
>>> +called by that thread.
>>> +
>>> +=== Shutdown
>>> +Shutdown is the logical reverse of the initialization procedure, with
>>> +'odp_term_local()' called for each thread before 'odp_term_global()' is
>>> +called to terminate ODP.
>>> +
>>> +.ODP Application Structure Flow Diagram
>>> +image::../images/resource_management.png[align="center"]
>>>
>>> -Startup
>>> -~~~~~~~~
>>> -The first API that must be called is 'odp_init_global()'.
>>> -This takes two pointers, odp_init_t contains ODP initialization data
>>> that is platform independent and portable.
>>> -The second odp_platform_init_t is passed un parsed to the
>>> implementation and can be used for platform specific data that is not yet,
>>> or may never be suitable for the ODP API.
>>> +== Common Conventions
>>> +Many ODP APIs share common conventions regarding their arguments and
>>> return
>>> +types. This section highlights some of the more common and frequently
>>> used
>>> +conventions.
>>> +
>>> +=== Handles and Special Designators
>>> +ODP resources are represented via _handles_ that have abstract type
>>> +_odp_resource_t_.  So pools are represented by handles of type
>>> +odp_pool_t+,
>>> +queues by handles of type +odp_queue_t+, etc. Each such type
>>> +has a distinguished type _ODP_RESOURCE_INVALID_ that is used to
>>> indicate a
>>> +handle that does not refer to a valid resource of that type. Resources
>>> are
>>> +typically created via an API named _odp_resource_create()_ that returns
>>> a
>>> +handle of type _odp_resource_t_ that represents the created object. This
>>> +returned handle is set to _ODP_RESOURCE_INVALID_ if, for example, the
>>> +resource could not be created due to resource exhaustion. Invalid
>>> resources
>>> +do not necessarily represent error conditions. For example,
>>> +ODP_EVENT_INVALID+
>>> +in response to an +odp_queue_deq()+ call to get an event from a queue
>>> simply
>>> +indicates that the queue is empty.
>>> +
>>> +=== Addressing Scope
>>> +Unless specifically noted in the API, all ODP resources are global to
>>> the ODP
>>> +application, whether it runs as a single process or multiple processes.
>>> ODP
>>> +handles therefore have common meaning within an ODP application but
>>> have no
>>> +meaning outside the scope of the application.
>>> +
>>> +=== Resources and Names
>>> +Many ODP resource objects, such as pools and queues, support an
>>> +application-specified character string _name_ that is associated with
>>> an ODP
>>> +object at create time.  This name serves two purposes: documentation,
>>> and
>>> +lookup. The lookup function is particularly useful to allow an ODP
>>> application
>>> +that is divided into multiple processes to obtain the handle for the
>>> common
>>> +resource.
>>> +
>>> +== Queues
>>> +Queues are the fundamental event sequencing mechanism provided by ODP
>>> and all
>>> +ODP applications make use of them either explicitly or implicitly.
>>> Queues are
>>> +created via the 'odp_queue_create()' API that returns a handle of type
>>> ++odp_queue_t+ that is used to refer to this queue in all subsequent
>>> APIs that
>>> +reference it. Queues have one of two ODP-defined _types_, POLL, and
>>> SCHED that
>>> +determine how they are used. POLL queues directly managed by the ODP
>>> +application while SCHED queues make use of the *ODP scheduler* to
>>> provide
>>> +automatic scalable dispatching and synchronization services.
>>> +
>>> +.Operations on POLL queues
>>> +[source,c]
>>> +----
>>> +odp_queue_t poll_q1 = odp_queue_create("poll queue 1",
>>> ODP_QUEUE_TYPE_POLL, NULL);
>>> +odp_queue_t poll_q2 = odp_queue_create("poll queue 2",
>>> ODP_QUEUE_TYPE_POLL, NULL);
>>> +...
>>> +odp_event_t ev = odp_queue_deq(poll_q1);
>>> +...do something
>>> +int rc = odp_queue_enq(poll_q2, ev);
>>> +----
>>>
>>> -The second API that must be called is 'odp_init_local()', this must be
>>> called once per odp_thread, regardless of odp_thread type.  Odp_threads may
>>> be of type ODP_THREAD_WORKER or ODP_THREAD_CONTROL
>>> +The key distinction is that dequeueing events from POLL queues is an
>>> +application responsibility while dequeueing events from SCHED queues is
>>> the
>>> +responsibility of the ODP scheduler.
>>>
>>> -Shutdown
>>> -~~~~~~~~~
>>> -Shutdown is the logical reverse of the initialization procedure, with
>>> 'odp_thread_term()' called for each worker before 'odp_term_global()' is
>>> called.
>>> +.Operations on SCHED queues
>>> +[source,c]
>>> +----
>>> +odp_queue_param_t qp;
>>> +odp_queue_param_init(&qp);
>>> +odp_schedule_prio_t prio = ...;
>>> +odp_schedule_group_t sched_group = ...;
>>> +qp.sched.prio = prio;
>>> +qp.sched.sync = ODP_SCHED_SYNC_[NONE|ATOMIC|ORDERED];
>>> +qp.sched.group = sched_group;
>>> +qp.lock_count = n; /* Only relevant for ordered queues */
>>> +odp_queue_t sched_q1 = odp_queue_create("sched queue 1",
>>> ODP_QUEUE_TYPE_SCHED, &qp);
>>> +
>>> +...thread init processing
>>> +
>>> +while (1) {
>>> +        odp_event_t ev;
>>> +       odp_queue_t which_q;
>>> +       ev = odp_schedule(&which_q, <wait option>);
>>> +       ...process the event
>>> +}
>>> +----
>>>
>>> -image::../images/resource_management.png[align="center"]
>>> +With scheduled queues, events are sent to a queue, and the the sender
>>> chooses
>>> +a queue based on the service it needs. The sender does not need to know
>>> +which ODP thread (on which core) or hardware accelerator will process
>>> +the event, but all the events on a queue are eventually scheduled and
>>> processed.
>>> +
>>> +As can be seen, SCHED queues have additional attributes that are
>>> specified at
>>> +queue create that control how the scheduler is to process events
>>> contained
>>> +on them. These include group, priority, and synchronization class.
>>> +
>>> +=== Scheduler Groups
>>> +The scheduler's dispatching job is to return the next event from the
>>> highest
>>> +priority SCHED queue that the caller is eligible to receive events from.
>>> +This latter consideration is determined by the queues _scheduler
>>> group_, which
>>> +is set at queue create time, and by the caller's _scheduler group mask_
>>> that
>>> +indicates which scheduler group(s) it belongs to. Scheduler groups are
>>> +represented by handles of type +odp_scheduler_group_t+ and are created
>>> by
>>> +the *odp_scheduler_group_create()* API. A number of scheduler groups are
>>> +_predefined_ by ODP.  These include +ODP_SCHED_GROUP_ALL+ (all threads),
>>> ++ODP_SCHED_GROUP_WORKER+ (all worker threads), and
>>> +ODP_SCHED_GROUP_CONTROL+
>>> +(all control threads). The application is free to create additional
>>> scheduler
>>> +groups for its own purpose and threads can join or leave scheduler
>>> groups
>>> +using the *odp_scheduler_group_join()* and
>>> *odp_scheduler_group_leave()* APIs
>>> +
>>> +=== Scheduler Priority
>>> +The +prio+ field of the +odp_queue_param_t+ specifies the queue's
>>> scheduling
>>> +priority, which is how queues within eligible scheduler groups are
>>> selected
>>> +for dispatch. Queues have a default scheduling priority of NORMAL but
>>> can be
>>> +set to HIGHEST or LOWEST according to application needs.
>>> +
>>> +=== Scheduler Synchronization
>>> +In addition to its dispatching function, which provide automatic
>>> scalability to
>>> +ODP applications in many core environments, the other main function of
>>> the
>>> +scheduler is to provide event synchronization services that greatly
>>> simplify
>>> +application programming in a parallel processing environment. A queue's
>>> +SYNC mode determines how the scheduler handles the synchronization
>>> processing
>>> +of multiple events originating from the same queue.
>>> +
>>> +Three types of queue scheduler synchronization area supported: Parallel,
>>> +Atomic, and Ordered.
>>> +
>>> +==== Parallel Queues
>>> +SCHED queues that specify a sync mode of ODP_SCHED_SYNC_NONE are
>>> unrestricted
>>> +in how events are processed.
>>> +
>>> +.Parallel Queue Scheduling
>>> +image::../images/parallel_queue.png[align="center"]
>>>
>>> -Queues
>>> -------
>>> -There are three queue types, atomic, ordered and parallel.
>>> -A queue belongs to a single odp_worker and a odp_worker may have
>>> multiple queues.
>>> +All events held on parallel queues are eligible to be scheduled
>>> simultaneously
>>> +and any required synchronization between them is the responsibility of
>>> the
>>> +application. Events originating from parallel queues thus have the
>>> highest
>>> +throughput rate, however they also potentially involve the most work on
>>> the
>>> +part of the application. In the Figure above, four threads are calling
>>> +*odp_schedule()* to obtain events to process. The scheduler has assigned
>>> +three events from the first queue to three threads in parallel. The
>>> fourth
>>> +thread is processing a single event from the third queue. The second
>>> queue
>>> +might either be empty, of lower priority, or not in a scheduler group
>>> matching
>>> +any of the threads being serviced by the scheduler.
>>> +
>>> +=== Atomic Queues
>>> +Atomic queues simplify event synchronization because only a single event
>>> +from a given atomic queue may be processed at a time. Events scheduled
>>> from
>>> +atomic queues thus can be processed lock free because the locking is
>>> being
>>> +done implicitly by the scheduler.
>>> +
>>> +.Atomic Queue Scheduling
>>> +image::../images/atomic_queue.png[align="center"]
>>>
>>> -Events are sent to a queue, and the the sender chooses a queue based on
>>> the service it needs.
>>> -The sender does not need to know which odp_worker (on which core) or HW
>>> accelerator will process the event, but all the events on a queue are
>>> eventually scheduled and processed.
>>> +In this example, no matter how many events may be held in an atomic
>>> queue, only
>>> +one of them can be scheduled at a time. Here two threads process events
>>> from
>>> +two different atomic queues. Note that there is no synchronization
>>> between
>>> +different atomic queues, only between events originating from the same
>>> atomic
>>> +queue. The queue context associated with the atomic queue is held until
>>> the
>>> +next call to the scheduler or until the application explicitly releases
>>> it
>>> +via a call to *odp_schedule_release_atomic()*.
>>>
>>> -NOTE: Both ordered and parallel queue types improve throughput over an
>>> atomic queue (due to parallel event processing), but the user has to take
>>> care of the context data synchronization (if needed).
>>> +Note that while atomic queues simplify programming, the serial nature of
>>> +atomic queues will impair scaling.
>>>
>>> -Atomic Queue
>>> -~~~~~~~~~~~~
>>> -Only one event at a time may be processed from a given queue. The
>>> processing maintains order and context data synchronization but this will
>>> impair scaling.
>>> +=== Ordered Queues
>>> +Ordered queues provide the best of both worlds by providing the inherent
>>> +scaleabilty of parallel queues, with the easy synchronization of atomic
>>> +queues.
>>>
>>> -.Overview Atomic Queue processing
>>> -image::../images/atomic_queue.png[align="center"]
>>> +.Ordered Queue Scheduling
>>> +image::../images/ordered_queue.png[align="center"]
>>>
>>> -Ordered Queue
>>> -~~~~~~~~~~~~~
>>> -An ordered queue will ensure that the sequencing at the output is
>>> identical to that of the input, but multiple events may be processed
>>> simultaneously and the order is restored before the events move to the next
>>> queue
>>> +When scheduling events from an ordered queue, the scheduler dispatches
>>> multiple
>>> +events from the queue in parallel to different threads, however the
>>> scheduler
>>> +also ensures that the relative sequence of these events on output queues
>>> +is identical to their sequence from their originating ordered queue.
>>> +
>>> +As with atomic queues, the ordering guarantees associated with ordered
>>> queues
>>> +refer to events originating from the same queue, not for those
>>> originating on
>>> +different queues. Thus in this figure three thread are processing
>>> events 5, 3,
>>> +and 4, respectively from the first ordered queue. Regardless of how
>>> these
>>> +threads complete processing, these events will appear in their original
>>> +relative order on their output queue.
>>> +
>>> +==== Order Preservation
>>> +Relative order is preserved independent of whether events are being
>>> sent to
>>> +different output queues.  For example, if some events are sent to
>>> output queue
>>> +A while others are sent to output queue B then the events on these
>>> output
>>> +queues will still be in the same relative order as they were on their
>>> +originating queue.  Similarly, if the processing consumes events so
>>> that no
>>> +output is issued for some of them (_e.g.,_ as part of IP fragment
>>> reassembly
>>> +processing) then other events will still be correctly ordered with
>>> respect to
>>> +these sequence gaps. Finally, if multiple events are enqueued for a
>>> given
>>> +order (_e.g.,_ as part of packet segmentation processing for MTU
>>> +considerations), then each of these events will occupy the originator's
>>> +sequence in the target output queue(s). In this case the relative order
>>> of these
>>> +events will be in the order that the thread issued *odp_queue_enq()*
>>> calls for
>>> +them.
>>> +
>>> +The ordered context associated with the dispatch of an event from an
>>> ordered
>>> +queue lasts until the next scheduler call or until explicitly released
>>> by
>>> +the thread calling *odp_schedule_release_ordered()*. This call may be
>>> used
>>> +as a performance advisory that the thread no longer requires ordering
>>> +guarantees for the current context. As a result, any subsequent enqueues
>>> +within the current scheduler context will be treated as if the thread
>>> was
>>> +operating in a parallel queue context.
>>> +
>>> +==== Ordered Locking
>>> +Another powerful feature of the scheduler's handling of ordered queues
>>> is
>>> +*ordered locks*. Each ordered queue has associated with it a number of
>>> ordered
>>> +locks as specified by the _lock_count_ parameter at queue create time.
>>> +
>>> +Ordered locks provide an efficient means to perform in-order sequential
>>> +processing within an ordered context. For example, supposed events with
>>> relative
>>> +order 5, 6, and 7 are executing in parallel by three different threads.
>>> An
>>> +ordered lock will enable these threads to synchronize such that they can
>>> +perform some critical section in their originating queue order. The
>>> number of
>>> +ordered locks supported for each ordered queue is implementation
>>> dependent (and
>>> +queryable via the *odp_config_max_ordered_locks_per_queue()* API). If
>>> the
>>> +implementation supports multiple ordered locks then these may be used to
>>> +protect different ordered critical sections within a given ordered
>>> context.
>>> +
>>> +==== Summary: Ordered Queues
>>> +To see how these considerations fit together, consider the following
>>> code:
>>> +
>>> +.Processing with Ordered Queues
>>> +[source,c]
>>> +----
>>> +void worker_thread()
>>> +{
>>> +        odp_init_local();
>>> +       ...other initialization processing
>>> +
>>> +        while (1) {
>>> +               ev = odp_schedule(&which_q, ODP_SCHED_WAIT);
>>> +               ...process events in parallel
>>> +               odp_schedule_order_lock(0);
>>> +               ...critical section processed in order
>>> +               odp_schedule_order_unlock(0);
>>> +               ...continue processing in parallel
>>> +               odp_queue_enq(dest_q, ev);
>>> +       }
>>> +}
>>> +----
>>>
>>> -.Overview Ordered Queue processing
>>> -image::../images/ordered_queue.png[align="center"]
>>> +This represents a simplified structure for a typical worker thread
>>> operating
>>> +on ordered queues. Multiple events are processed in parallel and the
>>> use of
>>> +ordered queues ensures that they will be placed on +dest_q+ in the same
>>> order
>>> +as they originated.  While processing in parallel, the use of ordered
>>> locks
>>> +enables critical sections to be processed in order within the overall
>>> parallel
>>> +flow. When a thread arrives at the _odp_schedule_order_lock()_ call, it
>>> waits
>>> +until the locking order for this lock for all prior events has been
>>> resolved
>>> +and then enters the critical section. The _odp_schedule_order_unlock()_
>>> call
>>> +releases the critical section and allows the next order to enter it.
>>>
>>> -Parallel Queue
>>> -~~~~~~~~~~~~~~
>>> -There are no restrictions on the number of events being processed.
>>> +=== Queue Scheduling Summary
>>>
>>> -.Overview parallel Queue processing
>>> -image::../images/parallel_queue.png[align="center"]
>>> +NOTE: Both ordered and parallel queues improve throughput over atomic
>>> queues
>>> +due to parallel event processing, but require that the application take
>>> +steps to ensure context data synchronization if needed.
>>> +
>>> +== Glossary
>>> +[glossary]
>>> +worker thread::
>>> +    A worker is a type of ODP thread. It will usually be isolated from
>>> +    the scheduling of any host operating system and is intended for
>>> fast-path
>>> +    processing with a low and predictable latency. Worker threads will
>>> not
>>> +    generally receive interrupts and will run to completion.
>>> +control thread::
>>> +    A control threadis a type of ODP thread. It will be isolated from
>>> the host
>>> +    operating system house keeping tasks but will be scheduled by it
>>> and may
>>> +    receive interrupts.
>>> +thread::
>>> +    An ODP thread is a flow of execution that in a Linux environment
>>> could be
>>> +    a Linux process or thread.
>>> +event::
>>> +    An event is a notification that can be placed in a queue.
>>> +queue::
>>> +    A communication channel that holds events
>>> --
>>> 2.1.4
>>>
>>> _______________________________________________
>>> lng-odp mailing list
>>> lng-odp@lists.linaro.org
>>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>>
>>
>>
>>
>> --
>> Mike Holmes
>> Technical Manager - Linaro Networking Group
>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>>
>>
>>
>


-- 
Mike Holmes
Technical Manager - Linaro Networking Group
Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to