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