Added some from video 12 and Start video 13

dev
Øyvind Skaaden 2021-05-15 16:35:26 +02:00
parent e5eae18389
commit 757b0a5799
1 changed files with 139 additions and 8 deletions

View File

@ -26,7 +26,7 @@ Hard to capture faults.
### Traditional error handeling
{% highlight c %}
{% highlight java %}
FILE *
openConfigFile(){
FILE * f = fopen("/path/to/config.conf");
@ -248,7 +248,7 @@ Controlling a pump filling a tank.
#### A trivial solution: "Cyclic Exectutive"
{% highlight c %}
{% highlight java %}
oldTime = now();
i = 0;
while(true) {
@ -282,7 +282,7 @@ while(true) {
* Scheduler often inculuded in OSes
* Introducing priorities
{% highlight c %}
{% highlight java %}
/**
* scheduler_registerThread(function, time, priority)
* Higher priority numer means higher priority in scheduler
@ -331,11 +331,11 @@ main() {
* Make a handler for a timer interrupt
* Store all registers (including IP & SP) in a "thread object"
* Organize queue of processes (Round Robin e.g. - a collection of thread objects?)
* Can synchronize by: while(!ready); (busy wating, "spin locks")
* Can synchronize by: `while(!ready);` (busy wating, "spin locks")
**Bad solution**
{% highlight c%}
{% highlight java%}
while(lock==1) {}
lock = 1;
// We may run
@ -344,7 +344,7 @@ lock = 0;
**Better solution**
{% highlight c%}
{% highlight java%}
void t1() {
flag1 = 1; // Declare my intention
turn = 2; // But try to be polite
@ -371,6 +371,137 @@ void t1() {
**Let us introduce another queue; the collection of threads not running, waiting for something**
* Fixes the bad performance of spin locks. Is conceptually better.
* "Suspend" moves a thread object from "run" queue to "blocked" queue
* "Resume" moves it back.
* `suspend` moves a thread object from "run" queue to "blocked" queue
* `resume` moves it back.
##### Two bad solutions
{% highlight java%}
t1(){
while(busy == 1) suspend();
busy = 1; // It is free; tak it - No
// Run
busy = 0; // Release resource
resume t2 // No
}
{% endhighlight %}
or
{% highlight java%}
t1(){
while(TestNSet(busy, 1) == 1) suspend();
// We own resource
// Run
busy = 0;
resume t2 // No
}
{% endhighlight %}
##### The suspend/resume problem
{% highlight java%}
// Global variables
bool g_initDone = False;
// Threads
t1(){ t2(){
/* Do init */ if (g_initDone == False) {
g_initDone = True; Suspend();
resume(t2) }
// Continue executing // Continue exectuting
} }
{% endhighlight %}
#### Priorities
* Threads mey have different *priorities*. (A sortet run-queue, or more of them.)
* Only if there are no running threads on a higher priority, a thread will run.
* We are not aiming for some sens of fairness (!). But predictability.
* And priorities supports schedulability proofs.
* But we open ourselves up to *starvation*. A thread may not ever get to run, even if it is runnable.
#### Application-level syncronization
**SO, the application programmer needs some syncronozation primitives...**
* `sleep()`? - Ok
* Publish `suspend` and `resume` - No
* Events (`wait` and `signal`) - Just named versions of suspend & resume semantics.
* Fixes the need to know aboud "thread objects". But no
* ...or "Condition variables" - same
### Semaphores
**A counting semaphore**
* `signal(SEM)` increases the counter (possibly resuming a thread waiting for the semaphore)
* `wait(SEM)` decrements the counter - will block (be suspended) `if SEM == 0`
* The semaphores value can not be negative
* Of course; These calls are protected from interleaving by disabling the timer interrupt
**We solve beautifully:**
* Mutual Exclusion
* Conditional Synchronization (ref `suspend`/`resume`)
* Basic resource allocation
**Semaphore variations**
* `wait` and `signal` nay take parameter value to add or subtract
* `getValue(SEM)` returning the value of the semaphore. (Fishy)
* BInary semaphores (`signal` will fail `if SEM == 1`)
* Who is woken at `signal` (FIFO, Arbitrary, Highest priority)
* The mutex
* binary
* ownership
* allows mulitple waits by owner
* regions (may be released by Javas `wait` or POSIX condition variables)
* RTFM
**Semaphore challenges**
* Breaks modules (both ways)
* Does not scale!
* Deadlocks
* Global analysis --> Does not scale
* Can not release "temporarily
* "Limited expressive power". Some reasonalbe problems are hard to solve
* Ref ["The Little Book of Semaphores"](https://greenteapress.com/semaphores/LittleBookOfSemaphores.pdf)
### Why shared-variable synchronization
**Why not?**
* "Shared variables" is bad code quality
* Ref global variables, and data members in module interfaces
* An obvious bottleneck? Scales terribly
* "Variables" are passive objects
* They can not protect themselves
* Why use synchronization when it is communication we need?
* Technology transfers badly to distibuted systems
* ... and this is before we start discussing how hard it is
**Why?**
* Part of the "real-time" design pattern
* "One thread per timing demand"
* We do have scheduling proofs and best practises
* Timing analysis is global anyway
* Scalability and deadlock analysis may not be the limiting constraint
* HW is shared memory architecture
* Infrastucture is avalible
* Communication systems requires infrastucture that we may not have
#### *All* resources are shared!
* Memory, certainly
* "Hidden" memory used by libraries (.. your own modules and the kernel)
* If the library takes care of this itself, it is called *"reentrant"*
* Sensors and actuators
* "CPU" - Computing capacity
* *This* is real-time programming; We solve it by *Scheduling*
* ... any other interface