怎么进行基于linuxthreads2.0.1线程源码分析mutex.c

发布时间:2021-12-09 09:40:25 作者:柒染
来源:亿速云 阅读:135

本篇文章为大家展示了怎么进行基于linuxthreads2.0.1线程源码分析mutex.c,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

mutex即互斥,用于控制多线程间同步、互斥访问资源。

相关的结构体。

    

/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER).  */
typedef struct
{
 // 自旋锁
 int m_spinlock; /* Spin lock to guarantee mutual exclusion.  */
 // 用于递归加锁,即某个线程多次获取了该互斥变量。m_count记录了次数
 int m_count; /* 0 if free, > 0 if taken.  */
 // 记录谁获取了该互斥变量,在递归加锁的时候会使用这个字段
 pthread_t m_owner; /* Owner of mutex (for recursive mutexes) */
 // 互斥变量的类型,递归或非递归
 int m_kind; /* Kind of mutex */
 // 等待该互斥变量的线程队列
 struct _pthread_queue m_waiting; /* Threads waiting on this mutex.  */
} pthread_mutex_t;
// 初始化互斥变量,类型是递归或非递归
#define PTHREAD_MUTEX_INITIALIZER \
 {0, 0, 0, PTHREAD_MUTEX_FAST_NP, {0, 0}}
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
 {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, {0, 0}}              

下面是实现的代码。

   
     
 
    
    

/* Linuxthreads - a simple clone()-based implementation of Posix        */
/* threads for Linux.                                                   */
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
/*                                                                      */
/* This program is free software; you can redistribute it and/or        */
/* modify it under the terms of the GNU Library General Public License  */
/* as published by the Free Software Foundation; either version 2       */
/* of the License, or (at your option) any later version.               */
/*                                                                      */
/* This program is distributed in the hope that it will be useful,      */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
/* GNU Library General Public License for more details.                 */

/* Mutexes */

#include <errno.h>
#include <sched.h>
#include <stddef.h>
#include "pthread.h"
#include "internals.h"
#include "spinlock.h"
#include "queue.h"
#include "restart.h"

// 利用属性结构体初始化mutex节点
int __pthread_mutex_init(pthread_mutex_t * mutex,
                      const pthread_mutexattr_t * mutex_attr)
{
 mutex->m_spinlock = 0;
 mutex->m_count = 0;
 mutex->m_owner = NULL;
 mutex->m_kind =
   mutex_attr == NULL ? PTHREAD_MUTEX_FAST_NP : mutex_attr->mutexkind;
 queue_init(&mutex->m_waiting);
 return 0;
}
weak_alias (__pthread_mutex_init, pthread_mutex_init)

// 销毁互斥锁
int __pthread_mutex_destroy(pthread_mutex_t * mutex)
{
 int count;
 acquire(&mutex->m_spinlock);
 count = mutex->m_count;
 release(&mutex->m_spinlock);
 // 正在被使用
 if (count > 0) return EBUSY;
 return 0;
}
weak_alias (__pthread_mutex_destroy, pthread_mutex_destroy)

// 非阻塞式获取锁
int __pthread_mutex_trylock(pthread_mutex_t * mutex)
{
 pthread_t self;

 acquire(&mutex->m_spinlock);
 switch(mutex->m_kind) {
 case PTHREAD_MUTEX_FAST_NP:
   // 还没有被使用,则使用数加一,返回成功
   if (mutex->m_count == 0) {
     mutex->m_count = 1;
     release(&mutex->m_spinlock);
     return 0;
   }
   break;
 // 递归获取互斥变量
 case PTHREAD_MUTEX_RECURSIVE_NP:
   self = thread_self();
   // 等于0则说明还没有被获取过,可以直接获取,或者已经被当前线程获取了,则次数加一
   if (mutex->m_count == 0 || mutex->m_owner == self) {
     mutex->m_count++;
     mutex->m_owner = self;
     release(&mutex->m_spinlock);
     return 0;
   }
   break;
 default:
   return EINVAL;
 }
 release(&mutex->m_spinlock);
 return EBUSY;
}
weak_alias (__pthread_mutex_trylock, pthread_mutex_trylock)

// 阻塞式获取互斥变量
int __pthread_mutex_lock(pthread_mutex_t * mutex)
{
 pthread_t self;

 while(1) {
   acquire(&mutex->m_spinlock);
   switch(mutex->m_kind) {
   case PTHREAD_MUTEX_FAST_NP:
     if (mutex->m_count == 0) {
       mutex->m_count = 1;
       release(&mutex->m_spinlock);
       return 0;
     }
     self = thread_self();
     break;
   case PTHREAD_MUTEX_RECURSIVE_NP:
     self = thread_self();
     // 等于0或者本线程已经获得过该互斥锁,则可以重复获得,m_count累加
     if (mutex->m_count == 0 || mutex->m_owner == self) {
       mutex->m_count++;
       // 标记该互斥锁已经被本线程获取
       mutex->m_owner = self;
       release(&mutex->m_spinlock);
       return 0;
     }
     break;
   default:
     return EINVAL;
   }
   /* Suspend ourselves, then try again */
   // 获取失败,需要阻塞,把当前线程插入该互斥锁的等待队列
   enqueue(&mutex->m_waiting, self);
   release(&mutex->m_spinlock);
   // 挂起等待唤醒
   suspend(self); /* This is not a cancellation point */
 }
}
weak_alias (__pthread_mutex_lock, pthread_mutex_lock)

int __pthread_mutex_unlock(pthread_mutex_t * mutex)
{
 pthread_t th;

 acquire(&mutex->m_spinlock);
 switch (mutex->m_kind) {
 case PTHREAD_MUTEX_FAST_NP:
   mutex->m_count = 0;
   break;
 case PTHREAD_MUTEX_RECURSIVE_NP:
   mutex->m_count--;
   if (mutex->m_count > 0) {
     release(&mutex->m_spinlock);
     return 0;
   }
   mutex->m_count = 0; /* so that excess unlocks do not break everything */
   break;
 default:
   return EINVAL;
 }
 // 取出一个被阻塞的线程(如果有的话),唤醒他
 th = dequeue(&mutex->m_waiting);
 release(&mutex->m_spinlock);
 if (th != NULL) restart(th);
 return 0;
}
weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)

int __pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
 attr->mutexkind = PTHREAD_MUTEX_FAST_NP;
 return 0;
}
weak_alias (__pthread_mutexattr_init, pthread_mutexattr_init)

int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
 return 0;
}
weak_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)

int __pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind)
{
 if (kind != PTHREAD_MUTEX_FAST_NP && kind != PTHREAD_MUTEX_RECURSIVE_NP)
   return EINVAL;
 attr->mutexkind = kind;
 return 0;
}
weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)

int __pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind)
{
 *kind = attr->mutexkind;
 return 0;
}
weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
// 保存init_routine只执行一次
int pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
{
 if (testandset(once_control) == 0) init_routine();
 return 0;
}  

上述内容就是怎么进行基于linuxthreads2.0.1线程源码分析mutex.c,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. 怎么进行ActionInvoker源码分析
  2. 如何进行ThreadLocal源码分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

linuxthreads

上一篇:Impala查询HBase表字段顺序不正确异常怎么办

下一篇:怎样进行基于linuxthreads2.0.1线程源码分析attr.c

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》