// 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; }
void wait_current_set(wait_queue_t *queue, wait_t *wait, uint32_t wait_state) { assert(current != NULL); wait_init(wait, current); current->state = PROC_SLEEPING; current->wait_state = wait_state; wait_queue_add(queue, wait); }
//TODO: Should be moved to a pipe_state function. static int pipe_inode_poll(struct inode *node, wait_t *wait, int io_requests) { struct pipe_inode *pipe_inode = vop_info(node, pipe_inode); struct pipe_state *state= pipe_inode->state; if(pipe_inode->pin_type == PIN_WRONLY) { if(io_requests | POLL_WRITE_AVAILABLE) { //TODO: This is ugly, should be using pipe_state macros. if (state->p_wpos - state->p_rpos >= PGSIZE - sizeof(struct pipe_state)) { if (state->isclosed) { return 0; } else { //unlock_state(state); if(wait != NULL) wait_queue_add(&state->writer_queue, wait); return 0; } } else { return POLL_WRITE_AVAILABLE; } } else { return 0; } } else { if(io_requests | POLL_READ_AVAILABLE) { //lock_state(state); if (state->p_rpos == state->p_wpos) { if (state->isclosed) { return 0; } else { //unlock_state(state); if(wait != NULL) wait_queue_add(&state->reader_queue, wait); return 0; } } else { return POLL_READ_AVAILABLE; } } else { return 0; } } }
void sleep_on(struct wait_queue *queue, struct task_struct *task) { assert(queue && task); //assert(task->pid != 0); if (!task->pid) return; wait_queue_add(queue,task); task->task_status = TASK_UNINTERRUPTIBLE; schedule_delete_task(task); schedule(); }