• 首页
  • 中国
  • OK6410A 开发板 (八) 74 linux-5.11 OK6410A linux 内核同步机制 信号量(count=1)的实现

OK6410A 开发板 (八) 74 linux-5.11 OK6410A linux 内核同步机制 信号量(count=1)的实现

2023-11-01 1浏览
百检网是一家专业的第三方检测平台,汇聚众多拥有权威资质的第三方检测机构为你提供一站式的检测服务,做检测就上百检网。百检网让检测从此检测,一份报告全国通用,专业值得信赖。

解决的问题是什么

所有异常原因

限制是什么

加锁函数会引起睡眠,所以不能...

实现

https://elixir.bootlin.com/linux/v4.0/source/kernel/locking/semaphore.c#L53

/*

向下-获取信号量

@sem:要获取的信号量

获取信号量。如果不允许更多任务获取信号量,则调用此函数将使任务进入睡眠状态,直到释放信号量。

不赞成使用此函数,请改用down_interruptible()或down_killable()。

*/

void down(struct semaphore *sem)

{

unsigned long flags;

raw_spin_lock_irqsave(&sem->lock, flags);

if (likely(sem->count > 0))

sem->count--;

else

__down(sem);

raw_spin_unlock_irqrestore(&sem->lock, flags);

}

EXPORT_SYMBOL(down);

https://elixir.bootlin.com/linux/v4.0/source/include/linux/spinlock.h#L215

#define raw_spin_lock_irqsave(lock, flags)

do {

typecheck(unsigned long, flags);

flags = _raw_spin_lock_irqsave(lock);

} while (0)

https://elixir.bootlin.com/linux/v4.0/source/kernel/locking/spinlock.c#L157

#ifndef CONFIG_INLINE_SPIN_LOCK_IRQSAVE

unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)

{

return __raw_spin_lock_irqsave(lock);

}

EXPORT_SYMBOL(_raw_spin_lock_irqsave);

#endif

https://elixir.bootlin.com/linux/v4.0/source/include/linux/spinlock_api_smp.h#L106

static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)

{

unsigned long flags;

local_irq_save(flags);

preempt_disable();

spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

/*

* On lockdep we dont want the hand-coded irq-enable of

* do_raw_spin_lock_flags() code, because lockdep assumes

* that interrupts are not re-enabled during lock-acquire:

*/

#ifdef CONFIG_LOCKDEP

LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);

#else

do_raw_spin_lock_flags(lock, &flags);

#endif

return flags;

}

https://elixir.bootlin.com/linux/v4.0/source/include/linux/spinlock.h#L151

static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)

{

__acquire(lock);

arch_spin_lock(&lock->raw_lock);

}

https://elixir.bootlin.com/linux/v4.0/source/arch/arm/include/asm/spinlock.h#L58

static inline void arch_spin_lock(arch_spinlock_t *lock)

{

unsigned long tmp;

u32 newval;

arch_spinlock_t lockval;

prefetchw(&lock->slock);

__asm__ __volatile__(

"1:ldrex%0, [%3]n"

"add%1, %0, %4n"

"strex%2, %1, [%3]n"

"teq%2, #0n"

"bne1b"

: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)

: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)

: "cc");

while (lockval.tickets.next != lockval.tickets.owner) {

wfe();

lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);

}

smp_mb();

}

https://elixir.bootlin.com/linux/v4.0/source/kernel/locking/semaphore.c#L236

static noinline void __sched __down(struct semaphore *sem)

{

__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);

}

https://elixir.bootlin.com/linux/v4.0/source/kernel/locking/semaphore.c#L204

/*

因为这个函数是内联的,所以'state'参数将是常量,因此由编译器优化。同样,对于没有超时的情况,“timeout”参数。

*/

static inline int __sched __down_common(struct semaphore *sem, long state,

long timeout)

{

struct task_struct *task = current;

struct semaphore_waiter waiter;

list_add_tail(&waiter.list, &sem->wait_list);

waiter.task = task;

waiter.up = false;

for (;;) {

if (signal_pending_state(state, task))

goto interrupted;

if (unlikely(timeout <= 0))

goto timed_out;

__set_task_state(task, state);

raw_spin_unlock_irq(&sem->lock);

timeout = schedule_timeout(timeout);

raw_spin_lock_irq(&sem->lock);

if (waiter.up)

return 0;

}

timed_out:

list_del(&waiter.list);

return -ETIME;

interrupted:

list_del(&waiter.list);

return -EINTR;

}

百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台