关于init_MUTEX()的消失的探索

28 Jun 2015 | Linux, Kernel, mutex, semaphore | | ˚C

前言

最近在学习ldd3,在写scull的时候,发现在输入#include <asm/semaphore.h>的时候,QtCreator竟然没有路径补全提示,隐隐约约感觉遇到坑了。果然,新版本内核是没有这个文件的,搜寻了一番,发现新版本中应该变成了<linux/semaphore.h>。本以为就这样解决了,却出了编译错误,init_MUTEX()找不到。百度了一番,找到了不少文章,比如这个。根据百度的结果,应该是说init_MUTEX()这个函数被废除了,网上的做法都是用sema_init()代替。也许是最近太无聊了,于是想把这一部分的前因后果搞清楚。

关于init_MUTEX()系列函数的变迁

用关键字init_MUTEX在内核git日志中搜寻,发现在2010年9月之后有一波密集的commits,将散在各处的init_MUTEXsema_init替代,后来就没有过类似改动。这些commits的tag是v2.6.37,于是查看了一下这个版本的所有提交,发现了下面这个:

author	Thomas Gleixner <tglx@linutronix.de>	2010-09-07 14:34:01 (GMT)
committer	Thomas Gleixner <tglx@linutronix.de>	2010-10-30 10:12:50 (GMT)
commit	4882720b267b7b1d1b0ce08334b205f0329d4615 (patch)
tree	dd54880f84b7b7fb2bbdb529ffada434aca1e4d9
parent	45f4d0243525b6bc747c946937ced437b135a84d (diff)
semaphore: Remove mutex emulation
Semaphores used as mutexes have been deprecated for years. Now that
all users are either converted to real semaphores or to mutexes remove
the cruft.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Christoph Hellwig <hch@infradead.org>
LKML-Reference: <20100907125057.562399240@linutronix.de>

正是这个提交最终废除了DECLARE_MUTEX()init_MUTEX()init_MUTEX_LOCKED()等函数(实则为宏)。此时的内核版本为2.6.37,而不是网上传的2.6.25。

为了进一步搞清楚semaphore.h是何时从<ams/semaphore.h>转移到<linux/semaphore.h>的,继续往前搜寻,确定了下面的commit:

author	Matthew Wilcox <matthew@wil.cx>	2008-03-08 02:55:58 (GMT)
committer	Matthew Wilcox <willy@linux.intel.com>	2008-04-17 14:42:34 (GMT)
commit	64ac24e738823161693bf791f87adc802cf529ff (patch)
tree	19c0b0cf314d4394ca580c05b86cdf874ce0a167 /include/linux
parent	e48b3deee475134585eed03e7afebe4bf9e0dba9 (diff)
Generic semaphore implementation
Semaphores are no longer performance-critical, so a generic C
implementation is better for maintainability, debuggability and
extensibility.  Thanks to Peter Zijlstra for fixing the lockdep
warning.  Thanks to Harvey Harrison for pointing out that the
unlikely() was unnecessary.

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Acked-by: Ingo Molnar <mingo@elte.hu>

这个commit以利于维护为理由,废除了位于arch/中各个平台的semaphore实现,在kernel/中实现了平台通用的semaphore。此时的内核版本是2.6.26,显然,网上所谓的“在2.6.25以后就再也找不到这个宏了”指的其实是<asm/semaphore.h>中的宏,2.6.25之后这个文件都没了当然“找不到这个宏了”,但是其实只是变了个位置而已。

至于<asm/semaphore.h>产生于何时,在linux内核转移至git管理之前就已经存在,姑且认为生于上古时代。如此,init_MUTEX()系列函数的变迁历史算是理清了。

init_MUTEX()系列函数的废除过程

那到底init_MUTEX()是怎么废除的呢?这需要确定三个问题:

  1. 何时开始废除

  2. 何时完成废除

  3. 废除的原因

第二个问题前面已经确定为commit 4882720b267b7b1d1b0ce08334b205f0329d4615。回顾一下,其中提到”Semaphores used as mutexes have been deprecated for years”,可见2010年9月那一次集中修改只是最后一波而已,类似动作可能几年前就开始了。于是继续向前查找,果然在大约2006、2007年期间出现了许多类似backlight:Convert semaphore -> mutex [PATCH] sem2mutex: inotify之类的commit,所不同的是,这些提交大多是将struct semaphore换成了struct mutex,头文件也换成了mutex.h。顺藤摸瓜,查到了创建mutex.h的commit:

author	Ingo Molnar <mingo@elte.hu>	2006-01-09 23:59:19 (GMT)
committer	Ingo Molnar <mingo@hera.kernel.org>	2006-01-09 23:59:19 (GMT)
commit	6053ee3b32e3437e8c1e72687850f436e779bd49 (patch)
tree	bb845004eb66554c569bc53a1efc87365c8a3cbe /include/linux
parent	2acbb8c657af86b2fa5b185f1d7048385e310585 (diff)
[PATCH] mutex subsystem, core
mutex implementation, core files: just the basic subsystem, no users of it.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@infradead.org>

这时的版本是2.6.16,在这个版本里,mutex子系统问世,原先许多基于semaphore的同步代码被替换为新的mutex实现,而由semaphore模拟的”mutex”代码继续留在内核中,直到2.6.37版本才最后清理完毕。第一个问题也搞清楚了。

init_MUTEX()系列函数的废除原因

至于第三个问题,也就是废除的原因,其实基本已经能明白了。上古时代,正统的mutex还未出世,于是人们用semaphore模拟了mutex,即所谓的“mutex emulation”。2006年的2.6.16版本里,mutex子系统出世,很多原先的代码开始转移到使用新的mutex子系统。直到2010年的2.6.37版本,用semaphore模拟的mutex被彻底清除。其实在3.17版本的Documention/mutex-design.txt(这个文档在3.16之前主要描述mutex和binary semaphore的区别,3.16开始改为mutex的一般性叙述,在3.18里干脆删除了)里也有描述:

Mutexes are sleeping locks which behave similarly to binary semaphores, and were introduced in 2006[1] as an alternative to these.

至于二元semaphore和真正的mutex的区别,从含义来讲,主要在于mutex有一个所有者,只有其所有者可以将其解锁,而semaphore则无此限制,因此mutex才是真正意义上的互斥锁。这个系列的文章从代码优化的角度谈了用mutex的理由。


Older · View Archive (22)

使用QtCreator进行Linux内核开发

Newer

DPDK中ACL(Access Control List)的使用