signal相关数据结构&代码结构优化 (#84)

* 解决由于spinlock.h中包含preempt_enable()带来的循环include问题

* new: 初步实现signal的数据结构
This commit is contained in:
login
2022-11-16 15:18:03 +08:00
committed by GitHub
parent fb6c29d01d
commit cffd7144fb
33 changed files with 549 additions and 281 deletions

View File

@ -1,5 +1,5 @@
#include <common/spinlock.h>
#include <common/wait_queue_head.h>
#include <common/wait_queue.h>
#include <process/process.h>
#include <time/sleep.h>
#include <time/timer.h>

View File

@ -9,8 +9,8 @@
*
*/
#pragma once
#include <asm/irqflags.h>
#include <common/glib.h>
#include <process/preempt.h>
#include <debug/bug.h>
/**
@ -22,6 +22,14 @@ typedef struct
int8_t lock; // 1:unlocked 0:locked
} spinlock_t;
extern void __arch_spin_lock(spinlock_t *lock);
extern void __arch_spin_unlock(spinlock_t *lock);
extern void __arch_spin_lock_no_preempt(spinlock_t *lock);
extern void __arch_spin_unlock_no_preempt(spinlock_t *lock);
extern long __arch_spin_trylock(spinlock_t *lock);
/**
* @brief 自旋锁加锁
*
@ -29,17 +37,7 @@ typedef struct
*/
void spin_lock(spinlock_t *lock)
{
__asm__ __volatile__("1: \n\t"
"lock decb %0 \n\t" // 尝试-1
"jns 3f \n\t" // 加锁成功跳转到步骤3
"2: \n\t" // 加锁失败,稍后再试
"pause \n\t"
"cmpb $0, %0 \n\t"
"jle 2b \n\t" // 若锁被占用,则继续重试
"jmp 1b \n\t" // 尝试加锁
"3:"
: "=m"(lock->lock)::"memory");
preempt_disable();
__arch_spin_lock(lock);
}
/**
@ -49,9 +47,7 @@ void spin_lock(spinlock_t *lock)
*/
void spin_unlock(spinlock_t *lock)
{
preempt_enable();
__asm__ __volatile__("movb $1, %0 \n\t"
: "=m"(lock->lock)::"memory");
__arch_spin_unlock(lock);
}
/**
@ -73,17 +69,9 @@ void spin_init(spinlock_t *lock)
*/
void spin_lock_no_preempt(spinlock_t *lock)
{
__asm__ __volatile__("1: \n\t"
"lock decb %0 \n\t" // 尝试-1
"jns 3f \n\t" // 加锁成功跳转到步骤3
"2: \n\t" // 加锁失败,稍后再试
"pause \n\t"
"cmpb $0, %0 \n\t"
"jle 2b \n\t" // 若锁被占用,则继续重试
"jmp 1b \n\t" // 尝试加锁
"3:"
: "=m"(lock->lock)::"memory");
__arch_spin_lock_no_preempt(lock);
}
/**
* @brief 自旋锁解锁(不改变自旋锁持有计数)
*
@ -91,8 +79,7 @@ void spin_lock_no_preempt(spinlock_t *lock)
*/
void spin_unlock_no_preempt(spinlock_t *lock)
{
__asm__ __volatile__("movb $1, %0 \n\t"
: "=m"(lock->lock)::"memory");
__arch_spin_unlock_no_preempt(lock);
}
/**
@ -103,74 +90,56 @@ void spin_unlock_no_preempt(spinlock_t *lock)
*/
long spin_trylock(spinlock_t *lock)
{
uint64_t tmp_val = 0;
preempt_disable();
// 交换tmp_val和lock的值若tmp_val==1则证明加锁成功
asm volatile("lock xchg %%bx, %1 \n\t" // 确保只有1个进程能得到锁
: "=q"(tmp_val), "=m"(lock->lock)
: "b"(0)
: "memory");
if (!tmp_val)
preempt_enable();
return tmp_val;
return __arch_spin_trylock(lock);
}
// 保存当前rflags的值到变量x内并关闭中断
#define local_irq_save(x) __asm__ __volatile__("pushfq ; popq %0 ; cli" \
: "=g"(x)::"memory")
// 恢复先前保存的rflags的值x
#define local_irq_restore(x) __asm__ __volatile__("pushq %0 ; popfq" ::"g"(x) \
: "memory")
#define local_irq_disable() cli();
#define local_irq_enable() sti();
/**
* @brief 保存中断状态,关闭中断,并自旋锁加锁
*
*/
#define spin_lock_irqsave(lock, flags) \
do \
{ \
local_irq_save(flags); \
spin_lock(lock); \
#define spin_lock_irqsave(lock, flags) \
do \
{ \
local_irq_save(flags); \
spin_lock(lock); \
} while (0)
/**
* @brief 恢复rflags以及中断状态并解锁自旋锁
*
*/
#define spin_unlock_irqrestore(lock, flags) \
do \
{ \
spin_unlock(lock); \
local_irq_restore(flags); \
#define spin_unlock_irqrestore(lock, flags) \
do \
{ \
spin_unlock(lock); \
local_irq_restore(flags); \
} while (0)
/**
* @brief 关闭中断并加锁
*
*/
#define spin_lock_irq(lock) \
do \
{ \
local_irq_disable(); \
spin_lock(lock); \
#define spin_lock_irq(lock) \
do \
{ \
local_irq_disable(); \
spin_lock(lock); \
} while (0)
/**
* @brief 解锁并开启中断
*
*/
#define spin_unlock_irq(lock) \
do \
{ \
spin_unlock(lock); \
local_irq_enable(); \
#define spin_unlock_irq(lock) \
do \
{ \
spin_unlock(lock); \
local_irq_enable(); \
} while (0)
/**
* @brief 判断自旋锁是否已经加锁
*
*
* @param lock 待判断的自旋锁
* @return true 已经加锁
* @return false 尚未加锁

View File

@ -13,7 +13,7 @@ typedef uint32_t gid_t;
typedef long long ssize_t;
typedef int __pid_t;
#define pid_t uint64_t
#define pid_t int64_t
typedef __SIZE_TYPE__ size_t;
typedef char *caddr_t;

View File

@ -1,5 +1,9 @@
#pragma once
#include <common/glib.h>
#include <common/spinlock.h>
struct process_control_block;
// todo: 按照linux里面的样子修正等待队列。也就是修正好wait_queue_node和wait_queue_head的意思。
/**
* @brief 信号量的等待队列
@ -31,8 +35,7 @@ void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head);
*
* @param wait_queue_head 队列头指针
*/
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head,
void *lock);
void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head, void *lock);
/**
* @brief 在等待队列上进行等待(允许中断)
*
@ -46,4 +49,70 @@ void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head);
* @param wait_queue_head 队列头
* @param state 要唤醒的进程的状态
*/
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
typedef struct
{
struct List wait_list;
spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
} wait_queue_head_t;
#define DECLARE_WAIT_ON_STACK(name, pcb) \
wait_queue_node_t name = {0}; \
wait_queue_init(&(name), pcb);
#define DECLARE_WAIT_ON_STACK_SELF(name) \
wait_queue_node_t name = {0}; \
wait_queue_init(&(name), current_pcb);
#define DECLARE_WAIT_ALLOC(name, pcb) \
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
wait_queue_init(&(name), pcb);
#define DECLARE_WAIT_ALLOC_SELF(name) \
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
wait_queue_init(&(name), current_pcb);
#define DECLARE_WAIT_QUEUE_HEAD(name) \
struct wait_queue_head_t name = {0}; \
wait_queue_head_init(&name);
/**
* @brief 初始化wait_queue队列头
*
* @param wait_queue
*/
void wait_queue_head_init(wait_queue_head_t *wait_queue);
/**
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param q 队列头指针
* @param wait wait节点
*/
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
/**
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param q 队列头指针
* @param wait wait节点
* @param lock
*/
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
/**
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param wait_queue_head 队列头指针
* @param wait wait节点
*/
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
/**
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
*
* @param wait_queue_head_t q: 队列头
* @param state 要唤醒的进程的状态
*/
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);

View File

@ -1,68 +0,0 @@
#include <common/spinlock.h>
#include <common/wait_queue.h>
typedef struct
{
struct List wait_list;
spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
} wait_queue_head_t;
#define DECLARE_WAIT_ON_STACK(name, pcb) \
wait_queue_node_t name = {0}; \
wait_queue_init(&(name), pcb);
#define DECLARE_WAIT_ON_STACK_SELF(name) \
wait_queue_node_t name = {0}; \
wait_queue_init(&(name), current_pcb);
#define DECLARE_WAIT_ALLOC(name, pcb) \
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
wait_queue_init(&(name), pcb);
#define DECLARE_WAIT_ALLOC_SELF(name) \
wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
wait_queue_init(&(name), current_pcb);
#define DECLARE_WAIT_QUEUE_HEAD(name) \
struct wait_queue_head_t name = {0}; \
wait_queue_head_init(&name);
/**
* @brief 初始化wait_queue队列头
*
* @param wait_queue
*/
void wait_queue_head_init(wait_queue_head_t *wait_queue);
/**
* @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param q 队列头指针
* @param wait wait节点
*/
void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
/**
* @brief 在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param q 队列头指针
* @param wait wait节点
* @param lock
*/
void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
/**
* @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
*
* @param wait_queue_head 队列头指针
* @param wait wait节点
*/
void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
/**
* @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
*
* @param wait_queue_head_t q: 队列头
* @param state 要唤醒的进程的状态
*/
void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);