コード例 #1
0
ファイル: ipc.c プロジェクト: AlexandrSalin/l4xpresso
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
ファイル: ipc.c プロジェクト: ajblane/f9-kernel
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);
	}
}
コード例 #3
0
ファイル: ipc.c プロジェクト: AlexandrSalin/l4xpresso
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_thr && to_thr->state == T_RECV_BLOCKED)
				|| to_tid == caller->t_globalid ) {
			/* To thread who waiting us or send 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)) {
			/* That is thread start protocol */

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

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

			/*Start thread*/
			to_thr->state = T_RUNNABLE;
		}
		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(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);
	}
}
コード例 #4
0
ファイル: ipc.c プロジェクト: ChiwenLin/f9-kernel
static void user_ipc_error(tcb_t *thr, enum user_error_t error)
{
	ipc_msg_tag_t tag;

	/* Set ipc unsuccessful */
	tag.raw = ipc_read_mr(thr, 0);
	tag.s.flags |= 0x8;
	ipc_write_mr(thr, 0, tag.raw);

	set_user_error(thr, error);
}
コード例 #5
0
ファイル: ipc.c プロジェクト: ChiwenLin/f9-kernel
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);
}
コード例 #6
0
ファイル: ipc.c プロジェクト: ChiwenLin/f9-kernel
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;
}