Safe and Reliable Embedded Linux Programming: How to Get There
Upcoming SlideShare
Loading in...5
×
 

Safe and Reliable Embedded Linux Programming: How to Get There

on

  • 8,949 views

The talk provides an overview of techniques to design and implement reliable embedded applications. The goal is to achieve safe and analyzable behavior by construction, including handling parallel ...

The talk provides an overview of techniques to design and implement reliable embedded applications. The goal is to achieve safe and analyzable behavior by construction, including handling parallel multiprocessor systems in an efficient and predictable way. The means to attain this objective is to statically configure the application to run on embedded linux platforms, and then to use run-time support to enforce constraints imposed to the system.

Statistics

Views

Total Views
8,949
Views on SlideShare
4,994
Embed Views
3,955

Actions

Likes
0
Downloads
45
Comments
0

11 Embeds 3,955

http://www.open-do.org 3553
http://www.adacore.com 219
http://www.redditmedia.com 149
http://libre.adacore.com 15
http://abtasty.com 7
http://iblunk.com 5
http://translate.googleusercontent.com 3
http://127.0.0.1 1
https://si0.twimg.com 1
http://www.twylah.com 1
http://webcache.googleusercontent.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Safe and Reliable Embedded Linux Programming: How to Get There Safe and Reliable Embedded Linux Programming: How to Get There Presentation Transcript

  • 7 June 2012 Safe and Reliable Embedded Linux Programming How to Get There José F. Ruiz Senior Software Engineer AdaCore EWiLi 2012, LorientCopyright © 2012 AdaCore Slide: 1
  • Outline • Safety issues – Language matters • Concurrent execution on monoprocessors – Ada Ravenscar Profile • Tasking on linux • Parallel execution on multiprocessors – Processor affinitiesCopyright © 2012 AdaCore Slide: 2
  • SafetyCopyright © 2012 AdaCore Slide: 3
  • Safety-Critical Software: Background • What is “safety critical” software? – Failure can cause loss of human life or have other catastrophic consequences • How does safety criticality affect software development? – Regulatory agencies require compliance with certification requirements – Safety-related standards may apply to the finished product, to the development process, or both • Choice of programming language has large impact on the cost of developing / certifying safety-critical systems – Dilemma: modern features that help in developing maintainable systems interfere with safety certification – Examples: Object-Oriented Programming, generics, exceptions, concurrency – Traditional approach: select subset (profile) amenable to safety certification – Chosen features depend on the analysis methods to be used (or dictate which methods are feasible)Copyright © 2012 AdaCore Slide: 4
  • Some language requirements (I) • Reliability – Support for development of readable, correct code – No “traps and pitfalls” – Intuitive lexical and syntactic features – Support for good software engineering practice – Encapsulation – Avoidance of concurrency bugs – Race conditions – Deadlock / livelock – Early error detection – Compile-time checking whenever possible – Run-time checking, at least • Predictability – Unambiguous language semantics – No undefined / implementation-dependent behavior – Ability to demonstrate statically that time and space constraints will be satisfied – Deadlines will be met – Stack and heap space will not be exhaustedCopyright © 2012 AdaCore Slide: 5
  • Some language requirements (II) • Analyzability – Control and data flow analysis – Detects / prevents references to uninitialized data – Information flow analysis – Identify dependencies between a routine’s inputs and outputs – Formal code verification – Range checking – Traceability between program representations and different levels – Dynamic analysis (testing) • Expressiveness – General-purpose features consistent with the above requirements – Support for specialized processing typical in embedded systems (safety) – Interrupt handling – Low-level programming – Fixed-point arithmeticCopyright © 2012 AdaCore Slide: 6
  • Modern programming languages • Many features help – Encapsulation / namespace control – Limit data coupling – Strong typing, compile-time checking – Early error detection • Some features present difficulties – High expressive power vs. need to constrain feature – Dynamic flexibility vs. need for static analysis – High-level features vs. need to certify the code that actually runs – Generated code may contain implicit loops, conditionals – Run-time library, API need to be certifiable – How, if at all, use features such as exceptions, concurrency, dynamic allocationCopyright © 2012 AdaCore Slide: 7
  • Modern programming languages – basic issues • No general-purpose language is appropriate for highest safety/security levels – Conflicts with reliability, predictability, analyzability • Key issue: can the language be subsetted so that applications restricted to the subset can be certified – Is/are the subset(s) precisely defined? – Can compliance with the subset(s) be enforced by a tool? – Who defines the subset(s)? – Standards agency? Tool/compiler vendor? Application developer? – Are there intrinsic problems with the language that cannot be solved by subsetting? • Current approaches – C-based – MISRA C / C++ – Ada-based – Ada profiles – SPARK Ada – Java-based – Real-Time / Safety-Critical Java TechnologyCopyright © 2012 AdaCore Slide: 8
  • MISRA C • Intended for embedded automotive systems – Around 170 rules • Prevent or restrict usage of C constructs with unpredictable behavior • Encourage static checking tools that enforce compliance with the subset Strengths Weaknesses – “Best practices” for C programming – C was not designed to meet the – General good style needs of high-integrity systems – Avoids C features intrinsically non- – Error-prone portable / ill-defined – Lacks features such as – Simplicity of C compared with other encapsulation, namespaces languages – C (and thus MISRA C) does not – Smaller run-time library – Easier certification “scale up” to large systems – Large population of candidate users – C standard has ambiguities and thus – And tools, service providers, etc. so does MISRA C – May be appropriate for small systems – Some rules are not enforceable by on specialized hardware lacking static tools compilers for alternative languages – Usage of MISRA C requires license – MISRA-C code may be produced as from MISRA output of source-to-source translatorCopyright © 2012 AdaCore Slide: 9
  • Ada – introduction • What is Ada? – General-purpose methodology-neutral strongly-typed ISO standard language – Intended for large, long-lived systems – Fits reliability-critical embedded real-time applications • Ada in a nutshell – Pascal-style foundation (syntax, basic data types) – Exception handling – Packages / encapsulation – Generic templates – Concurrency support (“tasking”) – Object-Oriented Programming – Support for “contracts” – Since Ada 2012 – Specialized support for particular domains, including: – Systems programming – Real-time systems – High-Integrity applicationsCopyright © 2012 AdaCore Slide: 10
  • Ada for safety-critical systems (I) • Full Ada not appropriate – Run-time library too large / complex – High level features interfere with traceability and analyzability • Why consider Ada for safety/security-critical software – General design philosophy promotes sound software engineering – Successful history from Ada 83 • Standard support for safety/security-critical systems – High-Integrity Systems Annex – Contracts – Profiles – Such as the Ravenscar profile – User-defined tailoring, specifying features that are not used (pragma Restrictions) – Compiler rejects programs that use these features – Executable program excludes run-time libraries for these features • Guidelines documents – Guide for Ada in High-Integrity Systems (an ISO Technical Report) – Guide for Ada Ravenscar Profile in High-Integrity SystemsCopyright © 2012 AdaCore Slide: 11
  • Ada for safety-critical systems (II) • Reliability – Very few features have surprising effects – Prevention of dangling references to declared objects, subprograms – Specification of intent on operation inheritance – Contracts – No garbage collection – Programmer responsible for memory management • Predictability – Language semantics are generally well-defined, in an ISO standard – But there are features whose effects are implementation defined, implementation dependent, unspecified, or “bounded errors” – Implementation decisions can affect time or space predictability – Functions returning unconstrained arrays – Solutions in practice – Analyze source program (e.g. no read of uninitialized object) – Adhere to subset (no functions returning unconstrained arrays) – Analyze object code so that implementation decision is knownCopyright © 2012 AdaCore Slide: 12
  • Ada for safety-critical systems (III) • Analyzability – Some features help analyzability – Child units may be used for testing packages with encapsulated state – But full language is too complex; need to subset – Key features are pragma Restrictions and pragma Profile – Ada is in effect a family of profiles, where user can select features à la carte – No such thing as the safety-critical Ada profile – Troublesome OOP features are easily avoided – But no standard annotation facility • Expressibility – Support for low-level and real-time programming – Ravenscar Profile for certifiable concurrent applications – Good inter-language interfacing facilities, to incorporate certifiable libraries from other languages – Some weaknesses – Limited support for distribution / networkingCopyright © 2012 AdaCore Slide: 13
  • Ada examples Configuration Spec (design by contract) pragma Profile (Ravenscar); package Arith is -- Only Ravenscar tasking allowed procedure Double (X : in out Integer) with Pre => X >= IntegerFirst / 2 and then pragma Restrictions (No_Allocators); X <= IntegerLast / 2, -- Avoid dynamic memory Post => X = 2 * XOld; end Arith; pragma Restrictions (No_Access_Subprograms); -- No pointers to subprograms System programming type Parity_Kind is (Even, Odd); for UART_Data_Register use record type Reserved_21 is mod 2**21; Data at 0 range 0 .. 7; for Reserved_21Size use 21; Data_Ready at 0 range 8 .. 8; Parity at 0 range 9 .. 9; Type UART_Data_Register is Parity_Error at 0 range 10 .. 10; record Reserved at 0 range 11 .. 31; Data : Character; end record; Data_Ready : Boolean; for UART_Data_RegisterSize use 32; Parity : Parity_Kind; Parity_Error : Boolean; UART_A : UART_Data_Register; Reserved : Reserved_21; pragma Atomic (UART_A); end record; for UART_A’Address use To_Address (16#8000_0100#);Copyright © 2012 AdaCore Slide: 14
  • Ada evaluation • Strengths – Sound base language for programming high-reliability systems – Allows construction of tailored high-integrity subsets that are: – Powerful enough to use for real systems – Simple enough to be amenable to certification – Scales up to large systems – ISO Standard – Concurrency support / Ravenscar Profile – Design by contract – Free and publicly available documents – Ada Reference Manual, Rationale – Guidelines documents – Good track record in avionics, train control, other safety-critical domains • Weaknesses – Whole language is too large, so must be subsetted – Aside from the standard Ravenscar Profile, others are vendor specific – Language has some features with implementation-dependent or unspecified behavior – Such as referencing a variable before its initialization – Smaller user / tool vendor community than other languagesCopyright © 2012 AdaCore Slide: 15
  • SPARK introduction (I) • SPARK is – A language, plus – Static analysis tools based on underlying principle of correctness by construction • Facilitate rigorous, static demonstration that program does what it is supposed to do – And only that • Guarantee bounded time and space requirements • Allow simple run-time library amenable to certification • Ada-based language – Ada plus contracts minus features that interfere with above principle – Contracts are special comments handled by the SPARK tools • Language restrictions (Ada features intentionally omitted) – Features that complicate analysis / formal proofs, e.g.: – Exceptions, goto statement, generic templates, function side effects – Features that interfere with bounded time / space requirement, e.g.: – Recursion, pointers, dynamically-sized arraysCopyright © 2012 AdaCore Slide: 16
  • SPARK introduction (II) • Language features include: – Most of Ada’s “static semantic” features, including packages, private types, unconstrained array types, “OOP Lite” – Concurrency (Ravenscar tasking profile) • Contracts – Data / information flow (use of global variables, formal parameters) – Inter-module dependencies – Specification of dynamic behavior (pre / post-conditions, assertions) • Analysis performed by SPARK tools – Static semantic analysis – detect aliasing, function side effects, … – Control flow analysis – detect dead code, banned constructs (goto, …) – Data-flow analysis – detect unused or uninitialized variables, … – Information-flow analysis – check input / output variable coupling – Verification condition generation – generate theorems – Theorem provingCopyright © 2012 AdaCore Slide: 17
  • SPARK example Contracts and flow information procedure Process (Output : out T; Input1, Input2 : in T); --# global out Global_Output; --# in Global_Input; --# derives Output from Input1, Input2 & --# Global_Output from Global_Input, Input2; --# pre Input1 /= 0; --# post Output = Input2 / Input1;Copyright © 2012 AdaCore Slide: 18
  • SPARK for safety-critical systems • Reliability – Inherits Ada’s general advantages (few syntactic surprises) – Avoids some errors that may occur in full Ada – Reference to uninitialized variable • Predictability – Unambiguous specification with no implementation dependencies – But not a formal standard – Contracts allow statically checkable assertions about resource requirements • Analyzability – SPARK Ada subset eliminates features that are complicated to analyze • Expressibility – Missing some useful functionality (e.g. generics) but does include some tasking featuresCopyright © 2012 AdaCore Slide: 19
  • SPARK evaluation • Strengths – Designed from the start to satisfy high-integrity requirements – Language rules are unambiguous, implementation independent – Insecurities (e.g., “aliasing” of formal parameter and global variable) and many kinds of hard-to-detect bugs (e.g. use before initialization) are prevented – Contracts show programmer’s intent, aid readability – Support for concurrency (Ravenscar profile) – Tedious aspects of constructing proofs are automated – Positive experience across a range of high-integrity projects – Lower certification costs and post-delivery bug rates – Excellent reference material • Weaknesses – Language lacks some useful features – No “pointers”, but in many kinds of safety critical systems a restricted style for pointers is permitted • Pointers to statically declared data • Dynamic allocation at system startup – Some restrictions (e.g. no recursion) require stylistic workarounds – Contracts require different development style than what most programmers are used to – Relatively small user community – Small number of suppliers for tools, servicesCopyright © 2012 AdaCore Slide: 20
  • ConcurrencyCopyright © 2012 AdaCore Slide: 21
  • Concurrency in Ada (short history) • Concurrency a first-class citizen in Ada – Easy to use and analyze – Since the beginning – Well-developed tasking in Ada 83 – Ada 95, Ada 2005 , Ada 2012 improved and extended tasking Ada Decades of experience in using Ada on multiprocessorsCopyright © 2012 AdaCore Slide: 22
  • Why Ravenscar • Use concurrency in embedded real-time systems – Verifiable – Simple – Implemented reliably and efficiently • Scheduling theory for accurate analysis of real-time behavior – Preemptive fixed priority scheduling – Rate Monotonic Analysis (RMA) – Response Time Analysis (RTA) – Priority Ceiling Protocol (PCP) – Avoids unbounded priority inversion and deadlocks • Tool support – RMA and RTA – Static simulation of concurrent real-time programsCopyright © 2012 AdaCore Slide: 23
  • What is the Ravenscar profile • A subset of the Ada tasking model • Defined to meet safety-critical real-time requirements – Determinism – Schedulability analysis – Memory-boundedness – Execution efficiency and small footprint – Suitability for certification • State-of-the-art concurrency constructs – Adequate for most types of real-time softwareCopyright © 2012 AdaCore Slide: 24
  • Tasks • Fixed set of tasks – Only at library level – No dynamic allocation – No nested declaration of tasks – Statically created – Task descriptors, stacks, … • Each task is infinite loop – Single “triggering” action (delay or event) • Task creation and activation is very simple and deterministic – All tasks are created at initialization – Then all activated and executed according to their priorityCopyright © 2012 AdaCore Slide: 25
  • How tasks look like in Ravenscar Time-triggered task Event-triggered task task body Cyclic is Period : constant Time_Span := Milliseconds (10); Activation : Time := Clock; task body Sporadic is begin begin loop loop delay until Activation; Monitor.Wait_Event; -- Protected entry -- Do something -- Do something Something; Something; end loop; -- Compute next activation time end Sporadic; Activation := Activation + Period; end loop; end Cyclic;Copyright © 2012 AdaCore Slide: 26
  • Periodic activity in Ada and C static void *periodic (void *arg) { struct timespec activation; clock_gettime (CLOCK_REALTIME, &activation); C Periodic while (1) { clock_nanosleep (CLOCK_REALTIME, TIMER_ABSTIME, &activation, NULL); Freq = 10 Hz /* Do something */ something (); /* Compute next activation time */ if (1000000000 - activation.tv_nsec < 100000000) { task body Periodic is activation.tv_sec += 1; Activation : Time := Clock; activation.tv_nsec += 100000000 - 1000000000; begin } else { loop activation.tv_nsec += 100000000; delay until Activation; } } -- Do something } Something; int main(void) { pthread_t thread; -- Compute next activation time pthread_attr_t attr; Activation := pthread_attr_init (&attr); Activation + Milliseconds (100); end loop; pthread_create (&thread, &attr, &periodic, NULL); end Periodic; … }Copyright © 2012 AdaCore Slide: 27
  • Synchronization in Ravenscar protected body Buffer is protected Buffer is procedure Put (Element : Item) procedure Put (Element : Item); is entry Get (Element : out begin Item); Container := Element; private Received := True; Container : Item; end Put; Received : Boolean := False; end Buffer; Pr Buffer entry Get (Element : out Item) when Received is Put begin Get Element := Container; Received := False; C Producer end Get; end Buffer; S Consumer task body Producer is Period : constant Time_Span := Milliseconds (10); Activation : Time := Clock; Element : Item; begin loop task body Consumer is delay until Activation; Element : Item; begin Element := Produce_It; loop Buffer.Get Buffer.Put (Element); (Element); Activation := Activation + Period; Consume (Element); end loop; end loop; end Producer; end Consumer;Copyright © 2012 AdaCore Slide: 28
  • Interrupt support in Ravenscar protected Monitor is pragma Priority (Interrupt_Priority’Last); Pr Monitor procedure Handler; External Interrupt pragma Attach_Handler (Handler, Handler Interrupt_ID); Wait entry Wait; private Signaled : Boolean := False; end Monitor; S Interrupt_Task protected body Monitor is task body Interrupt_Task procedure Handler is is begin begin Signaled := True; loop end Put; Monitor.Wait; entry Wait when Signaled is Handle_Interrupt; begin end loop; Signaled := False; end Interrupt_Task; end Wait; end Monitor;Copyright © 2012 AdaCore Slide: 29
  • Concurrency on linuxCopyright © 2012 AdaCore Slide: 30
  • The model – Ada tasks • Ada task runs on top of operating system thread – One-to-one correspondence • Task dispatching policy – Can be selected with pragma Dispatching_Policy – SCHED_OTHER by default – Preemptive priority scheduling – pragma Dispatching_Policy (FIFO_Within_Priorities) • pthread_setschedparam (Thread, SCHED_FIFO, Param’Access) – Means run until blocked (or preempted), no time slicing – Reduces non-determinism – NOTE!!: Requires special (root) privileges • Xenomai – Real-time behavior – The Ada run-time library can call the Xenomai API to create tasks in kernel domainCopyright © 2012 AdaCore Slide: 31
  • The model – Synchronization • A protected type is a data object with locks – Data encapsulation, accessible through interface (locked access routines) – functions (read the data with read lock) – procedures (read/write the data with write lock) – entries (wait until some condition is met, then read/write the data with write lock) • Priority inheritance – Guard against priority inversion – low priority task grabs resource X – high priority task needs resource X, waits – medium priority task preempts low priority task, and runs for a long time, holding up high priority task – Solution, while high priority task is waiting, lend high priority to low priority task • Implementation – Mutual exclusion – Mutex – Waiting / Signaling operations – Conditional variableCopyright © 2012 AdaCore Slide: 32
  • The model – System programming • Clock and delay – Clock uses gettimeofday – Delay operations use timed conditional variables – We can wakeup the task before expiration if needed • Interrupt handling – Underlying signal mechanism – A server task per interrupt served – With specific mask to serve the required signal – Call to sigwaitCopyright © 2012 AdaCore Slide: 33
  • MultiprocessorsCopyright © 2012 AdaCore Slide: 34
  • Why addressing multiprocessors? • The answer to increasing processing demands – We cannot increase the clock frequency forever – We cannot increase the instruction-level parallelism forever – Provides higher performance for less consumed energy Courtesy IEEE Computer, January 2011, page 33.Copyright © 2012 AdaCore Slide: 35
  • Periodic activity in Ada and C (multiprocessor version) static void *periodic (void *arg) { struct timespec activation; clock_gettime (CLOCK_REALTIME, &activation); while (1) { C Periodic clock_nanosleep (CLOCK_REALTIME, TIMER_ABSTIME, &activation, NULL); Freq = 10 Hz /* Do something */ CPU affinity = 1 something (); /* Compute next activation time */ if (1000000000 - activation.tv_nsec < 100000000) { activation.tv_sec += 1; activation.tv_nsec += 100000000 - 1000000000; task Periodic with CPU => 1; } else { activation.tv_nsec += 100000000; task body Periodic is } Activation : Time := Clock; } begin } loop delay until Activation; int main(void) { cpu_set_t cpuset; -- Do something pthread_t thread; pthread_attr_t attr; Something; CPU_ZERO (&cpuset); -- Compute next activation time CPU_SET (0, &cpuset); pthread_attr_init (&attr); Activation := pthread_attr_setaffinity_np Activation + Milliseconds (100); (&attr, sizeof (cpu_set_t), &cpuset); end loop; end Periodic; pthread_create (&thread, &attr, &periodic, NULL); … }Copyright © 2012 AdaCore Slide: 36
  • Some advantages of Ada • Better readability – No doubts, right? • Semantics – The Ada run time enforces required dispatching policy, signal mask, master-dependent tasks, … • Portability Platform Ada C Linux Solaris Windows VxWorks Bare boardCopyright © 2012 AdaCore Slide: 37
  • Ada 2012 • Ada 2012 added explicit support for controlling processor allocation – Dispatching_Domain • Ravenscar profile for multiprocessors • Parallel task synchronization • Memory barriersCopyright © 2012 AdaCore Slide: 38
  • Concurrent / parallel execution in Ada • Ada has always taken into account parallel architectures – Allow concurrent/parallel execution – Multicomputers, multiprocessors, interleaved execution – Even allow parallel execution of a single task – … if its effect is as executed sequentially – A task can be on the ready queues of more than one processor – Many partitioning schemes allowed – Via implementation-defined pragmas or non standard library packagesCopyright © 2012 AdaCore Slide: 39
  • Synchronization and communication of parallel activities • Task synchronization – Protected objects – No language-defined ordering or queuing presumed for tasks competing to start a protected action • Tasks are intended to spin lock on multi-processors – Shared variables – Cache coherence – Rendezvous – The call to the task entry is blockingCopyright © 2012 AdaCore Slide: 40
  • Symmetric Multi-Processor (SMP) • Several similar processors – All processors can perform the same functions • Centralized memory with uniformed access time – Problem of cache coherence Processor Processor Processor Processor One or One or One or One or more cache more cache more cache more cache levels levels levels levels Main memory I/O SystemCopyright © 2012 AdaCore Slide: 41
  • Partitioned versus global scheduling Partitioning Global Scheduling • Tasks assigned to a given • Task migration is permitted processor – Overhead of task migration • How to schedule a group of tasks increases with the number of CPUs on a processor is known – Reduced cache performance – Rate Monotonic Scheduling (static priorities) – Earliest Deadline First (dynamic None is better than the other in priorities) terms of guaranteed CPU utilization • But, dividing the tasks into groups is NP-hardCopyright © 2012 AdaCore Slide: 42
  • Typical OS support for multiprocessors • Set CPU affinity – Allocate tasks to one CPU (or to a group of CPUs) • Get CPU affinity • Task migration – From one CPU to another – Either user-requested or performed by the OS • Spin locks – Tasks wait in a loop until lock is free (busy waiting) – Multiprocessor synchronizationCopyright © 2012 AdaCore Slide: 43
  • Support for multiprocessors in Ada 83, 95, 05 • Ada has always allowed a program’s implementation to be on a multiprocessor system – Real parallelism – Inter-processor synchronization • No direct support for affinities – The OS can decide the best allocation – The developer – Implementation-defined pragmas or non standard library packages • Allows the full range of partitioning – But no user control defined in the standardCopyright © 2012 AdaCore Slide: 44
  • Explicit support for multiprocessors in Ada 2012 • Notion of dispatching domain • Safe multiprocessor tasking • Parallel task synchronization • Memory barriersCopyright © 2012 AdaCore Slide: 45
  • Ada 2012 dispatching domains • Focus on SMPs • Handle mapping of tasks to processors – Support all schemes – Partitioned • Tasks allocated to a subset of CPUs – Global • Implicit task migration supported • Explicit task migration allowed • Notion of processor dispatching domain – Group of processors across which global scheduling occurs – Non-overlapping dispatching domains – Tasks are assigned to an unique dispatching domain – A task may be allocated to a given processor within the dispatching domain – Or free to be in any of the domainCopyright © 2012 AdaCore Slide: 46
  • Static allocation to processors task type Allocated_Task (Affinity : CPU) with CPU => Affinity; T1 : Allocated_Task (1); T2 : Allocated_Task (2); T3 : Allocated_Task (3); T4 : Allocated_Task (4); GroupA : aliased Dispatching_Domain := Create (1, 2); GroupB : aliased Dispatching_Domain := Create (3, 4); GroupC : aliased Dispatching_Domain := Create (5, 6); GroupD : aliased Dispatching_Domain := Create (7, 8); task type Grouped_Task (Group : access Dispatching_Domain) with Dispatching_Domain => Group.all; T1, T2, T3, T4 : Grouped_Task (GroupA’Access); T5, T6 : Grouped_Task (GroupB’Access); T7, T8, T9 : Grouped_Task (GroupC’Access); T10, T11 : Grouped_Task (GroupD’Access);Copyright © 2012 AdaCore Slide: 47
  • Dynamic affinity handling GroupA : Dispatching_Domain := Create (1, 2); GroupB : Dispatching_Domain := Create (3, 4); GroupC : Dispatching_Domain := Create (5, 6); GroupD : Dispatching_Domain := Create (7, 8); task body T_In_A is Current_CPU : CPU; begin -- In processor 1 or 2 Do_Something; task T_In_A with Dispatching_Domain => GroupA; -- In processor 1 only task T_Non_Allocated; Set_CPU (1); task body Driver is Do_Something; begin -- Allocate T_Non_Allocated to GroupB -- In processor 2 only Assign_Task Set_CPU (Get_Last_CPU (GroupA)); (GroupB, 3, T_Non_Allocated’Identity); Do_Something; Do_Something; -- Now again in processor 1 or 2 -- Move it to a different processor Set_CPU (Not_A_Specific_CPU); if Proc_3_Overloaded then Do_Something; Set_CPU (4, T_Non_Allocated’Identity); end if; -- Now I am lost. Where am I? Do_Something; Current_CPU := Get_CPU; end Driver; pragma Assert (Current_CPU = Not_A_Specific_CPU); end T_In_A;Copyright © 2012 AdaCore Slide: 48
  • Handle affinity and dispatching policy • What I want – Create a group of processors – Define an specific scheduling policy for the group pragma Priority_Specific_Dispatching (FIFO_Within_Priorities, 20, 25); – Execute a set of tasks within the group Group : Dispatching_Domain := Create (1, 2); task T1 • What I have to do with Dispatching_Domain => Group, Priority => 22; – Create a dispatching domain – Define a non-overlapping priority band task T2 with Dispatching_Domain => Group, – Allocate tasks to the dispatching domain Priority => 23, CPU => 1; – Use priorities in the priority band task T3 with Dispatching_Domain => Group, Priority => 24;Copyright © 2012 AdaCore Slide: 49
  • Synchronization on multiprocessors • Protected objects – There is a lock-free optimization for monoprocessors (using priorities) – No longer viable on multiprocessors – Currently Ada advise that tasks should busy-wait (spin) at their active priority for the lock • Task entries – Requires internal synchronization primitives aware of multiprocessor – Spin locksCopyright © 2012 AdaCore Slide: 50
  • Multicores for real-time safety-critical embedded systems • We need to address: – Reliability – Predictability – Analyzability • The Ravenscar profile for monoprocessors is – Deterministic – Time analyzable – Simple to use and implement • Extend the Ravenscar profile model from monoprocessor to multiprocessor – Fully partitioned model – Fixed-priority scheduling – Static model • Allow for – Simple implementation – Verifiable – Schedulability analysisCopyright © 2012 AdaCore Slide: 51
  • Static model • Concurrent entities fixed and static – Tasks and shared memory defined before execution • Static fixed priority scheduling algorithm – Preemptive fixed priority scheduling in each CPU – Analyzable as in Ravenscar for monoprocessors – Dynamic-priority scheduling algorithms could increase CPU utilization but: – Higher complexity – Higher run-time overhead – Lower predictability, lower robustness in case of overload • Partitioned – Each task allocated to an user-defined processor forever – CPU utilization of partitioned scheduling is neither better nor worse than global – It relies on very well known monoprocessor techniques for priority allocation and timing analysis – It is much simpler to implement – No task migrationCopyright © 2012 AdaCore Slide: 52
  • Task scheduling • Tasks statically allocated to processors Ravenscar system on monoprocessor – No task migration • Preemptive fixed-priority scheduling 0 1 • Single shared run time 2 – Per-CPU ready queues – Spin-locks to protect shared data 3 – Disabling interrupts is not enough task Cyclic with Priority => 100, • Operations on a different CPU => 3; end Cyclic; processors – Triggering an special interrupt in the target processorCopyright © 2012 AdaCore Slide: 53
  • Task synchronization • Library-level protected objects – Shared data with mutual exclusion – Both for inter- and intra-processor communication • Simple and efficient mutual exclusion changing priority for intra-processor communication – As in Ravenscar monoprocessor – Could be statically detected – Efficiency – Simple timing analysis • Spin-locking for inter-processor synchronization • Awaking tasks from other processors – Inter-processor interrupt facility to modify the ready queuesCopyright © 2012 AdaCore Slide: 54
  • Parallel task synchronization • Goal – Effective parallel task synchronization – Set of tasks blocked and released at once • Typical case – A group of tasks must wait until all of them reach a synchronization point – And then be released together to work in parallel • Mimic the POSIX barrier mechanismCopyright © 2012 AdaCore Slide: 55
  • Parallel barrier example package Ada.Synchronous_Barriers is pragma Preelaborate (Synchronous_Barriers); subtype Barrier_Limit is Positive range 1 .. <imp- def>; type Synchronous_Barrier (Release_Threshold : Barrier_Limit) is limited private; procedure Wait_For_Release (The_Barrier : in out Synchronous_Barrier; Notified : out Boolean); Number_Of_Tasks : constant := 8; private Barrier : Synchronous_Barrier (Number_Of_Tasks); -- not specified by the language end Ada.Synchronous_Barriers; task type Worker (Affinity : CPU) with CPU => Affinity; task body Worker is Notified : Boolean; begin loop Wait_For_Release (Barrier, Notified); -- Do something in parallel at the same time Something; if Notified then -- Only one task does this Ask_For_More_Work; end if; end loop; end Worker;Copyright © 2012 AdaCore Slide: 56
  • Memory barriers • Goal – Have control over cache memories • Typical case – Non-blocking algorithms to effectively exploit hardware parallelism – lock-free and wait-free • Problem to solve – How to ensure the correct order of loads and stores with multi-level caches – Modern multicores do not guarantee this ordering between processors – Optimizations that can result in out-of-order execution – Unless special instructions are used • How to do it with Volatile – Until Ada 2005 – They can never be in cache or registers – The Ada 2012 (more realistic) approach – Volatiles can be handled in cache memories, but – Guarantee serial ordering • All tasks of the program (on all processors) that read or update volatile variables see the same order of updates to the variables • May need the use of an appropriate memory barrier to flush the cacheCopyright © 2012 AdaCore Slide: 57
  • Example of memory barriers Shared_Data : Integer; pragma Volatile (Shared_Data); • In Ada 83, 95, 2005 Barrier : Boolean := False; pragma Volatile (Barrier); – Shared_Data and Barrier can never be in cache task Producer with CPU => 1; task Consumer with CPU => 2; • In Ada 2012 task body Producer is begin – Shared_Data and Barrier can be in cache … Produce (Shared_Data); Barrier := True; … end Producer; task body Consumer is begin … while not Barrier loop null; end loop; -- If we see that Barrier has been updated, -- we must see the produced value of -- Shared_Data. Use(Shared_Data); … end Consumer;Copyright © 2012 AdaCore Slide: 58
  • Conclusion • There is support in programming environments for high-integrity • Embedded programming can use high-level abstraction constructs • Real-time support – Computational model amenable to timing analysis • Ada has supported execution on parallel architectures since its inception – Ada 2012 dispatching domains – Good flexibility and analyzability – Implementable on top of typical operating systems and kernels – Ravenscar for multiprocessors – Simple extension to Ravenscar on monoprocessors – Partitioning into a set of monoprocessor Ravenscar systems – Keep desired properties found in monoprocessor RavenscarCopyright © 2012 AdaCore Slide: 59