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); }
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); }
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); }