专利名称:一种自旋锁的加锁方法及计算机系统的制作方法
技术领域:
本发明涉及计算机领域,尤其涉及计算机领域中的一种自旋锁的加锁方法 和装置及计算机系统。
背景技术:
多核处理器在高端嵌入式系统中应用广泛,多核处理器是在一片处理器芯 片中集成多个处理器核心,每个处理器核心都能单独地运行程序,使程序认为 自己运行在一个独立的处理器上。与多台计算机不同的是多核处理器的所有处理器核心可以使用同一条总线访问存储器,因此它们可以共用同一片内存;它 们也可能享用同一套片上设备。嵌入式系统中不仅操作系统及驱动程序,包括 应用程序也会经常使用到共享内存、硬件寄存器等资源。而多核处理器使用共 享资源往往需要独占地使用,例如一块共享内存,如果两个处理器核心同时写 入就可能造成冲突,使结果变得不可控。为了解决这种沖突,出现了用来保护资源访问的机制,即自旋锁。自旋锁 是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等 部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式, 不需要自旋锁)。自旋锁最多只能被一个内核任务持有,如果一个内核任务试图 请求一个已经被持有的自旋锁,那么这个任务就会一直进行忙循环一旋转,等 待锁重新可用。要是锁未被持有,请求它的内核任务便能立刻得该自旋锁并进 行使用。 一般自旋锁的锁值为零值时为未被持有状态,为非零值时则该自旋锁 已经被持有。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区, 因此这种锁可有效地避免多处理器上并发运行的内核任务竟争共享资源。但是使用自旋锁的过程中,如果程序产生错误,有可能使得某个处理器核心对自旋锁加锁后没有进行解锁,那么这时候任何处理器核心试图再去取锁时 都会进入等待的状态,因无人解锁而长期等待陷入瘫痪。由于多核系统中自旋 锁应用非常广泛,所以自旋锁死锁问题会经常出现,长期困扰开发者。目前的嵌入式应用系统中,自旋锁的死锁问题一般通过任务死锁检测机制 来定位,例如看门狗复位系统。通过挂死任务的状态信息可以得知哪一处代码 取锁失败导致的系统挂死。但是无法得知那一部分软件代码加锁未释放导致当 前代码取锁失败,因此检测不到错误的位置,需要工作人员编写代码调试,利 用各种实验室手段进行定位,不仅浪费人力物力还往往会拖延调试周期。发明内容本发明实施例所要解决的技术问题在于,提供一种自旋锁的加锁方法及计 算机系统,能够在自旋锁发生死锁时快速查找到出错位置。本发明实施例提供了自旋锁的加锁方法,该方法包括检测到自旋锁为未被持有状态,内核任务获取所述自旋锁,并将所述内核 任务的程序代码标识写入锁值存储区,所述锁值存储区用于存储自旋锁的锁值。 本发明实施例还提供了一种自旋锁的加锁装置,包括锁值存储区,用于存储所述自旋锁锁值; 检测单元,用于检测所述自旋锁的状态;第一编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有 状态时,将所述内核任务的程序代码标识写入锁值存^f诸区。本发明实施例还提供一种计算机系统,包括多核处理器、存储器以及计算 机总线,所述存储器包含用于表示所述自旋锁锁值的锁值存储区,该计算机系 统还包括检测单元,用于检测所述自旋锁的状态;第一编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有 状态时,将所述内核任务的程序代码标识写入锁值存储区。码标识能够指示获取自旋锁的内核任务,在自旋锁死锁时根据锁值存储区中的 信息能够对出错的位置进行快速的定位,在占用系统较小开销的情况下能够较 大的缩短了调试周期。
为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施 例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述 中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付 出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。图1是本发明自旋锁的加锁方法的第一实施例流程图; 图2是本发明自旋锁的加锁方法的第二实施例流程图; 图3是本发明计算机系统的一实施例的结构示意图; 图4是本发明计算机系统的另 一 实施例的结构示意图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清 楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是 全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造 性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。请参见图1所示,图1是本发明自旋锁的加锁方法的第一实施例流程图。 如图1所示,该方法具体包括步骤S101,检查自旋锁的当前锁值,并判断该自旋锁是否为已被持有状态。 自旋锁的状态根据锁值的数值来判断,在本实施例中自旋锁的锁值存储在锁值 存储区中,如果自旋锁的当前锁值为非零值,那么系统判断该自旋锁为已被持 有状态;如果自旋锁的当前锁值为零值,那么系统判断该自旋锁为未被持有状 态。如果自旋锁被判断为已被持有状态时,那么试图获取该自旋锁的内核任务就会进行自旋等待,直到该自旋锁;故释放为止,即直到该自旋锁变为未被持有状态为止。在自旋锁为未被持有状态时,执行步骤S102。步骤S102,内核任务获取自旋锁,将所述内核任务的程序代码标识写入锁值 存储区。例如在32位的系统中,自旋锁的锁值一般用32位的锁值存储区来表 示,这里的32位存储区即为32位内存区,可以将能够有效识别内核任务的程 序代码标识写入该存储区,那么在自旋锁发生死锁时,开发者可以根据程序代 码标识准确的找到锁定内核任务的加锁代码。自旋锁死锁问题发生后代码被锁 死在一个固定的位置,这时可以通过死锁检测机制收集内核任务的状态,可保 存的信息一般至少包括通用寄存器的值、处理器状态寄存器的值。 一般商用操 作系统均带有类似的功能,无操作系统的软件也可借助看门狗中断来实现。本 实施例中采用的程序代码标识为代码行号,加锁代码的行号在不同文件间重复 的概率极小,也就是说仅凭行号即可以确定加锁代码。在上述32位系统中,可 以根据代码文件的长度上限来确定用于表示该代码行号信息的存储区的位数。基于C语言实现的操作系统或应用软件,只需修改自旋锁的实现方式,使用 宏定义加内嵌汇编方式实现。其中代码行号可以使用宏定义直接引用编译器的 变量取得。这种定位机制的移植非常简单,与C语言代码的规模无关。例如在 内嵌汇编实现自旋锁代码时可以通过读取这样的伪代码—asm__volatile—("检查锁是否被占用""load%l,0xl2341234\n""把%1中的值写入锁中");以上语句中load为汇编伪指令,用来向寄存器中写入一个立即数的值;%1 指定一个通用寄存器,0x12341234是立即数的值。这条语句可以把一个 0x12341234立即数写入一个指定的通用寄存器。自旋锁为未#1持有状态时,可 以把这个寄存器的值写到自旋锁所在的内存中,完成加锁的过程。在使用本实 施例时可以读取下列伪代码一asm__volatile一 ("检查锁是否被占用" "load %l,,,STR(_LINE」,,\n,, "把%1中的值写入锁中");在C编译器编译代码时,—LINE—会被编译成代码所在行号,STR()宏用来 将行号与指令字符串拼接在一起,这样加锁后的锁值即为内核任务的程序代码行号。加锁代码的行号在不同文件间重复的概率极小,那么凭行号即可以确定 加锁代码。代码行号可通过立即数写入指令,不必占用额外开销,而且仅代码 行数一项就已经是非零值,足以确保锁值为有效的非零值。采用本发明第一实 施例的加锁方法,在自旋锁死锁时根据该代码行号可以快速的检测到出错的位 置,能够大大缩短导致死锁错误的定位周期。除了代码行号之外,在存储区位 数足够的情况下还可以以内核任务的加锁代码的文件名或者其他能够表征该内 核任务程序加锁代码的数据信息作为代码标识,由于原理相同,在此不再赘述。请参见图2所示,图2是本发明自旋锁的加锁方法的第二实施例流程图。 如图2所示,该方法具体包括步骤S201,检查自旋锁的当前锁值,并判断该自旋锁是否为已被持有状态。 如果自旋锁被判断为已被持有状态时,那么试图获取该自旋锁的内核任务就会 进行自旋等待,直到该自旋锁被释放为止。如果该自旋锁为未被持有状态,则 执行步骤S202。步骤S202,内核任务获取自旋锁,将所述内核任务的程序代码标识写入锁 值存储区。本实施例的步骤S201和步骤S202同图1所示第一实施例的步骤相 同。除了代码行号之外,在存储区位数足够的情况下还可以以内核任务的加锁 代码的文件名或者其他能够表征该内核任务程序加锁代码的数据信息作为代码 标识,由于原理相同,在此不再赘述。步骤S203,将运行所述内核任务的多核处理器的核心标识写入锁值存储区。 本实施例中多核处理器的核心标识采用多核处理器的核心号,用于表示多核处理器核心号的位数可以根据多核处理器的核心个数来确定。通过写入程序代码 标识可以在发生自旋锁死锁后快速找到持有该自旋锁的内核任务程序的代码, 通过写入多核处理器的核心号可以准确的查找到执行该内核任务程序代码的处理器核心。多核处理器的核心号属于处理器内建j言息,一^l殳可通过一个cycle(循环)取到。步骤S204,将用于定位所述内核任务的自定义信息写入锁值存储区。除了 通过写入程序代码标识可以在发生自旋锁死锁后快速找到持有该自旋锁的内核 任务程序的代码,通过写入多核处理器的核心号可以准确的查找到执行该内核 任务程序代码的处理器核心,还可以根据不同内核任务的特点写入定位内核任 务的自定义信息,例如任务的ID (Identity,身份标识)等等。这样可以充分的利 用存储区来^是供更多的定位信息。代码行号可以通过编译生成立即数的方法写入,不会在系统运行时的带来 额外开销。多核处理器的处理器核心号或任务ID等信息也可通过极小开销取得。 当然,代码行号、处理器核心号或任务ID写入的顺序并不唯一,也可以将含有 代码行号、多核处理器的核心号以及自定义信息的锁值直接写入存储区。写入 多核处理器的核心号和自定义信息与图1所示第一实施例步骤S102中的为代码 类似,只是宏定义直接引用的编译器的变量不同,在此不再赘述。采用本发明 第二实施例的加锁方法,在自旋锁死锁时根据该代码行号可以快速的检测到出 错的位置,能够大大缩短导致死锁错误的定位周期。请参见图3所示,图3是本发明计算机系统的一实施例的结构示意图。请 参见图3所示,该计算机系统包括多核处理器310、存储器320、计算机总线 330、检测单元340以及第一编写单元350。多核处理器310、存储器320、检测 单元340以及第一编写单元350通过计算机总线330相连接。多核处理器310含有多个处理核心,每个处理核心都能单独的运行程序, 相当于程序运行在一个独立的处理器上。多核处理器310的所有处理器核心可 以使用同一条计算总线330访问存储器320。存储器320为与多核处理器310相关联的存储设备,本实施例中以内存为例进行详细说明,存储器320包含有锁值存储区,所述锁值存储区用来存储自 旋锁的锁值。检测单元340具体包括读取模块341和判断模块342。 读取模块341,用于读取的所述自旋锁的当前锁值。判断模块342,用于根据读取模块341读取的自旋锁的当前锁值判断该自旋 锁的状态,如果当前锁值为非零值,则判断为已被持有状态;如果当前锁值为 零值,则判断为未被持有状态。第一编写单元350,用于在4企测单元340检测出该自旋锁状态为未被持有状 态时,将试图获取该自旋锁的内核任务的程序代码标识写入锁值存储区,完成 该自旋锁的加锁过程。锁值存储区位于存储器320中。本实施例中采用的程序 代码标识为代码行号,加锁代码的行号在不同文件间重复的概率极小,也就是 说仅凭行号即可以确定加锁代码。用于表示该代码行号信息的存储区的位数可 以根据代码文件的长度上限来确定。将试图获取该自旋锁的内核任务的代码行 号写入锁值存储区时读取下面的伪代码 —asm__volatile一 ("检查锁是否被占用" "load %1,"STR(—LINE—),,W, "把%1中的值写入锁中");加锁代码的行号在不同文件间重复的概率极小,那么凭行号即可以确定加锁 代码。代码行号可通过立即数写入指令,不必占用额外开销,而且仅代码行数 一项就已经是非零值,足以确保锁值为有效的非零值。在自旋锁死锁时根据该 代码行号可以快速的检测到出错的位置,能够大大缩短导致死锁错误的定位周 期。请参见图4所示,图4为本发明计算机系统的另一实施例的结构示意图。请参见图4所示,该计算机系统包括多核处理器410、存储器420、计算机总线430、检测单元440、第一编写单元450、第二编写单元460以及第三编写单元470。多核处理器410、存储器420、检测单元440、第一编写单元450、第二 编写单元460以及第三编写单元470通过计算片几总线430相连接。多核处理器410含有多个处理核心,每个处理核心都能单独的运行程序, 相当于程序运行在一个独立的处理器上。多核处理器410的所有处理器核心可 以使用同一条计算总线430访问存储器420。存储器420为与多核处理器410相关联的存储设备,本实施例中以内存条 为例进行详细说明,存储器320包含有锁值存储区,所述锁值存储区用来存储 自旋锁锁值。检测单元440具体包括读取模块441和判断模块442。 读取模块441 ,用于在锁值存储区中读取的所述自旋锁的当前锁值。 判断模块442,用于根据读取模块441读取的自旋锁的当前锁值判断该自旋 锁的状态,如果当前锁值为非零值,则判断为已被持有状态;如果当前锁值为 零值,则判断为未被持有状态。第一编写单元450,用于在检测单元440检测出该自旋锁状态为未被持有状 态时,将试图获取该自旋锁的内核任务的程序代码标识写入锁值存储区,完成 该自旋锁的加锁过程。锁值存储区位于存储器420中。第二编写单元460,将运行所述内核任务的所述多核处理器的核心标识写入 锁值存储区。本实施例中多核处理器410的核心标识采用多核处理器的核心号, 用于表示多核处理器核心号的位数可以根据多核处理器410的核心个数来确定。 在发生自旋锁死锁时,通过写入多核处理器410的核心号可以准确的查找到执 行该内核任务程序代码的处理器核心。多核处理器410的核心号属于处理器内 建信息, 一般可通过一个cycle (循环)取到。第三编写单元470,用于将用于定位所述内核任务的自定义信息写入锁值存 储区。为了有效利用存储器410中用于表示自旋锁锁值的存储区,可以在该存 储区写入更多的用于定位获取内核任务的定位信息,还可以根据不同内核任务 的特点写入自定义信息,例如软件的版本等等。这样可以充分的利用存储区来 提供更多的定位信息。其中第一编写单元450、第二编写单元460以及第三编写单元470可以如本 实施例中按功能分为不同的编写单元,也可以合并为一个或者两个编写单元来 实现。锁死锁时根据该存储区中的信息能够对出错的位置进行快速的定位,在占用系 统较小开销的情况下能够较大的缩短了调试周期。以上所列举的仅为本发明较佳实施例而已,当然不能以此来限定本发明之 权利范围,因此依本发明权利要求所作的等同变化,仍属本发明所涵盖的范围。
权利要求
1、一种自旋锁的加锁方法,其特征在于,包括检测到自旋锁为未被持有状态,内核任务获取所述自旋锁,并将所述内核任务的程序代码标识写入锁值存储区,所述锁值存储区用于存储自旋锁的锁值。
2、 如权利要求1所述的自旋锁的加锁方法,其特征在于,所述程序代码标 识为代码行号。
3、 如权利要求1所述的自旋锁的加锁方法,其特征在于,所述检测到自旋 锁为未被持有状态包括检查所述自旋锁的当前锁值;根据所述自旋锁的当前锁值来判断该自旋锁的状态,如果当前锁值为非零 值,则判断为已纟皮持有状态。
4、 如权利要求1所述的自旋锁的加锁方法,其特征在于,所述检测到自旋 锁为未被持有状态,内核任务获取所述自旋锁后还包括将运行所述内核任务的多核处理器的核心标识写入锁值存储区。
5、 如权利要求4所述的自旋锁的加锁方法,其特征在于,所述多核处理器 的核心标识为多核处理器的核心号。
6、 如权利要求1所述的自旋锁的加锁方法,其特征在于,所述检测到自旋 锁为未被持有状态,内核任务获取所述自旋锁后还包括将用于定位所述内核任务的自定义信息写入用于锁值存储区。
7、 一种自旋锁的加锁装置,其特征在于,包括锁值存储区,用于存储所述自旋锁锁值; 检测单元,用于检测所述自旋锁的状态;第 一编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有 状态时,将所述内核任务的程序代码标识写入锁值存储区。
8、 如权利要求7所述的自旋锁的加锁装置,其特征在于,所述检测单元具 体包括读取^f莫块,用于读取的所述自旋锁的当前锁值;判断模块,用于根据所述读取模块读取的自旋锁的当前锁值来判断该自旋 锁的状态,如果当前锁值为非零值,则判断为已被持有状态;如果当前锁值为 零值,则判断为未被持有状态。
9、 如权利要求7所述的自旋锁的加锁装置,其特征在于,还包括 第二编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有状态时,将运行所述内核任务的所述多核处理器的核心标识写入锁值存储区。
10、 如权利要求7或8所述的自旋锁的加锁装置,其特征在于,还包括 第三编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有状态时,将用于定位所述内核任务的自定义信息写入锁值存储区。
11、 一种计算机系统,包括多核处理器、存储器以及计算机总线,其特征 在于,所述存储器包含用于表示所述自旋锁锁值的锁值存储区,该计算机系统 还包括检测单元,用于检测所述自旋锁的状态;第 一编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有 状态时,将所述内核任务的程序代码标识写入锁值存储区。
12、 如权利要求11所述的计算机系统,其特征在于,还包括 第二编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有状态时,将运行所述内核任务的所述多核处理器的核心标识写入锁值存储区。
13、 如权利要求11或12所述的计算机系统,其特征在于,还包括 第三编写单元,用于在所述检测单元检测到所述自旋锁的状态为未被持有状态时,将用于定位所述内核任务的自定义信息写入锁值存储区。
全文摘要
一种自旋锁的加锁方法,该方法包括检测到自旋锁为未被持有状态,内核任务获取所述自旋锁,并将所述内核任务的程序代码标识写入锁值存储区,所述锁值存储区用于存储自旋锁的锁值。相应的,本发明实施例还公开了一种自旋锁的加锁装置和计算机系统。本发明实施例通过用于表示自旋锁锁值的存储区中写入内核任务的程序代码标识,在自旋锁死锁时根据该存储区中的信息能够对出错的位置进行快速的定位,在占用系统较小开销的情况下能够较大的缩短了调试周期。
文档编号G06F9/46GK101403979SQ20081021710
公开日2009年4月8日 申请日期2008年10月27日 优先权日2008年10月27日
发明者珅 李 申请人:成都市华为赛门铁克科技有限公司