// Provided by linker (see linker.ld)
extern u8_t __kernel_start;
extern u8_t __kernel_end;
+extern u8_t __ktext_start;
+extern u8_t __ktext_end;
+
extern u8_t __init_hhk_end;
extern u8_t _k_stack;
void
-_init_page(ptd_t* ptd)
+_init_page(x86_page_table* ptd)
{
- SET_PDE(ptd, 0, NEW_L1_ENTRY(PG_PREM_RW, ptd + PG_MAX_ENTRIES))
+ ptd->entry[0] = NEW_L1_ENTRY(PG_PREM_RW, (ptd_t*)ptd + PG_MAX_ENTRIES);
// 对低1MiB空间进行对等映射(Identity
// mapping),也包括了我们的VGA,方便内核操作。
+ x86_page_table* id_pt =
+ (x86_page_table*)GET_PG_ADDR(ptd->entry[PG_TABLE_IDENTITY]);
+
for (u32_t i = 0; i < 256; i++) {
- SET_PTE(ptd,
- PG_TABLE_IDENTITY,
- i,
- NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS)))
+ id_pt->entry[i] = NEW_L2_ENTRY(PG_PREM_RW, (i << PG_SIZE_BITS));
}
// 对等映射我们的hhk_init,这样一来,当分页与地址转换开启后,我们依然能够照常执行最终的
// jmp 指令来跳转至
// 内核的入口点
for (u32_t i = 0; i < HHK_PAGE_COUNT; i++) {
- SET_PTE(ptd,
- PG_TABLE_IDENTITY,
- 256 + i,
- NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS)))
+ id_pt->entry[256 + i] =
+ NEW_L2_ENTRY(PG_PREM_RW, 0x100000 + (i << PG_SIZE_BITS));
}
// --- 将内核重映射至高半区 ---
// 当然,就现在而言,我们的内核只占用不到50个页(每个页表包含1024个页)
// 这里分配了3个页表(12MiB),未雨绸缪。
for (u32_t i = 0; i < PG_TABLE_STACK - PG_TABLE_KERNEL; i++) {
- SET_PDE(ptd,
- kernel_pde_index + i,
- NEW_L1_ENTRY(PG_PREM_URW, PT_ADDR(ptd, PG_TABLE_KERNEL + i)))
+ ptd->entry[kernel_pde_index + i] =
+ NEW_L1_ENTRY(PG_PREM_RW, PT_ADDR(ptd, PG_TABLE_KERNEL + i));
}
// 首先,检查内核的大小是否可以fit进我们这几个表(12MiB)
// 计算内核.text段的物理地址
ptr_t kernel_pm = V2P(&__kernel_start);
+ ptr_t ktext_start = V2P(&__ktext_start);
+ ptr_t ktext_end = V2P(&ktext_end);
// 重映射内核至高半区地址(>=0xC0000000)
for (u32_t i = 0; i < kernel_pg_counts; i++) {
- // FIXME: 只是用作用户模式(R3)测试!
- // 在实际中,内核代码除了极少部分需要暴露给R3(如从信号返回),其余的应为R0。
+ ptr_t paddr = kernel_pm + (i << PG_SIZE_BITS);
+ u32_t flags = PG_PREM_RW;
-#warning "fixme: kernel pages should not be user-accessable"
+ if (paddr >= ktext_start && paddr <= ktext_end) {
+ flags = PG_PREM_R;
+ }
SET_PTE(ptd,
PG_TABLE_KERNEL,
kernel_pte_index + i,
- NEW_L2_ENTRY(PG_PREM_URW, kernel_pm + (i << PG_SIZE_BITS)))
+ NEW_L2_ENTRY(flags, paddr))
}
// 最后一个entry用于循环映射
- SET_PDE(ptd, PG_MAX_ENTRIES - 1, NEW_L1_ENTRY(T_SELF_REF_PERM, ptd));
+ ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd);
}
u32_t
}
void
-_hhk_init(ptd_t* ptd, u32_t kpg_size)
+_hhk_init(x86_page_table* ptd, u32_t kpg_size)
{
// 初始化 kpg 全为0
"r"(pc) \
: "eax", "memory");
+#define push_arg1(stack_ptr, arg) *((typeof((arg))*)(stack_ptr)--) = arg
+#define push_arg2(stack_ptr, arg1, arg2) \
+ { \
+ *((typeof((arg1))*)(stack_ptr)--) = arg1; \
+ *((typeof((arg2))*)(stack_ptr)--) = arg2; \
+ }
+#define push_arg3(stack_ptr, arg1, arg2, arg3) \
+ { \
+ *((typeof((arg1))*)(stack_ptr)--) = arg1; \
+ *((typeof((arg2))*)(stack_ptr)--) = arg2; \
+ *((typeof((arg3))*)(stack_ptr)--) = arg3; \
+ }
+#define push_arg4(stack_ptr, arg1, arg2, arg3, arg4) \
+ { \
+ *((typeof((arg1))*)(stack_ptr)--) = arg1; \
+ *((typeof((arg2))*)(stack_ptr)--) = arg2; \
+ *((typeof((arg3))*)(stack_ptr)--) = arg3; \
+ *((typeof((arg4))*)(stack_ptr)--) = arg4; \
+ }
+
#endif /* __LUNAIX_ABI_H */
// 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
#define KERNEL_PID -1
+/*
+ |C|Bk|De|Tn|Pu|Rn|
+ \----/
+ Dt
+
+ Group Dt: whether this process is terminated.
+
+ Rn: Running
+ Tn: Terminated
+ De: Destoryed
+ Pu: Paused
+ Bk: Blocked
+ C : Created
+*/
+
#define PS_READY 0
#define PS_RUNNING 1
#define PS_TERMNAT 2
#define PS_DESTROY 4
-#define PS_BLOCKED 8
-#define PS_CREATED 16
+#define PS_PAUSED 8
+#define PS_BLOCKED 16
+#define PS_CREATED 32
-#define PROC_TERMINATED(state) (state & 0x6)
+#define PS_GrBP (PS_PAUSED | PS_BLOCKED)
+#define PS_GrDT (PS_TERMNAT | PS_DESTROY)
+
+#define PROC_TERMINATED(state) ((state)&PS_GrDT)
+#define PROC_HANGED(state) ((state)&PS_BLOCKED)
+#define PROC_RUNNABLE(state) ((state)&PS_PAUSED)
#define PROC_FINPAUSE 1
char fxstate[512] __attribute__((aligned(16)));
};
+struct sigact
+{
+ struct sigact* prev;
+ sigset_t sa_mask;
+ void* sa_actor;
+ void* sa_handler;
+ pid_t sender;
+};
+
+struct sighail
+{
+ sigset_t sig_pending;
+ sigset_t sig_mask;
+ struct sigact* inprogress;
+ struct sigact signals[_SIG_NUM];
+};
+
struct proc_sig
{
- void* signal_handler;
int sig_num;
+ void* sigact;
+ void* sighand;
struct proc_sigstate prev_context;
} __attribute__((packed));
u8_t state;
int32_t exit_code;
int32_t k_status;
- sigset_t sig_pending;
- sigset_t sig_mask;
- sigset_t sig_inprogress;
int flags;
- void* sig_handler[_SIG_NUM];
+ struct sighail sigctx;
struct v_fdtable* fdtable;
struct v_dnode* cwd;
pid_t pgid;
__current->state = PS_BLOCKED;
}
+static inline void
+pause_current()
+{
+ __current->state = PS_PAUSED;
+}
+
+static inline void
+resume_current()
+{
+ __current->state = PS_RUNNING;
+}
+
/**
* @brief 分配并初始化一个进程控制块
*
struct proc_info*
get_process(pid_t pid);
+void
+proc_setsignal(struct proc_info* proc, int signum);
+
#endif /* __LUNAIX_PROCESS_H */
#define _SIGSTOP SIGSTOP
#define _SIGCONT SIGCONT
#define _SIGTERM SIGTERM
-
-#define __SIGNAL(num) (1 << (num))
-#define __SIGSET(bitmap, num) (bitmap = bitmap | __SIGNAL(num))
-#define __SIGTEST(bitmap, num) (bitmap & __SIGNAL(num))
-#define __SIGCLEAR(bitmap, num) ((bitmap) = (bitmap) & ~__SIGNAL(num))
-
-#define _SIGNAL_UNMASKABLE (__SIGNAL(_SIGKILL) | __SIGNAL(_SIGSTOP))
-
#define _SIG_BLOCK SIG_BLOCK
#define _SIG_UNBLOCK SIG_UNBLOCK
#define _SIG_SETMASK SIG_SETMASK
+#define sigset(num) (1 << (num))
+#define sigset_add(set, num) (set = set | sigset(num))
+#define sigset_test(set, num) (set & sigset(num))
+#define sigset_clear(set, num) ((set) = (set) & ~sigset(num))
+#define sigset_union(set, set2) ((set) = (set) | (set2))
+#define sigset_intersect(set, set2) ((set) = (set) & (set2))
+
int
signal_send(pid_t pid, int signum);
typedef unsigned int sigset_t;
typedef void (*sighandler_t)(int);
+struct sigaction
+{
+ sigset_t sa_mask;
+ void (*sa_handler)(int);
+ void (*sa_sigaction)(int, void*, void*);
+};
+
+struct siginfo
+{
+ // TODO
+};
+
#endif /* __LUNAIX_SIGNAL_DEFS_H */
#define __SYSCALL_sigreturn 11
#define __SYSCALL_sigprocmask 12
-#define __SYSCALL_signal 13
+#define __SYSCALL_sys_sigaction 13
#define __SYSCALL_pause 14
#define __SYSCALL_kill 15
#define __SYSCALL_alarm 16
.section .bss
.align 16
lo_tmp_stack:
- .skip 128
+ .skip 256
tmp_stack:
/*
movw %ax, %ds
movw %ax, %es
- # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息,
- # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备
movl __current, %eax
+ # FIXME: Save x87 context to user stack, rather than kernel's memory.
# 保存x87FPU的状态
movl 68(%eax), %ebx
fxsave (%ebx)
+ # 保存用户栈顶指针。因为我们允许同级中断的产生,所以需要该手段跟踪用户栈的地址。
movl 124(%esp), %ebx # 取出esp
movl %ebx, 60(%eax) # 存入__current->ustack_top
handle_signal:
# 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性!
# 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈!
- leal 8(%eax), %ebx # arg1 in %eax: addr of proc_sig structure in user stack
+ # arg1 in %eax: addr of proc_sig structure in user stack
+ leal 12(%eax), %ebx # %ebx = &proc_sig->prev_context
pushl $UDATA_SEG # proc_sig->prev_context.proc_regs.ss
pushl %eax # esp
+
movl 48(%ebx), %ebx
pushl 68(%ebx) # proc_sig->prev_context.proc_regs.execp->eflags
+
pushl $UCODE_SEG # cs
- pushl $sig_wrapper # eip for sig wrapper
+ pushl 4(%eax) # %eip = proc_sig->sigact
movw $UDATA_SEG, %cx # switch data seg to user mode
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
- iret
-
-.section .usrtext
- sig_wrapper: # in user mode
- movl %esp, %eax
- and $0xfffffff0, %esp
- subl $8, %esp
- pushl %eax # Addr to proc_sig structure
- pushl 4(%eax) # proc_sig->sig_num ---- 16 bytes aligned
-
- call *(%eax) # invoke signal handler
-
- # invoke the sigreturn syscall to exit the signal wrapper
- movl $__SYSCALL_sigreturn, %eax
- movl 4(%esp), %ebx
- int $LUNAIX_SYS_CALL
-
- ud2 # never reach!
\ No newline at end of file
+ iret
\ No newline at end of file
#include <klibc/string.h>
+static u32_t
+get_ptattr(struct mm_region* vmr)
+{
+ u32_t vmr_attr = vmr->attr;
+ u32_t ptattr = PG_PRESENT | PG_ALLOW_USER;
+
+ if ((vmr_attr & PROT_WRITE)) {
+ ptattr |= PG_WRITE;
+ }
+
+ return ptattr & 0xfff;
+}
+
static void
kprintf(const char* fmt, ...)
{
goto segv_term;
}
- if ((errcode & PG_ALLOW_USER)) {
- // invalid access
- goto segv_term;
- }
-
volatile x86_pte_t* pte = &PTE_MOUNTED(VMS_SELF, ptr >> 12);
if (PG_IS_PRESENT(*pte)) {
+ if (((errcode ^ mapping.flags) & PG_ALLOW_USER)) {
+ // invalid access
+ kprintf(KDEBUG "invalid user access. (%p->%p, attr:0x%x)\n",
+ mapping.va,
+ mapping.pa,
+ mapping.flags);
+ goto segv_term;
+ }
if ((hit_region->attr & COW_MASK) == COW_MASK) {
// normal page fault, do COW
cpu_invplg((ptr_t)pte);
goto oom;
}
- *pte = *pte | pa | PG_PRESENT | PG_ALLOW_USER;
+ *pte = *pte | pa | get_ptattr(hit_region);
memset((void*)PG_ALIGN(ptr), 0, PG_SIZE);
goto resolved;
}
}
cpu_invplg((ptr_t)pte);
- *pte = (*pte & 0xFFF) | pa | PG_PRESENT | PG_ALLOW_USER;
+ *pte = (*pte & 0xFFF) | pa | get_ptattr(hit_region);
memset((void*)ptr, 0, PG_SIZE);
param->execp->eip,
param->execp->err_code);
- __SIGSET(__current->sig_pending, _SIGSEGV);
+ sigset_add(__current->sigctx.sig_pending, _SIGSEGV);
schedule();
// should not reach
.long __lxsys_waitpid /* 10 */
.long __lxsys_sigreturn
.long __lxsys_sigprocmask
- .long __lxsys_signal
+ .long __lxsys_sys_sigaction
.long __lxsys_pause
.long __lxsys_kill /* 15 */
.long __lxsys_alarm
assert_msg(0, "Unexpected Return");
}
-extern u8_t __usrtext_start;
-extern u8_t __usrtext_end;
-
// 按照 Memory map 标识可用的物理页
void
setup_memory(multiboot_memory_map_t* map, size_t map_size)
size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS;
pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED);
- for (ptr_t i = (ptr_t)&__usrtext_start; i < (ptr_t)&__usrtext_end;
- i += PG_SIZE) {
- vmm_set_mapping(VMS_SELF, i, V2P(i), PG_PREM_UR, VMAP_NULL);
- }
-
// reserve higher half
for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) {
assert(vmm_set_mapping(VMS_SELF, i << 22, 0, 0, VMAP_NOMAP));
int
can_schedule(struct proc_info* proc)
{
- if (__SIGTEST(proc->sig_pending, _SIGCONT)) {
- __SIGCLEAR(proc->sig_pending, _SIGSTOP);
- } else if (__SIGTEST(proc->sig_pending, _SIGSTOP)) {
+ if (!proc) {
+ return 0;
+ }
+
+ struct sighail* sh = &proc->sigctx;
+
+ if ((proc->state & PS_PAUSED)) {
+ return !!(sh->sig_pending & ~1);
+ }
+
+ if (sigset_test(sh->sig_pending, _SIGCONT)) {
+ sigset_clear(sh->sig_pending, _SIGSTOP);
+ } else if (sigset_test(sh->sig_pending, _SIGSTOP)) {
// 如果进程受到SIGSTOP,则该进程不给予调度。
return 0;
}
- return 1;
+ return (proc->state == PS_READY);
}
void
if (atime && now >= atime) {
pos->sleep.alarm_time = 0;
- __SIGSET(pos->sig_pending, _SIGALRM);
+ proc_setsignal(pos, _SIGALRM);
}
if (!wtime && !atime) {
struct proc_info* next;
int prev_ptr = sched_ctx.procs_index;
int ptr = prev_ptr;
+ int found = 0;
if (!(__current->state & ~PS_RUNNING)) {
__current->state = PS_READY;
// round-robin scheduler
redo:
+
do {
ptr = (ptr + 1) % sched_ctx.ptable_len;
next = sched_ctx._procs[ptr];
- } while (!next || (next->state != PS_READY && ptr != prev_ptr));
- sched_ctx.procs_index = ptr;
-
- if (next->state != PS_READY) {
- // schedule the dummy process if we're out of choice
- next = &dummy_proc;
- goto done;
- }
+ if (!(found = can_schedule(next))) {
+ if (ptr == prev_ptr) {
+ next = &dummy_proc;
+ goto done;
+ }
+ }
+ } while (!found);
- if (!can_schedule(next)) {
- // 如果该进程不给予调度,则尝试重新选择
- goto redo;
- }
+ sched_ctx.procs_index = ptr;
done:
run(next);
goto repeat;
done:
- status_flags |= PEXITSIG * (proc->sig_inprogress != 0);
if (status) {
*status = proc->exit_code | status_flags;
}
__current->state = PS_TERMNAT;
__current->exit_code = exit_code;
- __SIGSET(__current->parent->sig_pending, _SIGCHLD);
+ proc_setsignal(__current->parent, _SIGCHLD);
}
struct proc_info*
extern struct scheduler sched_ctx; /* kernel/sched.c */
-static u32_t term_sigs =
- (1 << SIGSEGV) | (1 << SIGINT) | (1 << SIGKILL) | (1 << SIGTERM);
+#define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
+#define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
// Referenced in kernel/asm/x86/interrupt.S
void*
signal_dispatch()
{
- if (!__current->sig_pending) {
+ if (!__current->sigctx.sig_pending) {
// 没有待处理信号
return 0;
}
- int sig_selected =
- 31 - __builtin_clz(__current->sig_pending &
- ~(__current->sig_mask | __current->sig_inprogress));
+ struct sighail* psig = &__current->sigctx;
+ struct sigact* prev_working = psig->inprogress;
+ sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
- __SIGCLEAR(__current->sig_pending, sig_selected);
+ int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
+
+ sigset_clear(psig->sig_pending, sig_selected);
+
+ struct sigact* action = &psig->signals[sig_selected];
if (sig_selected == 0) {
// SIG0 is reserved
return 0;
}
- if (!__current->sig_handler[sig_selected]) {
- if ((term_sigs & (1 << sig_selected))) {
- terminate_proc(sig_selected);
+ if (!action->sa_actor) {
+ if (sigset_test(TERMSIG, sig_selected)) {
+ terminate_proc(sig_selected | PEXITSIG);
schedule();
// never return
}
return 0;
}
- ptr_t ustack = __current->ustack_top & ~0xf;
+ ptr_t ustack = __current->ustack_top;
if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
// 用户栈没有空间存放信号上下文
return 0;
}
- struct proc_sig* sig_ctx =
- (struct proc_sig*)(ustack - sizeof(struct proc_sig));
+ struct proc_sig* sigframe =
+ (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
/*
这是一个相当恶心的坑。
- 问题是出在原本的sig_ctx->prev_context = __current->intr_ctx的上面
+ 问题是出在原本的sigframe->prev_context = __current->intr_ctx的上面
这个语句会被gcc在编译时,用更加高效的 rep movsl 来代替。
由于我们采用按需分页,所以在很多情况下,用户栈实际被分配的空间不允许我们进行完整的
__temp_save.proc_regs = __current->intr_ctx;
memcpy(__temp_save.fxstate, __current->fxstate, 512);
- sig_ctx->prev_context = __temp_save;
+ sigframe->sig_num = sig_selected;
- sig_ctx->sig_num = sig_selected;
- sig_ctx->signal_handler = __current->sig_handler[sig_selected];
+ sigframe->sigact = action->sa_actor;
+ sigframe->sighand = action->sa_handler;
+ sigframe->prev_context = __temp_save;
- __SIGSET(__current->sig_inprogress, sig_selected);
+ action->prev = prev_working;
+ psig->inprogress = action;
- return sig_ctx;
+ return sigframe;
+}
+
+void
+proc_setsignal(struct proc_info* proc, int signum)
+{
+ sigset_add(proc->sigctx.sig_pending, signum);
+ proc->sigctx.signals[signum].sender = __current->pid;
}
int
return -1;
}
+ pid_t sender_pid = __current->pid;
struct proc_info* proc;
+
if (pid > 0) {
proc = get_process(pid);
goto send_single;
struct proc_info *pos, *n;
llist_for_each(pos, n, &proc->grp_member, grp_member)
{
- __SIGSET(pos->sig_pending, signum);
+ struct sighail* sh = &pos->sigctx;
+ sigset_add(sh->sig_pending, signum);
+ sh->signals[signum].sender = sender_pid;
}
send_single:
__current->k_status = EINVAL;
return -1;
}
- __SIGSET(proc->sig_pending, signum);
+
+ sigset_add(proc->sigctx.sig_pending, signum);
+ proc->sigctx.signals[signum].sender = sender_pid;
+
return 0;
}
{
memcpy(__current->fxstate, sig_ctx->prev_context.fxstate, 512);
__current->intr_ctx = sig_ctx->prev_context.proc_regs;
- __current->flags &= ~PROC_FINPAUSE;
- __SIGCLEAR(__current->sig_inprogress, sig_ctx->sig_num);
+
+ struct sigact* current = __current->sigctx.inprogress;
+ if (current) {
+ __current->sigctx.inprogress = current->prev;
+ current->prev = NULL;
+ } else {
+ __current->sigctx.inprogress = NULL;
+ }
+
schedule();
// never reach!
sigset_t,
*oldset)
{
- *oldset = __current->sig_mask;
+ struct sighail* sh = &__current->sigctx;
+ *oldset = sh->sig_mask;
+
if (how == _SIG_BLOCK) {
- __current->sig_mask |= *set;
+ sigset_union(sh->sig_mask, *set);
} else if (how == _SIG_UNBLOCK) {
- __current->sig_mask &= ~(*set);
+ sigset_intersect(sh->sig_mask, ~(*set));
} else if (how == _SIG_SETMASK) {
- __current->sig_mask = *set;
+ sh->sig_mask = *set;
} else {
return 0;
}
- __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
+
+ sigset_intersect(sh->sig_mask, ~UNMASKABLE);
return 1;
}
-__DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
+__DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
{
if (signum <= 0 || signum >= _SIG_NUM) {
return -1;
}
- if ((__SIGNAL(signum) & _SIGNAL_UNMASKABLE)) {
+ if (sigset_test(UNMASKABLE, signum)) {
return -1;
}
- __current->sig_handler[signum] = (void*)handler;
+ struct sigact* sa = &__current->sigctx.signals[signum];
+
+ sa->sa_actor = (void*)action->sa_sigaction;
+ sa->sa_handler = (void*)action->sa_handler;
+ sigset_union(sa->sa_mask, sigset(signum));
return 0;
}
-void
-__do_pause()
+__DEFINE_LXSYSCALL(int, pause)
{
- __current->flags |= PROC_FINPAUSE;
-
- while ((__current->flags & PROC_FINPAUSE)) {
- sched_yieldk();
- }
+ pause_current();
+ sched_yieldk();
__current->k_status = EINTR;
-}
-
-__DEFINE_LXSYSCALL(int, pause)
-{
- __do_pause();
return -1;
}
__DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
{
- *sigset = __current->sig_pending;
+ *sigset = __current->sigctx.sig_pending;
return 0;
}
__DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
{
- sigset_t tmp = __current->sig_mask;
- __current->sig_mask = (*mask) & ~_SIGNAL_UNMASKABLE;
- __do_pause();
- __current->sig_mask = tmp;
+ sigset_t tmp = __current->sigctx.sig_mask;
+ __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
+
+ pause_current();
+ sched_yieldk();
+
+ __current->sigctx.sig_mask = tmp;
return -1;
}
\ No newline at end of file
__read_pending_sig(struct twimap* map)
{
struct proc_info* proc = twimap_data(map, struct proc_info*);
- twimap_printf(map, "%bb", proc->sig_pending);
+ twimap_printf(map, "%bb", proc->sigctx.sig_pending);
}
void
__read_masked_sig(struct twimap* map)
{
struct proc_info* proc = twimap_data(map, struct proc_info*);
- twimap_printf(map, "%bb", proc->sig_mask);
+ twimap_printf(map, "%bb", proc->sigctx.sig_mask);
}
void
/* 好了,我们的内核…… */
.text BLOCK(4K) : AT ( ADDR(.text) - 0xC0000000 ) {
__kernel_start = .;
+ PROVIDE(__ktext_start = .);
+
kernel/*.o (.text)
hal/*.o (.text)
debug/*.o (.text)
libs/*.o (.text)
- }
- __usrtext_start = ALIGN(4K);
- .usrtext BLOCK(4K) : AT ( ADDR(.usrtext) - 0xC0000000 ) {
- * (.usrtext)
+ PROVIDE(__ktext_end = .);
}
- __usrtext_end = ALIGN(4K);
.data BLOCK(4K) : AT ( ADDR(.data) - 0xC0000000 ) {
kernel/*.o (.data)
#include "syscall.h"
#include <lunaix/signal_defs.h>
-
-__LXSYSCALL2(int, signal, int, signum, sighandler_t, handler);
+#include <lunaix/types.h>
__LXSYSCALL1(int, sigpending, sigset_t, *set);
__LXSYSCALL1(int, sigsuspend, const sigset_t, *mask);
*set,
sigset_t,
*oldset);
+
+__LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action);
+
+__LXSYSCALL2(int, kill, pid_t, pid, int, signum);
+
+extern void
+sigtrampoline();
+
+sighandler_t
+signal(int signum, sighandler_t handler)
+{
+ struct sigaction sa = { .sa_handler = (void*)handler,
+ .sa_mask = (sigset_t)-1,
+ .sa_sigaction = (void*)sigtrampoline };
+
+ sys_sigaction(signum, &sa);
+
+ return handler;
+}
+
+int
+raise(int signum)
+{
+ return kill(0, signum);
+}
+
+int
+sigaction(int signum, struct sigaction* action)
+{
+ return sys_sigaction(signum, action);
+}
+
+struct siguctx
+{
+ void* sigact;
+ void (*sa_handler)(int);
+ unsigned char saved_frame[0];
+};
+
+void
+sig_dohandling(int signum, void* siginfo, void* sigctx)
+{
+ struct siguctx* uctx = (struct siguctx*)sigctx;
+ uctx->sa_handler(signum);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/syscallid.h>
+
+.section .text
+ .global sigtrampoline
+ sigtrampoline:
+ movl %esp, %eax
+ andl $0xfffffff0, %esp
+ pushl %eax
+
+ leal 4(%eax), %eax
+ pushl %eax
+ pushl $0
+ pushl -4(%eax)
+ call sig_dohandling
+
+ addl $12, %esp
+
+ movl $__SYSCALL_sigreturn, %eax
+ popl %ebx
+ int $33
\ No newline at end of file
__LXSYSCALL(int, pause)
-__LXSYSCALL2(int, kill, pid_t, pid, int, signum)
-
__LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
__LXSYSCALL2(int, link, const char*, oldpath, const char*, newpath)
#include <lunaix/signal_defs.h>
#include <lunaix/types.h>
-extern int
+extern sighandler_t
signal(int signum, sighandler_t handler);
+extern int
+kill(pid_t pid, int signum);
+
+extern int
+raise(int signum);
+
+extern int
+sigaction(int signum, struct sigaction* action);
+
extern int
sigpending(sigset_t* set);
extern int
pause();
-extern int
-kill(pid_t pid, int signum);
-
extern unsigned int
alarm(unsigned int seconds);
signal(SIGSEGV, sigsegv_handler);
signal(SIGALRM, sigalrm_handler);
- alarm(5);
-
int status;
pid_t p = 0;
+ alarm(5);
+
printf("Child sleep 3s, parent pause.\n");
if (!fork()) {
sleep(3);