PUBLIC void Ipc_gate::invoke(L4_obj_ref /*self*/, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb) { Syscall_frame *ipc_f = f; //LOG_MSG_3VAL(current(), "gIPC", Mword(_thread), _id, f->obj_2_flags()); //printf("Invoke: Ipc_gate(%lx->%p)...\n", _id, _thread); Thread *ct = current_thread(); Thread *sender = 0; Thread *partner = 0; bool have_rcv = false; if (EXPECT_FALSE(!_thread)) { L4_error e = block(ct, f->timeout().snd, utcb); if (!e.ok()) { f->tag(commit_error(utcb, e)); return; } if (EXPECT_FALSE(!_thread)) { f->tag(commit_error(utcb, L4_error::Not_existent)); return; } } bool ipc = _thread->check_sys_ipc(f->ref().op(), &partner, &sender, &have_rcv); LOG_TRACE("IPC Gate invoke", "gate", current(), Log_ipc_gate_invoke, l->gate_dbg_id = dbg_id(); l->thread_dbg_id = _thread->dbg_id(); l->label = _id | cxx::int_value<L4_fpage::Rights>(rights); );
PRIVATE L4_msg_tag Irq_sender::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /*f*/, Obj_space *o_space) { L4_snd_item_iter snd_items(utcb, tag.words()); Thread *thread = 0; if (tag.items() == 0) { // detach Reap_list rl; free(_irq_thread, rl.list()); _irq_id = ~0UL; cpu_lock.clear(); rl.del(); cpu_lock.lock(); return commit_result(0); } if (tag.items() && snd_items.next()) { L4_fpage bind_thread(snd_items.get()->d); if (EXPECT_FALSE(!bind_thread.is_objpage())) return commit_error(utcb, L4_error::Overflow); thread = Kobject::dcast<Thread_object*>(o_space->lookup_local(bind_thread.obj_index())); } if (!thread) thread = current_thread(); if (alloc(thread)) { _irq_id = utcb->values[1]; return commit_result(0); } return commit_result(-L4_err::EInval); }
PRIVATE L4_msg_tag Irq_muxer::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /*f*/, Obj_space *o_space) { L4_snd_item_iter snd_items(utcb, tag.words()); Irq *irq = 0; if (tag.items() == 0) return commit_result(-L4_err::EInval); if (tag.items() && snd_items.next()) { L4_fpage bind_irq(snd_items.get()->d); if (EXPECT_FALSE(!bind_irq.is_objpage())) return commit_error(utcb, L4_error::Overflow); irq = Kobject::dcast<Irq*>(o_space->lookup_local(bind_irq.obj_index())); } if (!irq) return commit_result(-L4_err::EInval); irq->unbind(); if (!irq->masked()) { Smword old; do old = _mask_cnt; while (!mp_cas(&_mask_cnt, old, old + 1)); } bind(irq, 0); irq->Irq_base::_next = Irq_base::_next; Irq_base::_next = irq; return commit_result(0); }
static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, git_rawobj *raw) { const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1; unsigned char *buffer = raw->data; unsigned char *buffer_end = buffer + raw->len; unsigned char *parents_start, *committer_start; int i, parents = 0; int commit_time; buffer += strlen("tree ") + GIT_OID_HEXSZ + 1; parents_start = buffer; while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) { parents++; buffer += parent_len; } commit->parents = alloc_parents(walk, commit, parents); GITERR_CHECK_ALLOC(commit->parents); buffer = parents_start; for (i = 0; i < parents; ++i) { git_oid oid; if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; buffer += parent_len; } commit->out_degree = (unsigned short)parents; if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); buffer++; if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); /* Skip trailing spaces */ while (buffer > committer_start && git__isspace(*buffer)) buffer--; /* Seek for the begining of the pack of digits */ while (buffer > committer_start && git__isdigit(*buffer)) buffer--; /* Skip potential timezone offset */ if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) { buffer--; while (buffer > committer_start && git__isspace(*buffer)) buffer--; while (buffer > committer_start && git__isdigit(*buffer)) buffer--; } if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0)) return commit_error(commit, "cannot parse commit time"); commit->time = (time_t)commit_time; commit->parsed = 1; return 0; }
PRIVATE inline L4_msg_tag Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) { if (this != current() || !(state() & Thread_vcpu_enabled)) return commit_result(-L4_err::EInval); Space *s = space(); Vcpu_state *vcpu = vcpu_state().access(true); L4_obj_ref user_task = vcpu->user_task; if (user_task.valid()) { L4_fpage::Rights task_rights = L4_fpage::Rights(0); Task *task = Kobject::dcast<Task*>(s->lookup_local(user_task.cap(), &task_rights)); if (EXPECT_FALSE(task && !(task_rights & L4_fpage::Rights::W()))) return commit_result(-L4_err::EPerm); if (task != vcpu_user_space()) vcpu_set_user_space(task); vcpu->user_task = L4_obj_ref(); } else if (user_task.op() == L4_obj_ref::Ipc_reply) vcpu_set_user_space(0); L4_snd_item_iter snd_items(utcb, tag.words()); int items = tag.items(); if (vcpu_user_space()) for (; items && snd_items.more(); --items) { if (EXPECT_FALSE(!snd_items.next())) break; Lock_guard<Lock> guard; if (!guard.check_and_lock(&static_cast<Task *>(vcpu_user_space())->existence_lock)) return commit_result(-L4_err::ENoent); cpu_lock.clear(); L4_snd_item_iter::Item const *const item = snd_items.get(); L4_fpage sfp(item->d); Reap_list rl; L4_error err = fpage_map(space(), sfp, vcpu_user_space(), L4_fpage::all_spaces(), item->b, &rl); rl.del(); cpu_lock.lock(); if (EXPECT_FALSE(!err.ok())) return commit_error(utcb, err); } if ((vcpu->_saved_state & Vcpu_state::F_irqs) && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) { assert_kdb(cpu_lock.test()); do_ipc(L4_msg_tag(), 0, 0, true, 0, L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), &vcpu->_ipc_regs, L4_fpage::Rights::FULL()); vcpu = vcpu_state().access(true); if (EXPECT_TRUE(!vcpu->_ipc_regs.tag().has_error() || this->utcb().access(true)->error.error() == L4_error::R_timeout)) { vcpu->_ts.set_ipc_upcall(); Address sp; // tried to resume to user mode, so an IRQ enters from user mode if (vcpu->_saved_state & Vcpu_state::F_user_mode) sp = vcpu->_entry_sp; else sp = vcpu->_ts.sp(); arch_load_vcpu_kern_state(vcpu, true); LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 4; l->state = vcpu->state; l->ip = vcpu->_entry_ip; l->sp = sp; l->space = static_cast<Task*>(_space.vcpu_aware())->dbg_id(); );