-
1. Data: 2009-09-29 15:42:52
Temat: printf i wielozadaniowosc (MicroC/OS-II)
Od: "Pszemol" <P...@P...com>
W systemie MicroC/OS-II wszystkie wątki uszeregowane są według swoich
priorytetów i wątek o niższym priorytecie dostaje procesor TYLKO WTEDY
gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na zdarzenie.
W swoim programie wielowątkowym dorobiłem na szybkiego logowanie
zdarzeń w celach debugging i używam "zakazanej" funkcji printf, jako że jest
ona bardzo wygodna zwłaszcza z parsingiem argumentów typu %d lub %x
w tekście... :-)
Spodziewałem się jakichś efektów związanych z niereentrantnością tej
funkcji, ale to co dostałem trochę mnie zaskoczyło...
Otóż co widzę, to że na wyjściu generowanym przez tą funkcję fprintf
(strumień znaków RS232, "plikiem" dla fprintf jest port szeregowy)
widzę że wątek o niższym priorytecie wchodzi z butami w linię tekstu
wątka o wyższym priorytecie i wcięcie jest tam, gdzie fprintf robi ten
parsing argumentów %d.
Podam przykłady.
Oto niezaburzona linia z tasku o najwyższym priorytecie (Barrier 0):
"Barrier 0: s:14 M: a8c09, M: b98f, M: 6e71b, M: d14a5, M: 3422e, M: 96ff6,
M: f9d77"
A oto podobna linia z wcięciami się od tasków o niższych priorytetach
(Barrier 4):
"Barrier 0: s:14 M: c5aa5Barrier 4: handling legacy sensor readings
(time:1607)
Barr 4: Decrement counter (26) for legacy sensor (time:1607)
Barrier task 4, 'unknown' - wait one dev delay increment... (time:1608)
, M: 28521, M: 8b227, M: eddfc, M: 50b03, M: b365c, M: 223b1, M: 66cf0"
Task o priorytecie 3 schodki niżej, wciął się w środek fprintf'a od tasku
o prawie najwyższym priorytecie i to w miejscu, gdzie skończyło się
parsowanie argumentu %x i zaczął text printf'a.
Tu inny przykład, ta sama sytuacja (barrier 7 to task o priorytecie 8):
"Barrier 0: s:09 R: 152ba, R: 78080Barrier 7: handling legacy sensor
readings (time:1613)
Barr 7: Decrement counter (42) for legacy sensor (time:1613)
Barrier task 7, 'unknown' - wait one dev delay increment... (time:1613)
, R: dae06, R: 3db91, R: a091a, R: 36a4, R: 66445, R: c91aa"
Jak wytłumaczyć takie efekty?
Rozumiem, że skoro wywołania fprintf'a z tasków dotyczą tego samego
portu szeregowego, przekazanego fprintf'owi jako argument nazwy pliku
(globalna zmienna) to może się coś kiepścić, i linie się będa przeplatać,
ale nie rozumiem jak taski o niższym priorytecie mogły się wstrzelić
z TRZEMA OSOBNYMI WYWOŁANIAMI fprintf'a w jedną linię tasku
o wyższym priorytecie? Przecież według filozofii MicroC/OS-II task
bariery 0, w czasie chodzenia sobie po kodzie fprintfa nie powinien być
przerwany i taski o priorytetach 4 czy tym bardziej 8 powinny grzecznie
czekać aż fprintf wywołany przez task o priorytecie 1 ukończy zadanie
i odda sterowanie systemowi operacyjnemu (nie ma tu wywłaszczania).
Czy ktoś mógłby mi to wytłumaczyć?
-
2. Data: 2009-09-29 16:18:21
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: Zbych <z...@o...pl>
Pszemol pisze:
> gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na zdarzenie.
[...]
> Otóż co widzę, to że na wyjściu generowanym przez tą funkcję fprintf
> (strumień znaków RS232, "plikiem" dla fprintf jest port szeregowy)
> widzę że wątek o niższym priorytecie wchodzi z butami w linię tekstu
> wątka o wyższym priorytecie
[...]
> Czy ktoś mógłby mi to wytłumaczyć?
Żeby to dobrze wytłumaczyć to trzeba zobaczyć jak to jest
zaimplementowane. Szklana kula mówi tylko, że wątek o wyższym
priorytecie oddaje czas innym wątkom, bo czeka na zwolnienie miejsca w
buforze nadawczym RSa. Przy czym nie masz żadnej gwarancji, że po
zwolnieniu miejsca pierwszy do RSa dobierze się wątek o najwyższym
priorytecie. Żeby wiedzieć co się dzieje to trzeba by na osobnym kanale
wyrzucać kiedy i jakie wątki są uruchamiane.
-
3. Data: 2009-09-29 16:47:34
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: "Pszemol" <P...@P...com>
"Zbych" <z...@o...pl> wrote in message news:h9tc37$135h$1@news.mm.pl...
> Pszemol pisze:
>
>> gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na
>> zdarzenie.
> [...]
>> Otóż co widzę, to że na wyjściu generowanym przez tą funkcję fprintf
>> (strumień znaków RS232, "plikiem" dla fprintf jest port szeregowy)
>> widzę że wątek o niższym priorytecie wchodzi z butami w linię tekstu
>> wątka o wyższym priorytecie
> [...]
>> Czy ktoś mógłby mi to wytłumaczyć?
>
> Żeby to dobrze wytłumaczyć to trzeba zobaczyć jak to jest
> zaimplementowane. Szklana kula mówi tylko, że wątek o wyższym priorytecie
> oddaje czas innym wątkom, bo czeka na zwolnienie miejsca w buforze
> nadawczym RSa. Przy czym nie masz żadnej gwarancji, że po zwolnieniu
> miejsca pierwszy do RSa dobierze się wątek o najwyższym priorytecie. Żeby
> wiedzieć co się dzieje to trzeba by na osobnym kanale wyrzucać kiedy i
> jakie wątki są uruchamiane.
To jest oczywista oczywistość, że wątek o priorytecie 1 czeka na port
RS i oddaje sterowanie :-) Mnie interesuje jak to się dzieje, że w czasie
gdy task 1 oddał sterowanie task 4 lub 7 był wstanie trzy razy wysłać
linię znaków do RS'a trzema osobnymi wywołaniami fprintfa...
Tu masz przykład:
"Barrier 0: s:14 M: c5aa5Barrier 4: handling legacy sensor readings
(time:1607)
Barr 4: Decrement counter (26) for legacy sensor (time:1607)
Barrier task 4, 'unknown' - wait one dev delay increment... (time:1608)
, M: 28521, M: 8b227, M: eddfc, M: 50b03, M: b365c, M: 223b1, M: 66cf0"
To wyżej to był efekt 4 osobnych wywołan funkcji fprintf:
task1 (barrier 0) zrobił najpierw to:
fprn(probe_out, "Barrier %d: s:%02ld M:%6lx, M:%6lx, M:%6lx, M:%6lx,
M:%6lx, M:%6lx, M:%6lx\r\n",
i w trakcie gdy utknął w tej linii czekając na RSa task 5 (barrier 4) zrobił
to:
fprn(barr_out, "Barrier %d: handling legacy sensor readings
(time:%ld)\r\n",
potem to w zupełnie innym miejscu kodu:
fprn(barr_out, "Barr %d: Decrement counter (%ld) for probe #%d
(time:%ld)\r\n",
i za moment to:
fprn(barr_out, "Barrier task %d, '%s' - wait one dev delay
increment... (time:%ld)\r\n",
w czasie gdy task 1 wisiał sobie i czekał na zwolnienie RSa...
Tak czy inaczej muszę przerobić to aby zostało to w kodzie na dłużej.
Chyba zrobię nowy task o najniższym priorytecie który zajmie się
odbiorem tekstów od tasków roboczych o wyższych priorytetach
i wstawianiem tych tekstów do portu szeregowego...
-
4. Data: 2009-09-29 16:59:54
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: A.L. <a...@a...com>
On Tue, 29 Sep 2009 10:42:52 -0500, "Pszemol" <P...@P...com>
wrote:
>
>Jak wytłumaczyć takie efekty?
>
[...]
>
>Czy ktoś mógłby mi to wytłumaczyć?
JA sie bardzd dawno tym zajmowlem i pod zupelnie inym systeme, a
bardzo dzawno znaczy BARDZO dawno. Ale mialem podobny problem
1. Task o wysokim priorytecie pisze do UART. UART ma wlasny bufor.
Bufor sie przepelnil i taksk dostal notyfikacje. System zawiesil task.
2. Wiec task o niskim priorytecie dostal CPU; w miedzyczasie UART
zaczal oproznaic budor, wiec taks o niskim priorytecie mogl pisac. Po
niedlugim czasie system zauwazyl ze task o wysokim priorytecie czeka
na UART, wiec zasiesil task o niskim priorytecie i ten zaczal pisac do
UART
W efekcie wyszla "sieczka" zlozona z fragmentow informacji z roznych
taskow.
Kluczowe pytanie jes co to znaczy ze printf "zakonczyl" dzialanie.
Powinien raportowac "zakonczenie" dzialania tylko wdedy gdy informacja
zostala rzeczywiscie fizycznie wyslana do klienta.
Nie wiem jak to jest w twoim systemie, ale podejrzewam ze cos takiego
lub podobnego.
Remedium byloby zamkniecie printf w osobnym tasku z wlasnum,
nieograniczonym buforem i potraktowanei calosci jako sekcji krytycznej
A.L.
-
5. Data: 2009-09-29 18:08:08
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: grg12 <g...@c...at>
Pszemol pisze:
> W systemie MicroC/OS-II wszystkie wątki uszeregowane są według swoich
> priorytetów i wątek o niższym priorytecie dostaje procesor TYLKO WTEDY
> gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na zdarzenie.
>
A aktywny wątek o niskim priorytecie może zostać przymusowo "uśpiony" na
rzecz wątku wysokopriorytetowego czy przełączenie następuje tylko jeśli
aktywny watek dobrowolnie odda sterowanie (tak było w np. win3.1)?
Przypuśćmy że wątek HiPrio pisze sobie coś do bufora łącza szeregowego,
bufor zostaje zapełniony więc wątek zostaje uśpiony do czasu opróżnienia
bufora, wątek LowPrio przejmuje pałeczkę, po pewnym czasie próbuje
zapisać do bufora łącza, który został już opróżniony przez obsługę portu
szeregowego (jakieś przerywanie zapewne) - wypisuje swoje i grzecznie
idzie spać. W tym momencie obudzony zostaje wątek HiPrio...
Pozdrawiam
GRG
-
6. Data: 2009-09-29 18:35:49
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: "Pszemol" <P...@P...com>
"grg12" <g...@c...at> wrote in message
news:25a0$4ac24d00$506cdd75$32156@news.chello.at...
> Pszemol pisze:
>> W systemie MicroC/OS-II wszystkie wątki uszeregowane są według swoich
>> priorytetów i wątek o niższym priorytecie dostaje procesor TYLKO WTEDY
>> gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na
>> zdarzenie.
>
> A aktywny wątek o niskim priorytecie może zostać przymusowo "uśpiony"
> na rzecz wątku wysokopriorytetowego czy przełączenie następuje tylko jeśli
> aktywny watek dobrowolnie odda sterowanie (tak było w np. win3.1)?
Wysoki priorytet zwykle śpi bo czeka np. na przerwanie od zegara
lub od urządzenia zewnętrznego, np. RS232. Czyli masz przerwanie
które przychodzi od RS232 a jesteś w tasku o priorytecie 3 to system
obsługuje przerwanie i po obsłudze znowu sprawdza gdzie wrócić.
Ponieważ mam dwa taski gotowe, task o priorytecie 1 czekał na RS232
a już nie czeka, to task 1 powinien dostać sterowanie...
Podsumowując, nie dziwiłbym się że w linii loga od tasku 3 mam
przerwy i z buciorami wchodzi task 0 czy 1 ze swoim tekstem...
Ja się dziwię że linia od tasku 0 została przerwana w połowie
i wszedł w jej środek task 3 Z TRZEMA WYWOŁANIAMI fprintf'a.
> Przypuśćmy że wątek HiPrio pisze sobie coś do bufora łącza szeregowego,
> bufor zostaje zapełniony więc wątek zostaje uśpiony do czasu opróżnienia
> bufora, wątek LowPrio przejmuje pałeczkę, po pewnym czasie próbuje zapisać
> do bufora łącza, który został już opróżniony przez obsługę portu
> szeregowego (jakieś przerywanie zapewne) - wypisuje swoje i grzecznie
> idzie spać. W tym momencie obudzony zostaje wątek HiPrio...
Ja nie widzę tutaj możliwości aby z dwu tasków czekających na
przerwanie od portu szeregowego dorwał się do RS232 ten
o niższym priorytecie i to w połowie parsingu od fprintfa HiPrio.
-
7. Data: 2009-09-29 20:46:22
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: Adam Dybkowski <a...@4...pl>
Pszemol pisze:
> Rozumiem, że skoro wywołania fprintf'a z tasków dotyczą tego samego
> portu szeregowego, przekazanego fprintf'owi jako argument nazwy pliku
> (globalna zmienna) to może się coś kiepścić, i linie się będa przeplatać,
> ale nie rozumiem jak taski o niższym priorytecie mogły się wstrzelić
> z TRZEMA OSOBNYMI WYWOŁANIAMI fprintf'a w jedną linię tasku
> o wyższym priorytecie?
Może chodzi o to, że [f]printf wywołany z zadania o wysokim priorytecie
jest dzielony na wiele odrębnych zapisów do portu szeregowego (w
najprostszej implementacji będą to zapisy po jednym znaku) a system
operacyjny w oczekiwaniu na gotowość portu do przyjmowania kolejnych
znaków (zgłaszaną zapewne w przerwaniu portu szeregowego) oddaje po
prostu sterowanie zadaniom o niższym priorytecie gotowym do wykonania. W
gruncie rzeczy to chyba lepsze podejście (a nuż zadanie o niskim
priorytecie cośtam sobie liczy powoli w tle) niż aktywne oczekiwanie na
zwolnienie się miejsca w buforze nadajnika portu szeregowego. Czasem
przy wolnej transmisji i długim buforze sprzętowym (zależy od procesora
lub zewnętrznego układu UART) takie oczekiwanie byłoby długie - a tak w
tym czasie procesor może się zająć obsługą zadań o niższym priorytecie.
Aby uniknąć takiego mieszania się printf'ów, wystarczy objąć je
semaforem / mutexem czy co tam masz podobnego w tym systemie.
--
Adam Dybkowski
http://dybkowski.net/
Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.
-
8. Data: 2009-09-29 21:04:24
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: Jerry1111 <j...@w...pl.pl.wp>
Pszemol wrote:
> W systemie MicroC/OS-II wszystkie wątki uszeregowane są według swoich
> priorytetów i wątek o niższym priorytecie dostaje procesor TYLKO WTEDY
> gdy wątek o wyższym priorytecie nie ma nic do roboty i czeka na zdarzenie.
>
> W swoim programie wielowątkowym dorobiłem na szybkiego logowanie
> zdarzeń w celach debugging i używam "zakazanej" funkcji printf, jako że
> jest
> ona bardzo wygodna zwłaszcza z parsingiem argumentów typu %d lub %x
> w tekście... :-)
Wcale nie jest zakazana.
> Spodziewałem się jakichś efektów związanych z niereentrantnością tej
> funkcji, ale to co dostałem trochę mnie zaskoczyło...
Bo tu nie chodzi o printf, tylko o reentrancje calej biblioteki newlib.
Z drugiej strony Altera ma to zalatwione, wiec nie rozumiem czemu problem?
> Otóż co widzę, to że na wyjściu generowanym przez tą funkcję fprintf
> (strumień znaków RS232, "plikiem" dla fprintf jest port szeregowy)
> widzę że wątek o niższym priorytecie wchodzi z butami w linię tekstu
> wątka o wyższym priorytecie i wcięcie jest tam, gdzie fprintf robi ten
> parsing argumentów %d.
Bo nie masz tego jako atomic operation. Jestem na 99% pewny ze jako
atomic jest tylko zrobione wysylanie pojedynczych znakow.
Ma to sens, bo inaczej blokowalbys system na dosc dlugi czas (chyba ze
masz duze fifo - wtedy mozna sie o to pokusic).
> Task o priorytecie 3 schodki niżej, wciął się w środek fprintf'a od tasku
> o prawie najwyższym priorytecie i to w miejscu, gdzie skończyło się
> parsowanie argumentu %x i zaczął text printf'a.
Bo w miedzyczasie byla zmiana kontekstu. Czemu? Bo wyzszy watek czekal
na wyslanie znaku...
> Rozumiem, że skoro wywołania fprintf'a z tasków dotyczą tego samego
> portu szeregowego, przekazanego fprintf'owi jako argument nazwy pliku
> (globalna zmienna) to może się coś kiepścić, i linie się będa przeplatać,
> ale nie rozumiem jak taski o niższym priorytecie mogły się wstrzelić
> z TRZEMA OSOBNYMI WYWOŁANIAMI fprintf'a w jedną linię tasku
> o wyższym priorytecie? Przecież według filozofii MicroC/OS-II task
> bariery 0, w czasie chodzenia sobie po kodzie fprintfa nie powinien być
> przerwany i taski o priorytetach 4 czy tym bardziej 8 powinny grzecznie
> czekać aż fprintf wywołany przez task o priorytecie 1 ukończy zadanie
> i odda sterowanie systemowi operacyjnemu (nie ma tu wywłaszczania).
>
> Czy ktoś mógłby mi to wytłumaczyć?
A jak w priority 0 wstawic OSTimeDly(10), to tez nic innego sie nie
uruchomi? AFAIR driver usart Altery czeka na signal jak ma pelny bufor,
wiec w miedzyczasie inny watek idzie.
--
Jerry1111
-
9. Data: 2009-09-29 22:06:11
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: "Pszemol" <P...@P...com>
"Jerry1111" <j...@w...pl.pl.wp> wrote in message
news:h9tsp1$pfi$1@news.onet.pl...
> Wcale nie jest zakazana.
Dlatego ująłem to w cudzysłów :-)
> Bo tu nie chodzi o printf, tylko o reentrancje calej biblioteki newlib. Z
> drugiej strony Altera ma to zalatwione, wiec nie rozumiem czemu problem?
No tak to ma załatwione że wcina się task 4 lub 7 w środek linii tasku 1.
> Bo nie masz tego jako atomic operation. Jestem na 99% pewny ze jako atomic
> jest tylko zrobione wysylanie pojedynczych znakow.
>
> Ma to sens, bo inaczej blokowalbys system na dosc dlugi czas (chyba ze
> masz duze fifo - wtedy mozna sie o to pokusic).
Dla dodania tła do zagadnienia:
Fifo softwareowe jest 64 znaki. Uart pracuje z baud 115200
bez handshake i procesor NiosII-e biega z zegarem 80MHz...
Przerwy w linii od tasku 1 są ZAWSZE przy granicy argumentu do
printfa (albo przed %d albo po). Nigdy nie przerywa w trakcie tak
aby urwało w środku wyrazu czy też w środku zmiennej integer :-)
Dlatego nie bardzo mi się chce wierzyć, że kwestia jest w wysyłaniu
znak po znaku - raczej chodzi o parser printfa.
>> Task o priorytecie 3 schodki niżej, wciął się w środek fprintf'a od tasku
>> o prawie najwyższym priorytecie i to w miejscu, gdzie skończyło się
>> parsowanie argumentu %x i zaczął text printf'a.
>
> Bo w miedzyczasie byla zmiana kontekstu. Czemu?
> Bo wyzszy watek czekal na wyslanie znaku...
[...]
> A jak w priority 0 wstawic OSTimeDly(10), to tez nic innego sie nie
> uruchomi? AFAIR driver usart Altery czeka na signal jak ma pelny bufor,
> wiec w miedzyczasie inny watek idzie.
Oczywiście niższe taski mogą działać tylko wtedy gdy wyższy czeka.
To wiem. Natomiast interesujące jest że przerwa i wcięcie się niskiego
tasku w linię wysokiego jest nie w przypadkowym miejjscu tylko
na granicy argumentu do printfa.
-
10. Data: 2009-09-30 13:25:22
Temat: Re: printf i wielozadaniowosc (MicroC/OS-II)
Od: Zbych <a...@o...pl>
Pszemol pisze:
> To jest oczywista oczywistość, że wątek o priorytecie 1 czeka na port
> RS i oddaje sterowanie :-) Mnie interesuje jak to się dzieje, że w czasie
> gdy task 1 oddał sterowanie task 4 lub 7 był wstanie trzy razy wysłać
> linię znaków do RS'a trzema osobnymi wywołaniami fprintfa...
Ktoś na pme podpowiedział ci, żebyś sprawdził, czy prawidłowo ustawiłeś
priorytety wątków. Od siebie dorzucę tylko pytanie: czy ten system
gwarantuje ci, że jak bufor RSa będzie wolny to w pierwszej kolejności
dobierze się do niego wątek o najwyższym priorytecie? A może kto
pierwszy ten lepszy?