---
# System prepended metadata

title: Lista 2
tags: [sju21, ćwiczenia]

---

# Lista 2

10 marca 2021: zadania 1-5
17 marca 2021: zadania 6-7

###### tags: `sju21` `ćwiczenia`

## Deklaracje

Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie w trakcie dyskusji (co najwyżej jedno!) oznacz je znakiem ==X== na żółtym tle.

**UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!**

:::danger
|                       | 2-1 | 2-2 | 2-3 | 2-4 | 2-5 | 2-6 | 2-7 |
| ---------------------:| --- | --- | --- | --- | --- | --- | --- |
|           Jacek Bizub |==X==|     |  X  |  X  |  X  |  X  |  X  |
|          Maciej Dudek |     |     |     |     |     |     |     |
|     Wojciech Jasiński |  X  |  X  |  X  |  X  |     |     |     |
|        Artur Juraszek |  X  |==X==|  X  |     |     |     |     |
|     Michał Myczkowski |     |     |     |     |     |     |     |
|       Michał Odorczuk |     |     |     |     |     |     |     |
|       Damian Ratajski |     |     |     |     |     |     |     |
|         Łukasz Siudek |  X  |  X  |     |     |     |     |     |
|           Błażej Sowa |  X  |  X  |     |     |     |     |     |
|         Andrzej Turko |  X  |  X  |  X  |  X  |  X  |==X==|  X  |
|  Maksymilian Zawartko |  X  |  X  |  X  |  X  |  X  |  .  |  X  |
:::

> [name=Krystian Bacławski] Uważam, że... moje pytanie jest zasadne!

:::spoiler
Moje rozwiązanie alternatywne.
:::

## Zadanie 2-1

