static __noinline uint32_t __down(semaphore_t *sem, uint32_t wait_state) { bool intr_flag; local_intr_save(intr_flag); if (sem->value > 0) { sem->value--; local_intr_restore(intr_flag); return 0; } wait_t __wait, *wait = &__wait; wait_current_set(&(sem->wait_queue), wait, wait_state); local_intr_restore(intr_flag); schedule(); local_intr_save(intr_flag); wait_current_del(&(sem->wait_queue), wait); local_intr_restore(intr_flag); if (wait->wakeup_flags != wait_state) { return wait->wakeup_flags; } return 0; }
__attribute__ ((noinline)) __down(semaphore_t * sem, uint32_t wait_state, timer_t * timer) { assert(sem->valid); bool intr_flag; local_intr_save(intr_flag); if (sem->value > 0) { sem->value--; local_intr_restore(intr_flag); return 0; } wait_t __wait, *wait = &__wait; wait_current_set(&(sem->wait_queue), wait, wait_state); ipc_add_timer(timer); local_intr_restore(intr_flag); schedule(); local_intr_save(intr_flag); ipc_del_timer(timer); wait_current_del(&(sem->wait_queue), wait); local_intr_restore(intr_flag); if (wait->wakeup_flags != wait_state) { return wait->wakeup_flags; } return 0; }
static int recv_event(int *pid_store, int *event_store, timer_t *timer) { bool intr_flag; local_intr_save(intr_flag); wait_queue_t *wait_queue = &(current->event_box.wait_queue); if (wait_queue_empty(wait_queue)) { current->state = PROC_SLEEPING; current->wait_state = WT_EVENT_RECV; ipc_add_timer(timer); local_intr_restore(intr_flag); schedule(); local_intr_save(intr_flag); ipc_del_timer(timer); } int ret = -1; wait_t *wait; if ((wait = wait_queue_first(wait_queue)) != NULL) { struct proc_struct *proc = wait->proc; *pid_store = proc->pid, *event_store = proc->event_box.event, ret = 0; wakeup_wait(wait_queue, wait, WT_EVENT_SEND, 1); } local_intr_restore(intr_flag); return ret; }
int try_to_wakeup(struct proc_struct *proc) { assert(proc->state != PROC_ZOMBIE); int ret; bool intr_flag; local_intr_save(intr_flag); { if (proc->state != PROC_RUNNABLE) { proc->state = PROC_RUNNABLE; proc->wait_state = 0; if (proc != current) { sched_class_enqueue(proc); } ret = 1; } else { ret = 0; } struct proc_struct *next = proc; while ( (next = next_thread(next)) != proc ) { if ( next->state == PROC_SLEEPING && next->wait_state == WT_SIGNAL ) { next->state = PROC_RUNNABLE; next->wait_state = 0; if ( next != current ) { sched_class_enqueue(next); } } } } local_intr_restore(intr_flag); return ret; }
// serial only atm void cons_putc(int c) { /* An temporary version, just for debugging.*/ //serial_putc(c); bool intr_flag; local_intr_save(intr_flag); { serial_putc(c); } local_intr_restore(intr_flag); /* bool intr_flag; local_intr_save(intr_flag); { #ifdef USE_UART serial_putc(c); #endif #ifdef HAS_SDS if (check_sds() && is_debugging()) sds_poll_proc(); sds_putc(0, c); #endif } local_intr_restore(intr_flag);*/ }
/* * * cons_getc - return the next input character from console, * or 0 if none waiting. * */ int cons_getc(void) { int c = 0; bool intr_flag; local_intr_save(intr_flag); { // poll for any pending input characters, // so that this function works even when interrupts are disabled // (e.g., when called from the kernel monitor). #ifdef USE_UART serial_intr(); #endif #ifdef HAS_SDS if (check_sds() && is_debugging()) sds_poll_proc(); sds_intr(); #endif //kbd_intr(); // grab the next character from the input buffer. if (cons.rpos != cons.wpos) { c = cons.buf[cons.rpos++]; if (cons.rpos == CONSBUFSIZE) { cons.rpos = 0; } } } local_intr_restore(intr_flag); return c; }
void schedule(void) { struct task_struct *task_next = NULL; struct list_head *le = NULL, *last = NULL; bool intr_flag = false; local_intr_store(intr_flag); { current->need_resched = false; // 如果当前是内核调度线程在执行,就从任务链起始开始,否则从当前任务开始 le = last = (current == glb_idle_task) ? &task_list : &(current->list); for (le = le->next; le != last; le = le->next) { if (le != &task_list) { task_next = le_to_task(le); if (task_next->state == TASK_RUNNABLE) { break; } } } // 未找到可运行的任务 if (!task_next || task_next->state != TASK_RUNNABLE) { task_next = glb_idle_task; } // 时间片递增 task_next->runs_time++; if (task_next != current) { task_run(task_next); } } local_intr_restore(intr_flag); }
void schedule(void) { bool intr_flag; struct proc_struct *next; local_intr_save(intr_flag); { cprintf("\n++++++ CURRENT PID = %d ++++++\n", current->pid); cprintf("++++++ IN SCHEDULE() ++++++\n"); current->need_resched = 0; if (current->state == PROC_RUNNABLE) { cprintf("++++++ CURRENT PID = %d RUNNABLE, CALL ENQUEUE ++++++\n", current->pid); sched_class_enqueue(current); } if ((next = sched_class_pick_next()) != NULL) { cprintf("++++++ NEXT PID = %d TO RUN, CALL DEQUEUE ++++++\n", next->pid); sched_class_dequeue(next); } if (next == NULL) { next = idleproc; } next->runs ++; if (next != current) { proc_run(next); } } local_intr_restore(intr_flag); }
void schedule(void) { bool intr_flag; struct proc_struct *next; local_intr_save(intr_flag); { current->need_resched = 0; if (current->state == PROC_RUNNABLE) { sched_class_enqueue(current); } if ((next = sched_class_pick_next()) != NULL) { sched_class_dequeue(next); } if (next == NULL) { next = idleproc; } next->runs++; if (next != current) { proc_run(next); } } local_intr_restore(intr_flag); }
// call scheduler to update tick related info, and check the timer is expired? If expired, then wakup proc void run_timer_list(void) { bool intr_flag; local_intr_save(intr_flag); { list_entry_t *le = list_next(&timer_list); if (le != &timer_list) { timer_t *timer = le2timer(le, timer_link); assert(timer->expires != 0); timer->expires --; while (timer->expires == 0) { le = list_next(le); struct proc_struct *proc = timer->proc; if (proc->wait_state != 0) { assert(proc->wait_state & WT_INTERRUPTED); } else { warn("process %d's wait_state == 0.\n", proc->pid); } cprintf("process pid = %d wait finished.",proc->pid); wakeup_proc(proc); del_timer(timer); if (le == &timer_list) { break; } timer = le2timer(le, timer_link); } } sched_class_proc_tick(current); } local_intr_restore(intr_flag); }
void schedule(void) { bool intr_flag; list_entry_t *le, *last; struct proc_struct *next = NULL; local_intr_save(intr_flag); { current->need_resched = 0; last = (current == idleproc) ? &proc_list : &(current->list_link); le = last; do { if ((le = list_next(le)) != &proc_list) { next = le2proc(le, list_link); if (next->state == PROC_RUNNABLE) { break; } } } while (le != last); if (next == NULL || next->state != PROC_RUNNABLE) { next = idleproc; } next->runs ++; if (next != current) { //proc_print(next); cprintf("sche! proc %d, pc=%08x\n\n",next->pid,next->context.pc); //cprintf("sp=%08x\n\n",read_sp()); proc_run(next); } } local_intr_restore(intr_flag); }
void schedule(void) { bool intr_flag; struct proc_struct *next; local_intr_save(intr_flag); { current->need_resched = 0; if (current->state == PROC_RUNNABLE) { cprintf("Timer finished for process pid = %d and push in the queue\n",current->pid); sched_class_enqueue(current); } if ((next = sched_class_pick_next()) != NULL) { cprintf("Picks process pid = %d to run and pop from the queue\n",next->pid); sched_class_dequeue(next); } if (next == NULL) { cprintf("No runnable process.\n"); next = idleproc; } next->runs ++; if (next != current) { proc_run(next); } } local_intr_restore(intr_flag); }
void schedule(void) { bool intr_flag; list_entry_t *le, *last; struct proc_struct *next = NULL; local_intr_save(intr_flag); { current->need_resched = 0; last = (current == idleproc) ? &proc_list : &(current->list_link); le = last; do { if ((le = list_next(le)) != &proc_list) { next = le2proc(le, list_link); if (next->state == PROC_RUNNABLE) { break; } } } while (le != last); if (next == NULL || next->state != PROC_RUNNABLE) { next = idleproc; } next->runs ++; if (next != current) { proc_run(next); } } local_intr_restore(intr_flag); }
// try_free_pages - calculate pressure to estimate the number(pressure<<5) of needed page frames in ucore currently, // - then call kswapd kernel thread. bool try_free_pages(size_t n) { struct proc_struct *current = pls_read(current); if (!swap_init_ok || kswapd == NULL) { return 0; } if (current == kswapd) { panic("kswapd call try_free_pages!!.\n"); } if (n >= (1 << 7)) { return 0; } pressure += n; wait_t __wait, *wait = &__wait; bool intr_flag; local_intr_save(intr_flag); { wait_init(wait, current); current->state = PROC_SLEEPING; current->wait_state = WT_KSWAPD; wait_queue_add(&kswapd_done, wait); if (kswapd->wait_state == WT_TIMER) { wakeup_proc(kswapd); } } local_intr_restore(intr_flag); schedule(); assert(!wait_in_queue(wait) && wait->wakeup_flags == WT_KSWAPD); return 1; }
int __ucore_wakeup_by_pid(int pid) { //kprintf("ucore_wakeup_by_pid %d\n", pid); struct proc_struct *proc = find_proc(pid); if (!proc) return -E_INVAL; bool flag; local_intr_save(flag); if (proc->state == PROC_ZOMBIE) { local_intr_restore(flag); return -E_INVAL; } if (proc->state == PROC_RUNNABLE) wakeup_proc(proc); local_intr_restore(flag); return 0; }
void free_pages(uint32_t addr, uint32_t n) { uint32_t eflag; local_intr_store(eflag); pmm_manager->free_pages(addr, n); local_intr_restore(eflag); }
/* cons_putc - print a single character @c to console devices */ void cons_putc(int c) { bool intr_flag; local_intr_save(intr_flag); { serial_putc(c); } local_intr_restore(intr_flag); }
static void kswapd_wakeup_all(void) { bool intr_flag; local_intr_save(intr_flag); { wakeup_queue(&kswapd_done, WT_KSWAPD, 1); } local_intr_restore(intr_flag); }
//free_pages - call pmm->free_pages to free a continuous n*PAGESIZE memory void free_pages(struct Page *base, size_t n) { bool intr_flag; local_intr_save(intr_flag); { pmm_manager->free_pages(base, n); } local_intr_restore(intr_flag); }
uint32_t todo_wait_interruptible(wait_queue_t* wait_queue, uint32_t wait_state) { bool intr_flag; local_intr_save(intr_flag); // wait_t __wait, *wait = &__wait; // wait_current_set(&wait_queue, wait, wait_state); local_intr_restore(intr_flag); schedule(); local_intr_save(intr_flag); // wait_current_del(&(sem->wait_queue), wait); local_intr_restore(intr_flag); // if (wait->wakeup_flags != wait_state) { // return wait->wakeup_flags; // } return 0; }
void __ucore_wait_self() { //kprintf("ucore_wait_self self=%d\n", current->pid); bool intr_flag; local_intr_save(intr_flag); current->state = PROC_SLEEPING; current->wait_state = WT_KERNEL_SIGNAL; local_intr_restore(intr_flag); schedule(); }
bool try_down(semaphore_t *sem) { bool intr_flag, ret = 0; local_intr_save(intr_flag); if (sem->value > 0) { sem->value --, ret = 1; } local_intr_restore(intr_flag); return ret; }
/** * free_pages - call pmm->free_pages to free a continuing n*PAGESIZE memory * @param base the first page to be freed * @param n number of pages to be freed */ void free_pages(struct Page *base, size_t n) { bool intr_flag; local_intr_save(intr_flag); { pmm_manager->free_pages(base, n); } local_intr_restore(intr_flag); pls_write(used_pages, pls_read(used_pages) - n); }
//free_pages - call pmm->free_pages to free a continuous n*PAGESIZE memory void free_pages(struct Page *base, size_t n) { bool intr_flag; local_intr_save(intr_flag); spinlock_acquire(&pmm_lock); { pmm_manager->free_pages(base, n); } spinlock_release(&pmm_lock); local_intr_restore(intr_flag); }
//nr_free_pages - call pmm->nr_free_pages to get the size (nr*PAGESIZE) //of current free memory size_t nr_free_pages(void) { size_t ret; bool intr_flag; local_intr_save(intr_flag); { ret = pmm_manager->nr_free_pages(); } local_intr_restore(intr_flag); return ret; }
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags // - if clone_flags & CLONE_VM, then "share" ; else "duplicate" static int copy_mm(uint32_t clone_flags, struct proc_struct *proc) { struct mm_struct *mm, *oldmm = current->mm; /* current is a kernel thread */ if (oldmm == NULL) { return 0; } if (clone_flags & CLONE_VM) { mm = oldmm; goto good_mm; } int ret = -E_NO_MEM; if ((mm = mm_create()) == NULL) { goto bad_mm; } if (setup_pgdir(mm) != 0) { goto bad_pgdir_cleanup_mm; } lock_mm(oldmm); { ret = dup_mmap(mm, oldmm); } unlock_mm(oldmm); if (ret != 0) { goto bad_dup_cleanup_mmap; } good_mm: if (mm != oldmm) { mm->brk_start = oldmm->brk_start; mm->brk = oldmm->brk; bool intr_flag; local_intr_save(intr_flag); { list_add(&(proc_mm_list), &(mm->proc_mm_link)); } local_intr_restore(intr_flag); } mm_count_inc(mm); proc->mm = mm; set_pgdir (proc, mm->pgdir); return 0; bad_dup_cleanup_mmap: exit_mmap(mm); put_pgdir(mm); bad_pgdir_cleanup_mm: mm_destroy(mm); bad_mm: return ret; }
uint32_t alloc_pages(uint32_t n) { uint32_t page; uint32_t eflag; local_intr_store(eflag); page = pmm_manager->alloc_pages(n); local_intr_restore(eflag); return page; }
void stop_proc(struct proc_struct *proc, uint32_t wait) { bool intr_flag; local_intr_save(intr_flag); proc->state = PROC_SLEEPING; proc->wait_state = wait; if ( !list_empty(&(proc->run_link)) ) { sched_class_dequeue(proc); } local_intr_restore(intr_flag); }
// 屏幕打印一个以 \0 结尾的字符串(默认黑底白字) void console_write(char *cstr) { bool intr_flag = false; local_intr_store(intr_flag); { while (*cstr) { console_putc_color(*cstr++, rc_black, rc_white); } _flush_console_current(); } local_intr_restore(intr_flag); }
// 屏幕打印一个以 \0 结尾的字符串(带颜色) void console_write_color(char *cstr, real_color_t back, real_color_t fore) { bool intr_flag = false; local_intr_store(intr_flag); { while (*cstr) { console_putc_color(*cstr++, back, fore); } _flush_console_current(); } local_intr_restore(intr_flag); }