Mach原语
26 February 2021
Mach原语
原语:是由若干条机器指令构成的完成某种特定功能的一段程序。具有不可分割性,执行也必须是连续的,且在执行过程中不允许被中断。
同步原语
Mach IPC架构中的两个重要组件,一个是消息传递机制;另一个是同步机制(synchronization)。而同步机制在根本上是由同步原语来实现的。
自旋锁(hw_lock_t)
- 自旋锁是让没有获取到锁的线程一直循环等待判断该资源是否已经释放锁,它不会把线程阻塞起来。
- 互斥体与信息量都是阻塞等待的对象。阻塞等待是指如果锁对象被其他线程持有,那么请求访问的线程就被加入到等待队列中,因而被阻塞。阻塞一处线程意味着放弃线程的时间片,把处理器让给调度器认为下一个要执行的线程。当锁可用时,调度器会得到通知,然而根据自己的判断将线程从等待队列中取出并重新调度。然而这种方式可能会严重的影响性能,由于在很多情况下锁对象只需要持有短短几个周期时间,而因此造成的两次或更多次的上下文切换带来的开销则要大好几个数量级。在这种情况下,如果线程不放弃处理器,而是继续 重复地尝试访问锁对象可能是更明智的选择,这种方式就称为忙等(busy-wait)。如果当前锁的持有者确实在几个周期之后就放弃锁了,那么这样就可以节省到少两次上下文切换。
- 自旋锁是计算机科学用于多执行者同步的一种锁,执行者反覆检查锁变量是否可用。由于执行者在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,执行者会一直保持该锁,直至显式释放自旋锁。自旋锁避免了进程上下文的调度开销,因此对于执行者只会阻塞很短时间的场合是有效的。
互斥体(lck_mtx_t)
- 互斥体可以看成是二值信号量的特殊情况。是最常用的锁对象。它的实现是把没有获取到锁的线程自己阻塞起来,等待重新调度请求。
- 互斥体必须属于一个锁组。锁组对象(lck_grp_t)就是一个链表中的一个元素,带有一个给你写的名字,以及最多3种锁的类型:自旋锁、互斥体和读写锁。
读写锁(lck_rw_t)
- 读写锁是更”智能”的互斥体,能够区分读访问与写访问。
信号量(semaphore)
- 信息量是泛化的互斥体,其取值为某个正数,即允许并发持有信号量的持有者的个数。
- 信号量可以在用户态使用,而互斥体只能在内核态使用。
锁集(lock_set_t)
- 锁集就是锁(实际上是互斥体)的数组,通过给定的锁ID可以访问锁。
- 锁可以传递给其他线程。交出一个锁会阻塞交出锁的线程,并唤醒接受锁的线程。
- Task(任务,Mac上管理进程叫任务)可以在用户态使用锁集。
机器原语
Mach通过一些所谓的”机器原语”对运行的机器的逻辑抽象,机器原理处理的对象包括主机(物理机器的抽象)、时钟(维护时间)、处理器(CPU)、处理器集(CPU的逻辑分组)。
主机
- 提供机器信息
- 提供子系统的访问
- 提供默认的异常处理
时钟
- Mach内核提供的一个简单的”时钟(clock)”对象抽象。这个对象用于计时和闹铃。
- 最重要的内部API: clock_deadline_for_periodic_event()
处理器
- 基本操作:关闭或启动CPU
- runq元素是指分发到这个处理器的线程的本地队列
处理器集抽象
- active_queue保存当前正在执行线程的处理器
- idle_queue用于保存当前空闲的处理器
- run_queue保存在这个集合中的处理器 执行的线程
- pset_self 用于对处理器集进行操作
- pset_name_self 用于获得处理器集的信息