1. 程式人生 > >RTT任務間同步及通訊之關閉中斷

RTT任務間同步及通訊之關閉中斷

關閉中斷也叫中斷鎖,是禁止多工訪問臨界區最簡單的一種方式,即使是在分時操作
系統中也是如此。當中斷關閉的時候,就意味著當前任務不會被其他事件打斷(因為整個系
統已經不再響應那些可以觸發執行緒重新排程的外部事件),也就是當前執行緒不會被搶佔,除
非這個任務主動放棄了處理器控制權。關閉中斷/恢復中斷API介面由BSP實現,根據平臺的

不同其實現方式也大不相同。

關閉、開啟中斷介面由兩個函式完成:
• 關閉中斷

rt_base_t rt_hw_interrupt_disable(void);

這個函式用於關閉中斷並返回關閉中斷前的中斷狀態。
函式引數

函式返回
返回呼叫這個函式前的中斷狀態。
• 恢復中斷

void rt_hw_interrupt_enable(rt_base_t level);

這個函式“使能”中斷,它採用恢復呼叫rt_hw_interrupt_disable()函式前的中斷狀態,

進行“使能”中斷狀態,如果呼叫rt_hw_interrupt_disable() 函式前是關中斷狀態,那麼調
用此函式後依然是關中斷狀態。level引數是上一次呼叫rt_hw_interrupt_ disable()時的返回

值。

這個函式“使能”中斷,它採用恢復呼叫rt_hw_interrupt_disable()函式前的中斷狀態,
進行“使能”中斷狀態,如果呼叫rt_hw_interrupt_disable() 函式前是關中斷狀態,那麼調
用此函式後依然是關中斷狀態。level引數是上一次呼叫rt_hw_interrupt_ disable()時的返回
值。
函式引數
引數 描述
level 前一次rt_hw_interrupt_disable返回的中斷狀態。
函式返回

使用開關中斷進行執行緒間同步的例子程式碼如下例程式碼所示:

#include <rtthread.h>
/* 同時訪問的全域性變數 */
static rt_uint32_t cnt;
void thread_entry(void* parameter)
{
rt_uint32_t no;
rt_uint32_t level;
no = (rt_uint32_t) parameter;
while(1)
{
/* 關閉中斷 */
level = rt_hw_interrupt_disable();
cnt += no;
/* 恢復中斷 */
rt_hw_interrupt_enable(level);
rt_kprintf("thread[%d]'s counter is %d\n", no, cnt);
rt_thread_delay(no);
}

}

/* 使用者應用程式入口 */
void rt_application_init()
{
rt_thread_t thread;
/* 建立t1執行緒 */
thread = rt_thread_create("t1", thread_entry, (void*)10,
512, 10, 5);
if (thread != RT_NULL) rt_thread_startup(thread);
/* 建立t2執行緒 */
thread = rt_thread_create("t2", thread_entry, (void*)20,
512, 20, 5);
if (thread != RT_NULL) rt_thread_startup(thread);

}

使用中斷鎖來作業系統的方法可以應用於任何場合,且其他幾類同步方式都是依賴於中
斷鎖而實現的,可以說中斷鎖是最強大的和最高效的同步方法。只是使用中斷鎖最主要的問
題在於,在中斷關閉期間系統將不再響應任何中斷,也就不能響應外部的事件。所以中斷鎖
對系統的實時性影響非常巨大,當使用不當的時候會導致系統完全無實時性可言(可能導致
系統完全偏離要求的時間需求);而使用得當,則會變成一種快速、高效的同步方式。
例如,為了保證一行程式碼(例如賦值)的互斥執行,最快速的方法是使用中斷鎖而不是
訊號量或互斥量:
/* 關閉中斷*/
level = rt_hw_interrupt_disable();
a = a + value;
/* 恢復中斷*/
rt_hw_interrupt_enable(level);
在使用中斷鎖時,需要確保關閉中斷的時間非常短,例如上面程式碼中的a = a + value; 也
可換成另外一種方式,例如使用訊號量:
/* 獲得訊號量鎖*/
rt_sem_take(sem_lock, RT_WAITING_FOREVER);
a = a + value;
/* 釋放訊號量鎖*/
rt_sem_release(sem_lock);
這段程式碼在rt_sem_take 、rt_sem_release 的實現中,已經存在使用中斷鎖保護訊號量
內部變數的行為,所以對於簡單如a = a + value;的操作,使用中斷鎖將更為簡潔快速。