|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 1:19 am
Глобални променливи и прекъсвания
| Автор |
Съобщение |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Обясни как.
Get() връща m_Shadow.
Set() пише в m_Original.
Ако след излизане от while, стойноста бъде променена това няма да омаже променливата. Просто ще вземеш старата стойност все едно извикването на Get() е изпреварило извикването на Set(). Това винаги го имаш като вариант. Независимо какво използваш - опашки, ОС, ...
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Чет Дек 10, 2009 5:20 pm |
|
 |
|
nik
Ранг: Форумен бог
Регистриран на: Сря Мар 22, 2006 3:25 am Мнения: 6418
|
точно това е метода и си работи даже, преди година две писах подобна програма заради една недомислица на микрочип, да сложи 16 битов брояч в 8 битов контролер без буфер за паралелно четене(18ф4431 мисля беше говедото, на брояча на енкодера), наложи се да прилагам подобен трик като в примера на Реконструкора, по различно го бях реализирал но идеята беше същата
наистина има забавяне, но поне гарантира че няма да омаже положението
иначе това което питаш ако се застъпят get() и refresh() е вярно , за целта в get() трябва още една проверка дали не е рефрешнато току що, при мен не се наложи защото и двете бяха с основната програма, само set() беше в прекъсването
|
| Чет Дек 10, 2009 5:25 pm |
|
 |
|
perlsite
Ранг: Ориентиран
Регистриран на: Пон Апр 17, 2006 1:44 pm Мнения: 291
|
void Set(T NewVal)
{
m_Original = NewVal; // 1)
}
T Get()
{
do
{
m_Shadow = m_Original;
}
while(m_Shadow != m_Original);
// 2)
return m_Shadow;
}
Ако в момент 2) се извика от прекъсване Set и в позиция 1) се промени стойността на нещо друго, то Get() ще върне старата стойност, което може да е силно нежелателно в накои случаи. Може би аз пропускам нещо, но ми се струва възможно, след като е извикан Set(), след това Get() да върне грешна стойност при определени времеви "обстоятелства".
|
| Чет Дек 10, 2009 5:44 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Пич, в това няма нищо лошо... да получиш старата стойност. Лошото е ако получиш старшия байт от старата и младшия от новата например. За това са тези гимнастики тука. Когато нямаме атомик read/write...
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Чет Дек 10, 2009 6:03 pm |
|
 |
|
i_dachev
Ранг: Новодошъл
Регистриран на: Вто Ное 16, 2004 3:29 pm Мнения: 108 Местоположение: София
|
Аз казах че е безсмислен или се ползва от друг код именно защото тоя
цикъл никога не се върти или тоя рефреш метод се вика от другаде.
И  бога ми пиша от 15 години (Java, C, C++) и пак ви казвам тоя код за мен е безсмислен
в смисъла на фиксване на синхронизации. Без да имаш поддръжка както цецо каза RTOS
навиждам тоя код как може да ми помогне изследвайте го внимателно и пак да обсъждаме.
|
| Пет Дек 11, 2009 1:03 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
volatile int g_p;
volatile int l_p;
void main() {
while(1){
...
do{
l_p = g_p;
}while(l_p != g_p);
...
}
}
isr...
void isr() {
...
g_p = 0xFF40;
...
}
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Пет Дек 11, 2009 6:53 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
ISR> 1234
ISR> 4567 l_p = 1267
ISR> 1234
ISR> 4567 l_p != 1267
По друг начин казано, ако при присвояването се прочете грешна стойност и при проверката се повтори същата грешка, излиза че грешката е "вярна" 
|
| Пет Дек 11, 2009 8:09 pm |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
Не че може да се каже по по-ясен начин от Мировия, но може би едно обобщение
няма да е излишно: *няма* софтуерен заместител на хардуерно непрекъсваемите
операции (atomic accesses). Затова и все още правят маски за прекъсвания, както и различни
според архитектурата и нуждите механизми от по-ниско ниво.
Това с търсенето на софтуерен вариант на последните е като търсенето на перпетуум
мобиле (никога не става, но винаги има търсещи..  ).
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Пет Дек 11, 2009 11:05 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
 |  |  |  | tgi написа: Не че може да се каже по по-ясен начин от Мировия, но може би едно обобщение няма да е излишно: *няма* софтуерен заместител на хардуерно непрекъсваемите операции (atomic accesses). Затова и все още правят маски за прекъсвания, както и различни според архитектурата и нуждите механизми от по-ниско ниво. Това с търсенето на софтуерен вариант на последните е като търсенето на перпетуум мобиле (никога не става, но винаги има търсещи..  ). |  |  |  |  |
