//Operations of Console object. static VOID ConPrintStr(const char* pszStr) { DWORD dwWriteSize = 0; DWORD i; //Low level output should be used if in context or in system initialization phase. if(IN_INTERRUPT() || IN_SYSINITIALIZATION()) { dwWriteSize = strlen(pszStr); for(i = 0;i < dwWriteSize;i ++) { __LL_Output(pszStr[i]); } return; } if(!Console.bInitialized) { return; } //Write string to COM interface. IOManager.WriteFile((__COMMON_OBJECT*)&IOManager, Console.hComInt, strlen(pszStr), (LPVOID)pszStr, &dwWriteSize); return; }
static VOID ConGotoHome(void) { DWORD dwWriteSize = 0; CHAR chTarg = '\r'; //Low level output operation should be used when in interrupt context or in process //of OS initialization. if(IN_INTERRUPT() || IN_SYSINITIALIZATION()) { __LL_Output(chTarg); return; } if(!Console.bInitialized) { return; } //Write string to COM interface. IOManager.WriteFile((__COMMON_OBJECT*)&IOManager, Console.hComInt, 1, (LPVOID)&chTarg, &dwWriteSize); return; }
void up_release_pending(void) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; slldbg("From TCB=%p\n", rtcb); /* Merge the g_pendingtasks list into the g_readytorun task list */ /* sched_lock(); */ if (sched_mergepending()) { /* The currently active task has changed! We will need to * switch contexts. First check if we are operating in * interrupt context: */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current context into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; slldbg("New Active Task TCB=%p\n", rtcb); /* Then setup so that the context will be performed on exit * from the interrupt. */ SET_IRQCONTEXT(rtcb); } /* Copy the exception context into the TCB of the task that * was currently active. if SAVE_USERCONTEXT returns a non-zero * value, then this is really the previously running task * restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; slldbg("New Active Task TCB=%p\n", rtcb); /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } }
static VOID ConClearScreen(void) { //Adopt low level output operation if in interrupt context or in process //of system initialization. if(IN_INTERRUPT() || IN_SYSINITIALIZATION()) { return; } if(!Console.bInitialized) { return; } return; }
// returns nonzero if handled int phantom_check_user_trap( struct trap_state *ts ) { // In interrupt? Surely this is a kernel problem, don't // deliver to curr thread! if(IN_INTERRUPT()) return 0; // TODO move to some arch func? #if ARCH_ia32 if( ts->cs == KERNEL_CS ) { //printf("kernel CS in trap\n"); return 0; } #endif phantom_thread_t *t = GET_CURRENT_THREAD(); int tid = t->tid; if(t->thread_flags & THREAD_FLAG_USER) { // Try thread trap handler first. If it returns zero - trap // is supposed to be handled if(t->trap_handler) { int sig_no = trap2signo(ts); if( 0 == ( t->trap_handler( sig_no, ts ) ) ) return 1; } #ifdef ARCH_ia32 if(ts->trapno == T_PAGE_FAULT) printf("Page fault addr %p\n", (void *)arch_get_fault_address() ); #endif printf("Usermode thread %d killed due to unexpected trap %d, eip %p\n", tid, ts->trapno, (void *)(ts->TS_PROGRAM_COUNTER) ); t_kill_thread( tid ); // Will panic below if returned printf("Usermode trap panic in thread %d\n", tid); trap_panic(ts); } printf("? trap not from kernel CS, and thread has no THREAD_FLAG_USER, tid %d\n", tid); // Not user mode, return return 0; }
/* Show out bug information. */ VOID __BUG(LPSTR lpszFileName,DWORD dwLineNum) { DWORD dwFlags; unsigned int processor_id = __CURRENT_PROCESSOR_ID; __KERNEL_THREAD_OBJECT* pKernelThread = __CURRENT_KERNEL_THREAD; /* Show general bug info. */ _hx_printk("\r\nBUG encountered[curr_processor = %d].\r\n",processor_id); _hx_printk("File name : %s\r\nCode Lines : %d\r\n",lpszFileName,dwLineNum); /* Show out specific information according current execution context. */ if (IN_INTERRUPT()) { /* Show interrupt related information. */ _hx_printk("In interrupt context,vector:%d.\r\n", System.ucCurrInt[processor_id]); /* Show out interrupted kernel thread information. */ if (pKernelThread) { _hx_printk("Interrupted kernel thread:%s\r\n", pKernelThread->KernelThreadName); } } else if (IN_SYSINITIALIZATION()) { /* In process of system initialization. */ _hx_printf("In process of system initialization.\r\n"); } else { /* In normal thread context. */ _hx_printf("Current kthread: %s\r\n", __CURRENT_KERNEL_THREAD->KernelThreadName); } /* Current CPU dive into a halt state. */ __DISABLE_LOCAL_INTERRUPT(dwFlags); while (TRUE) { /* Enter halt state to save energy. */ HaltSystem(); } __RESTORE_LOCAL_INTERRUPT(dwFlags); }
static VOID ConGotoPrev(void) { DWORD dwWriteSize = 0; CHAR chTarg = VK_BACKSPACE; //Interrupt context or OS initialization phase. if(IN_INTERRUPT()) { __LL_Output(chTarg); return; } if(!Console.bInitialized) { return; } //Write string to COM interface. IOManager.WriteFile((__COMMON_OBJECT*)&IOManager, Console.hComInt, 1, (LPVOID)&chTarg, &dwWriteSize); return; }
static VOID ConChangeLine(void) { DWORD dwWriteSize = 0; CHAR chTarg = '\n'; //Interrupt context or OS initialization phase output. if(IN_INTERRUPT() || IN_SYSINITIALIZATION()) { __LL_Output(chTarg); return; } if(!Console.bInitialized) { return; } //Write string to COM interface. IOManager.WriteFile((__COMMON_OBJECT*)&IOManager, Console.hComInt, 1, (LPVOID)&chTarg, &dwWriteSize); return; }
void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; bool switch_needed; /* Verify that the context switch can be performed */ ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && (tcb->task_state <= LAST_READY_TO_RUN_STATE)); /* dbg("Blocking TCB=%p\n", tcb); */ /* Remove the tcb task from the ready-to-run list. If we * are blocking the task at the head of the task list (the * most likely case), then a context switch to the next * ready-to-run task is needed. In this case, it should * also be true that rtcb == tcb. */ switch_needed = sched_removereadytorun(tcb); /* Add the task to the specified blocked task list */ sched_addblocked(tcb, (tstate_t)task_state); /* If there are any pending tasks, then add them to the g_readytorun * task list now */ if (g_pendingtasks.head) { switch_needed |= sched_mergepending(); } /* Now, perform the context switch if one is needed */ if (switch_needed) { /* Are we in an interrupt handler? */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current registers into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; /* dbg("New Active Task TCB=%p\n", rtcb); */ /* Then setup so that the context will be performed on exit * from the interrupt. */ SET_IRQCONTEXT(rtcb); } /* Copy the user C context into the TCB at the (old) head of the * g_readytorun Task list. if SAVE_USERCONTEXT returns a non-zero * value, then this is really the previously running task restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; /* dbg("New Active Task TCB=%p\n", rtcb); */ /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } }
void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; bool switch_needed; /* Verify that the context switch can be performed */ ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && (tcb->task_state <= LAST_READY_TO_RUN_STATE)); /* dbg("Blocking TCB=%p\n", tcb); */ /* Remove the tcb task from the ready-to-run list. If we * are blocking the task at the head of the task list (the * most likely case), then a context switch to the next * ready-to-run task is needed. In this case, it should * also be true that rtcb == tcb. */ switch_needed = sched_removereadytorun(tcb); /* Add the task to the specified blocked task list */ sched_addblocked(tcb, (tstate_t)task_state); /* If there are any pending tasks, then add them to the g_readytorun * task list now */ if (g_pendingtasks.head) { switch_needed |= sched_mergepending(); } /* Now, perform the context switch if one is needed */ if (switch_needed) { /* Update scheduler parameters */ sched_suspend_scheduler(rtcb); /* Are we in an interrupt handler? */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current registers into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; /* Reset scheduler parameters */ sched_resume_scheduler(rtcb); /* Then setup so that the context will be performed on exit * from the interrupt. Any necessary address environment * changes will be made when the interrupt returns. */ SET_IRQCONTEXT(rtcb); } /* Copy the user C context into the TCB at the (old) head of the * g_readytorun Task list. if SAVE_USERCONTEXT returns a non-zero * value, then this is really the previously running task restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR struct tcb_s*)g_readytorun.head; #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, * MMU flushed) and set up the address environment for the new * thread at the head of the ready-to-run list. */ (void)group_addrenv(rtcb); #endif /* Reset scheduler parameters */ sched_resume_scheduler(rtcb); /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } }
void up_unblock_task(FAR struct tcb_s *tcb) { FAR struct tcb_s *rtcb = this_task(); /* Verify that the context switch can be performed */ ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && (tcb->task_state <= LAST_BLOCKED_STATE)); /* _info("Unblocking TCB=%p\n", tcb); */ /* Remove the task from the blocked task list */ sched_removeblocked(tcb); /* Add the task in the correct location in the prioritized * ready-to-run task list */ if (sched_addreadytorun(tcb)) { /* The currently active task has changed! We need to do * a context switch to the new task. */ /* Update scheduler parameters */ sched_suspend_scheduler(rtcb); /* Are we in an interrupt handler? */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current context into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. */ rtcb = this_task(); /* Update scheduler parameters */ sched_resume_scheduler(rtcb); /* Then setup so that the context will be performed on exit * from the interrupt. Any necessary address environment * changes will be made when the interrupt returns. */ SET_IRQCONTEXT(rtcb); } /* We are not in an interrupt handler. Copy the user C context * into the TCB of the task that was previously active. if * SAVE_USERCONTEXT returns a non-zero value, then this is really the * previously running task restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the new task that is ready to * run (probably tcb). This is the new rtcb at the head of the * ready-to-run task list. */ rtcb = this_task(); #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, * MMU flushed) and set up the address environment for the new * thread at the head of the ready-to-run list. */ (void)group_addrenv(rtcb); #endif /* Update scheduler parameters */ sched_resume_scheduler(rtcb); /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } }
void up_release_pending(void) { FAR struct tcb_s *rtcb = this_task(); slldbg("From TCB=%p\n", rtcb); /* Merge the g_pendingtasks list into the ready-to-run task list */ /* sched_lock(); */ if (sched_mergepending()) { /* The currently active task has changed! We will need to switch * contexts. * * Update scheduler parameters. */ sched_suspend_scheduler(rtcb); /* Are we operating in interrupt context? */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current context into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. */ rtcb = this_task(); /* Update scheduler parameters */ sched_resume_scheduler(rtcb); /* Then setup so that the context will be performed on exit * from the interrupt. Any necessary address environment * changes will be made when the interrupt returns. */ SET_IRQCONTEXT(rtcb); } /* Copy the exception context into the TCB of the task that * was currently active. if SAVE_USERCONTEXT returns a non-zero * value, then this is really the previously running task * restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. */ rtcb = this_task(); #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, * MMU flushed) and set up the address environment for the new * thread at the head of the ready-to-run list. */ (void)group_addrenv(rtcb); #endif /* Update scheduler parameters */ sched_resume_scheduler(rtcb); /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } }
void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) { dbg("tcb=0x%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); /* Refuse to handle nested signal actions */ if (tcb->xcp.sigdeliver == NULL) { irqstate_t flags; /* Make sure that interrupts are disabled */ flags = irqsave(); /* First, handle some special cases when the signal is being delivered * to the currently executing task. */ if (tcb == (FAR struct tcb_s*)g_readytorun.head) { /* CASE 1: We are not in an interrupt handler and a task is * signalling itself for some reason. */ if (!IN_INTERRUPT()) { /* In this case just deliver the signal now. */ sigdeliver(tcb); } /* CASE 2: We are in an interrupt handler AND the interrupted task * is the same as the one that must receive the signal, then we * will have to modify the return state as well as the state in * the TCB. */ else { /* Set up to vector to the trampoline with interrupts disabled. */ z80_sigsetup(tcb, sigdeliver, IRQ_STATE()); /* And make sure that the saved context in the TCB * is the same as the interrupt return context. */ SAVE_IRQCONTEXT(tcb); } } /* Otherwise, we are (1) signaling a task is not running from an interrupt * handler or (2) we are not in an interrupt handler and the running task * is signalling some non-running task. */ else { /* Set up to vector to the trampoline with interrupts disabled. */ z80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); } irqrestore(flags); } }
void up_reprioritize_rtr(FAR _TCB *tcb, uint8_t priority) { /* Verify that the caller is sane */ if (tcb->task_state < FIRST_READY_TO_RUN_STATE || tcb->task_state > LAST_READY_TO_RUN_STATE || priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; bool switch_needed; slldbg("TCB=%p PRI=%d\n", tcb, priority); /* Remove the tcb task from the ready-to-run list. * sched_removereadytorun will return true if we just * remove the head of the ready to run list. */ switch_needed = sched_removereadytorun(tcb); /* Setup up the new task priority */ tcb->sched_priority = (uint8_t)priority; /* Return the task to the specified blocked task list. * sched_addreadytorun will return true if the task was * added to the new list. We will need to perform a context * switch only if the EXCLUSIVE or of the two calls is non-zero * (i.e., one and only one the calls changes the head of the * ready-to-run list). */ switch_needed ^= sched_addreadytorun(tcb); /* Now, perform the context switch if one is needed */ if (switch_needed) { /* If we are going to do a context switch, then now is the right * time to add any pending tasks back into the ready-to-run list. * task list now */ if (g_pendingtasks.head) { sched_mergepending(); } /* Are we in an interrupt handler? */ if (IN_INTERRUPT()) { /* Yes, then we have to do things differently. * Just copy the current context into the OLD rtcb. */ SAVE_IRQCONTEXT(rtcb); /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR _TCB*)g_readytorun.head; slldbg("New Active Task TCB=%p\n", rtcb); /* Then setup so that the context will be performed on exit * from the interrupt. */ SET_IRQCONTEXT(rtcb); } /* Copy the exception context into the TCB at the (old) head of the * g_readytorun Task list. if SAVE_USERCONTEXT returns a non-zero * value, then this is really the previously running task restarting! */ else if (!SAVE_USERCONTEXT(rtcb)) { /* Restore the exception context of the rtcb at the (new) head * of the g_readytorun task list. */ rtcb = (FAR _TCB*)g_readytorun.head; slldbg("New Active Task TCB=%p\n", rtcb); /* Then switch contexts */ RESTORE_USERCONTEXT(rtcb); } } } }