mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
将进程同步原语移动到common文件夹下
This commit is contained in:
@ -3,7 +3,7 @@ CFLAGS += -I .
|
||||
|
||||
kernel_common_subdirs:=libELF math
|
||||
|
||||
all: glib.o printk.o cpu.o bitree.o kfifo.o
|
||||
all: glib.o printk.o cpu.o bitree.o kfifo.o wait_queue.o
|
||||
@list='$(kernel_common_subdirs)'; for subdir in $$list; do \
|
||||
echo "make all in $$subdir";\
|
||||
cd $$subdir;\
|
||||
@ -25,3 +25,6 @@ bitree.o: bitree.c
|
||||
|
||||
kfifo.o: kfifo.c
|
||||
gcc $(CFLAGS) -c kfifo.c -o kfifo.o
|
||||
|
||||
wait_queue.o: wait_queue.c
|
||||
gcc $(CFLAGS) -c wait_queue.c -o wait_queue.o
|
||||
|
99
kernel/common/atomic.h
Normal file
99
kernel/common/atomic.h
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file atomic.h
|
||||
* @author fslongjin (longjin@RinGoTek.cn)
|
||||
* @brief 原子变量
|
||||
* @version 0.1
|
||||
* @date 2022-04-12
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define atomic_read(atomic) ((atomic)->value) // 读取原子变量
|
||||
#define atomic_set(atomic,val) (((atomic)->value) = (val)) // 设置原子变量的初始值
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile long value;
|
||||
} atomic_t;
|
||||
|
||||
/**
|
||||
* @brief 原子变量增加值
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
* @param val 要增加的值
|
||||
*/
|
||||
inline void atomic_add(atomic_t *ato, long val)
|
||||
{
|
||||
asm volatile("lock addq %1, %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "m"(val)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子变量减少值
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
* @param val 要减少的值
|
||||
*/
|
||||
inline void atomic_sub(atomic_t *ato, long val)
|
||||
{
|
||||
asm volatile("lock subq %1, %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "m"(val)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子变量自增
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
*/
|
||||
void atomic_inc(atomic_t *ato)
|
||||
{
|
||||
asm volatile("lock incq %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "m"(ato->value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 原子变量自减
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
*/
|
||||
void atomic_dec(atomic_t *ato)
|
||||
{
|
||||
asm volatile("lock decq %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "m"(ato->value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置原子变量的mask
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
*/
|
||||
inline void atomic_set_mask(atomic_t *ato, long mask)
|
||||
{
|
||||
__asm__ __volatile__("lock orq %1, %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "r"(mask)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除原子变量的mask
|
||||
*
|
||||
* @param ato 原子变量对象
|
||||
*/
|
||||
inline void atomic_clear_mask(atomic_t *ato, long mask)
|
||||
{
|
||||
__asm__ __volatile__("lock andq %1, %0 \n\t"
|
||||
: "=m"(ato->value)
|
||||
: "r"(mask)
|
||||
: "memory");
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
#include "kprint.h"
|
||||
#include <driver/multiboot2/multiboot2.h>
|
||||
#include <mm/mm.h>
|
||||
#include <process/spinlock.h>
|
||||
#include <common/spinlock.h>
|
||||
|
||||
#include <driver/uart/uart.h>
|
||||
#include <driver/video/video.h>
|
||||
|
83
kernel/common/semaphore.h
Normal file
83
kernel/common/semaphore.h
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file semaphore.h
|
||||
* @author fslngjin (lonjin@RinGoTek.cn)
|
||||
* @brief 信号量
|
||||
* @version 0.1
|
||||
* @date 2022-04-12
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <common/atomic.h>
|
||||
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
#include "wait_queue.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief 信号量的结构体
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
atomic_t counter;
|
||||
wait_queue_node_t wait_queue;
|
||||
} semaphore_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化信号量
|
||||
*
|
||||
* @param sema 信号量对象
|
||||
* @param count 信号量的初始值
|
||||
*/
|
||||
void semaphore_init(semaphore_t *sema, ul count)
|
||||
{
|
||||
atomic_set(&sema->counter, count);
|
||||
wait_queue_init(&sema->wait_queue, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 信号量down
|
||||
*
|
||||
* @param sema
|
||||
*/
|
||||
void semaphore_down(semaphore_t *sema)
|
||||
{
|
||||
if (atomic_read(&sema->counter) > 0) // 信号量大于0,资源充足
|
||||
atomic_dec(&sema->counter);
|
||||
else // 资源不足,进程休眠
|
||||
{
|
||||
// 将当前进程加入信号量的等待队列
|
||||
wait_queue_node_t wait;
|
||||
wait_queue_init(&wait, current_pcb);
|
||||
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
|
||||
list_append(&sema->wait_queue.wait_list, &wait.wait_list);
|
||||
|
||||
// 执行调度
|
||||
sched_cfs();
|
||||
}
|
||||
}
|
||||
|
||||
void semaphore_up(semaphore_t *sema)
|
||||
{
|
||||
if (list_empty(&sema->wait_queue.wait_list)) // 没有进程在等待资源
|
||||
{
|
||||
atomic_inc(&sema->counter);
|
||||
}
|
||||
else // 有进程在等待资源,唤醒进程
|
||||
{
|
||||
|
||||
wait_queue_node_t *wq = container_of(list_next(&sema->wait_queue.wait_list), wait_queue_node_t, wait_list);
|
||||
list_del(&wq->wait_list);
|
||||
|
||||
wq->pcb->state = PROC_RUNNING;
|
||||
sched_cfs_enqueue(wq->pcb);
|
||||
// 当前进程缺少需要的资源,立即标为需要被调度
|
||||
current_pcb->flags |= PF_NEED_SCHED;
|
||||
}
|
||||
}
|
168
kernel/common/spinlock.h
Normal file
168
kernel/common/spinlock.h
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @file spinlock.h
|
||||
* @author fslongjin (longjin@RinGoTek.cn)
|
||||
* @brief 自旋锁
|
||||
* @version 0.1
|
||||
* @date 2022-04-07
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
#include <process/preempt.h>
|
||||
|
||||
/**
|
||||
* @brief 定义自旋锁结构体
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__volatile__ char lock; // 1:unlocked 0:locked
|
||||
} spinlock_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化自旋锁
|
||||
*
|
||||
* @param lock
|
||||
*/
|
||||
void spin_init(spinlock_t *lock)
|
||||
{
|
||||
lock->lock = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 自旋锁加锁
|
||||
*
|
||||
* @param lock
|
||||
*/
|
||||
void spin_lock(spinlock_t *lock)
|
||||
{
|
||||
__asm__ __volatile__("1: \n\t"
|
||||
"lock decq %0 \n\t" // 尝试-1
|
||||
"jns 3f \n\t" // 加锁成功,跳转到步骤3
|
||||
"2: \n\t" // 加锁失败,稍后再试
|
||||
"pause \n\t"
|
||||
"cmpq $0, %0 \n\t"
|
||||
"jle 2b \n\t" // 若锁被占用,则继续重试
|
||||
"jmp 1b \n\t" // 尝试加锁
|
||||
"3:"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
preempt_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 自旋锁解锁
|
||||
*
|
||||
* @param lock
|
||||
*/
|
||||
void spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
preempt_enable();
|
||||
__asm__ __volatile__("movq $1, %0 \n\t"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 自旋锁加锁(不改变自旋锁持有计数)
|
||||
*
|
||||
* @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误
|
||||
*/
|
||||
void spin_lock_no_preempt(spinlock_t *lock)
|
||||
{
|
||||
__asm__ __volatile__("1: \n\t"
|
||||
"lock decq %0 \n\t" // 尝试-1
|
||||
"jns 3f \n\t" // 加锁成功,跳转到步骤3
|
||||
"2: \n\t" // 加锁失败,稍后再试
|
||||
"pause \n\t"
|
||||
"cmpq $0, %0 \n\t"
|
||||
"jle 2b \n\t" // 若锁被占用,则继续重试
|
||||
"jmp 1b \n\t" // 尝试加锁
|
||||
"3:"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
}
|
||||
/**
|
||||
* @brief 自旋锁解锁(不改变自旋锁持有计数)
|
||||
*
|
||||
* @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误
|
||||
*/
|
||||
void spin_unlock_no_preempt(spinlock_t * lock)
|
||||
{
|
||||
__asm__ __volatile__("movq $1, %0 \n\t"
|
||||
: "=m"(lock->lock)::"memory");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 尝试加锁
|
||||
*
|
||||
* @param lock
|
||||
* @return long 锁变量的值(1为成功加锁,0为加锁失败)
|
||||
*/
|
||||
long spin_trylock(spinlock_t *lock)
|
||||
{
|
||||
uint64_t tmp_val = 0;
|
||||
preempt_disable();
|
||||
// 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功
|
||||
asm volatile("lock xchgq %0, %1 \n\t" // 确保只有1个进程能得到锁
|
||||
: "=q"(tmp_val), "=m"(lock->lock)
|
||||
: "0"(0)
|
||||
: "memory");
|
||||
if (!tmp_val)
|
||||
preempt_enable();
|
||||
return tmp_val;
|
||||
}
|
||||
|
||||
// 保存当前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); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 恢复rflags以及中断状态并解锁自旋锁
|
||||
*
|
||||
*/
|
||||
#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); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 解锁并开启中断
|
||||
*
|
||||
*/
|
||||
#define spin_unlock_irq(lock) \
|
||||
do \
|
||||
{ \
|
||||
spin_unlock(lock); \
|
||||
local_irq_enable(); \
|
||||
} while (0)
|
67
kernel/common/wait_queue.c
Normal file
67
kernel/common/wait_queue.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "wait_queue.h"
|
||||
#include <sched/sched.h>
|
||||
#include <process/process.h>
|
||||
#include <mm/slab.h>
|
||||
|
||||
/**
|
||||
* @brief 初始化等待队列
|
||||
*
|
||||
* @param wait_queue 等待队列
|
||||
* @param pcb pcb
|
||||
*/
|
||||
void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb)
|
||||
{
|
||||
list_init(&wait_queue->wait_list);
|
||||
wait_queue->pcb = pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head)
|
||||
{
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kmalloc(sizeof(wait_queue_node_t), 0);
|
||||
wait_queue_init(wait, current_pcb);
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
list_append(&wait_queue_head->wait_list, &wait->wait_list);
|
||||
|
||||
sched_cfs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断)
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head)
|
||||
{
|
||||
wait_queue_node_t *wait = (wait_queue_node_t *)kmalloc(sizeof(wait_queue_node_t), 0);
|
||||
wait_queue_init(wait, current_pcb);
|
||||
current_pcb->state = PROC_INTERRUPTIBLE;
|
||||
list_append(&wait_queue_head->wait_list, &wait->wait_list);
|
||||
|
||||
sched_cfs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程
|
||||
*
|
||||
* @param wait_queue_head
|
||||
* @param state
|
||||
*/
|
||||
void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state)
|
||||
{
|
||||
if (list_empty(&wait_queue_head->wait_list))
|
||||
return;
|
||||
wait_queue_node_t *wait = container_of(list_next(&wait_queue_head->wait_list), wait_queue_node_t, wait_list);
|
||||
|
||||
// 符合唤醒条件
|
||||
if (wait->pcb->state & state)
|
||||
{
|
||||
list_del(&wait->wait_list);
|
||||
process_wakeup(wait->pcb);
|
||||
kfree(wait);
|
||||
}
|
||||
}
|
42
kernel/common/wait_queue.h
Normal file
42
kernel/common/wait_queue.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <common/glib.h>
|
||||
// #include <process/process.h>
|
||||
/**
|
||||
* @brief 信号量的等待队列
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
struct List wait_list;
|
||||
struct process_control_block *pcb;
|
||||
} wait_queue_node_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化等待队列
|
||||
*
|
||||
* @param wait_queue 等待队列
|
||||
* @param pcb pcb
|
||||
*/
|
||||
void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on(wait_queue_node_t * wait_queue_head);
|
||||
|
||||
/**
|
||||
* @brief 在等待队列上进行等待(允许中断)
|
||||
*
|
||||
* @param wait_queue_head 队列头指针
|
||||
*/
|
||||
void wait_queue_sleep_on_interriptible(wait_queue_node_t * wait_queue_head);
|
||||
|
||||
/**
|
||||
* @brief 唤醒在等待队列的头部的进程
|
||||
*
|
||||
* @param wait_queue_head 队列头
|
||||
* @param state 要唤醒的进程的状态
|
||||
*/
|
||||
void wait_queue_wakeup(wait_queue_node_t * wait_queue_head, int64_t state);
|
Reference in New Issue
Block a user