Зависи какво ти трябва. Ако ти е нужно обикновена синхронизирана променлива, простото забраняване на прекъсванията докато се чете, или код подобен на моя, са напълно достатъчни.
|
| Съб Дек 12, 2009 4:15 am |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
Рек, простото забраняване на прекъсване върши работа - и е хардуерен метод, без
какъвто тия работи не стават.
Код като твоя работи в някои случаи, но както например Миро демонстрира, може
да зависи от данните.
Понякога знаеш, че данните не могат да те объркат - например така се четат timebase
регистрите в power, старшия, младшия, пак старшия - ако старшият е мръднал, повтаря се.
Е там се знае, че старшият мърда ако ще мърда само напред и то веднъж на много
секунди (32-бита са), та няма проблем.
Но за произволни данни без хардуерна помощ не става.
За произволни данни примерно в power има чифт иструкции - lwarx/stwcx. .
Първата чете 32 бита и прави хардуерна резервация, която писане в тоя адрес
обърсва. С втората човек пише на тоя адрес ако резервацията все още е необърсана
и set-ва Z флага в контролния регистър според успеха; ако не стане, опитваме пак и така.
При еднопроцесорни системи маскирането на прекъсване стига, при повече от
един възможни пипачи на тоя адрес трябва нещо като тоя механизъм в power
(повечето ги правеха с непрекъсваем read-modify-write цикъл, но така се губи малко
латентност пък е и по-трудно за реализация като хардуер).
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Съб Дек 12, 2009 5:14 am |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
Забрана на прекъсванията е най-чисто и просто решение и ще се избегнат подобни "тънки" бъгчета.
Но това работи само при малки процесори, защото при ядра от сорта на куртекс дето има повече от една шина към паметта дори и забрана на прекъсванията не е абсолютно решение. Там трябва да се използват и "бариери", щото ти забраняваш нови прекъсвания, но може да има "висящи" записи в write буфера от стари прекъсвания. Особено ако записа е на неподравнен адрес може да се получат доста интересни ситуации
Та затова, най-чистото решение е използване на ОС (когато е възможно, предполагам не и в конкретния случай). Има си стандартни примитиви за синхронизация, които трябва да са гарантирани от самата ОС и да бачкат без издънки на съответната платформа.
Тия две решения - ОС или прекъсвания са "чисти" и са за препоръчване, но съвсем не единствени. Има множество други начини подобни на предложените по-горе. Но проблемът тук е, че чрез тях много лесно се вкарват трудни за хващане бъгове. Човек трябва да е много добре запознат с теориите за синхронизации. Аз лично препоръчвам на всеки "да знае" теорията, но да се ползва с особено внимание. Защото дори и да знаеш какво правиш днес, утре тоя код ще се наложи да се портне за друга машина, или пък някой колега ще тръгне "да оптимизира" и ще се омажат нещата...
С други думи теориите за синхронизация са като бойните изкуства - добре е да се изучават, но не и да се прилагат излишно на практика
Иначе теорията според мен е обща и аз не бих я разделил на "хардуерни" и "софтуерни" решения. Дали ще синхронизираш две шини в различни клок домейни или данни между две нишки проблемите и решенията са едни същи.
Един семафор или една опашка може да се реализира както хардуерно, така и софтуерно. И tqi не е прав, че софтуерно не могат да се синхронизира произволни данни. Винаги има някаква атомична операция. При хардуера за това се счита промяната на един единствен бит. И на базата на това се прави синхронизация на произволно сложни неща. Същото е и при софтуера - винаги имаш някаква атомична операция, било то бит, байт или дума, било единичен read/write или цял modify - няма значение. Разбира се колкото по-високо стъпваш, толкова по-лесно... Но *винаги* има решение 
|
| Съб Дек 12, 2009 2:05 pm |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
"някаква"-та "атомична (на български непрекъсваема, на английски "atomic access") е
хардуерната помощ, без която не може и за която говоря.
Чисто софтуерно - без ползване на прекъсвания и без непрекъсваеми операции - не може.
В архитектурите, които знам, винаги има такъв хардуер, разбира се. Но в контекста
ставаше дума за синхронизация без да се ползва такъв, което не става.
Не толкова лесни са нещата и когато ги има. Примерно за код, който върви на
user ниво забраната на прекъсванията не е вариант. В power вариант има - lwarx/stwcx. са
user level инструкции, в 68к TAS и тя е user level. Как е в ARM? Може ли да прави такива
работи без да минава в supervisor mode? (не го знам и ми е любопитно).
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Съб Дек 12, 2009 5:41 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
Значи аз досега не съм срещал архитектура без "някаква" "непрекъсваема" операция. В случая човека има атомични 8-бит операции - това е достатъчно за синхронизация и *може* да се избегне забраняването на прекъсванията (ако това се цели). Решението е елементарно - кръгов буфер с два 8-бит указателя. Ако приемем, че прекъсването е предаваща страна - то първо проверява дали има място в буфера, ако няма данните се изхвърлят. Ако има място се пишат в свободното място и след това се мести указателя. Отдолу приложението чака да види че има нещо и като го види може да си го чете на спокойствие и след като го пречете мести своя указател. Тъй че става и без прекъсвания, макар че пак се ползват "хардуерните" 8-бит операции. Но пак казвам, че архитектура без "някакви" такива операции няма...
До 6-та архитектура включително (АРМ7,9,11) всички единични четения/записи са непрекъсваеми. Така че синхронизацията прекъсване<->нишка не е проблем. Същото важи и за синхронизация "един към един", т.е. само между два обекта.
Проблемът е при синхронизация между повече от два обекта (един към много или много към много). Примерно между едно прекъсване и две нишки. Тук идеята с кръговия буфер не върви, трябва си семафорче. За целта АРМ са оставили "вратичка" - SWAP инструкция, чрез която може да прочетеш и запишеш нова стойност без да те прекъсват.
С две думи на теория може да постигнеш всякаква синхронизация. На практика е много дървено, щото SWAP-а е само в АРМ-режим, демек ако си в Thumb трябва да сменяш режими, после като смениш то не е само един SWAP. В крайна сметка отива много код, време и нерви само за синхронизацията. Затова в такива случаи аз си правя нещата в системни функции (SWI), които се изпълняват при забранени прекъсвания. Демек предпочитам забраната на прекъсванията, макар че в случая те се забраняват косвено сами (от SWI-инструкцията).
Сега от 7-ма архитектура (т.н. кУртекс) нещата малко са омазани. Първо вече дори единичните четения/записи може да не са атомично, щото не ползват кеш ами write буфери за по-евтинджос. Второ няма вече SWAP изобщо и трето SWI е заменено с SVC и яко омазано. Демек хората дето сме свикнали с предните архитектури много се "кефим"
Аз затова казвам, че трябва да се ползва ОС, щото изведнъж могат да ти обърнат всичко с главата надолу
Разбира се, добавили са инструкции за синхронизация LOAD/STORE EXCLUSIVE т.е. LDREX и STREX, които са пълни аналози на твоите lwarx/stwcx, тъй че вероятно ти си по-добре запознат практически от мен, щото аз още не съм ги ползвал 
|
| Съб Дек 12, 2009 8:23 pm |
|
 |
