4,438
社区成员
发帖
与我相关
我的任务
分享
//这是提供给驱动的接口
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);
}
//这个函数会根据CPU所支持的ARM指令版本而选择不同的版本,以下为V5以下
//arm指令通用的函数,V5以上的在arch/arm目录下
static inline void
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_xchg(count, 0) != 1))
fail_fn(count);
}
static __used noinline void __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_);
}
//以下为没有获得锁而处理的最核心的函数,看着多,其实不难
static inline int __sched
__mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
unsigned long ip)
{
struct task_struct *task = current;
struct mutex_waiter waiter;
unsigned long flags;
preempt_disable();
mutex_acquire(&lock->dep_map, subclass, 0, ip);
spin_lock_mutex(&lock->wait_lock, flags);
debug_mutex_lock_common(lock, &waiter);
debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
/* add waiting tasks to the end of the waitqueue (FIFO): */
list_add_tail(&waiter.list, &lock->wait_list);
waiter.task = task;
if (atomic_xchg(&lock->count, -1) == 1)
goto done;
lock_contended(&lock->dep_map, ip);
for (;;) {
if (atomic_xchg(&lock->count, -1) == 1)
break;
if (unlikely(signal_pending_state(state, task))) {
mutex_remove_waiter(lock, &waiter,
task_thread_info(task));
mutex_release(&lock->dep_map, 1, ip);
spin_unlock_mutex(&lock->wait_lock, flags);
debug_mutex_free_waiter(&waiter);
preempt_enable();
return -EINTR;
}
__set_task_state(task, state);
//printk(KERN_DEBUG "%s: before, lock_count: 0x%x, pid: %d\n", __func__, \
//(int)lock->count.counter, task_tgid_vnr(current));
/* didnt get the lock, go to sleep: */
spin_unlock_mutex(&lock->wait_lock, flags);
preempt_enable_no_resched();
schedule();
preempt_disable();
printk(KERN_DEBUG "%s: after, lock_count: 0x%x, pid: %d\n", __func__, \
(int)lock->count.counter, task_tgid_vnr(current));
spin_lock_mutex(&lock->wait_lock, flags);
}
done:
//printk(KERN_DEBUG "%s: lock_count: 0x%x, pid: %d\n", __func__, \
//(int)lock->count.counter, task_tgid_vnr(current));
lock_acquired(&lock->dep_map, ip);
/* got the lock - rejoice! */
mutex_remove_waiter(lock, &waiter, current_thread_info());
mutex_set_owner(lock);
/* set it to 0 if there are no waiters left: */
if (likely(list_empty(&lock->wait_list)))
atomic_set(&lock->count, 0);
spin_unlock_mutex(&lock->wait_lock, flags);
debug_mutex_free_waiter(&waiter);
preempt_enable();
return 0;
}
//以下为释放锁的
void __sched mutex_unlock(struct mutex *lock)
{
__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
}
static inline void
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_xchg(count, 1) != 0))
fail_fn(count);
}
static __used noinline void
__mutex_unlock_slowpath(atomic_t *lock_count)
{
__mutex_unlock_common_slowpath(lock_count, 1);
}
static inline void
__mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
{
struct mutex *lock = container_of(lock_count, struct mutex, count);
unsigned long flags;
spin_lock_mutex(&lock->wait_lock, flags);
mutex_release(&lock->dep_map, nested, _RET_IP_);
debug_mutex_unlock(lock);
if (__mutex_slowpath_needs_to_unlock())
atomic_set(&lock->count, 1);
if (!list_empty(&lock->wait_list)) {
/* get the first entry from the wait-list: */
struct mutex_waiter *waiter =
list_entry(lock->wait_list.next,
struct mutex_waiter, list);
debug_mutex_wake_waiter(lock, waiter);
wake_up_process(waiter->task);
printk(KERN_DEBUG "%s: lock_count: 0x%x, pid: %d\n", __func__, \
(int)lock->count.counter, task_tgid_vnr(current));
}
spin_unlock_mutex(&lock->wait_lock, flags);
}
/这是互斥锁的log
<7>[ 83.890838] i2c_transfer: get i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
<7>[ 83.890930] i2c_transfer: get i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 1
<7>[ 83.890960] __mutex_lock_common: before, lock_count: 0xffffffff, pid: 1041
<7>[ 83.891143] __mutex_unlock_common_slowpath: lock_count: 0x1, pid: 206
<7>[ 83.891174] i2c_transfer: release i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
<7>[ 83.891174]
<7>[ 83.891204] i2c_transfer: get i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
<7>[ 83.891235] __mutex_lock_common: after, lock_count: 0x0, pid: 1041
<7>[ 83.891235] __mutex_lock_common: before, lock_count: 0xffffffff, pid: 1041
<7>[ 83.891510] __mutex_unlock_common_slowpath: lock_count: 0x1, pid: 206
<7>[ 83.891510] i2c_transfer: release i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
<7>[ 83.891876]
<7>[ 83.891876] i2c_transfer: get i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
<7>[ 83.891906] __mutex_lock_common: after, lock_count: 0x0, pid: 1041
<7>[ 83.891937] __mutex_lock_common: before, lock_count: 0xffffffff, pid: 1041
<7>[ 83.895751] __mutex_unlock_common_slowpath: lock_count: 0x1, pid: 206
<7>[ 83.895751] i2c_transfer: release i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 1
.........
<7>[ 83.904693] i2c_transfer: get i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 2
<7>[ 83.904693] __mutex_lock_common: after, lock_count: 0x0, pid: 1041
<7>[ 83.904724] __mutex_lock_common: before, lock_count: 0xffffffff, pid: 1041
<7>[ 83.904876] __mutex_unlock_common_slowpath: lock_count: 0x1, pid: 206
<7>[ 83.904876] i2c_transfer: release i2c lock, slave->addr: 0x34, cur_pid: 206, flags: 0x0, len: 2
<7>[ 83.904907]
<7>[ 83.904937] __mutex_lock_common: after, lock_count: 0x1, pid: 1041
<7>[ 83.904937] __mutex_lock_common: lock_count: 0xffffffff, pid: 1041
<7>[ 83.905090] i2c_transfer: release i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 1
//以下是信号量的log
<7>[ 53.400207] i2c_transfer: get i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 1
<7>[ 53.400329] i2c_transfer: get i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1
<7>[ 53.400360] __down_common: before count: 0x0, pid: 5, up: 0
<7>[ 53.400390] __up: count: 0x0, pid: 1041, up: 1
<7>[ 53.400390] i2c_transfer: release i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 1
<7>[ 53.400421]
<7>[ 53.400421] i2c_transfer: get i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x1, len: 32
<7>[ 53.400451] __down_common: before count: 0x0, pid: 1041, up: 0
<7>[ 53.400451] __down_common: after count: 0x0, pid: 5, up: 1
<7>[ 53.400695] __up: count: 0x0, pid: 5, up: 1
<7>[ 53.400726] i2c_transfer: release i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1
<7>[ 53.400726]
<7>[ 53.400726] i2c_transfer: get i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1
<7>[ 53.400756] __down_common: before count: 0x0, pid: 5, up: 0
<7>[ 53.400756] __down_common: after count: 0x0, pid: 1041, up: 1
<7>[ 53.402404] __up: count: 0x0, pid: 1041, up: 1
<7>[ 53.402435] i2c_transfer: release i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x1, len: 32
<7>[ 53.402435]
<7>[ 53.402465] i2c_transfer: get i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 2
<7>[ 53.402496] __down_common: before count: 0x0, pid: 1041, up: 0
<7>[ 53.402557] __down_common: after count: 0x0, pid: 5, up: 1
<7>[ 53.402832] __up: count: 0x0, pid: 5, up: 1
<7>[ 53.402862] i2c_transfer: release i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1
<7>[ 53.402862]
<7>[ 53.402862] i2c_transfer: get i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1
<7>[ 53.402893] __down_common: before count: 0x0, pid: 5, up: 0
<7>[ 53.402923] __down_common: after count: 0x0, pid: 1041, up: 1
<7>[ 53.403106] __up: count: 0x0, pid: 1041, up: 1
<7>[ 53.403106] i2c_transfer: release i2c lock, slave->addr: 0x67, cur_pid: 1041, flags: 0x0, len: 2
<7>[ 53.403137]
<7>[ 53.404083] __down_common: after count: 0x0, pid: 5, up: 1
<7>[ 53.404479] i2c_transfer: release i2c lock, slave->addr: 0x44, cur_pid: 5, flags: 0x0, len: 1