linux核心功能sleep_on_common中的自旋鎖

來源:互聯網
上載者:User

注意第一次調用的是spin_lock_irqsave(),但之後釋放鎖卻用的是spin_unlock()

第二次擷取自旋瑣用的是spin_lock_irq(),但釋放鎖卻用的是spin_unlock_irqrestore(),why?

static long __sched

sleep_on_common(wait_queue_head_t *q, int state, long timeout)
{
    unsigned long flags;
    wait_queue_t wait;
    init_waitqueue_entry(&wait, current);
    __set_current_state(state);
    spin_lock_irqsave(&q->lock, flags);
    __add_wait_queue(q, &wait);
    spin_unlock(&q->lock);
    timeout = schedule_timeout(timeout);
    spin_lock_irq(&q->lock);
    __remove_wait_queue(q, &wait);
    spin_unlock_irqrestore(&q->lock, flags);
    return timeout;
}
解釋:

第一次調用spin_lock_irqsave(),擷取了自旋鎖禁止了中斷,同時也儲存了先前的中斷狀態到flags中,接著調用__add_wait_queue()就可以安全的向等待隊列中增加等待事件了,接下來調用spin_unlock()釋放了自旋鎖,但沒有恢複之前的中斷狀態,這樣做也沒有什麼問題。

然後調用schedule_timeout()當前進程讓出CPU(被調度出去)進入等待狀態。

之後當等待事件到達後此任務又被啟用,於是接著執行schedule_timeout()之後的代碼,即第二個自旋鎖spin_lock_irq(),關於spin_lock_irq()就是說,我們能夠確保沒有任何其它代碼禁止本地處理器的中斷(或者換句話說,我們能夠確保在釋放自旋鎖時應該啟用中斷:LDD3中的原話)時才使用,在這裡使用也是恰當的,因此,這句spin_lock_irq()執行後獲得鎖,就可以安全的執行__remove_wait_queue()把之前加入的等待事件從等待鏈表中刪除,之後調用spin_unlock_irqrestore()達到了這些目的:1,釋放自旋鎖;2,恢複之前儲存的中斷狀態;

可以看出,這樣做很巧妙的讓進程徹底恢複到了它執行等待事件之前的中斷狀態。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.