You are on page 1of 47

CHAPTER 7

CONCURRENT SOFTWARE

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Program Organization of a
Foreground/Background System
start Interrupt Interrupt Interrupt

ISR for ISR for ISR for


Initialize
Task #1 Task #2 Task #3

Wait for
Interrupts
IRET IRET IRET

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Foreground/Background System
• Most of the actual work is performed in the
"foreground" ISRs, with each ISR
processing a particular hardware event.
• Main program performs initialization and
then enters a "background" loop that waits
for interrupts to occur.
• Allows the system to respond to external
events with a predictable amount of latency.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Task State and Serialization
unsigned int byte_counter ;

void Send_Request_For_Data(void)
{
outportb(CMD_PORT, RQST_DATA_CMD) ;
byte_counter = 0 ;
}

void interrupt Process_One_Data_Byte(void)


{
BYTE8 data = inportb(DATA_PORT) ;
switch (++byte_counter)
{
case 1: Process_Temperature(data) ; break ;
case 2: Process_Altitude(data) ; break ;
case 3: Process_Humidity(data) ; break ;
……
}
} Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Input Ready

STI

Input Data
ISR with Long
Execution Time
Process Data

Output Device
Ready?
Yes
Output Data

Send EOI
Command to
PIC

IRET Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Input Enter
Ready Background

STI Initialize

Input Data
Data
Enqueued
Removing
?
Yes the Waiting
Loop from
Process Output
Data Device
Ready?

the ISR
Yes
Enqueue FIFO Dequeue
Data Queue Data

Send EOI Output


Command Data
to PIC

IRET
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Input Output
Ready Ready

STI STI

Input Data
Interrupt-
Process
Data
Data Enqueued?
Driven
Output
Yes
Enqueue FIFO Dequeue
Data Queue Data

Output Data

Send EOI Send EOI


Command to Command to
PIC PIC

IRET IRET

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Input
Ready
Kick Starting Output
STI

SendData Output
Input Data Subroutine Ready

Process Data Data Enqueued? STI

Yes
Enqueue Data FIFO Dequeue Data
Queue Clear Busy
Flag
Output No! Output Data
Device
Busy?
CALL SendData
CALL SendData
(Kick Start) Set Busy Flag

Send EOI
Send EOI RET Command to
Command to PIC
PIC

IRET Copyright © 2000, Daniel W. Lewis. All Rights Reserved. IRET


Preventing Interrupt Overrun
Input Input Data Removes the interrupt request
Ready that invoked this ISR.

Send EOI When interupts get re-enabled (see STI below),


Command to allow interrupts from lower priority devices (and
PIC this device too).

ISR Busy Flag Yes  Ignore this Interrupt!


Set?
(Interrupts are re-enabled by the IRET)

Set ISR Busy


Flag

STI Allow interrupts from any device.

Process data, write result to


output queue, & kick start.

Clear ISR IRET


Busy Flag

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Preventing Interrupt Overrun
Input STI Allow interrupts from higher
Ready priority devices.

Input Data Removes the interrupt


request that invoked this
ISR.

Disable future
Set the mask bit for this interrupts from
device in the 8259 PIC this device.

Send EOI Allow interrupts from


Command to lower priority devices.
PIC
Process data, write result to output
queue, & kick start.

Clear the mask bit for this Enable future


interrupts from IRET
device in the 8259 PIC
this device.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Moving Work into Background
• Move non-time-critical work (such as
updating a display) into background task.

• Foreground ISR writes data to queue, then


background removes and processes it.

• An alternative to ignoring one or more


interrupts as the result of input overrun.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Limitations
• Best possible performance requires moving
as much as possible into the background.
• Background becomes collection of queues
and associated routines to process the data.
• Optimizes latency of the individual ISRs,
but background begs for a managed
allocation of processor time.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Multi-Threaded Architecture
Queue Background Queue
ISR ISR
Thread

ISR Queue Background Queue ISR


Thread

Multi-threaded run-time function library (the real-time kernel)

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Thread Design
• Threads usually perform some initialization
and then enter an infinite processing loop.

• At the top of the loop, the thread


relinquishes the processor while it waits for
data to become available, an external event
to occur, or a condition to become true.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Concurrent Execution of
Independent Threads
• Each thread runs as if it had its own CPU
separate from those of the other threads.
• Threads are designed, programmed, and
behave as if they are the only thread
running.
• Partitioning the background into a set of
independent threads simplifies each thread,
and thus total program complexity.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Each Thread Maintains Its Own
Stack and Register Contents
Context of Thread 1 Context of Thread N

Stack Registers Stack Registers

