<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • x
    x

    Linux內核同步機制的自旋鎖原理

    發布時間:2010-11-24 12:12    發布者:eetech
    關鍵詞: linux , 內核 , 同步機制 , 原理 , 自旋鎖
    一、自旋鎖

    自旋鎖是專為防止多處理器并發而引入的一種鎖,它在內核中大量應用于中斷處理等部分(對于單處理器來說,防止中斷處理中的并發可簡單采用關閉中斷的方式,即在標志寄存器中關閉/打開中斷標志位,不需要自旋鎖)。

    自旋就是自己連續的循環等待。如果你有抱著你的愛人旋轉的經歷,那么你應該知道一件事情,為了安全,你不能旋轉太久,你的愛人如果頭昏,也想你早日釋放。是的,自旋的缺點,就是它頻繁的循環直到等待鎖的釋放,將它用于可以快速完成的代碼中才好。

    自旋不能搶占,但能中斷。

    相關話題:SMP和cpu。多個cpu和單個cpu。很多書說自旋鎖只能在多處理機中使用,這是不正確的。

    首先定義

    Spinlock_t lock;

    對不起,我只能找到arm平臺的鎖了

    /*
    * ARMv6 Spin-locking.
    *
    * We (exclusively) read the old value, and decrement it. If it
    * hits zero, we may have won the lock, so we try (exclusively)
    * storing it.
    *
    * Unlocked value: 0
    * Locked value: 1
    */
    typedef struct {
    volatile unsigned int lock;
    #ifdef CONFIG_PREEMPT
    unsigned int break_lock;
    #endif
    } spinlock_t;

    #define SPINLOCK_MAGIC0x1D244B3C
    typedef struct {
    unsigned long magic;
    volatile unsigned long lock;
    volatile unsigned int babble;
    const char *module; // 所屬模塊
    char *owner;
    int oline;
    } spinlock_t;

    Lock為0時可以用,1是等待。0像鎖孔,當沒有鑰匙插進去時,它才可以插進去


    怎么初始化呢?

    #define spin_lock_init(x)
    do {
    (x)->magic = SPINLOCK_MAGIC;
    (x)->lock = 0;  ;0初始化,表示可用
    (x)->babble = 5;
    (x)->module = __FILE__;  
    (x)->owner = NULL;
    (x)->oline = 0;
    } while (0)

    定義一個自旋鎖的方法很有意思,Spinlock_t lock=?????

    可以通過spin_lock
    Spin_lock_irqsave 來調用自旋鎖,后者不允許中斷。前者有可能在上鎖中發生中斷。
    還有spin_trylock 這是一個絕不妥協的函數,它不等待。


    恢復為spin_unlock

    Spin_unlock_irqrestore

    考查下面代碼

    #define spin_lock_irqsave(lock, flags)_spin_lock_irqsave(lock, flags)
    #define _spin_lock_irqsave(lock, flags)
    do {
    local_irq_save(flags);  保存中斷請求標志
    preempt_disable();  不允許搶占
    _raw_spin_lock(lock);
    __acquire(lock);
    } while (0)

    二、自旋鎖綜合使用

    下面是一個使用的例子,你可以使用source insight查到它

    /* never called when PTRS_PER_PMD > 1 */
    void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
    {
    unsigned long flags; /* can be called from interrupt context */

    spin_lock_irqsave(&pgd_lock, flags); 枷鎖
    pgd_list_del(pgd);
    spin_unlock_irqrestore(&pgd_lock, flags); 釋放
    }

    中斷枷鎖

    #define spin_lock_irqsave(lock, flags)_spin_lock_irqsave(lock, flags)
    分析
    unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
    {
    unsigned long flags;

    local_irq_save(flags); 將寄存器存入flags,并關中斷
    preempt_disable(); 搶占鎖
    _raw_spin_lock_flags(lock, flags); 枷鎖
    return flags;
    }
    EXPORT_SYMBOL(_spin_lock_irqsave);

    /* For spinlocks etc */
    #define local_irq_save(x)__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")

    將標志寄存器的內容放在內存x中。請查看gcc匯編

    static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
    {
    #ifdef CONFIG_DEBUG_SPINLOCK
    if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
    printk("eip: %p ", __builtin_return_address(0));
    BUG();
    }
    #endif
    __asm__ __volatile__(
    spin_lock_string_flags
    :"=m" (lock->slock) : "r" (flags) : "memory");
    }

    #define spin_lock_string_flags
    " 1: "
    "lock ; decb %0 "  ;lock總線鎖住,原子操作
    "jns 4f "
    "2: "
    "testl $0x200, %1 "
    "jz 3f "
    "sti "
    "3: "
    "rep;nop "
    "cmpb $0, %0 "
    "jle 3b "
    "cli "
    "jmp 1b "
    "4: "

    理解一下大概意思,就可以了。當lock-1后大于等于0就可以關中斷繼續執行了,否則nop空操作。Nop期間,cpu可以執行其他任務的代碼。

    解鎖

    #define spin_unlock_irqrestore(lock, flags)_spin_unlock_irqrestore(lock, flags)
    void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
    {
    _raw_spin_unlock(lock);
    local_irq_restore(flags);
    preempt_enable();
    }

    static inline void _raw_spin_unlock(spinlock_t *lock)
    {
    #ifdef CONFIG_DEBUG_SPINLOCK
    BUG_ON(lock->magic != SPINLOCK_MAGIC);
    BUG_ON(!spin_is_locked(lock));
    #endif
    __asm__ __volatile__(
    spin_unlock_string
    );
    }

    Raw赤裸的解鎖,表示最低沉的解鎖原理。

    #define spin_unlock_string
    "xchgb %b0, %1"
    :"=q" (oldval), "=m" (lock->slock)
    :"0" (oldval) : "memory"
    加1.解鎖
    本文地址:http://www.portaltwn.com/thread-41345-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • EtherCAT®和Microchip LAN925x從站控制器介紹培訓教程
    • MPLAB®模擬設計器——在線電源解決方案,加速設計
    • 讓您的模擬設計靈感,化為觸手可及的現實
    • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
    • 貿澤電子(Mouser)專區

    相關視頻

    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