struct cpu_state* syscall(struct cpu_state* cpu) { save_cpu_state(cpu); cpu = get_current_task()->cpuState; switch (cpu->eax) { case 1: /* exit */ return terminate_current(cpu); case 3: /* exec */ { cpu->eax = vfs_exec((char*) cpu->ebx, (char**) cpu->ecx); } break; case 4: /* getargs */ { cpu->eax = (uint32_t) get_current_task()->args; } break; case 5: /* yield */ { cpu = schedule(cpu); } break; case 10: /* fopen */ { char* name = strclone((char*) cpu->ebx); uint32_t fmode = (uint32_t) cpu->ecx; struct res_handle* handle = vfs_open(name, fmode); if(handle) { register_handle(handle); cpu->eax = (uint32_t) handle; } else { cpu->eax = 0; } free(name); } break; case 11: /* fclose */ { struct res_handle* handle = (void*) cpu->ebx; if(!unregister_handle(handle)) { vfs_close(handle); cpu->eax = 0; } else { cpu->eax = (uint32_t) -1; } } break; case 12: /* fwrite */ { struct res_handle* handle = (void*) cpu->ebx; if(handle != 0) { cpu->eax = vfs_write(handle, (char*) cpu->ecx, cpu->edx, 1); } else { cpu->eax = RW_ERR_VFS; } } break; case 13: /* fread */ { struct res_handle* handle = (void*) cpu->ebx; if(handle != 0) { cpu->eax = vfs_read(handle, (char*) cpu->ecx, cpu->edx, 1); } else { cpu->eax = RW_ERR_VFS; } } break; case 14: /* fmkfifo */ { char* name = strclone((char*) cpu->ebx); vfs_create_kfile(name, ramfs_fifo_driver_struct(), &(uint32_t){4096}); //default to 4k Buffer-size struct res_handle* handle = vfs_open(name, FM_READ | FM_WRITE); if(handle) { register_handle(handle); cpu->eax = (uint32_t) handle; } else { cpu->eax = 0; } free(name); } break; case 20: /* getpmhandle */ { struct res_handle* handle = 0; switch(cpu->ebx) { case PMID_STDOUT: handle = get_current_task()->stdout; break; case PMID_STDIN: handle = get_current_task()->stdin; break; case PMID_STDERR: handle = get_current_task()->stderr; break; default: handle = get_current_task()->stdout; break; } cpu->eax = (uint32_t) handle; } break; case 21: /* fopenpmhandle */ { char* path = strclone((char*)cpu->ecx); struct res_handle* open; uint32_t fm = FM_WRITE; if(cpu->ebx == PMID_STDIN) { fm = FM_READ; } open = vfs_open(path, fm); free(path); if(!open) { cpu->eax = (uint32_t) -1; break; } struct res_handle* oldhandle = 0; switch(cpu->ebx) { case PMID_STDOUT: oldhandle = get_current_task()->stdout; get_current_task()->stdout = open; break; case PMID_STDIN: oldhandle = get_current_task()->stdin; get_current_task()->stdin = open; break; case PMID_STDERR: oldhandle = get_current_task()->stderr; get_current_task()->stderr = open; break; default: oldhandle = get_current_task()->stdout; get_current_task()->stdout = open; break; } if(oldhandle != 0) { vfs_close(oldhandle); } cpu->eax = 0; } break; case 201: /* kputc */ cpu->eax = kprintf("%c", cpu->ebx); break; case 202: /* kputs */ cpu->eax = kprintf("%s", cpu->ebx); break; case 203: /* vmm_alloc_ucont */ cpu->eax = (uint32_t) vmm_alloc_ucont(cpu->ebx); break; case 204: /* vmm_free */ cpu->eax = 0; if (cpu->ebx >= PROGRAM_BOTTOM) { //Only in PROGRAM AREA ;) vmm_free((void*) cpu->ebx); } break; case 205: /* pmm_print_stats */ pmm_print_stats(); break; default: kprintf("Invalid Syscall %d...", cpu->eax); break; } return cpu; }
bool task::wait(int timeout_milliseconds) { dassert(this != task::get_current_task(), "task cannot wait itself"); auto cs = state(); if (cs >= TASK_STATE_FINISHED) { spec().on_task_wait_post.execute(get_current_task(), this, true); return true; } // TODO: using event pool instead void *evt = _wait_event.load(); if (evt == nullptr) { evt = new utils::notify_event(); void *null_h = nullptr; if (!_wait_event.compare_exchange_strong(null_h, evt)) { delete (utils::notify_event *)evt; evt = _wait_event.load(); } } spec().on_task_wait_pre.execute(get_current_task(), this, (uint32_t)timeout_milliseconds); bool ret = (state() >= TASK_STATE_FINISHED); if (!ret) { auto nevt = (utils::notify_event *)evt; ret = (nevt->wait_for(timeout_milliseconds)); } spec().on_task_wait_post.execute(get_current_task(), this, ret); return ret; }
void syscall_handler(struct cpu_ctx *ctx, u32 id) { (void) ctx; switch (id) { /* task reschedule */ case 0: if (get_current_task()->flags & TASK_RUNNABLE) get_current_task()->time_slice = 0; scheduler(); break; } }
void exception_handler(int exception_num) { if (exception_num < 32) { printfcolor(ERROR_COLOR, "%s exception!\n", exception_messages[exception_num]); } Task_t * exceptionProducer = (Task_t *) get_current_task(); char * exceptionProducerName = exceptionProducer->name; printf("Exception producer %s\n", exceptionProducer->name); if (nestexc > MAX_NESTED_EXCEPTIONS) { kprintf("PANIC"); printfcolor(ERROR_COLOR, "PANIC: Exception could not be solved!\n\tSystem failure, please reboot.\n"); _debug(); } nestexc++; // EOI(); if (terminate_task(exceptionProducer->pid) == EXIT_SUCCESS) { nestexc--; yield(); // printfcolor(COMMAND_COLOR, "Failure tolerant module: Process \"%s\" has been killed.\n", exceptionProducerName); }else{ kprintf("PANIC 2"); printfcolor(ERROR_COLOR, "PANIC 2: Exception could not be solved!\n\tSystem failure, please reboot.\n"); // _debug(); } }
/* * scheduler_unlock * This function will enable preemption for this task so that it can be * preempted. */ void scheduler_unlock(void) { TASK *tcb = get_current_task(); /* Check if we have a current task. */ if (tcb != NULL) { /* Should never happen. */ ASSERT(tcb->lock_count == 0); /* Decrement the lock count for this task. */ tcb->lock_count --; /* If scheduler is actually unlocked, and we might have missed a * context switch because of this lock. */ if ((tcb->lock_count == 0) && (tcb->flags & TASK_SCHED_DRIFT)) { /* Clear the drift flag. */ tcb->flags &= (uint8_t)(~(TASK_SCHED_DRIFT)); /* Try to yield this task. */ task_yield(); } } } /* scheduler_unlock */
boolean_t uniproc_preempt(void) { if (mutex_try_lock(&uniproc_preemption_mutex)) { uniproc_change_current(current, get_current_task()); #if CONFIG_OSFMACH3_DEBUG { struct server_thread_priv_data *priv_datap; priv_datap = server_thread_get_priv_data(cthread_self()); if (priv_datap->preemptive) { /* * We actually preempted another thread... * account for this glorious deed ! */ uniproc_preemptions++; } else { /* * It's just the preemptible thread * preempting itself */ } } #endif /* CONFIG_OSFMACH3_DEBUG */ return TRUE; } return FALSE; }
/* Intended to be called from interrupt context only */ void task_trigger_exception (struct task *task, int exception, busword_t textaddr, busword_t data, int code) { DECLARE_CRITICAL_SECTION (except); ASSERT (get_current_context () == KERNEL_CONTEXT_INTERRUPT); ASSERT (get_current_task () == task); if (exception < 0 || exception >= EX_MAX) FAIL ("exception code unrecognized\n"); if (task->ts_ex_handlers[exception] == NULL) { /* Process shall be killed */ TASK_ATOMIC_ENTER (except); (void) wake_up (task, TASK_STATE_EXITED, 0); task_destroy (task); schedule (); TASK_ATOMIC_LEAVE (except); } else (task->ts_ex_handlers[exception]) (task, exception, textaddr, data, code); }
void yield_to() { task_context_t* stack = (task_context_t*)(curr_task->esp); int pid = stack->eax; //If we call yield with a target pid of 0 we just want to pass on control, so we sleep and schedule if(pid==0 || pid>SCHEDULER_MAX_TASKS) { curr_task->waiting_on = (lock_t*)pid; curr_task->state = TSK_Sleeping; //terminal_writestring("Making process sleep\n"); schedule(); return; } task_t* tsk = get_task(pid); if(tsk) { //terminal_writestring("yielded control from "); task_t* ct = get_current_task(); //terminal_writeuint32(ct->pid); tsk->lender_task = ct; tsk->state = TSK_Waiting; tsk->time_slice = ct->time_slice; curr_task = tsk; //terminal_writestring("to "); //terminal_writeuint32(curr_task->pid); //terminal_writestring("\n"); } }
bool task::cancel(bool wait_until_finished, /*out*/ bool *finished /*= nullptr*/) { task_state READY_STATE = TASK_STATE_READY; task *current_tsk = get_current_task(); bool finish = false; bool succ = false; if (current_tsk != this) { if (_state.compare_exchange_strong( READY_STATE, TASK_STATE_CANCELLED, std::memory_order_relaxed)) { succ = true; finish = true; } else { task_state old_state = READY_STATE; if (old_state == TASK_STATE_CANCELLED) { succ = false; // this cancellation fails finish = true; } else if (old_state == TASK_STATE_FINISHED) { succ = false; finish = true; } else if (wait_until_finished) { _wait_for_cancel = true; bool r = wait_on_cancel(); dassert( r, "wait failed, it is only possible when task runs for more than 0x0fffffff ms"); succ = false; finish = true; } else { succ = false; finish = false; } } } else { // task cancel itself // for timer task, we should set _wait_for_cancel flag to // prevent timer task from enqueueing again _wait_for_cancel = true; } if (current_tsk != nullptr) { current_tsk->spec().on_task_cancel_post.execute(current_tsk, this, succ); } if (succ) { spec().on_task_cancelled.execute(this); signal_waiters(); // we call clear_callback only cancelling succeed. // otherwise, task will successfully exececuted and clear_callback will be called // in "exec_internal". clear_non_trivial_on_task_end(); } if (finished) *finished = finish; return succ; }
asmlinkage long my_open(const char __user *filename, int flags, umode_t mode) { char *fname = 0; struct task_struct *cur = 0; // Get the filename fname = getname(filename); if (!fname) { printk("[ACE - ERROR] - Could not get the name of the file!\n"); return (-ENOENT); } // Get the current task cur = get_current_task(); if (!cur) { printk("[ACE - ERROR] - Could not get the current task!\n"); return (-ENOENT); } printk("[ACE - INFO] Checking file '%s'...\n", fname); if (policy_check(fname, __task_cred(cur)->euid) == 0) return sys_open(filename, flags, mode); else return (-EACCES); }
void erase_buffer(){ shellLine_t * lineBuffer = getLineBuffer(get_current_task()); int i = 0; for (i = 0; i < LINEBUF_LEN; i++) { lineBuffer->buffer[i]=0; } }
void trace_context_switch(int end) { static unsigned int prev_tick, tick_count; static size_t prev_task; char buf[128]; int len; /* * The SVC and SysTick handler share the same handler, so we * need to make sure that the SysTick is configured and starts to * count. * * Context switch call path: * 1) systick_handler (restore user state and load kernel state) * 2) choose the next task (while(1) loop of the "main" function) * 3) activate function (restore kernel state and load user state) * * That's why this function is invoked in the beginning of the * systick_handler and in the end of the activate function. */ if (!get_current()) return; /* * Do nothing if the previous tick is zero. This only happens during * the system boots up. */ if (end && !prev_tick) return; if (!end) { prev_task = get_current_task(); prev_tick = get_current(); tick_count++; return; } len = snprintf(buf, 128, "switch %d %d %d %d %d %d\n", prev_task, get_current_task(), tick_count, get_reload(), prev_tick, get_current()); write(fd, buf, len); }
void parse_command(command_t * c) { shellLine_t * lineBuffer = getLineBuffer(get_current_task()); int initpos = 0; /* Remover espacios en blanco */ while ( (lineBuffer->buffer[initpos] == ' ') && (++initpos < LINEBUF_LEN - 1) ); sscanf(&lineBuffer->buffer[initpos], "%s %s", c->name, c->args); }
void uniproc_has_entered(void) { UNIPROC_ASSERT(uniproc_holder == NULL); UNIPROC_ASSERT(uniproc_holder_cthread == NULL); current_set[smp_processor_id()] = get_current_task(); #if CONFIG_OSFMACH3_DEBUG uniproc_holder = current; #endif /* CONFIG_OSFMACH3_DEBUG */ uniproc_holder_cthread = cthread_self(); }
int clear_screen(int argc, char *argv){ ttyScreen_t * screen = getScreen(get_current_task()); clearScreen(); clearScreenBuffer(); print_header(); printTicks(); screen->wpos=TTY_SCREEN_SSTART; move_cursor(screen->wpos/2); }
/* ================================================================================== Funtion :pit_intterupt Input :struct ctx_reg *reg < saved context > Output :void Return :void Description :interrupt for a timer interval of a pit ================================================================================== */ LOCAL void pit_intterupt(struct ctx_reg *reg) { struct task *task = get_current_task(); if (task) { if (reg->eip < KERNEL_BASE_ADDR) { task->utime++; } else { task->stime++; } } timer_handler(); }
/* 指导语句: #pragma omp parallel for 结构功能: for调度函数 函数功能: 当一个线程完成指定给它的任务时,调用该函数分配下个任务 */ int GOMP_loop_guided_next(long *p1, long *p2) { int res = 0; Record_Event Event = Event_init (); Event.event_name = "GOMP_loop_guided_next"; Event.eid = 216; Event.type = NONE; Event.omp_rank = get_thread_num (); Event.omp_level = get_level (); Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1); Event.p_task_id_start = current_task.task_parent_id; Event.task_id_start = current_task.task_id; Event.task_state_start= TASK_END; GOMP_loop_guided_next_real=(int(*)(long*,long*)) dlsym (RTLD_NEXT, "GOMP_loop_guided_next"); if (GOMP_loop_guided_next_real != NULL) { Event.starttime=gettime(); res = GOMP_loop_guided_next_real (p1, p2); Event.endtime=gettime(); Record(&Event, OMPI_TRACE); } else { printf_d("GOMP_loop_guided_next is not hooked! exiting!!\n"); } if (res == 1) //Create a new task for this thread { current_task = create_itask (); Event.p_task_id_end = current_task.task_parent_id; Event.task_id_end= current_task.task_id; Event.task_state_end = TASK_CREATE; } else { current_task = get_current_task (); if (current_task.flag == 1) { Event.p_task_id_end = current_task.task_parent_id; Event.task_id_end= current_task.task_id; Event.task_state_end = TASK_RESUME; } } Record (&Event, OMPI_TRACE); return res; }
void task::enqueue(task_worker_pool *pool) { this->add_ref(); // released in exec_internal (even when cancelled) dassert(pool != nullptr, "pool %s not ready, and there are usually two cases: " "(1). thread pool not designatd in '[%s] pools'; " "(2). the caller is executed in io threads " "which is forbidden unless you explicitly set [task.%s].allow_inline = true", _spec->pool_code.to_string(), _node->spec().config_section.c_str(), _spec->name.c_str()); if (spec().type == TASK_TYPE_COMPUTE) { spec().on_task_enqueue.execute(get_current_task(), this); } // for delayed tasks, refering to timer service if (_delay_milliseconds != 0) { pool->add_timer(this); return; } // fast execution if (_is_null) { dassert(_node == task::get_current_node(), ""); exec_internal(); return; } if (_spec->allow_inline) { // inlined // warning - this may lead to deadlocks, e.g., allow_inlined // task tries to get a non-recursive lock that is already hold // by the caller task if (_node != get_current_node()) { tools::node_scoper ns(_node); exec_internal(); return; } else { exec_internal(); return; } } // normal path pool->enqueue(this); }
/* * scheduler_lock * This function will disable preemption for this task so that it cannot be * preempted. */ void scheduler_lock(void) { TASK *tcb = get_current_task(); /* Check if we have a current task. */ if (tcb != NULL) { /* Should never happen. */ ASSERT(tcb->lock_count >= SCHEDULER_MAX_LOCK); /* Increment the lock count for this task. */ tcb->lock_count ++; } } /* scheduler_lock */
void shell(void){ Task_t * c_t = get_current_task(); ttyScreen_t * screen = getScreen(c_t); shellLine_t * lineBuffer = getLineBuffer(c_t); char c; command_t * a = (command_t *) malloc(sizeof(command_t)); printf("BrunOS tty%d:~$ ", c_t->tty_number); while( (c=getc()) != '\n' ){ switch(c){ case '\b': if( lineBuffer->pos>0){ lineBuffer->buffer[--lineBuffer->pos]=0; putc('\b'); } break; case '\t': parse_command(a); auto_complete(a); break; default: if(lineBuffer->pos < lineBuffer->size-1){ lineBuffer->buffer[lineBuffer->pos++]=c; lineBuffer->buffer[lineBuffer->pos]=0; } putc(c); break; } } putc('\n'); parse_command(a); run_command(a); lineBuffer->pos=0; erase_buffer(); }
/* 指导语句: #pragma omp parallel for 结构功能: for结束函数 函数功能: 结束一个任务共享结构,不同步所有线程 */ void GOMP_loop_end_nowait (void) { TaskInfo old_task; Record_Event Event = Event_init (); Event.event_name = "GOMP_loop_end_nowait"; Event.eid = 222; Event.type = NONE; Event.omp_rank = get_thread_num (); Event.omp_level = get_level (); Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1); old_task = current_task; if (current_task.flag == 1) { Event.p_task_id_start = current_task.task_parent_id; Event.task_id_start = current_task.task_id; Event.task_state_start = TASK_WAIT; } GOMP_loop_end_nowait_real=(void(*)(void)) dlsym (RTLD_NEXT, "GOMP_loop_end_nowait"); if (GOMP_loop_end_nowait_real != NULL) { Event.starttime=gettime(); GOMP_loop_end_nowait_real(); Event.endtime=gettime(); } else { printf_d("GOMP_loop_end_nowait is not hooked! exiting!!\n"); } current_task = old_task; Event.p_task_id_end = current_task.task_parent_id; Event.task_id_end = current_task.task_id; Event.task_state_end = TASK_END; remove_team (); current_task = get_current_task (); Record(&Event, OMPI_TRACE); }
void auto_complete(command_t *command){ Task_t * c_t = get_current_task(); ttyScreen_t * screen = getScreen(c_t); shellLine_t * lineBuffer = getLineBuffer(c_t); int i, j, size, lenght, eq = TRUE; lenght = strlen(command->name); char * commName; if (streq(command->name, "")) return; for (i = 0; i < NUM_COMMANDS; i++) { commName = commands[i].name; for (j = 0; j < lenght && eq == TRUE; j++) { if (command->name[j] != commName[j]) eq = FALSE; if (j == strlen(commName) - 1) eq = FALSE; } if (eq == TRUE) { size = strlen(lineBuffer->buffer); erase_buffer(); clearfromto(screen->wpos - size * 2, screen->wpos); lineBuffer->pos = 0; lenght = strlen(commName); for (j = 0; j < lenght; j++) { lineBuffer->buffer[lineBuffer->pos++] = commName[j]; lineBuffer->buffer[lineBuffer->pos] = 0; putc(commName[j]); } } eq = !eq; } command->name[0] = 0; }
/* * sleep_ticks * @ticks: Number of ticks for which this task is needed to sleep. * This function sleeps/suspends the current task for the given number of system * ticks. */ void sleep_ticks(uint32_t ticks) { TASK *tcb; uint32_t interrupt_level; /* Save the current task pointer. */ tcb = get_current_task(); /* Current task should not be null. */ OS_ASSERT(tcb == NULL); /* Interrupts must not be locked. */ OS_ASSERT(tcb->interrupt_lock_count != 0); /* Lock the scheduler. */ scheduler_lock(); /* Add current task to the sleep list. */ sleep_add_to_list(tcb, ticks); /* Disable interrupts. */ interrupt_level = GET_INTERRUPT_LEVEL(); DISABLE_INTERRUPTS(); /* Task is being suspended. */ tcb->status = TASK_SUSPENDED; /* Return control to the system. * We will resume from here when our required delay has been achieved. */ CONTROL_TO_SYSTEM(); /* Restore old interrupt level. */ SET_INTERRUPT_LEVEL(interrupt_level); /* Enable scheduling. */ scheduler_unlock(); } /* sleep_ticks */
task::task(task_code code, int hash, service_node* node) : _state(TASK_STATE_READY) { _spec = task_spec::get(code); _task_id = (uint64_t)(this); _wait_event.store(nullptr); _hash = hash; _delay_milliseconds = 0; _wait_for_cancel = false; _is_null = false; if (node != nullptr) { _node = node; } else { auto p = get_current_task(); dassert(p != nullptr, "tasks without explicit service node " "can only be created inside other tasks"); _node = p->node(); } }
// // return - whether this cancel succeed // bool task::cancel(bool wait_until_finished, /*out*/ bool* finished /*= nullptr*/) { task_state READY_STATE = TASK_STATE_READY; task *current_tsk = get_current_task(); bool finish = false; bool succ = false; if (current_tsk == this) { /*dwarn( "task %s (id=%016llx) cannot cancel itself", spec().name(), id() );*/ // make sure timers are cancelled _wait_for_cancel = true; if (finished) *finished = false; return false; } if (_state.compare_exchange_strong(READY_STATE, TASK_STATE_CANCELLED, std::memory_order_relaxed)) { succ = true; finish = true; } else { task_state old_state = READY_STATE; if (old_state == TASK_STATE_CANCELLED) { succ = false; // this cancellation fails finish = true; } else if (old_state == TASK_STATE_FINISHED) { succ = false; finish = true; } else if (wait_until_finished) { _wait_for_cancel = true; bool r = wait(TIME_MS_MAX, true); dassert(r, "wait failed, it is only possible when task runs for more than 0x0fffffff ms"); succ = false; finish = true; } else { succ = false; finish = false; } } if (current_tsk != nullptr) { current_tsk->spec().on_task_cancel_post.execute(current_tsk, this, succ); } if (succ) { // // TODO: pros and cons of executing on_cancel here // or in exec_internal // if (_on_cancel) { _on_cancel(_context); } spec().on_task_cancelled.execute(this); signal_waiters(); _error.end_tracking(); } if (finished) *finished = finish; return succ; }