CS:EIP CS:EIP
SS:ESP SS:ESP
EAX EAX
EBX EBX

EFlags EFlags

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Concurrency
• Only one thread runs at a time while others are
suspended.
• Processor switches from one thread to another so
quickly that it appears all threads are running
simultaneously. Threads run concurrently.
• Programmer assigns priority to each thread and
the scheduler uses this to determine which thread
to run next

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Real-Time Kernel
• Threads call a library of run-time routines
(known as the real-time kernel) manages
resources.

• Kernel provides mechanisms to switch


between threads, for coordination,
synchronization, communications, and
priority.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Context Switching
• Each thread has its own stack and a special
region of memory referred to as its context.
• A context switch from thread "A" to thread
"B" first saves all CPU registers in context
A, and then reloads all CPU registers from
context B.
• Since CPU registers includes SS:ESP and
CS:EIP, reloading context B reactivates
thread B's stack and returns to where it left
off when it was last suspended.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Context Switching
Thread A Thread B

Executing Suspended

Save context A Restore context


B

Suspended Executing

Restore context Save context B


Executing A
Suspended

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Non-Preemptive Multi-Tasking
• Threads call a kernel routine to perform the
context switch.
• Thread relinquishes control of processor,
thus allowing another thread to run.
• The context switch call is often referred to
as a yield, and this form of multi-tasking is
often referred to as cooperative multi-
tasking.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Non-Preemptive Multi-Tasking
• When external event occurs, processor may be executing a
thread other than one designed to process the event.

• The first opportunity to execute the needed thread will not


occur until current thread reaches next yield.

• When yield does occur, other threads may be scheduled to


run first.

• In most cases, this makes it impossible or extremely


difficult to predict the maximum response time of non-
preemptive multi-tasking systems.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Non-Preemptive Multi-Tasking
• Programmer must call the yield routine frequently,
or else system response time may suffer.

• Yields must be inserted in any loop where a thread


is waiting for some external condition.

• Yield may also be needed inside other loops that


take a long time to complete (such as reading or
writing a file), or distributed periodically
throughout a lengthy computation.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Context Switching in a Non-
Preemptive System
Start
Scheduler selects highest
priority thread that is ready to
Thread run. If not the current thread,
Initialization the current thread is suspended
and the new thread resumed.

Yes
Wait? Yield to other
threads

Data
Processing

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Preemptive Multi-Tasking
• Hardware interrupts trigger context switch.
• When external event occurs, a hardware
ISR is invoked.
• After servicing the interrupt request the ISR
raises the priority of the thread that
processes the associated data, then switches
context switch to the highest priority thread
that is ready to run and returns to it.
• Significantly improves system response
time.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Preemptive Multi-Tasking
• Eliminates the programmer's obligation to
include explicit calls to the kernel to
perform context switches within the various
background threads.
• Programmer no longer needs to worry about
how frequently the context switch routine is
called; it's called only when needed - i.e., in
response to external events.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Preemptive Context Switching
Thread A Thread B
Thread A
Executing Thread B
Suspended
ISR
Hardware
Interrupt
Process Scheduler selects highest
Interrupt priority thread that is ready to
Request run. If not the current thread,
the current thread is
suspended and the new thread
Context resumed.
Switch

IRET
Thread B
Thread A Executing
Suspended
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Critical Sections
• Critical section: A code sequence whose proper
execution is based on the assumption that it has
exclusive access to the shared resources that it
is using during the execution of the sequence.

• Critical sections must be protected against


preemption, or else integrity of the computation
may be compromised.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Atomic Operations
• Atomic operations are those that execute to
completion without preemption.

• Critical sections must be made atomic.


– Disable interrupts for their duration, or
– Acquire exclusive access to the shared resource
through arbitration before entering the critical
section and release it on exit.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Threads, ISRs, and Sharing
1. Between a thread and an ISR:
Data corruption may occur if the thread's critical
section is interrupted to execute the ISR.
2. Between 2 ISRs:
Data corruption may occur if the critical section
of one ISR can be interrupted to execute the
other ISR.
3. Between 2 threads:
Data corruption may occur unless execution of
their critical sections is coordinated.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Shared Resources
• A similar situation applies to other kinds of
shared resources - not just shared data.

• Consider two or more threads that want to


simultaneously send data to the same (shared)
disk, printer, network card, or serial port. If
access is not arbitrated so that only one thread
uses the resource at a time, the data streams
might get mixed together, producing nonsense at
the destination.
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Uncontrolled Access to a Shared
Resource (the Printer)
Shared Printer
Thread A
Thread B

