构建64位操作系统-多核运行互斥与同步机制

1.自旋锁

 1.1.论述

        自旋锁实现的前提是汇编提供了Lock指令前缀可用于修饰需要访问目标操作数在内存的汇编指令。

        Lock修饰的汇编指令在执行过程前会锁住内存。这样所有逻辑处理器均无法执行内存访问。在汇编指令结束后,解除锁定。这样其他需要访问内存的逻辑处理器的访问操作(可能是读取或写入)才能正常进行。

        自旋锁的死锁问题:

        当一个逻辑处理器持有一个自旋锁A时,且该自旋锁A只能被自己后续释放时,被中断,中断处理时,该逻辑处理器再次通过spin_lock获取自旋锁A时,将产生死锁。

        注意:

        当一个逻辑处理器1持有一个自旋锁A时,

        另一个逻辑处理器2通过spin_lock获取自旋锁A时,不会产生死锁。逻辑处理器2将通过循环等待,直到自旋锁A被释放。然后,获得锁,继续执行。

        自旋锁评价:

        自旋锁是是实现互斥访问的核心技术。因为等待锁时自选等待,会持续让逻辑处理器忙碌,但不会涉及上下文切换,执行现场保存与恢复。比较适合,短期持有锁的场景下的互斥保护。

1.2.实践

#ifndef __SPINLOCK_H__
#define __SPINLOCK_H__

#include "preempt.h"
typedef struct
{
	// __volatile__修饰的作用是每次访问变量时候必须访问内存 
	__volatile__ unsigned long lock;		//1:unlock,0:lock
}spinlock_T;

inline void spin_init(spinlock_T * lock)
{
	lock->lock = 1;
}

// 自旋锁的背景是:
// 多核并行场景。
// 多个核访问同一个共享数据区时,需要互斥。
// 比如每个核同时进行打印。
// 每个核各自打印一行,
// 多个核如果同时打印,打印会混乱。互斥保护下,可保证各自打印的完整。
// 比如每个核,同时对一个变量进行自增1(可能只需一个汇编指令,但是由于流水线技术,这个汇编指令会被拆分为多个独立执行单元)。
// 自增可能拆分为3个汇编指令:取内存到寄存器,寄存器数值+1,写回内存。
// 没有互斥保护下,两个核并行操作,结果可能是+1,也可能是+2
// 等等。

// 自旋锁依赖的是:
// 目的操作数指向内存时,汇编指令允许加前缀Lock修饰。
// 修饰后,这个汇编指令执行期间,内存总线会被锁定。
// 这意味着,这个汇编指令执行期间,其他处理器无法访问内存。
inline void spin_lock(spinlock_T * lock)
{
	preempt_disable();
	__asm__	__volatile__	(	"1:	\n\t"
					"lock	decq	%0	\n\t"
					"jns	3f	\n\t"
					"2:	\n\t"
					"pause	\n\t"
					"cmpq	$0,	%0	\n\t"
					"jle	2b	\n\t"
					"jmp	1b	\n\t"
					"3:	\n\t"
					:"=m"(lock->lock)
					:
					:"memory"
				);
}

inline void spin_unlock(spinlock_T * lock)
{
	__asm__	__volatile__	(	"movq	$1,	%0	\n\t"
					:"=m"(lock->lock)
					:
					:"memory"
				);
	preempt_enable();
}

inline long spin_trylock(spinlock_T * lock)
{
	unsigned long tmp_value = 0;
	preempt_disable();
	// xchgq自身是原子的。相当于加了Lock修饰。
	__asm__	__volatile__	(	"xchgq	%0,	%1	\n\t"
				:"=q"(tmp_value),"=m"(lock->lock)
				:"0"(0)
				:"memory"
			);
	if(!tmp_value)
		preempt_enable();
	return tmp_value;
}

#endif

2.原子变量

2.1.论述

        有了自旋锁的基础,原子变量很好理解。

        就是对变量的操作是原子的。

        我们正常将一个内存变量执行加1。处理器执行时,可能被分解为:

        从内存读取数值到寄存器A

        对寄存器A执行加1

        将寄存器A内容写回内存

        如果两个逻辑处理器单元,同时执行内存变量加1。则最后写回内存的可能是+1也可能是+2。

        原子变量,执行上述操作时,就是:

        锁定内存

        从内存读取数值到寄存器A

        对寄存器A执行加1

        将寄存器A内容写回内存

        解除内存锁定

        从而杜绝上述问题。

2.2.实践

#ifndef __ATOMIC_H__
#define __ATOMIC_H__

typedef struct 
{
	__volatile__ long value;
} atomic_T;

// 读取也只一个执行单元。
// 不加lock修饰也可以。
#define atomic_read(atomic)	((atomic)->value)