|
tgi
Ранг: Форумен бог
Регистриран на: Нед Юни 10, 2007 2:22 pm Мнения: 6492 Местоположение: София
|
Не е. Трябва ти непрекъсваема (или атомна, ако държиш на чуждицата, на английски atom -> atomic, на български атом -> атомна, няма дума атомична - не че е толкова важно в случая) read-modify-write операция. Инак между четенето и писането винаги може да се набута някой. Кръговите буфери наистина се правят така в много случаи (в повечето от мене поне), но това няма връзка със синхронизациите за които говорим, защото не са нужни. Показалците се пишат изключително или от единия, или от другия; проблем със синхронизацията, за който трябва въпросната хардуерна помощ възниква само когато и двамата могат да пишат на едно и също място. За най-просто представи си TEST AND SET тип инструкция, **няма** чисто софтуерен вариант за нея. Трябва хардуерно да ти бъде осигурен начинът да го направиш (т.е. да знаеш, че си прочел бита какъвто е бил и си написал нова стойност в него без той да е бил променен междувременно). Затова и повечето архитектури имат някакъв такъв вариант. Е, в мякои по-малки, дето не са мислени за мултипроцесорна работа направо няма вариант, трябва хардуерно сам някак да си го направи човек - правил съм и това - но това не е съществено.
А, това стига за всичко. Ако имаш много места за непрекъсваема подмяна просто ги заключваш с
един отделен флаг с lwarx/stwcx. , мажеш навсякъде където искаш, след това ги отключваш. Естествено
всеки, който пише някъде по това поле трябва първо да успее да го заключи.
Това преполагам върви на user ниво? В power върви, и сума то разкошно замислени и почти
направени процесори с E6 ядрото ги скапаха - нещо са го омазали и увисва от неправилно
чифтосани такива инструкции... което като е възможно на user level прави цялото ядро
пълен провал, разбира се.
_________________------------------- www.tgi-sci.com------------------- http://www.flickr.com/photos/didi_tgi/
|
| Съб Дек 12, 2009 9:54 pm |
|
 |
|
zaphod
Ранг: Форумен бог
Регистриран на: Нед Юли 24, 2005 10:28 am Мнения: 2658
|
tgi е прав миро, изтървал си някаква част от теорията. не е достатъчно "някаква" непрекъсваема операция, трябва си нещо което да може да служи като тест&сет. тоя буфер дето го измисли може и да ти реши ситуация за предаване на данни, но в общия случай ти трябват синхронизиращи примитиви. все пак не е само прехвърляне на данни в тоя свят
|
| Съб Дек 12, 2009 11:27 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 3 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|