:::info
Autor: Błażej Sowa
:::
[pxCurrentTCB](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#337)  

`pxCurrentTCB` - Wskaźnik na TCB ("Task Control Block") dla zadania, które jest aktualnie w stanie "Running".
`pxReadyTaskLists` - Tablica kolejek zadań dla każdego priorytetu.

[xTaskIncrementCount](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#2707)
`xTickCount` - Aktualny czas zmierzony przez kernel. Jest inkrementowany w przerwaniu które wykonuje się ze stałą częstotliwością. 
> Czemu zadania, które zakończyły swoje działanie wywołując procedurę vTaskDelete, są umieszczane na liście xTasksWaitingTermination?

Ponieważ nie mogą zwolnić pamięci, którą sami używają. Musi to zrobić za nich inne zadanie.
[tasks.c:1198](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#1198)
> Kto i gdzie zajmuje się zwolnieniem pamięci takich zadań?

Zwolnieniem pamięci zajmie się zadanie Idle (Jałowe).
[tasks.c:3409](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#3409)

---

> [name=Jacek Bizub]

:::spoiler
![](https://www.unitedchurchofsoro.org/wp-content/uploads/blog-road-runner-self-defeating-statements-2048px-2000x1200.jpg)
:::

## Zadanie 2-2

:::info
Autor: Łukasz Siudek
:::

`pxTopOfStack` - wskaźnik na ostatni element stosu zadania. [tasks.c:254](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#254)

---

`uxPriority` - wartość z zakresu od `0` do `configMAX_PRIORITIES – 1` określająca priorytet zadania. [tasks.c:262](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#262)

---

`uxBasePriority` - priorytet nadawany zadaniu w momencie jego utworzenia. Jest wykorzystywany w przypadku, gdy zadanie próbuje przejąć muteks który jest trzymany przez zadanie o niższym priorytecie. Wtedy priorytet zadania trzymającego ten muteks zostaje zwiększony do wartości priorytetu zablokowanego zadania. Takie zachowanie minimalizuje czas oczekiwania zadań o wyższym priorytecie.
[tasks.c:280](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#280)

---

`ulRunTimeCounter` - licznik czasu spędzonego przez zadanie w stanie "Running" od momentu utworzenia. [tasks.c:293](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#293)

---

*Q*: Zadanie może być umieszczone jednocześnie na dwóch listach przy użyciu węzłów
`xStateListItem` i `xEventListItem`. Skąd wynika taka potrzeba? Uzasadnij ją na podstawie miejsc wywołań
`vListInsert`, `vListInsertEnd` i `uxListRemove` posługujących się wyżej wymienionymi węzłami.

*A*: `xStateListItem` wskazuje na jeden z węzłów list:
* `pxReadyTasksLists`, gdy zadanie znajduje się w stanie "Ready"
* `xSuspendedTaskList`, gdy zadanie znajduje się w stanie "Suspended"
* `pxDelayedTaskList` bądź `pxOverflowDelayedTaskList`, gdy zadanie znajduje się w stanie "Blocked"
* `xTasksWaitingTermination`, gdy zadanie zostało zakończone i powinny zostać zwolnione jego zasoby.

Zadanie może być wybudzone po wystąpieniu jakiegoś zdarzenia bądź wybudzone przez planistę po upływie określonej liczby ticków. Obecność węzła `xEventListItem` jest zatem wykorzystywana w przypadku nastąpienia eventu.

Przykładowo, zadanie może wejść w stan zblokowany oczekując na pojawienie się elementu w pustej kolejce. W takiej sytuacji wykonywana jest procedura [`vTaskPlaceOnEventList`](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8&fi=vTaskPlaceOnEventList#3064) i `xEventListItem` umieszczany jest w liście [`xTasksWaitingToReceive`](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#1378) należącej do kolejki, aby zostać odblokowanym w momencie pojawienia się danych.

## Zadanie 2-3

:::info
Autor: Artur Juraszek
:::

Oddanie sterowania - dobrowolne zrzeczenie się przez zadanie przydzielonego mu czasu pracy procesora

`pxTopOfStack` musi/powinien być pierwszym polem w TCB, ponieważ w interakcję z nim wchodzi kod zrzucający kontekst przełączanego właśnie zadania napisany w assemblerze - gdyby znajdował się na dalszym offsecie, to kod assemblerowy musiałby być w jakiś sposób parametryzowany szerokościami poszczególnych pól w TCB (które są konfigurowalne) oraz ewentualnych zwyczajów danego kompilatora na temat wyrównywania struktur.

Sam mechanizm przełączania wygląda tak (chyba najlepiej skomentować to już pokazując ekran):

```c=
#define portSAVE_CONTEXT()                                              \
        or.w    #0x0700,sr;             /* mask all interrupts */       \
        movem.l d0-a6,-(sp);            /* save D0-A6 registers */      \
        move.l  usp,a0;                 /* save USP register */         \
        move.l  a0,-(sp);                                               \
        move.l  pxCurrentTCB,a0;        /* load current task pointer */ \
        move.l  sp,(a0);                /* save stack pointer */
```

skaczemy do [vTaskSwitchContext](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#vTaskSwitchContext) - tutaj odbywa się proces [decydowania](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#133) o tym, który zadanie zostanie wykonane jako następne. Kiedy procedura się zakończy, pxCurrentTCB będzie wskazywało już na nowe zadanie

```c=
#define portRESTORE_CONTEXT()                                           \
        move.l  pxCurrentTCB,a0;        /* load current task pointer */ \
        move.l  (a0),sp;                /* restore stack pointer */     \
        move.l  (sp)+,a0;               /* restore USP register */      \
        move.l  a0,usp;                                                 \
        movem.l (sp)+,d0-a6;            /* restore D0-A6 registers */   \
        rte;                            /* restore SR and PC */
```


## Zadanie 2-4

:::info
Autor: Wojciech Jasiński
:::
  * Co się dzieje w trakcie rozruchu planisty?
    1. utwórz zadanie jałowe (alokacja statyczna lub dynamiczna) [[kod](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#1980)]
    2. (opcjonalnie) utwórz zadanie obsługujące zegary (przetwarza zdarzenia zegara i śpi) [[kod](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#2022)]
    3. ustaw obsługę `trap #0` na `yPortYieldHandler`
    4. zmień kontekst na pierwsze zadanie [[kod](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/portable/m68k-amiga/portasm.S?r=a3121d83#38)]
  * Pokaż w jaki sposób procesor zaczyna wykonywać instrukcje pierwszego wybranego zadania
    - ustawiamy kontekst (`pxCurrentTCB`) w [main](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/examples/graphics/main.c?r=84123706#78) : [xTaskCreate](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#810) : [prvAddNewTaskToReadyList](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#1088)
    - aktywujemy ten kontekst (przywracamy stan wliczając PC i wykonujemy RTE (ReTurn from Exception)) w [main](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/examples/graphics/main.c?r=84123706#81) : [vTaskStartScheduler](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8&fi=vTaskStartScheduler#2075) : [xPortStartScheduler](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/portable/m68k-amiga/port.c?r=a3121d83&fi=xPortStartScheduler#93) : [vPortStartFirstTask](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/portable/m68k-amiga/portasm.S?r=a3121d83#39)
  * Kto i jak tworzy rozruchowy kontekst zadania?
    - [main : xTaskCreate](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/examples/graphics/main.c?r=84123706#78)
    - [xTaskCreate : prvInitialiseNewTask](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#809)
    - a tutaj konkretnie inicjalizujemy stos: [prvInitialiseNewTask](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#1023) : [pxPortInitialiseStack](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/portable/m68k-amiga/port.c?r=a3121d83&fi=pxPortInitialiseStack#62)

## Zadanie 2-5

:::info
Autor: Maksymilian Zawartko
:::

Blokowanie przerwań to chwilowe wyłączenie ich obsługi, celem realizacji zadania, w którym mogłyby przeszkodzić.

Przerwania należy blokować, kiedy w sekcji krytycznej aktualizowane lub odczytywane są listy zadań (a więc w szczególności zadania) i, ogólniej, dowolne globalne dane.
[queue.c:241](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#241)
[queue.c:261](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#261)
[queue.c:542](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#542)
[queue.c:761](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#761)
[queue.c:1303](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#1303)
[queue.c:1448](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#1448)
[queue.c:1556](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#1556)
[queue.c:1607](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/queue.c?r=9f4d3da8#1607)

Sekcja krytyczna to fragment kodu, w którym realizowany jest dostęp do dzielonego zasobu. W sekcji krytycznej może wykonywać się tylko jeden kontekst naraz.

Liczba wywołań `taskENTER_CRITICAL` jest utrzymywana dla każdego wątku osobno, bo będąc w sekcji krytycznej wątek może stworzyć inny i przełączyć się na niego. Wychodząc z tego nowego wątku chcemy wiedzieć, czy zamknął za sobą wszystkie sekcje krytyczne.

## Zadanie 2-6

:::info
Autor: Andrzej Turko 
:::

Te procedury blokują wywłaszczanie, ale nie przerwania. Ponadto, przetwarzanie ticków jest zablokowane, ponieważ jest ono obsługiwane przez scheduler, który jest zawieszany.
Dlatego tymi procedurami tworzy się sekcje krytyczne do:
* odczytywania liczby ticków
[przykład](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#2609)

* Przetwarzania list stanów zadań (np. delayed albo ready), ale nie event list, która może być modyfikowana przez przerwania (nawet gdy scheduler jest zawieszony, zadania są usuwane z event list)
[przykład](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#2629)


[xTaskResumeAll](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/tasks.c?r=9f4d3da8#xTaskResumeAll) oprócz zmiany wartości licznika musi:

* Dodać do kolejki ready wszystkie zadania, które są w stanie pending ready: Zadania odblokowane podczas gdy scheduler był zawieszony, nie mogły zostać dodane bezpośrednio do kolejki ready 
* Przetworzyć wszystkie ticki: Zawieszenie schedulera powoduje też zatrzymanie przetwarzania ticków. Nie można ich opuścić, aby wszystkie zadania, które były opóźnione, zostały uruchomione w odpowiednim czasie. 
* Oddać sterowanie innemu zadaniu: Powyższe akcje mogły sprawić, że na kolejce ready pojawiło się zadanie o wyższym priorytecie niż obecnie wykonywane. W takim wypadku konieczny jest rescheduling.

## Zadanie 2-7

:::info
Autor: Jacek Bizub
:::

> Procedury FreeRTOS, które można wołać tylko z procedur obsługi przerwań (sufiks `FromISR`), używają `portSET_INTERRUPT_MASK_FROM_ISR` i `portCLEAR_INTERRUPT_MASK_FROM_ISR`. Przy ich pomocy realizuje się sekcje krytyczne na architekturach dopuszczających zagnieżdżanie przerwań. Na podstawie [4, 6.8] wyjaśnij dlaczego jest to koniecznie i o jakie sekcje krytyczne chodzi.

Przerwanie może zostać przerwane przez inne przerwanie (o wyższym priorytecie). Może się zdarzyć tak, że przerwania te operują na wspólnych strukturach danych. Maskując `wszystkie` przerwania synchronizujemy dostęp do takiej pamięci.

> Przeprowadź uczestników zajęć przez procedurę ulPortSetIPL i wyjaśnij co ona robi.


```c
19 ENTRY(ulPortSetIPL)
20         move.l  4(sp),d0
21         move.w  sr,-(sp)
22         move.w  sr,d1
23         and.w   #0xf8ff,d1              /* old SR with IPL bits cleared */
24         and.w   #0x0700,d0              /* argument with IPL bits left */
25         or.w    d0,d1
26         move.w  d1,sr                   /* set new value of IPL in SR */
27         move.w  (sp)+,d0
28         and.w   #0x0700,d0              /* return IPL bits of original SR */
29         rts
30 END(ulPortSetIPL)
```
[ulPortSetIPL](https://mimiker.ii.uni.wroc.pl/source/xref/FreeRTOS-Amiga/FreeRTOS/portable/m68k-amiga/portasm.S?r=a3121d83#ulPortSetIPL)