__interrupt void Port2GPIOHandler(void) { static uint8_t pll_count; if (P2IFG & BIT3) { // PLL FEEDBACK P2IFG &= ~BIT3; pll_count++; if (pll_count == 100) { P2OUT |= BIT2; } if (pll_count >= 200) { P2OUT &= ~BIT2; pll_count = 0; } //TICK THE TIME time_tick(); run_led_driver(); if (ready_to_sample()) { sample_enabled_sensors(); } } if(inside_non_blocking_interrupt == FALSE) { inside_non_blocking_interrupt = TRUE; do_non_blocking_interrupt(); inside_non_blocking_interrupt = FALSE; } }
TEST(guards_test, is_game_timeout_false) { //given auto ticks = std::make_shared<time_ticks>(0); auto game_time = 10; is_game_timeout guard(ticks, game_time); //when && then EXPECT_FALSE(guard(time_tick())); }
TEST(guards_test, is_game_timeout_true) { //given auto ticks = std::make_shared<time_ticks>(15); auto game_time = 10; is_game_timeout guard(ticks, game_time); //when && then EXPECT_TRUE(guard(time_tick())); }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. int32_t ret; switch (tf->tf_trapno){ case T_PGFLT:{ //14 page_fault_handler(tf); return; } case T_BRKPT:{ //3 breakpoint_handler(tf); return; } case T_DEBUG:{ breakpoint_handler(tf); return; } case T_SYSCALL:{ ret = system_call_handler(tf); tf->tf_regs.reg_eax = ret; return; } case IRQ_OFFSET+IRQ_TIMER:{ lapic_eoi(); time_tick(); sched_yield(); return; } case IRQ_OFFSET+IRQ_KBD:{ kbd_intr(); return; } case IRQ_OFFSET+IRQ_SERIAL:{ serial_intr(); return; } case IRQ_OFFSET+IRQ_E1000:{ e1000_trap_handler(); return; } } // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // Handle clock interrupts. Don't forget to acknowledge the // interrupt using lapic_eoi() before calling the scheduler! // LAB 4: Your code here. // Add time tick increment to clock interrupts. // Be careful! In multiprocessors, clock interrupts are // triggered on every CPU. // LAB 6: Your code here. // Handle keyboard and serial interrupts. // LAB 5: Your code here. // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }
static void trap_dispatch(struct Trapframe *tf) { int32_t res; // Handle processor exceptions. // LAB 3: Your code here. // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // Handle clock interrupts. Don't forget to acknowledge the // interrupt using lapic_eoi() before calling the scheduler! // LAB 4: Your code here. // Add time tick increment to clock interrupts. // Be careful! In multiprocessors, clock interrupts are // triggered on every CPU. // LAB 6: Your code here. // Handle keyboard and serial interrupts. // LAB 5: Your code here. //if(tf->tf_trapno == 48 && tf->tf_regs.reg_eax==7) //{ //cprintf("trap no = %d at cpu %d env %x\n",tf->tf_trapno,cpunum(),curenv->env_id); //print_trapframe(tf); //} switch(tf->tf_trapno) { case IRQ_OFFSET + IRQ_TIMER: //cprintf("clock interrupt on irq 7 on cpu %d\n",cpunum()); //print_trapframe(tf); //cprintf(" eip 0x%08x\n", tf->tf_eip); //cprintf(" esp 0x%08x\n", tf->tf_esp); lapic_eoi(); time_tick(); sched_yield(); break; case IRQ_OFFSET + IRQ_SERIAL: serial_intr(); break; case IRQ_OFFSET + IRQ_KBD: kbd_intr(); break; case T_DIVIDE: tf->tf_regs.reg_ecx = 1; break; case T_PGFLT: page_fault_handler(tf); goto err; case T_SYSCALL: res = syscall(tf->tf_regs.reg_eax,tf->tf_regs.reg_edx,tf->tf_regs.reg_ecx,tf->tf_regs.reg_ebx,tf->tf_regs.reg_edi,tf->tf_regs.reg_esi); tf->tf_regs.reg_eax = res; break; case T_BRKPT:print_trapframe(tf);monitor(NULL);break; default: goto err; } return; err: // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. switch(tf->tf_trapno) { case T_PGFLT: page_fault_handler(tf); return; case T_BRKPT: case T_DEBUG: monitor(tf); return; case T_SYSCALL: tf->tf_regs.reg_eax = syscall(tf->tf_regs.reg_eax, // syscall # tf->tf_regs.reg_edx, // arg1 tf->tf_regs.reg_ecx, // arg2 tf->tf_regs.reg_ebx, // arg3 tf->tf_regs.reg_edi, // arg4 tf->tf_regs.reg_esi);// arg5 return; } // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // Handle clock interrupts. Don't forget to acknowledge the // interrupt using lapic_eoi() before calling the scheduler! // Add time tick increment to clock interrupts. // Be careful! In multiprocessors, clock interrupts are // triggered on every CPU. // LAB 4: Your code here. // LAB 6: Your code here. if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) { time_tick(); lapic_eoi(); sched_yield(); return; } // Handle keyboard and serial interrupts. // LAB 7: Your code here. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) { serial_intr(); return; } if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) { kbd_intr(); return; } // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }
// Main loop the game int game_loop() { SDL_Rect dest; int x, y, aux; SDL_Event event; unsigned long t1, t2; int no_unselect = 0; // Main loop t1 = SDL_GetTicks(); while (1) { // Restart the game if (game_state.state == NEW_GAME){ if (gm == GM_MULTIPLAYER) { aux = BOARD_RESTARTED; write_socket(&aux, sizeof(int)); new_game(false, GM_MULTIPLAYER, false); } else { new_game(false, GM_SINGLE, false); } } else if (game_state.state == GAME_LOSE || game_state.state == GAME_WIN || game_state.state == GAME_EXIT) { if (gm == GM_MULTIPLAYER) { if (game_state.state == GAME_EXIT) { aux = END_GAME; write_socket(&aux, sizeof(int)); } finish_attack(game_state.state == GAME_WIN); } dest.x = 386; dest.y = 151; dest.w = dest.h = 0; if (game_state.state != GAME_EXIT) { SDL_BlitSurface(game_state.state == GAME_WIN ? win : lose, NULL, screen, &dest); SDL_Update(386, 151, 365, 178); SDL_Delay(4000); } return (game_state.state == GAME_LOSE); } if (SDL_PollEvent(&event)) { switch (event.type) { // Key pressed case SDL_KEYDOWN: if (event.key.state == SDL_PRESSED) { // Quit if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_F4 || event.key.keysym.sym == SDLK_F5 || event.key.keysym.sym == SDLK_F6) { game_state.state = GAME_EXIT; } } // Quit the game case SDL_QUIT: game_state.state = GAME_EXIT; break; // Window focus change #if 0 case SDL_ACTIVEEVENT: if (event.active.gain == 0 && gm != GM_MULTIPLAYER) { game_state.state = GAME_EXIT; } break; #endif // Button pressed case SDL_MOUSEBUTTONUP: case SDL_FINGERUP: no_unselect = 1; if (game_state.state == UNSELECTED_FIRST) { game_state.state = IDLE; break; } case SDL_MOUSEBUTTONDOWN: case SDL_FINGERDOWN: if (event.type == SDL_FINGERDOWN) { event.button.x = event.tfinger.x; event.button.y = event.tfinger.y; } // Diamond area if (event.button.x >= BOARD_OFFSETX && event.button.x < BOARD_WIDTH * DIAMOND_WIDTH + BOARD_OFFSETX && event.button.y >= BOARD_OFFSETY && event.button.y < BOARD_HEIGHT * DIAMOND_HEIGHT + BOARD_OFFSETY) { x = (event.button.x - BOARD_OFFSETX) / DIAMOND_WIDTH; y = (event.button.y - BOARD_OFFSETY) / DIAMOND_HEIGHT; if (game_state.state == IDLE) { game_state.state = SELECTED_FIRST; game_state.x_first = x; game_state.y_first = y; draw = true; } else if (game_state.state == SELECTED_FIRST) { if(game_state.x_first == x && game_state.y_first == y && !no_unselect) { game_state.state = UNSELECTED_FIRST; draw = true; } else if ((abs(game_state.x_first - x) == 1 && (game_state.y_first == y)) || ((game_state.x_first == x) && (abs(game_state.y_first - y) == 1))){ game_state.state = SELECTED_SECOND; game_state.x_second = x; game_state.y_second = y; draw = true; } else { game_state.x_first = x; game_state.y_first = y; draw = true; } } } else if (event.button.x >= BACK2_OFFSETX && event.button.y >= BACK2_OFFSETY && event.button.x < BACK2_OFFSETX2 && event.button.y < BACK2_OFFSETY2) { game_state.state = GAME_EXIT; break; } no_unselect = 0; break; } } // Update screen and reset timer time_tick(); if (draw_screen()) { t1 = SDL_GetTicks(); } // Calculate time and send attack for multiplayer if (gm == GM_MULTIPLAYER) { update_player(); if (ss == SS_CLOSE) { return 0; } else { t2 = SDL_GetTicks(); if (t2 - t1 >= 3500 || combo_score > 310) { t1 = t2; total_score += combo_score; // Update life if (combo_score) { if (total_score >= 1400) { total_score = 1400; game_state.state = GAME_WIN; } else start_attack(1); dest.x = LIFE_ENEMYX - total_score / 10; dest.y = LIFEY; dest.w = total_score / 10; dest.h = LIFE_HEIGHT; SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 0, 0)); SDL_Update(LIFE_ENEMYX - LIFE_WIDTH, LIFEY, LIFE_WIDTH, LIFE_HEIGHT); write_socket(&combo_score, sizeof(int)); combo_score = 0; // Erase progress bar dest.x = 21; dest.y = 335; dest.w = 311; dest.h = 36; SDL_BlitSurface(bg, &dest, screen, &dest); SDL_Update(dest.x, dest.y, dest.w, dest.h); } } } // Timer for single player } else { t2 = SDL_GetTicks(); if (t2 - t1 >= timer_delay) { t1 = t2; single_timer -= 2; if (single_timer <= 0) game_state.state = GAME_LOSE; draw_timer_bar(true); } } } }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. if (tf->tf_trapno == T_BRKPT) { print_trapframe(tf); // cprintf("Breakpoint!\n"); while (1) monitor(NULL); } else if (tf->tf_trapno == T_PGFLT) { page_fault_handler(tf); return; } else if (tf->tf_trapno == T_SYSCALL) { uint32_t syscallno; uint32_t a1, a2, a3, a4, a5; syscallno = tf->tf_regs.reg_eax; a1 = tf->tf_regs.reg_edx; a2 = tf->tf_regs.reg_ecx; a3 = tf->tf_regs.reg_ebx; a4 = tf->tf_regs.reg_edi; a5 = tf->tf_regs.reg_esi; int32_t ret = syscall(syscallno, a1, a2, a3, a4, a5); tf->tf_regs.reg_eax = ret; return; } // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // Handle clock interrupts. Don't forget to acknowledge the // interrupt using lapic_eoi() before calling the scheduler! // LAB 4: Your code here. if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) { time_tick(); lapic_eoi(); /* what's that? */ sched_yield(); } // Handle keyboard and serial interrupts. // LAB 5: Your code here. if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) { kbd_intr(); return; } if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) { serial_intr(); return; } // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. //<<<<<<< HEAD // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } //cprintf("entering trap dispathc\n"); // Handle clock interrupts. Don't forget to acknowledge the // interrupt using lapic_eoi() before calling the scheduler! // LAB 4: Your code here. //<<<<<<< HEAD // Add time tick increment to clock interrupts. // Be careful! In multiprocessors, clock interrupts are // triggered on every CPU. // LAB 6: Your code here. //======= //<<<<<<< HEAD //>>>>>>> lab5 // Handle keyboard and serial interrupts. // LAB 5: Your code here. if(tf->tf_trapno==IRQ_OFFSET+IRQ_KBD) { //cprintf("IRQ_OFFSET+IRQ_KBD trap\n"); kbd_intr(); return; } if(tf->tf_trapno==IRQ_OFFSET+IRQ_SERIAL) { //cprintf("IRQ_OFFSET+IRQ_serial trap\n"); serial_intr(); return; } //======= //======= if(tf->tf_trapno==T_PGFLT) { // cprintf("pagefault handler\n"); page_fault_handler(tf); return; } else if((tf->tf_trapno==T_GPFLT)) { print_trapframe(tf); return; } else if(tf->tf_trapno==T_BRKPT) { // cprintf("T_BRKPT"); monitor(tf); return; } else if(tf->tf_trapno==T_SYSCALL) {// cprintf("calling syscal'\n"); tf->tf_regs.reg_rax =syscall(tf->tf_regs.reg_rax,tf->tf_regs.reg_rdx,tf->tf_regs.reg_rcx,tf->tf_regs.reg_rbx,tf->tf_regs.reg_rdi,tf->tf_regs.reg_rsi); // cprintf("syscall exit\n"); return; } //>>>>>>> lab3 //>>>>>>> lab4 // Unexpected trap: The user process or the kernel has a bug. else if(tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) { lapic_eoi(); time_tick(); sched_yield(); } print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { cprintf("destroy env\n"); env_destroy(curenv); return; } // cprintf("exiting trap_dispatch\n"); }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. int32_t ret; // if (tf->tf_trapno != 48) cprintf("****** No. %d\n", tf->tf_trapno); // Handle clock interrupts. // LAB 4: Your code here. if (tf->tf_trapno == IRQ_OFFSET + 0){ // cprintf("Timer interrupt\n"); time_tick(); sched_yield(); return ; } // Add time tick increment to clock interrupts. // LAB 6: Your code here. // Add time_tick above sched_yield // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // LAB 7: Keyboard interface if (tf->tf_trapno == IRQ_OFFSET + 1){ kbd_intr(); return ; } if (tf->tf_trapno == IRQ_OFFSET + 4){ serial_intr(); return ; } if (tf->tf_trapno == T_DIVIDE || tf->tf_trapno == T_ILLOP || tf->tf_trapno == T_GPFLT){ // cprintf("*************"); // return ; } if (tf->tf_trapno == T_DEBUG){ // Debug info // cprintf("*** trap %08x %s ***\n", tf->tf_trapno, trapname(tf->tf_trapno)); // Invoke monitor monitor(tf); return ; } if (tf->tf_trapno == T_BRKPT){ // Debug info // cprintf("*** trap %08x %s ***\n", tf->tf_trapno, trapname(tf->tf_trapno)); // Invoke monitor monitor(tf); return ; } if (tf->tf_trapno == T_PGFLT){ page_fault_handler(tf); } if (tf->tf_trapno == T_SYSCALL){ ret = syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_edx, tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx, tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); tf->tf_regs.reg_eax = ret; return ; } // Handle keyboard and serial interrupts. // LAB 7: Your code here. // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT){ if (tf->tf_trapno == T_DEBUG){ return ; } panic("unhandled trap in kernel"); } else { env_destroy(curenv); return; } }
/** ********************************************************** * @brief Draws the gems changing location * * This function draws gems changing location * * **********************************************************/ void changing_location(){ SDL_Event event; int i, min, max,temp; SDL_Rect dest, dest_gem; //moving vertically if (game_state.x_first == game_state.x_second) { min = game_state.y_first > game_state.y_second ? game_state.y_second : game_state.y_first; max = game_state.y_first < game_state.y_second ? game_state.y_second : game_state.y_first; dest.x = game_state.x_first*DIAMOND_WIDTH +BOARD_OFFSETX; dest.w = DIAMOND_WIDTH; dest.y = min*DIAMOND_HEIGHT+BOARD_OFFSETY; dest.h = 2*DIAMOND_HEIGHT; dest_gem.x = dest.x; dest_gem.w = DIAMOND_WIDTH; dest_gem.h = DIAMOND_HEIGHT; for(i=0; i<=DIAMOND_HEIGHT; i += 3){ SDL_BlitSurface(bg, &dest, screen, &dest); dest_gem.y = i+min*DIAMOND_HEIGHT+BOARD_OFFSETY; SDL_BlitSurface(diamond[matrix[min][game_state.x_second]], NULL, screen, &dest_gem); dest_gem.y = max*DIAMOND_HEIGHT+BOARD_OFFSETY-i; SDL_BlitSurface(diamond[matrix[max][game_state.x_first]], NULL, screen, &dest_gem); //drawing the selection dest_gem.w = 0; dest_gem.h = 0; dest_gem.x = game_state.x_first * DIAMOND_WIDTH + BOARD_OFFSETX; dest_gem.y = game_state.y_first * DIAMOND_HEIGHT + BOARD_OFFSETY; SDL_BlitSurface(selection, NULL, screen, &dest_gem); dest_gem.y = game_state.y_second * DIAMOND_HEIGHT + BOARD_OFFSETY; SDL_BlitSurface(selection, NULL, screen, &dest_gem); SDL_Update(dest.x, dest.y,dest.w,dest.h); update_player(); time_tick(); } temp=matrix[max][game_state.x_first]; matrix[max][game_state.x_first]=matrix[min][game_state.x_second]; matrix[min][game_state.x_second]=temp; } //moving horizontally else { min = game_state.x_first > game_state.x_second ? game_state.x_second : game_state.x_first; max = game_state.x_first < game_state.x_second ? game_state.x_second : game_state.x_first; dest.x = min*DIAMOND_WIDTH +BOARD_OFFSETX; dest.w = 2*DIAMOND_WIDTH; dest.y = game_state.y_first*DIAMOND_HEIGHT+BOARD_OFFSETY; dest.h = DIAMOND_HEIGHT; dest_gem.y = dest.y; dest_gem.w = DIAMOND_WIDTH; dest_gem.h = DIAMOND_HEIGHT; for(i=0; i<=DIAMOND_HEIGHT; i += 3){ SDL_BlitSurface(bg, &dest, screen, &dest); dest_gem.x = i+min*DIAMOND_WIDTH+BOARD_OFFSETX; SDL_BlitSurface(diamond[matrix[game_state.y_second][min]], NULL, screen, &dest_gem); dest_gem.x = max*DIAMOND_WIDTH+BOARD_OFFSETX-i; SDL_BlitSurface(diamond[matrix[game_state.y_first][max]], NULL, screen, &dest_gem); //drawing the selection dest_gem.w = 0; dest_gem.h = 0; dest_gem.x = game_state.x_first * DIAMOND_WIDTH + BOARD_OFFSETX; dest_gem.y = game_state.y_first * DIAMOND_HEIGHT + BOARD_OFFSETY; SDL_BlitSurface(selection, NULL, screen, &dest_gem); dest_gem.x = game_state.x_second * DIAMOND_WIDTH + BOARD_OFFSETX; SDL_BlitSurface(selection, NULL, screen, &dest_gem); SDL_Update(dest.x, dest.y,dest.w,dest.h); update_player(); time_tick(); } temp=matrix[game_state.y_first][max]; matrix[game_state.y_first][max]=matrix[game_state.y_second][min]; matrix[game_state.y_second][min]=temp; } while (SDL_PollEvent(&event)); }
static void trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. int32_t sc_ret; assert(tf != NULL); switch (tf->tf_trapno) { case T_PGFLT: page_fault_handler(tf); return; case T_BRKPT: case T_DEBUG: /* break into the kernel monitor */ while (1) { monitor(tf); } return; case T_SYSCALL: sc_ret = syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_edx, tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx, tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); tf->tf_regs.reg_eax = sc_ret; return; default: break; } // Handle clock interrupts. // LAB 4: Your code here. // Add time tick increment to clock interrupts. // LAB 6: Your code here. switch (tf->tf_trapno) { case (IRQ_OFFSET + IRQ_TIMER): time_tick(); sched_yield(); return; case (IRQ_OFFSET + IRQ_KBD): //cprintf("Keyboard interrupt on irq %d\n", IRQ_KBD); kbd_intr(); return; case (IRQ_OFFSET + IRQ_SERIAL): //cprintf("Serial interrupt on irq %d\n", IRQ_SERIAL); serial_intr(); return; default: break; } if (tf->tf_trapno == (IRQ_OFFSET + e100_irq_line)) { cprintf("E100 interrupt on irq %d\n", e100_irq_line); return; } // Handle spurious interrupts // The hardware sometimes raises these because of noise on the // IRQ line or other reasons. We don't care. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) { cprintf("Spurious interrupt on irq 7\n"); print_trapframe(tf); return; } // Handle keyboard and serial interrupts. // LAB 7: Your code here. // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }