您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎么進行基于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,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。