[英]creating 3 threads and each doing individual work using semapore for synchronization. how can i do it?
[英]data synchronization without using semapore in C
我需要在代碼中進行數據同步。 目前,我正在中斷內部以及局部函數中訪問全局值,如果頻繁調用中斷,則該局部值可能會破壞數據。 我需要避免這種情況。 我的代碼中未使用操作系統,因此無法使用信號燈。 使用與信號量類似的鎖定方法可以解決我的問題。
任何幫助,將不勝感激
中斷的工作方式不同於線程或進程-如果線程等待信號量,則直到信號量可用或等待超時(如果給定)過去時,線程才進行調度。 同時,可以調度其他線程,其中一個線程可能會發回信號量。
中斷服務例程不是這種情況-這些不會被任何線程調度中斷(如果有的話,只會被其他中斷中斷),但是會執行直到返回。 因此,如果ISR等待信號量(或您所要求的類似機制),我們將陷入僵局,因為持有該信號的線程無法再被調度以返回信號量了。
因此,您需要一種完全不同的機制!
執行此操作的通常方法是,只要您的函數需要訪問公用數據,就禁用該中斷,然后再重新啟用它(並且您可能也需要在ISR本身中執行此操作)。
怎么樣? 好吧,特定於操作系統/硬件-只要您不提供更多詳細信息,我就在這里...
僅有一些提示:保持禁用中斷的時間盡可能短,並確保將通常訪問的數據聲明為易失性!
在您的主代碼中可能就這么簡單:
disable_interrupts();
value += 1;
enable_interrupts();
因此,請確保在使用主代碼中的值時不會觸發中斷。
您需要的是對數據的原子訪問。 如果它是單個變量,並且您可以保證訪問是原子的,那么這就足夠了。 但是,這涉及到反匯編C代碼並查看最終結果。 即使機器代碼最終以原子(單指令)的形式出現,它也不是可移植的。
如果您具有支持C11的現代編譯器,則可以將共享變量聲明為_Atomic
,這樣可以解決此問題。
另一種選擇是在調用者進行變量訪問期間簡單地關閉特定中斷。 但是,這會破壞實時性能,並且您可能會錯過中斷。
普遍“最佳”的解決方案可能是自己發明一個信號燈。 例:
// volatile to prevent dangerous compiler optimizations; does not solve re-entrancy
volatile uint32_t data;
volatile bool guard;
void ISR (void)
{
if(!guard)
{
data = SOME_REGISTER;
}
}
void main (void)
{
...
guard = true;
uint32_t local = data;
guard = false;
}
在上面的示例中,根本無法保證原子訪問,甚至不能保證可以訪問guard
變量。 但是,這不再是必需的,因為在main()
將要讀取數據的那一點上,可以保證設置了guard
。 如果在讀取期間插入中斷,則不會破壞數據。
該解決方案的唯一缺點是,設置了防護后,您將丟失更新data
的機會。 如果這是一個問題,則您將必須實施某種方式的臨時存儲。
(請注意,此代碼不會導致“內存障礙”,因此在復雜的多核處理器上,此方法可能不起作用,並且volatile
不一定會導致內存障礙。但是在普通微控制器上,它會很好地工作。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.