"HELLO\n" HgoELodLO "goodbye"


bye

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Protecting Critical Sections
• Non-preemptive system: Programmer has explicit
control over where and when context switch occurs.
– Except for ISRs!

• Preemptive system: Programmer has no control over the


time and place of a context switch.

• Protection Options:
– Disabling interrupts
– Spin lock
– mutex
– semaphore

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Disabling Interrupts
• The overhead required to disable (and later
re-enable) interrupts is negligible.
– Good for short critical sections.

• Disabling interrupts during the execution of


a long critical section can significantly
degrade system response time.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Spin Locks
If the flag is set, another thread is currently using the
shared memory and will clear the flag when done.

do {
Flag disable() ; L1: MOV AL,1
set? ok = !flag ; XCHG [_flag],AL
flag = TRUE ; OR AL,AL
No enable() ; JNZ L1
} while (!ok) ;
Set Flag

Critical Spin-lock in
Spin-lock in C.
Section assembly.

Clear Flag flag = FALSE ; MOV BYTE [_flag],0

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Spin Locks vs. Semaphores
• Non-preemptive system requires kernel call
inside spin lock loop to let other threads
run.
• Context-switching during spin lock can be a
significant overhead (saving and restoring
threads’ registers and stack).
• Semaphores eliminate the context-switch
until flag is released.

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Semaphores

Kernel suspends this thread


Semaphore “Pend” if another thread has
possession of the
semaphore; this thread does
not get to run again until
the other thread releases
Critical Section the semaphore with a “post”
operation.

Semaphore “Post”

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Kernel Services
• Initialization • Semaphores
• Threads • Mailboxes
• Scheduling • Queues
• Priorities • Time
• Interrupt Routines

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Initialization Services
Multi-C:
n/a

C/OS-II:
OSInit() ;
OSStart() ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Thread Services
Multi-C:
ECODE MtCCoroutine(void (*fn)(…)) ;
ECODE MtCSplit(THREAD **new, MTCBOOL *old) ;
ECODE MtCStop(THREAD *) ;

C/OS-II:
BYTE8 OSTaskCreate(void (*fn)(void *), void *data,
void *stk, BYTE8 prio) ;
BYTE8 OSTaskDel(BYTE8 prio) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Scheduling Services
Multi-C:
ECODE MtCYield(void) ;

C/OS-II:
void OSSchedLock(void) ;
void OSSchedUnlock(void) ;
BYTE8 OSTimeTick(BYTE8 old, BYTE8 new) ;
void OSTimeDly(WORD16) ;]

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Priority Services
Multi-C:
ECODE MtCGetPri(THREAD *, MTCPRI *) ;
ECODE MtCSetPri(THREAD *, MTCPRI) ;

C/OS-II:
BYTE8 OSTaskChangePrio(BYTE8 old, BYTE8 new) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


ISR Services
Multi-C:
n/a

C/OS-II:
OS_ENTER_CRITICAL() ;
OS_EXIT_CRITICAL() ;
void OSIntEnter(void) ;
void OSIntExit(void) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Semaphore Services
Multi-C:
ECODE MtCSemaCreate(SEMA_INFO **) ;
ECODE MtCSemaWait(SEMA_INFO *, MTCBOOL *) ;
ECODE MtCSemaReset(SEMA_INFO *) ;
ECODE MtCSemaSet(SEMA_INFO *) ;

C/OS-II:
OS_EVENT *OSSemCreate(WORD16) ;
void OSSemPend(OS_EVENT *, WORD16, BYTE8 *) ;
BYTE8 OSSemPost(OS_EVENT *) ;
Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Mailbox Services
Multi-C:
n/a

C/OS-II:
OS_EVENT *OSMboxCreate(void *msg) ;
void *OSMboxPend(OS_EVENT *, WORD16, BYTE8 *) ;
BYTE8 OSMboxPost(OS_EVENT *, void *) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Queue Services
Multi-C:
ECODE MtCReceive(void *msgbfr, int *msgsize) ;
ECODE MtCSendTHREAD *, void *msg, int size, int pri) ;
ECODE MtCASendTHREAD *, void *msg, int size, int pri) ;

C/OS-II:
OS_EVENT *OSQCreate(void **start, BYTE8 size) ;
void *OSQPend(OS_EVENT *, WORD16, BYTE8 *) ;
BYTE8 OSQPost(OS_EVENT *, void *) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.


Time Services
Multi-C:
n/a

C/OS-II:
DWORD32 OSTimeGet(void) ;
void OSTimeSet(DWORD32) ;

Copyright © 2000, Daniel W. Lewis. All Rights Reserved.

You might also like