diff --git a/ntnu/21v/ttk4145/summary/summary.md b/ntnu/21v/ttk4145/summary/summary.md index e67e7e0..d543e77 100644 --- a/ntnu/21v/ttk4145/summary/summary.md +++ b/ntnu/21v/ttk4145/summary/summary.md @@ -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 \ No newline at end of file