// 因为此变量的其他操作都是锁定的。
// 所以,这里设置值本身就一个执行单元。不加lock修饰也可以。
#define atomic_set(atomic,val)	(((atomic)->value) = (val))
// 原子变量--增加值
inline void atomic_add(atomic_T * atomic,long value)
{
	__asm__ __volatile__	(	"lock	addq	%1,	%0	\n\t"
					:"=m"(atomic->value)
					:"r"(value)
					:"memory"
				);
}

// 原子变量--减少值
inline void atomic_sub(atomic_T *atomic,long value)
{
	__asm__ __volatile__	(	"lock	subq	%1,	%0	\n\t"
					:"=m"(atomic->value)
					:"r"(value)
					:"memory"
				);
}

// 原子自增
inline void atomic_inc(atomic_T *atomic)
{
	__asm__ __volatile__	(	"lock	incq	%0	\n\t"
					:"=m"(atomic->value)
					:"m"(atomic->value)
					:"memory"
				);
}

// 原子自减
inline void atomic_dec(atomic_T *atomic)
{
	__asm__ __volatile__	(	"lock	decq	%0	\n\t"
					:"=m"(atomic->value)
					:"m"(atomic->value)
					:"memory"
				);
}

// 原子or--比特位的或
inline void atomic_set_mask(atomic_T *atomic,long mask)
{
	__asm__ __volatile__	(	"lock	orq	%1,	%0	\n\t"
					:"=m"(atomic->value)
					:"r"(mask)
					:"memory"
				);
}

// 原子and--比特位的与
inline void atomic_clear_mask(atomic_T *atomic,long mask)
{
	__asm__ __volatile__	(	"lock	andq	%1,	%0	\n\t"
					:"=m"(atomic->value)
					:"r"(~(mask))
					:"memory"
				);
}

#endif

3.信号量

3.1.论述

        信号量用于描述一个资源有若干份。

        生产者执行资源增加。消费者执行资源消费。

        消费者消费时,如果有资源可供消费,更新资源后继续执行。如果没有,则需要阻塞自己,放弃逻辑处理器使用权,等待后续有资源时,被生产者唤醒(重新加入可调度队列,等待调度)。

        生产者生产后,如果没有人在阻塞等待,只需更新资源可供数量,继续执行。如果有人在阻塞等待,则需要找到一个等待着,唤醒它(重新加入可调度队列)。

3.2.实践

#ifndef __SEMAPHORE_H__
#define __SEMAPHORE_H__

#include "atomic.h"
#include "lib.h"
#include "task.h"
#include "schedule.h"

typedef struct
{
	// 双向链表
	struct List wait_list;
	// 任务控制对象
	struct task_struct *tsk;
} wait_queue_T;

// wait_queue_T初始化,关联到一个任务控制对象
void wait_queue_init(wait_queue_T * wait_queue,struct task_struct *tsk)
{
	list_init(&wait_queue->wait_list);
	wait_queue->tsk = tsk;
}

// wait_queue_T&atomic_T构成信号量
typedef struct 
{
	atomic_T counter;
	wait_queue_T wait;//哨兵节点
} semaphore_T;

// 信号量
// 适合场景:
// 房间10个位置。
// 有人要进入房间,执行semaphore_down
// 有人离开房间,执行semaphore_up
// semaphore_down,semaphore_up需要是原子的。
void semaphore_init(semaphore_T * semaphore,unsigned long count)
{
	// 原子设置值
	atomic_set(&semaphore->counter,count);
	// 初始化
	wait_queue_init(&semaphore->wait,NULL);
}

void __up(semaphore_T * semaphore)
{
	// 从链式结构找到首个wait_queue_T
	wait_queue_T * wait = container_of(list_next(&semaphore->wait.wait_list),wait_queue_T,wait_list);
	// 将其从链式结构移除
	list_del(&wait->wait_list);
	// 设置为运行
	wait->tsk->state = TASK_RUNNING;
	// 加入调度队列。等待调度。
	insert_task_queue(wait->tsk);
}

// 对外接口--资源增加
void semaphore_up(semaphore_T * semaphore)
{
	if(list_is_empty(&semaphore->wait.wait_list))// 目前没人再等待
		atomic_inc(&semaphore->counter);// 这个计数,可以认为是可用资源数
	else
		__up(semaphore);// 因为当前有资源可用。所以需要找到一个等待者。唤醒它。
}

void __down(semaphore_T * semaphore)
{
	wait_queue_T wait;
	wait_queue_init(&wait,current);
	current->state = TASK_UNINTERRUPTIBLE;
	list_add_to_before(&semaphore->wait.wait_list,&wait.wait_list);// 执行尾部放入
	schedule();// 因为当前进程陷入等待。所以,需要触发调度。重新选择进程执行。
}

// 对外接口--资源减少
void semaphore_down(semaphore_T * semaphore)
{
	if(atomic_read(&semaphore->counter) > 0)// 因为有资源可用
		atomic_dec(&semaphore->counter);// 更新剩余资源数
	else // 没有资源可用 
		__down(semaphore);// 需要放入等待队列
}

#endif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值