sc_addr sc_generator::enter_system(const char *idtf,sc_type type,sc_segment *segment) { sc_addr el = generate_find_internal(idtf,type,segment); if (!el) return 0; return enter_system(el); }
/* This is the C kernel entry point */ void kmain(struct multiboot *mboot_header, addr_t initial_stack) { /* Store passed values, and initiate some early things * We want serial log output as early as possible */ kernel_state_flags=0; mtboot = mboot_header; i_stack = initial_stack; parse_kernel_elf(mboot_header, &kernel_elf); #if CONFIG_MODULES init_kernel_symbols(); #endif init_serial(); console_init_stage1(); load_tables(); puts("~ SeaOS Version "); char ver[32]; get_kernel_version(ver); puts(ver); puts(" Booting Up ~\n\r"); #if CONFIG_MODULES init_module_system(); #endif init_syscalls(); load_initrd(mtboot); install_timer(1000); pm_init(placement, mtboot); init_main_cpu_1(); /* Now get the management stuff going */ printk(1, "[kernel]: Starting system management\n"); init_memory(mtboot); init_main_cpu_2(); console_init_stage2(); parse_kernel_cmd((char *)(addr_t)mtboot->cmdline); init_multitasking(); init_cache(); init_dm(); init_vfs(); /* Load the rest... */ process_initrd(); init_kern_task(); get_timed(&kernel_start_time); printk(KERN_MILE, "[kernel]: Kernel is setup (%2.2d:%2.2d:%2.2d, %s, kv=%d, ts=%d bytes: ok)\n", kernel_start_time.tm_hour, kernel_start_time.tm_min, kernel_start_time.tm_sec, kernel_name, KVERSION, sizeof(task_t)); assert(!set_int(1)); if(!fork()) init(); sys_setsid(); enter_system(255); kernel_idle_task(); }
int syscall_handler(volatile registers_t *regs) { /* SYSCALL_NUM_AND_RET is defined to be the correct register in the syscall regs struct. */ if(unlikely(SYSCALL_NUM_AND_RET >= num_syscalls)) return -ENOSYS; if(unlikely(!syscall_table[SYSCALL_NUM_AND_RET])) return -ENOSYS; volatile long ret; if(!check_pointers(regs)) return -EINVAL; if(kernel_state_flags & KSF_SHUTDOWN) for(;;); //if(got_signal(current_task) || (unsigned)(ticks-current_task->slice) > (unsigned)current_task->cur_ts) // schedule(); enter_system(SYSCALL_NUM_AND_RET); /* most syscalls are re-entrant, so we enable interrupts and * expect handlers to disable them if needed */ set_int(1); /* start accounting information! */ current_task->freed = current_task->allocated=0; #ifdef SC_DEBUG if(current_task->tty == curcons->tty) printk(SC_DEBUG, "syscall %d: enter %d\n", current_task->pid, SYSCALL_NUM_AND_RET); int or_t = ticks; #endif __do_syscall_jump(ret, syscall_table[SYSCALL_NUM_AND_RET], _E_, _D_, _C_, _B_, _A_); #ifdef SC_DEBUG if(current_task->tty == curcons->tty && (ticks - or_t >= 10 || 1) && (ret < 0 || 1) && (ret == -EINTR || 1)) printk(SC_DEBUG, "syscall %d: %d ret %d, took %d ticks\n", current_task->pid, current_task->system, ret, ticks - or_t); #endif set_int(0); exit_system(); __engage_idle(); /* if we need to reschedule, or we have overused our timeslice * then we need to reschedule. this prevents tasks that do a continuous call * to write() from starving the resources of other tasks. syscall_count resets * on each call to schedule() */ if(current_task->flags & TF_SCHED || (unsigned)(ticks-current_task->slice) > (unsigned)current_task->cur_ts || ++current_task->syscall_count > 2) { /* clear out the flag. Either way in the if statement, we've rescheduled. */ lower_flag(TF_SCHED); schedule(); } /* store the return value in the regs */ SYSCALL_NUM_AND_RET = ret; /* if we're going to jump to a signal here, we need to back up our * return value so that when we return to the system we have the * original systemcall returning the proper value. */ if((current_task->flags & TF_INSIG) && (current_task->flags & TF_JUMPIN)) { #if CONFIG_ARCH == TYPE_ARCH_X86 current_task->reg_b.eax=ret; #elif CONFIG_ARCH == TYPE_ARCH_X86_64 current_task->reg_b.rax=ret; #endif lower_flag(TF_JUMPIN); } return ret; }