void release(struct w_spinlock* lk){ if(!is_held(lk)) return; lk->cpu = 0; atomic_set(&lk->locked,0); pop_cli(); }
int sig_handle(void) { /* Make sure there is a signal being waited on. */ if(!rproc->sig_queue) return 0; /* Not sure if interrupts will mess this up but better be sure */ push_cli(); /* Get the signal from the top of the queue */ struct signal_t* sig = rproc->sig_queue; void (*sig_handler)(int sig_num) = rproc->sigactions[sig->signum].sa_handler; int caught = 0; /* Did we catch the signal? */ int terminated = 0; /* Did we get terminated? */ int stopped = 0; /* Did we get stopped? */ int core = 0; /* Should we dump the core? */ int ignored = 0; /* Was the default action caught and ignored? */ /* Does the user want us to use the default action? */ if(rproc->sigactions[sig->signum].sa_handler == SIG_DFL) sig->catchable = 0; /* Make signal uncatchable */ switch(rproc->sig_queue->default_action) { case SIGDEFAULT_KPANIC: panic("kernel: Invalid signal handled!\n"); break; case SIGDEFAULT_TERM: if(sig->catchable) { caught = 1; } else { terminated = 1; } break; case SIGDEFAULT_CORE: if(sig->catchable) { caught = 1; } else { core = terminated = 1; } break; case SIGDEFAULT_STOP: if(sig->catchable) { caught = 1; } else { stopped = 1; } break; case SIGDEFAULT_CONT: if(sig->catchable) { caught = 1; } break; case SIGDEFAULT_IGN: if(sig->catchable) { caught = 1; } break; } /** * If the user wants this signal to be ignored, ignore it. * EXCEPTIONS: if we are terminated, dumped or stopped then * we must continue with the default action. */ if(rproc->sigactions[sig->signum].sa_handler == SIG_IGN) { if(!terminated && !stopped && !core) ignored = 1; caught = 0; } /* Were we able to catch the signal? */ if(caught) { /* Do we have a signal stack? */ if(!rproc->sig_stack_start) { /* TODO: probably don't use mmap here, this will */ /* change in the future. */ /* Allocate a signal stack */ int pages = SIG_DEFAULT_STACK + SIG_DEFAULT_GUARD; uint end = (uint)mmap(NULL, pages * PGSIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); /* Unmap all guard pages */ int x; for(x = 0;x < SIG_DEFAULT_GUARD;x++) { vm_unmappage(end, rproc->pgdir); end += PGSIZE; } /* Set sig stack start */ rproc->sig_stack_start = end + (SIG_DEFAULT_STACK * PGSIZE); } /* Save the current trap frame if we need to */ if(!rproc->sig_handling) { /* We weren't handling a signal until now */ memmove(&rproc->sig_saved, (char*)rproc->k_stack - sizeof(struct trap_frame), sizeof(struct trap_frame)); } pstack_t stack = rproc->sig_stack_start; /* set the return address to the sig handler */ rproc->tf->eip = (uintptr_t)sig_handler; vmflags_t dir_flags = VM_DIR_USRP | VM_DIR_READ | VM_DIR_WRIT; vmflags_t tbl_flags = VM_TBL_USRP | VM_TBL_READ | VM_TBL_WRIT; /* Push argument (sig) */ stack -= sizeof(int); vm_memmove((void*)stack, &sig->signum, sizeof(int), rproc->pgdir, rproc->pgdir, dir_flags, tbl_flags); /* (safely) Push our magic return value */ stack -= sizeof(int); uint32_t mag = SIG_MAGIC; vm_memmove((void*)stack, &mag, sizeof(int), rproc->pgdir, rproc->pgdir, dir_flags, tbl_flags); /* Update stack pointer */ rproc->tf->esp = stack; /* We are now actively handling this signal */ rproc->sig_handling = 1; } pop_cli(); /* Check to see if we need to dump the core */ if(core) { /* Dump memory for gdb analysis */ #ifdef DEBUG cprintf("%s:%d: CORE DUMPED\n", rproc->name, rproc->pid); #endif rproc->status_changed = 1; rproc->return_code = ((sig->signum & 0xFF) << 0x8) | 0x02; rproc->state = PROC_ZOMBIE; wake_parent(rproc); yield_withlock(); } /* If we got stopped, we will enter scheduler. */ if(stopped) { #ifdef DEBUG cprintf("%s:%d: process stopped.\n", rproc->name, rproc->pid); #endif rproc->status_changed = 1; rproc->state = PROC_STOPPED; rproc->return_code = ((sig->signum & 0xFF) << 0x08) | 0x04; /* Should we wake the parent? */ if(!rproc->orphan && rproc->parent && (rproc->parent->wait_options & WUNTRACED)) { wake_parent(rproc); } sig_dequeue(rproc); yield_withlock(); /* Should we wake our parent now that we've continued */ rproc->status_changed = 1; if(!rproc->orphan && rproc->parent && (rproc->parent->wait_options & WCONTINUED)) { wake_parent(rproc); } } /* Check to see if we got terminated */ if(terminated) { #ifdef DEBUG cprintf("%s:%d: Process killed by signal. No core dumped.\n", rproc->name, rproc->pid); #endif rproc->status_changed = 1; rproc->return_code = ((sig->signum & 0xFF) << 0x08) | 0x01; rproc->state = PROC_ZOMBIE; wake_parent(rproc); yield_withlock(); } if(ignored) sig_dequeue(rproc); return 0; }