同步---自旋鎖

1 自旋鎖的基本概念

自旋鎖最多只能被一個可執行線程持有,如果一個執行線程試圖獲得一個已經被使用的自旋鎖,那么該線程就會一直進行自旋,等待鎖重新可用。在任何時刻,自旋鎖都可以防止多余一個的執行線程同時進入臨界區。

Linux內核實現的自旋鎖是不可遞歸的,如果你請求一個你已經持有的自旋鎖,那么你將會自旋,等待釋放這個鎖,由于自旋,釋放這個鎖的操作不會被執行,所以會一直處于自旋忙等待中,于是就被鎖死了。

自旋鎖可以在中斷處理程序中使用。在中斷處理程序中使用自旋鎖時,一定要在獲取鎖之前,首先禁止本地中斷(當前處理器上的中斷請求),否則,中斷處理程序就會打斷正持有鎖的內核代碼,有可能試圖去爭用這個已經被持有的自旋鎖,這樣一來,中斷處理程序就會自旋,但是鎖的持有者在這個中斷處理程序執行完畢前不可能運行,會造成死鎖。注意,需要關閉的只是當前處理器上的中斷,如果中斷發生在不同的處理器上,即使中斷處理程序在同一鎖上自旋,也不會妨礙鎖的持有者最終釋放鎖。

自旋鎖的實現和體系結構體密切相關,代碼往往通過匯編實現,這些與體系結構相關的代碼定義在文件asm/spinlock.h中,實際需要用到的接口定義在文件linux/spinlock.h中,內核提供了對自旋鎖的操作接口:
請添加圖片描述

2 自旋鎖在內核的實現

spinlock_t

自旋鎖用spinlock_t的實例表示,spinlock_t定義在include/linux/spinlock_types.h

