示例#1
0
void release(struct w_spinlock* lk){

	if(!is_held(lk))
		return;

	lk->cpu = 0;
	atomic_set(&lk->locked,0);

	pop_cli();
}
示例#2
0
文件: signal.c 项目: jdetter/Chronos
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;
}