Example #1
0
uint32_t ipc_deliver(void *data)
{
	tcb_t *thr = NULL, *from_thr = NULL, *to_thr = NULL;
	l4_thread_t receiver;
	int i;

	for (i = 1; i < thread_count; ++i) {
		thr = thread_map[i];
		switch (thr->state) {
		case T_RECV_BLOCKED:
			if (thr->ipc_from != L4_NILTHREAD &&
				thr->ipc_from != L4_ANYTHREAD &&
				thr->ipc_from != TID_TO_GLOBALID(THREAD_INTERRUPT)) {
				from_thr = thread_by_globalid(thr->ipc_from);
				if (from_thr->state == T_SEND_BLOCKED)
					do_ipc(from_thr, thr);
			}
			break;
		case T_SEND_BLOCKED:
			receiver = thr->utcb->intended_receiver;
			if (receiver != L4_NILTHREAD && receiver != L4_ANYTHREAD) {
				to_thr = thread_by_globalid(receiver);
				if (to_thr->state == T_RECV_BLOCKED)
					do_ipc(thr, to_thr);
			}
			break;
		default:
			break;
		}
	}

	return 4096;
}
Example #2
0
void sys_ipc(uint32_t *param1)
{
	/* TODO: Checking of recv-mask */
	tcb_t *to_thr = NULL;
	l4_thread_t to_tid = param1[REG_R0], from_tid = param1[REG_R1];

	if (to_tid != L4_NILTHREAD) {
		to_thr = thread_by_globalid(to_tid);

		if (to_tid == TID_TO_GLOBALID(THREAD_LOG)) {
			user_log(caller);
			caller->state = T_RUNNABLE;
		} else if ((to_thr && to_thr->state == T_RECV_BLOCKED)
		           || to_tid == caller->t_globalid) {
			/* To thread who is waiting for us or sends to myself */
			do_ipc(caller, to_thr);
		} else if (to_thr && to_thr->state == T_INACTIVE &&
		           GLOBALID_TO_TID(to_thr->utcb->t_pager) == GLOBALID_TO_TID(caller->t_globalid)) {
			if (ipc_read_mr(caller, 0) == 0x00000003) {
				/* thread start protocol */

				memptr_t sp = ipc_read_mr(caller, 2);
				size_t stack_size = ipc_read_mr(caller, 3);

				dbg_printf(DL_IPC, "IPC: %t thread start\n", to_tid);

				to_thr->stack_base = sp - stack_size;
				to_thr->stack_size = stack_size;

				thread_init_ctx((void *) sp, (void *) ipc_read_mr(caller, 1), to_thr);
				caller->state = T_RUNNABLE;

				/* Start thread */
				to_thr->state = T_RUNNABLE;
			} else {
				do_ipc(caller, to_thr);
				to_thr->state = T_INACTIVE;
			}
		} else  {
			/* No waiting, block myself */
			caller->state = T_SEND_BLOCKED;
			caller->utcb->intended_receiver = to_tid;

			dbg_printf(DL_IPC, "IPC: %t sending\n", caller->t_globalid);

			return;
		}
	}

	if (from_tid != L4_NILTHREAD) {
		/* Only receive phases, simply lock myself */
		caller->state = T_RECV_BLOCKED;
		caller->ipc_from = from_tid;

		dbg_printf(DL_IPC, "IPC: %t receiving\n", caller->t_globalid);
	}
}
Example #3
0
void sys_ipc(uint32_t *param1)
{
	/* TODO: Checking of recv-mask */
	tcb_t *to_thr = NULL;
	l4_thread_t to_tid = param1[REG_R0], from_tid = param1[REG_R1];
	uint32_t timeout = param1[REG_R2];

	if (to_tid == L4_NILTHREAD &&
		from_tid == L4_NILTHREAD) {
		caller->state = T_INACTIVE;
		if (timeout)
			sys_ipc_timeout(timeout);
		return;
	}

	if (to_tid != L4_NILTHREAD) {
		to_thr = thread_by_globalid(to_tid);

		if (to_tid == TID_TO_GLOBALID(THREAD_LOG)) {
			user_log(caller);
			caller->state = T_RUNNABLE;
			return;
		} else if (to_tid == TID_TO_GLOBALID(THREAD_IRQ_REQUEST)) {
			user_interrupt_config(caller);
			caller->state = T_RUNNABLE;
			return;
		} else if ((to_thr && to_thr->state == T_RECV_BLOCKED)
		           || to_tid == caller->t_globalid) {
			/* To thread who is waiting for us or sends to myself */
			do_ipc(caller, to_thr);
			return;
		} else if (to_thr && to_thr->state == T_INACTIVE &&
		           GLOBALID_TO_TID(to_thr->utcb->t_pager) == GLOBALID_TO_TID(caller->t_globalid)) {
			if (ipc_read_mr(caller, 0) == 0x00000005) {
				/* mr1: thread func, mr2: stack addr, mr3: stack size*/
				/* mr4: thread entry, mr5: thread args */
				/* thread start protocol */

				memptr_t sp = ipc_read_mr(caller, 2);
				size_t stack_size = ipc_read_mr(caller, 3);
				uint32_t regs[4];	/* r0, r1, r2, r3 */

				dbg_printf(DL_IPC, "IPC: %t thread start\n", to_tid);

				to_thr->stack_base = sp - stack_size;
				to_thr->stack_size = stack_size;

				regs[REG_R0] = (uint32_t)&kip;
				regs[REG_R1] = (uint32_t)to_thr->utcb;
				regs[REG_R2] = ipc_read_mr(caller, 4);
				regs[REG_R3] = ipc_read_mr(caller, 5);
				thread_init_ctx((void *) sp, (void *) ipc_read_mr(caller, 1),
				                regs, to_thr);

				caller->state = T_RUNNABLE;

				/* Start thread */
				to_thr->state = T_RUNNABLE;

				return;
			} else {
				do_ipc(caller, to_thr);
				to_thr->state = T_INACTIVE;

				return;
			}
		} else  {
			/* No waiting, block myself */
			caller->state = T_SEND_BLOCKED;
			caller->utcb->intended_receiver = to_tid;
			dbg_printf(DL_IPC, "IPC: %t sending\n", caller->t_globalid);

			if (timeout)
				sys_ipc_timeout(timeout);

			return;
		}
	}

	if (from_tid != L4_NILTHREAD) {
		tcb_t *thr = NULL;

		if (from_tid == L4_ANYTHREAD) {
			int i;
			/* Find out if there is any sending thread waiting for caller */
			for (i = 1; i < thread_count; ++i) {
				thr = thread_map[i];
				if (thr->state == T_SEND_BLOCKED &&
				    thr->utcb->intended_receiver == caller->t_globalid) {
					do_ipc(thr, caller);
					return;
				}
			}
		} else if (from_tid != TID_TO_GLOBALID(THREAD_INTERRUPT)) {
			thr = thread_by_globalid(from_tid);

			if (thr->state == T_SEND_BLOCKED &&
			    thr->utcb->intended_receiver == caller->t_globalid) {
				do_ipc(thr, caller);
				return;
			}
		}

		/* Only receive phases, simply lock myself */
		caller->state = T_RECV_BLOCKED;
		caller->ipc_from = from_tid;

		if (from_tid == TID_TO_GLOBALID(THREAD_INTERRUPT)) {
			/* Threaded interrupt is ready */
			user_interrupt_handler_update(caller);
		}

		if (timeout)
			sys_ipc_timeout(timeout);

		dbg_printf(DL_IPC, "IPC: %t receiving\n", caller->t_globalid);

		return;
	}

	caller->state = T_SEND_BLOCKED;
}