typedef struct spinlock {union {struct raw_spinlock rlock;#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))struct {u8 __padding[LOCK_PADSIZE];struct lockdep_map dep_map;};
#endif};
} spinlock_t;

spinlock_t由raw_spinlock表示,該類型和spinlock_t定義在同一個文件中:

typedef struct raw_spinlock {arch_spinlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAKunsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCKunsigned int magic, owner_cpu;void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_map dep_map;
#endif
} raw_spinlock_t;

raw_spinlock由arch_spinlock_t 表示,arch_spinlock_t的實現與體系結構相關,所以spinlock_t的實現與體系結構相關,我們看arm實現的代碼,在文件arch/arm/include/asm/spinlock_types.h中:

typedef struct {union {u32 slock;struct __raw_tickets {
#ifdef __ARMEB__u16 next;u16 owner;
#elseu16 owner;u16 next;
#endif} tickets;};
} arch_spinlock_t;

owner表示持有這個數字的thread可以獲得自旋鎖,next表示如果后續再有thread請求獲取這個自旋鎖,就給他分配這個數字。

spinlock的實現原理:

  1. 剛開始owner=next=0
  2. 第一個thread獲取spinlock,可獲取成功,此時owner=0,next=0
  3. 第二個thread獲取spinlock,如果第一個thread還沒有釋放spinlock,則next++,next變為1
  4. 第三個thread獲取spinlock,如果第一個thread還沒有釋放spinlock,則next++,next就變為2
  5. 此時第一個thread釋放spinlock,則執行owner++,owner=1
  6. 雖然此時第二個thread和第三個thread都在等待spinlock,但是因為第二個thread的next=owner,所以第二個thread可以獲取spinlock,第三個spinlock繼續等待

這樣保證了spinlock的喚醒機制是先到先喚醒,后到后喚醒,保證了公平性。

spin_lock_init

spin_lock_init的定義在include/linux/spinlock.h中

#define spin_lock_init(_lock)				\
do {							\spinlock_check(_lock);				\raw_spin_lock_init(&(_lock)->rlock);		\
} while (0)

spin_lock_init只是對_lock做了一些檢查,我們看raw_spin_lock_init的具體實現,只對spinlock_t中的rlock的初始化。raw_spin_lock_init的實現如下,lock是struct raw_spinlock類型

# define raw_spin_lock_init(lock)				\do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
#endif
#define __RAW_SPIN_LOCK_UNLOCKED(lockname)	\(raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)#define __RAW_SPIN_LOCK_INITIALIZER(lockname)	\{					\.raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,	\SPIN_DEBUG_INIT(lockname)		\SPIN_DEP_MAP_INIT(lockname) }

__ARCH_SPIN_LOCK_UNLOCKED的值與體系架構有關,在arm架構上:

#define __ARCH_SPIN_LOCK_UNLOCKED	{ { 0 } }

SPIN_DEBUG_INIT(lockname)、SPIN_DEP_MAP_INIT(lockname)是為了調試的,如果不調試什么都不做,所以spin_lock_init只是將互斥鎖設置為沒有被鎖住的狀態,即raw_lock的值設為__ARCH_SPIN_LOCK_UNLOCKED

spin_lock

spin_lock的實現在include/linux/spinlock.h中

static __always_inline void spin_lock(spinlock_t *lock)
{raw_spin_lock(&lock->rlock);
}#define raw_spin_lock(lock)	_raw_spin_lock(lock)

spin_lock在單核(up)和多核(smp)的實現不同。

up

在一個處理器下,在文件include/linux/spinlock_api_up.h中定義

#define _raw_spin_lock(lock)			__LOCK(lock)
#define __LOCK(lock) \do { preempt_disable(); ___LOCK(lock); } while (0)

只是關閉了搶占功能

smp

在多處理器下,在文件include/linux/spinlock_api_smp.h中定義

#define _raw_spin_lock(lock) __raw_spin_lock(lock)static inline void __raw_spin_lock(raw_spinlock_t *lock)
{preempt_disable();spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

__raw_spin_lock的實現靠do_raw_spin_lock

void do_raw_spin_lock(raw_spinlock_t *lock)
{debug_spin_lock_before(lock);arch_spin_lock(&lock->raw_lock);debug_spin_lock_after(lock);
}

可以看到do_raw_spin_lock的實現與體系結構有關,因為調用了arch_spin_lock,arch_spin_lock中會將next值加1,然后一直判斷next和onwer是否相同,如果相同,則獲取鎖,進入臨界區執行,否則會一直判斷

所以spin_lock首先會禁止搶占,接著看能不能獲得鎖,如果能夠獲得鎖,則進入臨界區,不能獲得,則一直判斷,直到可以進去臨界區。

spin_unlock

spin_unlock定義在include/linux/spinlock.h中

static __always_inline void spin_unlock(spinlock_t *lock)
{raw_spin_unlock(&lock->rlock);
}
#define raw_spin_unlock(lock)		_raw_spin_unlock(lock)

_raw_spin_unlock在多處理器(SMP)和單處理器(UP)的實現不同

up

在include/linux/spinlock_api_up.h中

#define _raw_spin_unlock(lock)			__UNLOCK(lock)#define __UNLOCK(lock) \do { preempt_enable(); ___UNLOCK(lock); } while (0)

僅僅允許搶占

smp

#define _raw_spin_unlock(lock) __raw_spin_unlock(lock)
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{spin_release(&lock->dep_map, 1, _RET_IP_);do_raw_spin_unlock(lock);preempt_enable();
}

spin_unlock在單處理器下,把搶占設為允許,在多處理器下,先將owner增加1,然后把搶占設為允許

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379561.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379561.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379561.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

實習日志----4.播放時段參數設置

由于客戶在下發廣告時,一則廣告可在多個時段播放,這就需要設置多個播放時段的參數。 但在這種情況下,我并不知道用戶每次需要下發幾個時段,所以前臺不能設定死。 因此我要實現這么一個功能,讓用戶根據自己的需要來動態…

線性插值算法實現圖像_C程序實現插值搜索算法

線性插值算法實現圖像Problem: 問題: We are given an array arr[] with n elements and an element x to be searched amongst the elements of the array. 給定一個數組arr [],其中包含n個元素和一個要在該數組的元素中搜索的元素x 。 Solution: 解&…

hdu 1197

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1197 題意&#xff1a;求一個數轉換成10&#xff0c;12&#xff0c;16進制后各個位上的數的和是否相等。 mark&#xff1a;模擬進制轉換。 代碼&#xff1a; #include <stdio.h>int zh(int a, int n) {int su…

linux系統編程---線程總結

線程總結1 線程的實現線程創建線程退出線程等待線程清理2 線程的屬性線程的分離線程的棧地址線程棧大小線程的調度策略線程優先級3 線程的同步互斥鎖讀寫鎖條件變量信號量線程是系統獨立調度和分配的基本單位。同一進程中的多個線程將共享該進程中的全部系統資源&#xff0c;例…

博客上一些項目相關源碼鏈接

GitHub&#xff1a;https://github.com/beyondyanyu/Sayingyy

重新開啟Ctrl+Alt+Backspace快捷鍵

UBUNTU老用戶知道CtrlAltBackspace這個快捷鍵是用來快速重啟X的在9.04中被默認關閉了&#xff0c;那如何來打開它呢&#xff1f;在終端中輸入&#xff1a;sudo gedit /etc/X11/xorg.conf在其中加入&#xff1a;Section “ServerFlags”Option “DontZap” “false”EndSection退…

Java LocalDate類| 帶示例的getDayOfYear()方法

LocalDate類的getDayOfYear()方法 (LocalDate Class getDayOfYear() method) getDayOfYear() method is available in java.time package. getDayOfYear()方法在java.time包中可用。 getDayOfYear() method is used to get the day-of-year field value of this LocalDate obje…

火腿三明治定理

定理&#xff1a;任意給定一個火腿三明治&#xff0c;總有一刀能把它切開&#xff0c;使得火腿、奶酪和面包片恰好都被分成兩等份。 而且更有趣的是&#xff0c;這個定理的名字真的就叫做“火腿三明治定理”&#xff08;ham sandwich theorem&#xff09;。它是由數學家亞瑟?斯…

如何給Linux操作系統(CentOS 7為例)云服務器配置環境等一系列東西

1.首先&#xff0c;你得去購買一個云服務器&#xff08;這里以阿里云學生服務器為例&#xff0c;學生必須實名認證&#xff09; 打開阿里云&#xff0c;搜索學生服務器點擊進入即可 公網ip為連接云服務器的主機 自定義密碼為連接云服務器是需要輸入的密碼 購買即可 點擊云服…

Linux系統編程---I/O多路復用

文章目錄1 什么是IO多路復用2 解決什么問題說在前面I/O模型阻塞I/O非阻塞I/OIO多路復用信號驅動IO異步IO3 目前有哪些IO多路復用的方案解決方案總覽常見軟件的IO多路復用方案4 具體怎么用selectpollepolllevel-triggered and edge-triggered狀態變化通知(edge-triggered)模式下…

[轉帖]純屬娛樂——變形金剛vs天網

[轉帖]變形金剛2的影評-《變形金剛3 天網反擊戰》有一個問題困擾了我足足二十年&#xff1a;為什么汽車人要幫地球人&#xff1f;光用“所有有感知的生物都應享有自由”這個法則是根本說不過去的&#xff0c;因為豬也有感知&#xff0c;但人類就把豬圈養起來&#xff0c;隨意殺…

c#中textbox屬性_C#.Net中的TextBox.MaxLength屬性與示例

c#中textbox屬性Here we are demonstrating use of MaxLength property of TextBox. 在這里&#xff0c;我們演示了TextBox的MaxLength屬性的使用。 MaxLength property of TextBox is used to set maximum number of character that we can input into a TextBox. Limit of M…

IIS7 MVC網站生成、發布

(1)生成。 確保System.Web.Mvc.dll在bin目錄下 (2)發布網站到文件系統 (3)在IIS中為網站添加應用程序池&#xff08;一個虛擬目錄&#xff0c;一個應用程序池&#xff09; (4)添加在默認網站下添加虛擬目錄 &#xff08;5&#xff09;轉換為應用程序 至此&#xff0c;部署完畢 …

標題:明碼

轉載&#xff1a;https://blog.csdn.net/u011747888/article/details/79781040 標題&#xff1a;明碼 漢字的字形存在于字庫中&#xff0c;即便在今天&#xff0c;16點陣的字庫也仍然使用廣泛。 16點陣的字庫把每個漢字看成是16x16個像素信息。并把這些信息記錄在字節中。 一…

C語言多維數組

文章目錄多維數組數組名下標指向數組的指針作為函數參數的多維數組指針數組小結多維數組 如果某個數組的維數超過1&#xff0c;它就被稱為多維數組&#xff0c;例如&#xff0c;下面這個聲明&#xff1a; int matrix[6][10]創建了一個包含60個元素的矩陣。但是&#xff0c;它…

ubuntu路由器聯網_路由器及其協議簡介| 聯網

ubuntu路由器聯網路由器簡介 (Introduction to Router) Routers are network layer devices. Data on the network layer is known as packets. Routers work to forward packets from one network to another. Routers also maintain the address table. 路由器是網絡層設備。…

XPath學習:軸(5)——descendant-or-self

XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。 XPath 是 W3C XSLT 標準的主要元素&#xff0c;并且 XQuery 和 XPointer 同時被構建于 XPath 表達之上。 推薦一個挺不錯的網站&#xff1a;http://www.zvon.org/xxl/XPathTutorial…

linux設備驅動開發---平臺設備驅動程序

文章目錄1 平臺驅動程序2 平臺設備2.1 資源和平臺數據1 設備配置---廢棄的舊方法資源平臺數據聲明平臺設備2 設備配置---推薦的新方法3 設備、驅動程序和總線匹配OF風格ACPIID表匹配匹配平臺設備的名字和平臺驅動的名字平臺設備和平臺驅動程序如何匹配4 Platfrom架構驅動程序有…

標題:乘積尾零

標題&#xff1a;乘積尾零 如下的10行數據&#xff0c;每行有10個整數&#xff0c;請你求出它們的乘積的末尾有多少個零&#xff1f; 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070…

Robots.txt指南

Robots.txt指南當搜索引擎訪問一個網站時&#xff0c;它首先會檢查該網站的根域下是否有一個叫做robots.txt的純文本文件。Robots.txt文件用于限定搜索引擎對其 網站的訪問范圍&#xff0c;即告訴搜索引擎網站中哪些文件是允許它進行檢索(下載)的。這就是大家在網絡上常看到的“…