Пример #1
0
void do_ipc(tcb_t* from, tcb_t* to) {
	ipc_msg_tag_t tag;
	ipc_typed_item	typed_item;
	int untyped_idx, typed_idx, typed_item_idx;
	int typed_last, untyped_last;
	uint32_t typed_data;		/* typed item extra word*/

	/*Copy tag of message*/
	tag.raw = ipc_read_mr(from, 0);
	untyped_last = tag.s.n_untyped + 1;
	typed_last = untyped_last + tag.s.n_typed;

	if(typed_last > IPC_MR_COUNT) {
		set_user_error(from, UE_IPC_MSG_OVERFLOW | UE_IPC_PHASE_SEND);
		set_user_error(to, UE_IPC_MSG_OVERFLOW | UE_IPC_PHASE_RECV);
		return;
	}

	ipc_write_mr(to, 0, tag.s.label << 16);

	/*Copy untyped words*/
	for(untyped_idx = 1; untyped_idx < untyped_last; ++untyped_idx) {
		ipc_write_mr(to, untyped_idx, ipc_read_mr(from, untyped_idx));
	}

	typed_item_idx = -1;
	/* Copy typed words
	 * FSM: j - number of byte*/
	for(typed_idx = untyped_idx; typed_idx < typed_last; ++typed_idx) {
		if(typed_item_idx == -1) {
			/*If typed_item_idx == -1 - read ti's tag*/
			typed_item.raw = ipc_read_mr(from, typed_idx);
			++typed_item_idx;
		}
		else if(typed_item.s.header & IPC_TI_MAP_GRANT) {
			/* MapItem / GrantItem have 1xxx in header */
			typed_data = ipc_read_mr(from, typed_idx);

			map_area(from->as, to->as, typed_item.raw & 0xFFFFFFC0, typed_data & 0xFFFFFFC0,
						(typed_item.s.header & IPC_TI_GRANT)? GRANT : MAP, thread_ispriviliged(from));
			typed_item_idx = -1;
		}

		/*TODO: StringItem support*/
	}

	to->utcb->sender = from->t_globalid;

	to->state = T_RUNNABLE;
	to->ipc_from = L4_NILTHREAD;
	from->state = T_RUNNABLE;

	/*Dispatch communicating threads*/
	sched_slot_dispatch(SSI_NORMAL_THREAD, from);
	sched_slot_dispatch(SSI_IPC_THREAD, to);

	dbg_printf(DL_IPC, "IPC: %t to %t\n", caller->t_globalid, to->t_globalid);
}
Пример #2
0
static void do_ipc(tcb_t *from, tcb_t *to)
{
	ipc_msg_tag_t tag;
	ipc_typed_item	typed_item;
	int untyped_idx, typed_idx, typed_item_idx;
	int typed_last, untyped_last;
	uint32_t typed_data;		/* typed item extra word */
	l4_thread_t from_recv_tid;

	/* Clear timeout event when ipc is established. */
	from->timeout_event = 0;
	to->timeout_event = 0;

	/* Copy tag of message */
	tag.raw = ipc_read_mr(from, 0);
	untyped_last = tag.s.n_untyped + 1;
	typed_last = untyped_last + tag.s.n_typed;

	if (typed_last > IPC_MR_COUNT) {
		do_ipc_error(from, to,
		             UE_IPC_MSG_OVERFLOW | UE_IPC_PHASE_SEND,
		             UE_IPC_MSG_OVERFLOW | UE_IPC_PHASE_RECV,
		             T_RUNNABLE,
		             T_RUNNABLE);
		return;
	}

	ipc_write_mr(to, 0, tag.raw);

	/* Copy untyped words */
	for (untyped_idx = 1; untyped_idx < untyped_last; ++untyped_idx) {
		ipc_write_mr(to, untyped_idx, ipc_read_mr(from, untyped_idx));
	}

	typed_item_idx = -1;
	/* Copy typed words
	 * FSM: j - number of byte */
	for (typed_idx = untyped_idx; typed_idx < typed_last; ++typed_idx) {
		uint32_t mr_data = ipc_read_mr(from, typed_idx);

		/* Write typed mr data to 'to' thread */
		ipc_write_mr(to, typed_idx, mr_data);

		if (typed_item_idx == -1) {
			/* If typed_item_idx == -1 - read typed item's tag */
			typed_item.raw = mr_data;
			++typed_item_idx;
		} else if (typed_item.s.header & IPC_TI_MAP_GRANT) {
			/* MapItem / GrantItem have 1xxx in header */
			int ret;
			typed_data = mr_data;

			ret = map_area(from->as, to->as,
			         typed_item.raw & 0xFFFFFFC0,
			         typed_data & 0xFFFFFFC0,
			         (typed_item.s.header & IPC_TI_GRANT) ? GRANT : MAP,
			         thread_ispriviliged(from));
			typed_item_idx = -1;

			if (ret < 0) {
				do_ipc_error(from, to,
				             UE_IPC_ABORTED | UE_IPC_PHASE_SEND,
				             UE_IPC_ABORTED | UE_IPC_PHASE_RECV,
				             T_RUNNABLE,
				             T_RUNNABLE);
				return;
			}
		}

		/* TODO: StringItem support */
	}

	if (!to->ctx.sp || !from->ctx.sp) {
		do_ipc_error(from, to,
		             UE_IPC_ABORTED | UE_IPC_PHASE_SEND,
		             UE_IPC_ABORTED | UE_IPC_PHASE_RECV,
		             T_RUNNABLE,
		             T_RUNNABLE);
		return;
	}

	to->utcb->sender = from->t_globalid;

	to->state = T_RUNNABLE;
	to->ipc_from = L4_NILTHREAD;
	((uint32_t*)to->ctx.sp)[REG_R0] = from->t_globalid;

	/* If from has receive phases, lock myself */
	from_recv_tid = ((uint32_t*)from->ctx.sp)[REG_R1];
	if (from_recv_tid == L4_NILTHREAD) {
		from->state = T_RUNNABLE;
	} else {
		from->state = T_RECV_BLOCKED;
		from->ipc_from = from_recv_tid;

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

	/* Dispatch communicating threads */
	sched_slot_dispatch(SSI_NORMAL_THREAD, from);
	sched_slot_dispatch(SSI_IPC_THREAD, to);

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