void print_lcd_menu() { if (!global->lcd_output_possible()) return; // dir std::string dir = "/"; if (folders.size() != 1) { std::stack<std::pair<std::list<std::string>, int > > tmp_folders = folders; std::string name = tmp_folders.top().first.front(); for (int number_of_slashes = tmp_folders.size(); number_of_slashes > 0; --number_of_slashes) { int p = name.rfind('/'); if (p != std::string::npos) { if (number_of_slashes != tmp_folders.size()) dir = name.substr(p) + dir; name = name.substr(0, p); } else break; } } // current std::string cur_name = "> " + get_name_from_file(vector_lookup(files, folders.top().second)); std::string prev_name = ""; if (files.size() > 2) { // prev int prev_pos = folders.top().second - 1; if (prev_pos == -1) prev_pos = files.size()-1; prev_name = get_name_from_file(vector_lookup(files, prev_pos)); } std::string next_name = ""; if (files.size() > 1) { // next int next_pos = folders.top().second + 1; if (next_pos == files.size()) next_pos = 0; next_name = get_name_from_file(vector_lookup(files, next_pos)); } if (global->lcd_rows() > 1) global->lcd_add_output(string_format::pretty_print_string_copy(dir,global->lcd_pixels())); if (global->lcd_rows() > 2) global->lcd_add_output(string_format::pretty_print_string_copy(prev_name,global->lcd_pixels())); global->lcd_add_output(cur_name); if (global->lcd_rows() > 3) global->lcd_add_output(string_format::pretty_print_string_copy(next_name,global->lcd_pixels())); global->lcd_print(); }
static void kerext_page_wait_info(void *data) { struct kerargs_page_wait_info *kap = data; int id; unsigned index; pid_t pid; PROCESS *prp; THREAD *thp; unsigned pt_info; pt_info = kap->value; id = SYNC_PINDEX(pt_info); if(id < process_vector.nentries && (prp = VECP(prp, &process_vector, id)) && id == PINDEX(prp->pid) && (thp = vector_lookup(&prp->threads, SYNC_TID(pt_info))) && (thp->state == STATE_WAITPAGE)) { kap->vaddr = (uintptr_t)thp->next.thread; *kap->ppid = prp->pid; *kap->ptid = thp->tid + 1; *kap->pflags = (unsigned)thp->status; pid = (unsigned)thp->prev.thread; index = PINDEX(pid); if((index >= process_vector.nentries) || ((prp = VECP(prp, &process_vector, index)) == NULL) || (prp->pid != pid)) { pid = 0; } *kap->paspace_pid = pid; } else { kap->vaddr = ~0; } }
static void ker_deliver_event(void *data) { THREAD *thp; struct kerargs_deliver_event *kap = data; PROCESS *prp = lookup_pid(kap->evtdest->pid); kap->err = ESRCH; if ((prp != NULL) && ((thp = vector_lookup(&prp->threads, MTINDEX(kap->evtdest->rcvid))) != NULL)) { KerextLock(); kap->evtdest->in_progress = bool_t_TRUE; // Since this is a user request for an event and can handle // an error return, we shouldn't delve into the critical list // for any pulse that we need to allocate for the event - save // the critical heap for important pulses like hwintrs and // CPU exception fault delivery pulse_souls.flags &= ~SOUL_CRITICAL; kap->err = sigevent_exe(kap->event, thp, 1); pulse_souls.flags |= SOUL_CRITICAL; kap->evtdest->in_progress = bool_t_FALSE; } }
// commands void action_play() { Multifile e = vector_lookup(files, folders.top().second); int nfiles = e.filenames.size(); if (nfiles > 0) playmovie(e); else DialogWaitPrint pdialog(dgettext("mms-movie", "Folder is empty"), 1000); }
int main () { int *x1=(int*)malloc(sizeof(int)); int *x2=(int*)malloc(sizeof(int)); *x1=8; *x2=9; vector vec=vector_init(3); vector_set(vec,x1); vector_set(vec,x2); printf("size:%d\n",vector_count(vec)); int * find=vector_lookup(vec,1); printf("value:%d\n",*find); return 0; }
static void kerext_page_cont(void *data) { struct kerargs_page_cont *kap = data; PROCESS *prp; THREAD *act = actives[KERNCPU], *thp; // Verify the target process and thread exists. if((prp = lookup_pid(kap->pid)) == NULL || (thp = vector_lookup(&prp->threads, kap->tid-1)) == NULL || (thp->state != STATE_WAITPAGE)) { kererr(act, ESRCH); return; } lock_kernel(); if(kap->err != EOK) { kererr(thp, kap->err); } else if(kap->code_signo) { if(kap->code_signo & SIGCODE_KERNEL) { if((kap->code_signo & SIGCODE_INXFER) == 0) { // Fault occured while we were in a kernel call. Unwind properly if(!(kap->code_signo & SIGCODE_KEREXIT)) { // Fixup ip SETKIP(thp,KIP(thp) + KER_ENTRY_SIZE); } if(thp->flags & _NTO_TF_WAAA) { thp->status = (void *)EAGAIN; thp->flags |= (_NTO_TF_KILLSELF | _NTO_TF_ONLYME); } else { kererr(thp, EFAULT); } } else { // Else we just restart kernel call, this time it will unwind properly } } else { // Make sure that the signal will be delivered by // knocking down all higher priority specret flags, // except for KILLSELF and TO_BE_STOPPED thp->flags &= ~(_NTO_TF_SIG_ACTIVE - 1) | (_NTO_TF_KILLSELF|_NTO_TF_TO_BE_STOPPED); // Deliver the signal // PageWait() stored the faulting address in "thp->next" usr_fault(kap->code_signo, thp, (uintptr_t)thp->next.thread); } } ready(thp); SETKSTATUS(act, EOK); }
static void kerext_process_swap(void *data) { struct kerargs_process_swap *kap = data; PROCESS *parent = kap->parent; PROCESS *child = kap->child; CONNECT *proc_cop; pid_t pid; int i; DEBUG *swap; lock_kernel(); /* Swap process containers */ process_vector.vector[PINDEX(parent->pid)] = child; process_vector.vector[PINDEX(child->pid)] = parent; if(child->parent != parent) crash(); process_swap(child); pid = parent->pid; parent->pid = child->pid; child->pid = pid; if(parent->ocb_list || child->ocb_list) { void *ocb_list; ocb_list = parent->ocb_list; parent->ocb_list = child->ocb_list; child->ocb_list = ocb_list; } if(parent->alarm) { TIMER *alarm = parent->alarm; parent->alarm = 0; alarm->thread = child->valid_thp; child->alarm = alarm; } /* Flags to inherit */ #define FLAGS (_NTO_PF_WAITINFO | \ _NTO_PF_WAITDONE | \ _NTO_PF_SLEADER | \ _NTO_PF_ORPHAN_PGRP | \ _NTO_PF_NOCLDSTOP | \ _NTO_PF_PTRACED | \ _NTO_PF_NOZOMBIE) i = parent->flags; parent->flags = (parent->flags & ~FLAGS) | (child->flags & FLAGS); child->flags = (child->flags & ~FLAGS) | (i & FLAGS); #undef FLAGS // Find the child's connection to proc (It's always the first chancon entry) proc_cop = vector_lookup(&child->chancons, SYSMGR_COID & ~_NTO_SIDE_CHANNEL); #ifndef NDEBUG // There should be two links, One from the Send() and one from the ConnectAttach() if(!proc_cop || !proc_cop->channel || proc_cop->links != 2) crash(); if(proc_cop->un.lcl.pid != SYSMGR_PID || proc_cop->un.lcl.chid != SYSMGR_CHID) crash(); if(parent->chancons.nentries != parent->chancons.nfree) crash(); if(child->chancons.nentries != child->chancons.nfree + 1) crash(); if(child->fdcons.nentries != child->fdcons.nfree) crash(); #endif for(i = 0 ; i < parent->fdcons.nentries ; ++i) { CONNECT *cop; if((cop = vector_rem(&parent->fdcons, i))) { if(vector_add(&child->fdcons, cop, i) != i) { crash(); } parent->nfds--; child->nfds++; cop->process = child; // Check if this connects to proc's channel, if so, share it... if(proc_cop && cop->channel == proc_cop->channel) { vector_rem(&child->chancons, SYSMGR_COID & ~_NTO_SIDE_CHANNEL); vector_add(&child->chancons, cop, SYSMGR_COID & ~_NTO_SIDE_CHANNEL); cop->links++; proc_cop->links--; proc_cop = 0; } } } swap = child->debugger; if((swap != NULL) && (swap->process == child)) { swap->process = parent; } swap = parent->debugger; if((swap != NULL) && (swap->process == parent)) { swap->process = child; } parent->debugger = child->debugger; child->debugger = swap; SETKSTATUS(actives[KERNCPU], 0); }
static void kerext_process_destroy(void *data) { PROCESS *prp, *parent, *child; pid_t pid = (pid_t)data; THREAD *act = actives[KERNCPU]; lock_kernel(); if(!(prp = vector_lookup(&process_vector, PINDEX(pid)))) { kererr(act, ESRCH); return; } if(prp->querying) { // Some proc thread is looking at the process fields // (a QueryOject() has been done on it). We have to wait // before we can destroy the process and free the memory SETKSTATUS(act, 0); return; } _TRACE_PR_EMIT_DESTROY(prp, pid); // retarget all children to PROC if((child = prp->child)) { PROCESS *proc = sysmgr_prp; do { //Loop might take a while - give intr queue a chance to drain. KEREXT_PREEMPT(act); prp->child = child->sibling; if(procmgr.process_threads_destroyed) { if (((child->flags & (_NTO_PF_LOADING | _NTO_PF_TERMING | _NTO_PF_ZOMBIE)) == _NTO_PF_ZOMBIE) || (child->flags & _NTO_PF_NOZOMBIE)) { struct sigevent ev; child->flags &= ~(_NTO_PF_ZOMBIE | _NTO_PF_WAITINFO); (*procmgr.process_threads_destroyed)(child, &ev); sigevent_proc(&ev); } } child->parent = proc; child->sibling = proc->child; proc->child = child; --prp->num_processes; ++proc->num_processes; } while((child = prp->child)); } vector_rem(&process_vector, PINDEX(pid)); // Remove the thread vector if(prp->threads.nentries && prp->threads.nentries == prp->threads.nfree) vector_free(&prp->threads); // Remove the timer vector if(prp->timers.nentries && prp->timers.nentries == prp->timers.nfree) vector_free(&prp->timers); // Remove the fd vector if(prp->fdcons.nentries && prp->fdcons.nentries == prp->fdcons.nfree) vector_free(&prp->fdcons); // Remove the channel vector if(prp->chancons.nentries && prp->chancons.nentries == prp->chancons.nfree) vector_free(&prp->chancons); // Unlink the credential if(prp->cred) { cred_set(&prp->cred, NULL); } // undo all session stuff if(prp->session && atomic_sub_value(&prp->session->links, 1) == 1) { _sfree(prp->session, sizeof *prp->session); } prp->session = 0; // Unlink the limits if(prp->limits && --prp->limits->links == 0) { LINK1_REM(limits_list, prp->limits, LIMITS); object_free(NULL, &limits_souls, prp->limits); } if(prp->limits && prp->limits->links == ~0U) crash(); if(prp->pid) crash(); if(prp->cred) crash(); if(prp->alarm) crash(); if(pril_first(&prp->sig_pending)) crash(); if(prp->sig_table) crash(); if(prp->nfds) crash(); if(prp->chancons.vector) crash(); if(prp->fdcons.vector) crash(); if(prp->threads.vector) crash(); if(prp->timers.vector) crash(); if(prp->memory) crash(); if(prp->join_queue) crash(); // if(prp->session) crash(); if(prp->debugger) crash(); if(prp->lock) crash(); if(prp->num_active_threads) crash(); if(prp->vfork_info) crash(); // FIX ME - this is not NULL now ... why? if(prp->rsrc_list) crash(); if(prp->conf_table) crash(); // Unlink from parent parent = prp->parent; --parent->num_processes; if(prp == parent->child) { parent->child = prp->sibling; } else { for(parent = parent->child ; parent ; parent = parent->sibling) { if(parent->sibling == prp) { parent->sibling = prp->sibling; break; } } } //Keep pids as positive numbers pid_unique = (pid_unique + (PID_MASK + 1)) & INT_MAX; /* diassociate prp from all partitions */ /* apparently prp->pid gets looked at even though we are about to object_free(prp). prp->pid = pid; // stick it back in so we have the info for the disassociate event */ (void)SCHEDPART_DISASSOCIATE(prp, part_id_t_INVALID); (void)MEMPART_DISASSOCIATE(prp, part_id_t_INVALID); (void)MUTEX_DESTROY(prp, &prp->mpartlist_lock); (void)MUTEX_DESTROY(prp, &prp->spartlist_lock); CRASHCHECK(prp->mpart_list.vector != NULL); CRASHCHECK(prp->spart_list != NULL); // no vector for sched partitions since only 1 object_free(NULL, &process_souls, prp); SETKSTATUS(act, 1); }
static int proc_start(PROCESS *prp, uintptr_t *start_ip) { THREAD *thp; struct loader_context *lcp = prp->lcp; if(!(thp = vector_lookup(&prp->threads, lcp->tid - 1)) || thp->state != STATE_REPLY) { return EL3HLT; } if((lcp->state & LC_STATE_MASK) == LC_FORK) { THREAD *pthp; int tid; struct _thread_local_storage *tsp; char buff[0x100]; struct _thread_local_storage tls; unsigned size = 0; uintptr_t sp; if(!(lookup_rcvid(0, lcp->rcvid, &pthp)) || pthp->state != STATE_REPLY) { return EL3HLT; } sp = GetSp(pthp); tid = thp->un.lcl.tls->__tid; tsp = thp->un.lcl.tls = pthp->un.lcl.tls; thp->un.lcl.stacksize = pthp->un.lcl.stacksize; if(!(lcp->flags & _FORK_ASPACE)) { memcpy(&tls, tsp, sizeof(tls)); #ifdef STACK_GROWS_UP if ((size = sp - lcp->start.stackaddr) >= sizeof(buff)) return ENOMEM; memcpy(buff, (void *)lcp->start.stackaddr, size); #else if ((size = lcp->start.stackaddr - sp) >= sizeof(buff)) return ENOMEM; memcpy(buff, (void *)sp, size); #endif } KerextLock(); tsp->__pid = prp->pid; tsp->__tid = tid; tsp->__owner = ((tsp->__pid << 16) | tsp->__tid) & ~_NTO_SYNC_WAITING; thp->reg = pthp->reg; thp->runmask = thp->default_runmask = pthp->default_runmask; prp->flags |= _NTO_PF_FORKED; if(!(lcp->flags & _FORK_ASPACE)) { struct vfork_info *vip; if(size > sizeof buff || !(vip = prp->vfork_info = malloc(offsetof(struct vfork_info, frame) + size))) { return ENOMEM; } vip->rcvid = lcp->rcvid; vip->tls = tls; #ifdef STACK_GROWS_UP vip->frame_base = (void *)lcp->start.stackaddr; #else vip->frame_base = (void *)sp; #endif vip->frame_size = size; memcpy(vip->frame, buff, size); } if(!(lcp->flags & _FORK_NOZOMBIE)) { prp->flags &= ~_NTO_PF_NOZOMBIE; } // Don't allow anything to change the IP thp->flags |= _NTO_TF_KERERR_SET; return EOK; }
int apm_deliver_event(evtdest_t *evtdest, struct sigevent *se) { int r; /* * in the process of sending an event, we may cause memory to be allocated * (ex. growing the pulse soul list) which could trigger an event (in the * case where the heap needed growing to accomodate the soul list grow). * This mechanism breaks the recursion */ if (evtdest->in_progress) return EINPROGRESS; if (!KerextAmInKernel()) { struct kerargs_deliver_event data; data.err = EOK; data.evtdest = evtdest; data.event = se; __Ring0(ker_deliver_event, &data); r = data.err; #ifndef NDEBUG if (r != EOK) { if ((++evt_delivery_fail_cnt % 100) == 0) { /* kprintf("%u event delivery failures @ %d, err = %d\n", evt_delivery_fail_cnt, __LINE__, r);*/ } } #endif /* NDEBUG */ } else { /* * in the case we are already in the kernel,it may be a procnto thread * or a user thread that is triggering the event delivery. Because there * are many places in the kernel which are not re-entrant we will not * deliver the event now but instead, add it to the event queue for * delivery at kernel exit. Because the 'evtdest->rcvid' relates to the * connection established with 'procnto', we cannot lookup the connection * and instead must know the process to deliver the event to as recorded * in the 'evtdest' structure at registration time. We use this info to * find a thread to deliver to. */ THREAD *thp = NULL; PROCESS *prp = lookup_pid(evtdest->pid); r = ESRCH; if (prp != NULL) { thp = vector_lookup(&prp->threads, MTINDEX(evtdest->rcvid)); } if (thp != NULL) { evtdest->in_progress = bool_t_TRUE; r = event_add(se, thp); evtdest->in_progress = bool_t_FALSE; } #ifndef NDEBUG if ((thp == NULL) || (r != EOK)) { if ((++inker_evt_delivery_fail_cnt % 100) == 0) { kprintf("%u inkernel event delivery failures @ %d, err = %d\n", inker_evt_delivery_fail_cnt, __LINE__, r); } } #endif /* NDEBUG */ } #ifndef NDEBUG if (r == EOK) ++delivered_events; else ++undelivered_events; #endif /* NDEBUG */ return r; }
int kdecl ker_msg_receivev(THREAD *act, struct kerargs_msg_receivev *kap) { CHANNEL *chp; CONNECT *cop; THREAD *thp; THREAD **owner; int tid, chid; unsigned tls_flags; VECTOR *chvec; chid = act->last_chid = kap->chid; // Used for priority boost chvec = &act->process->chancons; if(chid & _NTO_GLOBAL_CHANNEL) { chid &= ~_NTO_GLOBAL_CHANNEL; chvec = &chgbl_vector; } if((chp = vector_lookup(chvec, chid)) == NULL || chp->type != TYPE_CHANNEL) { lock_kernel(); return ESRCH; } if(kap->info) { WR_VERIFY_PTR(act, kap->info, sizeof(*kap->info)); // NOTE: // Make sure the receive info pointer is valid. Note that we need some // extra checks in the mainline when filling in the rcvinfo (this is no // longer done in specret). // // Note: we don't probe the whole buffer, rather touch start and end, // which is faster and sufficient // WR_PROBE_INT(act, kap->info, 1); WR_PROBE_INT(act, &kap->info->reserved, 1); } if(chp->flags & (_NTO_CHF_ASYNC | _NTO_CHF_GLOBAL)) { if(chp->flags & _NTO_CHF_GLOBAL) { cop = NULL; if(kap->coid) { if((cop = lookup_connect(kap->coid)) == NULL || cop->type != TYPE_CONNECTION) { return EBADF; } } return msgreceive_gbl(act, (CHANNELGBL*) chp, kap->rmsg, -kap->rparts, kap->info, cop, kap->coid); } else { return msgreceive_async(act, (CHANNELASYNC*) chp, kap->rmsg, kap->rparts); } } /* * Validate incoming IOVs and calculate receive length */ if(kap->rparts >= 0) { int len = 0; int len_last = 0; IOV *iov = kap->rmsg; int rparts = kap->rparts; if (kap->rparts != 0) { if (!WITHIN_BOUNDRY((uintptr_t)iov, (uintptr_t)(&iov[rparts]), act->process->boundry_addr)) { return EFAULT; } } // Calculate receive length -- even if not requested, we use it for msginfo // Do boundary check while(rparts) { uintptr_t base, last; len += GETIOVLEN(iov); if (len <len_last ) { /*overflow. excessively long user IOV, possibly overlayed. pr62575 */ return EOVERFLOW; } len_last = len; base = (uintptr_t)GETIOVBASE(iov); last = base + GETIOVLEN(iov) - 1; if(((base > last) || !WITHIN_BOUNDRY(base, last, act->process->boundry_addr)) && (GETIOVLEN(iov) != 0)) { return EFAULT; } ++iov; --rparts; } act->args.ms.srcmsglen = len; } else { // Single part -- validate receive address uintptr_t base, last; base = (uintptr_t) kap->rmsg; last = base + (-kap->rparts) - 1; if((base > last) || !WITHIN_BOUNDRY(base, last, act->process->boundry_addr)) { // We know length is non-zero from test above return EFAULT; } act->args.ms.srcmsglen = -kap->rparts; } restart: // Was there was a waiting thread or pulse on the channel? thp = pril_first(&chp->send_queue); restart2: if(thp) { int xferstat; unsigned type = TYPE_MASK(thp->type); // Yes. There is a waiting message. if((type == TYPE_PULSE) || (type == TYPE_VPULSE)) { PULSE *pup = (PULSE *)(void *)thp; act->restart = NULL; xferstat = xferpulse(act, kap->rmsg, kap->rparts, pup->code, pup->value, pup->id); if(type == TYPE_VPULSE) { thp = (THREAD *)pup->id; get_rcvinfo(thp, -1, thp->blocked_on, kap->info); } lock_kernel(); act->timeout_flags = 0; // By default the receiver runs with message driven priority. // RUSH: Fix for partition inheritance if(act->priority != pup->priority && (chp->flags & _NTO_CHF_FIXED_PRIORITY) == 0) { adjust_priority(act, pup->priority, act->process->default_dpp, 1); act->real_priority = act->priority; } else if(act->dpp != act->process->default_dpp) { adjust_priority(act, act->priority, act->process->default_dpp, 1); } pulse_remove(chp->process, &chp->send_queue, pup); if((thp = act->client) != 0) { /* need to clear client's server field */ act->client = 0; thp->args.ms.server = 0; } if(xferstat) { return EFAULT; } _TRACE_COMM_IPC_RET(act); return EOK; } // If the receive request was for a pulse only, keep checking the list.. if(KTYPE(act) == __KER_MSG_RECEIVEPULSEV) { thp = thp->next.thread; goto restart2; } #if defined(VARIANT_smp) && defined(SMP_MSGOPT) // If thp is in the xfer status in another CPU, try next one if(thp->internal_flags & _NTO_ITF_MSG_DELIVERY) { thp = thp->next.thread; goto restart2; } #endif // If an immediate timeout was specified we unblock the sender. if(IMTO(thp, STATE_REPLY)) { lock_kernel(); force_ready(thp, ETIMEDOUT); unlock_kernel(); KER_PREEMPT(act, ENOERROR); goto restart; } if(thp->flags & _NTO_TF_BUFF_MSG) { xferstat = xfer_cpy_diov(act, kap->rmsg, thp->args.msbuff.buff, kap->rparts, thp->args.msbuff.msglen); } else { act->args.ri.rmsg = kap->rmsg; act->args.ri.rparts = kap->rparts; START_SMP_XFER(act, thp); xferstat = xfermsg(act, thp, 0, 0); lock_kernel(); END_SMP_XFER(act, thp); #if defined(VARIANT_smp) && defined(SMP_MSGOPT) if(thp->internal_flags & _NTO_ITF_MSG_FORCE_RDY) { force_ready(thp,KSTATUS(thp)); thp->internal_flags &= ~_NTO_ITF_MSG_FORCE_RDY; KERCALL_RESTART(act); act->restart = 0; return ENOERROR; } if(act->flags & (_NTO_TF_SIG_ACTIVE | _NTO_TF_CANCELSELF)) { KERCALL_RESTART(act); act->restart = 0; return ENOERROR; } #endif } if(xferstat) { lock_kernel(); // Only a send fault will unblock the sender. if(xferstat & XFER_SRC_FAULT) { // Let sender know it faulted and restart receive. force_ready(thp, EFAULT); unlock_kernel(); KER_PREEMPT(act, ENOERROR); goto restart; } if((thp = act->client) != 0) { /* need to clear client's server field */ act->client = 0; thp->args.ms.server = 0; } // Let receiver and sender know reason for fault. act->timeout_flags = 0; return EFAULT; } if(TYPE_MASK(thp->type) == TYPE_VTHREAD) { tid = thp->args.ri.rparts; } else { tid = thp->tid; } cop = thp->blocked_on; if(thp->args.ms.srcmsglen == ~0U) { // This should never occur with the new code crash(); /* NOTREACHED */ thp->args.ms.srcmsglen = thp->args.ms.msglen; } // If the receive specified an info buffer stuff it as well. // thp->args.ms.msglen was set by xfermsg if(kap->info) { // get_rcvinfo(thp, -1, cop, kap->info); STUFF_RCVINFO(thp, cop, kap->info); if(thp->flags & _NTO_TF_BUFF_MSG) { if(kap->info->msglen > act->args.ms.srcmsglen) kap->info->msglen = act->args.ms.srcmsglen; } } lock_kernel(); _TRACE_COMM_IPC_RET(act); act->timeout_flags = 0; act->restart = NULL; // Because _NTO_TF_RCVINFO and _NTO_TF_SHORT_MSG will not be set, set this to NULL thp->restart = NULL; if(act->client != 0) { /* need to clear client's server field */ act->client->args.ms.server = 0; } thp->args.ms.server = act; act->client = thp; pril_rem(&chp->send_queue, thp); if(thp->state == STATE_SEND) { thp->state = STATE_REPLY; snap_time(&thp->timestamp_last_block,0); _TRACE_TH_EMIT_STATE(thp, REPLY); SETKSTATUS(act, (tid << 16) | cop->scoid); } else { thp->state = STATE_NET_REPLY; _TRACE_TH_EMIT_STATE(thp, NET_REPLY); SETKSTATUS(act, -((tid << 16) | cop->scoid)); } LINKPRIL_BEG(chp->reply_queue, thp, THREAD); // By default the receiver runs with message driven priority. // RUSH: Fix for partition inheritance if((act->priority != thp->priority || act->dpp != thp->dpp) && (chp->flags & _NTO_CHF_FIXED_PRIORITY) == 0) { AP_INHERIT_CRIT(act, thp); adjust_priority(act, thp->priority, thp->dpp, 1); if(act->real_priority != act->priority) act->real_priority = act->priority; } else { AP_CLEAR_CRIT(act); } return ENOERROR; } // No-one waiting for a msg so block tls_flags = act->un.lcl.tls->__flags; lock_kernel(); _TRACE_COMM_IPC_RET(act); if((thp = act->client) != 0) { /* need to clear client's server field */ act->client = 0; thp->args.ms.server = 0; } if(IMTO(act, STATE_RECEIVE)) { return ETIMEDOUT; } if(PENDCAN(tls_flags)) { SETKIP_FUNC(act, act->process->canstub); return ENOERROR; } // Can't call block() here, because act may not be actives[KERNCPU] // anymore - if the sender faulted, we call force_ready() above and // that might change actives[KERNCPU] unready(act, STATE_RECEIVE); // End inheritance of partition and critical state. This must be after block() so that we microbill // the partition we where running in before we reset to the original partition. PR26990 act->dpp = act->orig_dpp; AP_CLEAR_CRIT(act); act->blocked_on = chp; act->args.ri.rmsg = kap->rmsg; act->args.ri.rparts = kap->rparts; act->args.ri.info = kap->info; // Add to the receive queue, put pulse only receives at the end of // the list so the ker_msg_send() only has to check the head of the list owner = &chp->receive_queue; if(KTYPE(act) == __KER_MSG_RECEIVEPULSEV) { act->internal_flags |= _NTO_ITF_RCVPULSE; for( ;; ) { thp = *owner; if(thp == NULL) break; if(thp->internal_flags & _NTO_ITF_RCVPULSE) break; owner = &thp->next.thread; } } LINKPRIL_BEG(*owner, act, THREAD); return ENOERROR; }