`
sunzixun
  • 浏览: 74860 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

<Learn From Kernel> Mutex Subsystem

阅读更多

 

在我想办法弄懂supermirco 服务用的Super IO w83795的驱动的时候 ,我不幸又陷入了mutex_lock :

 

具体的设计文档见 document/mutex-design. 我这里只是摘录演义~

 

故事开始:

 

"为什么在这个地球上 ,我们需要一个新的mutex 子系统 ,

  原来的semaphore怎了么他不行了吗 "

 

   让我来帮大家怀恋一下他吧

struct semaphore {
	spinlock_t		lock;
	unsigned int		count;
	struct list_head	wait_list;
};

void down(struct semaphore *sem);//ldd上说 你是惹恼的用户的好方法
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);

void up(struct semaphore *sem); 

 其实,错不在semaphore . 而是我的心变了.

 

现在有一个简单的 mutex语义出现了,他完全满足我的代码需要, 而且semaphore 有下面的诱惑.

 

第一:

'struct mutex'  在大多数的平台上他更小 只有16字节 而你 'struct semaphore' 有20个字节

要知道更小的结构意味着 更少的 RAM空间 ,能更好的被CPU cache利用

 

第二:

紧凑的代码, 在x86上, .text的大小比较:

 

写道
text data bss dec hex filename
3280380 868188 396860 4545428 455b94 vmlinux-semaphore
3255329 865296 396732 4517357 44eded vmlinux-mutex

 

 

 

你看 25051字节的代码被节省了  小代码意味着更优越的指令高速缓冲存储器占用 ,这是linux 内核当前优化的主要目标

 

第三:

mutex 子系统 对于竞争带来的负载 表现的更轻盈更可扩展(想想长矛).  在一个8-way的 x86系统上,允许一个

基于mutex的内核测试 creat+unlink+close  在/tmp文件系统下 16个并行的任务:

 

写道
Semaphores: Mutexes:

$ ./test-mutex V 16 10 $ ./test-mutex V 16 10
8 CPUs, running 16 tasks. 8 CPUs, running 16 tasks.
checking VFS performance. checking VFS performance.
avg loops/sec: 34713 avg loops/sec: 84153
CPU utilization: 63% CPU utilization: 22%

 

 


结果显而易见 ~

 

第四:

 

没有快路径的开销(看下面) 只要2条汇编指令这和 semaphora是一样的

 

    c0377ccb <mutex_lock>:
    c0377ccb:       f0 ff 08                lock decl (%eax)
    c0377cce:       78 0e                   js     c0377cde <.text.lock.mutex>
    c0377cd0:       c3                      ret
 

 

 

 

不容忽视的好处:

 

 struct mutex 被很好的赋义 

 

* 一次只有一个任务可以拥有mutex

*   只有拥有者可以解锁

*  多次解锁是不允许的

*  递归加锁也是不可以的

*  一个mutex对象必须通过api初始化不能memset啥的

*  拥有mutex的任务不能exit

* 被锁控制的内存区域不能free

* mutex不能在软件中断或者硬件中断中

* 可以在tasklets软中断或者timers的context中

 

(ps 以上除了第3条当 mutexattr_init 为"PTHREAD_MUTEX_RECURSIVE_NP" 前几条大家其实和 pthread_mutex是一样一样的~)

 

 当编译内核的 CONFIG_DEBUG_MUTEXES  打开后会变得更强大

   * - uses symbolic names of mutexes, whenever they are printed in debug output
   * - point-of-acquire tracking, symbolic lookup of function names
   * - list of all locks held in the system, printout of them
   * - owner tracking
   * - detects self-recursing locks and prints out all relevant info
   * - detects multi-task circular deadlocks and prints out all affected
   *   locks and tasks (and only those tasks)

--------------------------------------------------------------------------------

当然他也有一些缺点

 

你不能用在中断上下文 也不能在不同的context中解锁 但是semaphore可以

 

 

 

下面来简单看一些函数

 

void __sched mutex_lock(struct mutex *lock)
{
	might_sleep();
	/*
	 * The locking fastpath is the 1->0 transition from
	 * 'unlocked' into 'locked' state.
	 */
	__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
	mutex_set_owner(lock);
}

 

这里有一个  might_sleep();
如果编译内核打开了 CONFIG_PREEMPT_VOLUNTARY 宏,那么在这里就如果需要就会面临 schedule();

 

__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);

 

其实是把原子计数 conut 从1变成0 ,如果初始值不是1 ,那么这里就去调用 __mutex_lock_slowpath 函数

 

这样就进入了慢加锁的 路径(原来是不是很快呢,有的体系结构上是用汇编写的)

 

static __used noinline void __sched//__used gcc版本适应 __sched 
__mutex_lock_slowpath(atomic_t *lock_count)
{
	struct mutex *lock = container_of(lock_count, struct mutex, count);

	__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, _RET_IP_);
}

 

 

首先container_of  获得对应原子数的 mutex,然后去调用不可中断的 __mutex_lock_common()

 

待续

 

分享到:
评论

相关推荐

    Linux 应用和驱动编程基础.

    &lt;br&gt;&lt;br&gt;1 Linux Programming 1&lt;br&gt;1.1 Linux Useful Programming Interfaces 1&lt;br&gt;1.1.1 POSIX pThread semaphore interface 1&lt;br&gt;1.1.2 POSIX pthread Mutex interface 2&lt;br&gt;1.1.3 POSIX pthread Condition ...

    Windows多线程编程缺少pthread.h文件问题

    #include &lt;pthread.h&gt; pthread_t newThread; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_...

    动态分区的分配与回收

    #include&lt;iostream.h&gt; #include&lt;stdio.h&gt; #include&lt;windows.h&gt; const int maxlength=10;//空闲分区最大个数 int length=1;//空闲分区实际个数 const int minsize=5;//规定的不再切割的剩余分区的大小 int request;//...

    Linux下多线程计算圆周率 C语言

    #include &lt;pthread.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;sys/time.h&gt; #define N 50000//设定计算次数 #define NUM 2//设定线程数,经过反复实验,在装有1个双核CPU的机器上,两个线程最快 double ...

    Visual C++.NET编程技术体验

    &lt;br&gt;8.4.6 示例——图像浏览器&lt;br&gt;第9章 多线程编程&lt;br&gt;9.6.1 示例——使用全局变量通信&lt;br&gt;9.6.2 示例——使用Windows消息通信&lt;br&gt;9.7.5 示例——使用CriticalSection对象&lt;br&gt;9.7.7 示例——使用Mutex对象&lt;br&gt;9.7.9...

    Visual C++.NET编程技术体验__实例源码

    &lt;br&gt;8.4.6 示例——图像浏览器&lt;br&gt;第9章 多线程编程&lt;br&gt;9.6.1 示例——使用全局变量通信&lt;br&gt;9.6.2 示例——使用Windows消息通信&lt;br&gt;9.7.5 示例——使用CriticalSection对象&lt;br&gt;9.7.7 示例——使用Mutex对象&lt;br&gt;9.7.9...

    linux下的生产者消费者问题

    #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;unistd.h&gt; #include &lt;pthread.h&gt; #include &lt;semaphore.h&gt; #define N 2 // 消费者或者生产者的数目 #define M 10 // 缓冲数目 int in = 0; // 生产者放置产品的...

    实验5--Linux-高级程序设计.doc

    (2) 编写一个多线程程序(pthread),实现2程同步互斥 #include &lt;stdio.h&gt; #include &lt;pthread.h&gt; #define BUFFER_SIZE 16 struct prodcons { // 缓冲区相关数据结构 int buffer[BUFFER_SIZE]; pthread_mutex_t lock...

    qt 下进程条

    #include &lt;pthread.h&gt; #include &lt;stdio.h&gt; int count; pthread_mutex_t count_mutex=PTHREAD_MUTEX_INITIALIZER; void *thread_test(void *vptr) { int i,value; for(i=0;i&lt;1000;i++) { pthread_mutex_lock(&count;_...

    C++11 并发指南之std::mutex详解

    Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 &lt;mutex&gt; 头文件中,所以如果你需要使用 std::mutex,就必须包含 &lt;mutex&gt; 头文件。 &lt;mutex&gt; 头文件介绍 Mutex 系列类(四种) std::mutex,...

    哲学家就餐问题(整理)

    哲学家就餐问题(整理)的几个总结WaitForSingleObject(mutex, INFINITE); cout &lt;&lt; "philosopher " &lt;&lt; myid &lt;&lt; " begin.... cout &lt;&lt; "philosopher " &lt;&lt; myid &lt;&lt; " is : " &lt;&lt; stateStr &lt;&lt; endl; ReleaseMutex(mutex);

    C++11中的mutex, lock, condition variable实现分析

    C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装。不过里面也有很多细节值得... mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)&lt;strong&gt;PTHREAD_MUTEX_INITIALIZER&lt;/strong&gt;;} ~mutex();

    linux mutex.c 内核源码分析

    kernel/mutex.c源代码分析 内核抢占:如果进程正执行内核函数时,即它在内核态运行时,允许发生内核切换,这个内核就是抢占的。 临界区就是指访问和操作共享数据的代码段。 并发是指两个或两个以上数目的执行线程在...

    基于DOS的多任务系统

    #include&lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;dos.h&gt; /*线程的四个状态*/#define finished 0#define running 1#define ready 2#define blocked 3#define null 0#define NTCB 5 /*最大线程数为5*/ #define GET_IN...

    C++11实现简易定时器的示例代码

    定时器timer是多线程编程中经常设计到的工具类 定时器的原理其实很简单: 创建一个新线程 在那个线程里等待 等待指定时长后做任务 这里用C++11实现了一个简单易用的定时器...#include &lt;mutex&gt; #include &lt;condit

    C++11用两个线程轮流打印整数的实现方法

    使用C++11标准的的线程语法,用两个线程...#include &lt;mutex&gt; #include &lt;condition&gt; std::mutex data_mutex; std::condition_variable data_var; bool label = false; void printodd() { std::unique_lock&lt;std::mut

    C++多线程中的锁和条件变量使用教程

    在做多线程编程时,有两个场景我们都会遇到: ...#include &lt;mutex&gt; #include &lt;thread&gt; #include &lt;condition&gt; std::mutex g_mutex; // 用到的全局锁 std::condition_variable g_cond; // 用到的条件变量 int g_i

    互斥量mutex的简单使用(实例讲解)

    #include &lt;pthread&gt; int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutex_t *restrict attr); //初始化mutex int pthread_mutex_destroy(pthread_mutex_t *mutex); //如果mutex是动态...

    cdefer:在 C 中延迟函数调用的类似 Golang 的功能

    例子# include &lt; cdefer&gt;# include &lt; pthread&gt;pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;int main ( void ) { pthread_mutex_lock (&m); defer ( pthread_mutex_unlock (&m)); // m is still locked until end...

Global site tag (gtag.js) - Google Analytics