Date: Mon, 20 Sep 2004 07:26:51 GMT From: Julian Elischer <julian@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 61838 for review Message-ID: <200409200726.i8K7QpIv012181@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=61838 Change 61838 by julian@julian_ref on 2004/09/20 07:25:55 code cleanups and slot debugging support. Affected files ... .. //depot/projects/nsched/sys/kern/kern_kse.c#29 edit .. //depot/projects/nsched/sys/kern/kern_switch.c#35 edit .. //depot/projects/nsched/sys/kern/kern_thr.c#19 edit .. //depot/projects/nsched/sys/kern/kern_thread.c#39 edit .. //depot/projects/nsched/sys/kern/sched_4bsd.c#57 edit Differences ... ==== //depot/projects/nsched/sys/kern/kern_kse.c#29 (text+ko) ==== @@ -518,16 +518,10 @@ struct thread *newtd; p = td->td_proc; + kg = td->td_ksegrp; if ((err = copyin(uap->mbx, &mbx, sizeof(mbx)))) return (err); - /* - * Processes using the other threading model can't - * suddenly start calling this one - */ - if ((p->p_flag & (P_SA|P_HADTHREADS)) == P_HADTHREADS) - return (EINVAL); - ncpus = mp_ncpus; if (virtual_cpu != 0) ncpus = virtual_cpu; @@ -547,10 +541,32 @@ } PROC_LOCK(p); + /* + * Processes using the other threading model can't + * suddenly start calling this one + */ + if ((p->p_flag & (P_SA|P_HADTHREADS)) == P_HADTHREADS) { + PROC_UNLOCK(p); + return (EINVAL); + } + + /* + * Limit it to NCPU upcall contexts per ksegrp in any case. + * There is a small race here as we don't hold proclock + * until we inc the ksegrp count, but it's not really a big problem + * if we get one too many, but we save a proc lock. + */ + if ((!uap->newgroup) && (kg->kg_numupcalls >= ncpus)) { + PROC_UNLOCK(p); + return (EPROCLIM); + } + if (!(p->p_flag & P_SA)) { first = 1; p->p_flag |= P_SA|P_HADTHREADS; } + + PROC_UNLOCK(p); /* * Now pay attention! @@ -565,22 +581,21 @@ if (!sa && !(uap->newgroup || first)) return (EINVAL); - kg = td->td_ksegrp; if (uap->newgroup) { newkg = ksegrp_alloc(); bzero(&newkg->kg_startzero, RANGEOF(struct ksegrp, kg_startzero, kg_endzero)); bcopy(&kg->kg_startcopy, &newkg->kg_startcopy, RANGEOF(struct ksegrp, kg_startcopy, kg_endcopy)); + sched_init_concurrency(newkg); PROC_LOCK(p); - mtx_lock_spin(&sched_lock); if (p->p_numksegrps >= max_groups_per_proc) { - mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); ksegrp_free(newkg); return (EPROCLIM); } ksegrp_link(newkg, p); + mtx_lock_spin(&sched_lock); sched_fork_ksegrp(td, newkg); mtx_unlock_spin(&sched_lock); PROC_UNLOCK(p); @@ -595,6 +610,7 @@ */ if (!first && ((td->td_pflags & TDP_SA) != sa)) return (EINVAL); + newkg = kg; } @@ -647,20 +663,11 @@ if (td->td_standin == NULL) thread_alloc_spare(td); - /* - * Creating upcalls more than number of physical cpu does - * not help performance. - */ PROC_LOCK(p); - if (newkg->kg_numupcalls >= ncpus) { - PROC_UNLOCK(p); - upcall_free(newku); - return (EPROCLIM); - } /* * If we are the first time, and a normal thread, - * then trnasfer all the signals back to the 'process'. + * then transfer all the signals back to the 'process'. * SA threading will make a special thread to handle them. */ if (first && sa) { @@ -991,6 +998,8 @@ * for upcall. Initialize thread's large data area outside sched_lock * for thread_schedule_upcall(). The crhold is also here to get it out * from the schedlock as it has a mutex op itself. + * XXX BUG.. we need to get the cr ref after the thread has + * checked and chenged its own, not 6 months before... */ void thread_alloc_spare(struct thread *td) ==== //depot/projects/nsched/sys/kern/kern_switch.c#35 (text+ko) ==== @@ -426,7 +426,7 @@ sched_rem(tda); tda = kg->kg_last_assigned = TAILQ_PREV(tda, threadqueue, td_runq); - kg->kg_avail_opennings++; + SLOT_RELEASE(kg); } /* @@ -891,6 +891,7 @@ sched_init_concurrency(struct ksegrp *kg) { + CTR1(KTR_RUNQ,"kg %p init slots and concurrency to 1", kg); kg->kg_concurrency = 1; kg->kg_avail_opennings = 1; } @@ -907,7 +908,11 @@ sched_set_concurrency(struct ksegrp *kg, int concurrency) { - /* Handle the case for a declining concurrency */ + CTR4(KTR_RUNQ,"kg %p set concurrency to %d, slots %d -> %d", + kg, + concurrency, + kg->kg_avail_opennings, + kg->kg_avail_opennings + (concurrency - kg->kg_concurrency)); kg->kg_avail_opennings += (concurrency - kg->kg_concurrency); kg->kg_concurrency = concurrency; } @@ -925,7 +930,7 @@ sched_thread_exit(struct thread *td) { - td->td_ksegrp->kg_avail_opennings++; + SLOT_RELEASE(td->td_ksegrp); slot_fill(td->td_ksegrp); } ==== //depot/projects/nsched/sys/kern/kern_thr.c#19 (text+ko) ==== ==== //depot/projects/nsched/sys/kern/kern_thread.c#39 (text+ko) ==== @@ -724,8 +724,6 @@ p->p_flag &= ~(P_SA|P_HADTHREADS); td->td_mailbox = NULL; td->td_pflags &= ~(TDP_SA | TDP_CAN_UNBIND); - p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT); /* maybe not */ - p->p_singlethread = NULL; if (td->td_standin != NULL) { thread_stash(td->td_standin); td->td_standin = NULL; @@ -786,17 +784,16 @@ if (p->p_singlethread) return (1); - if (force_exit == SINGLE_EXIT) { - p->p_flag |= P_SINGLE_EXIT; - } else - p->p_flag &= ~P_SINGLE_EXIT; p->p_flag |= P_STOPPED_SINGLE; mtx_lock_spin(&sched_lock); p->p_singlethread = td; - if (force_exit == SINGLE_EXIT) + if (force_exit == SINGLE_EXIT) { remaining = p->p_numthreads; - else + p->p_flag |= P_SINGLE_EXIT; + } else { remaining = p->p_numthreads - p->p_suspcount; + p->p_flag &= ~P_SINGLE_EXIT; + } while (remaining != 1) { FOREACH_THREAD_IN_PROC(p, td2) { if (td2 == td) @@ -860,8 +857,9 @@ * we try our utmost to revert to being a non-threaded * process. */ + p->p_singlethread = NULL; + p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT); thread_unthread(td); - p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT); } mtx_unlock_spin(&sched_lock); return (0); @@ -1018,7 +1016,6 @@ /* * End the single threading mode.. - * Part of this is duplicated in thread-single in the SINGLE_EXIT case. */ void thread_single_end(void) ==== //depot/projects/nsched/sys/kern/sched_4bsd.c#57 (text+ko) ==== @@ -119,6 +119,32 @@ #define kg_concurrency kg_sched->skg_concurrency #define kg_runq_kses kg_sched->skg_runq_kses +#define SLOT_RELEASE(kg) \ +do { \ + kg->kg_avail_opennings++; \ + CTR5(KTR_RUNQ, "%s line %d: kg %p(%d) Slot released (->%d)", \ + __FUNCTION__, \ + __LINE__, \ + kg, \ + kg->kg_concurrency, \ + kg->kg_avail_opennings); \ + KASSERT((kg->kg_avail_opennings <= kg->kg_concurrency), \ + ("slots out of whack")); \ +} while (0) + +#define SLOT_USE(kg) \ +do { \ + kg->kg_avail_opennings--; \ + CTR5(KTR_RUNQ, "%s line %d: kg %p(%d) Slot used (->%d)", \ + __FUNCTION__, \ + __LINE__, \ + kg, \ + kg->kg_concurrency, \ + kg->kg_avail_opennings); \ + KASSERT((kg->kg_avail_opennings >= 0), \ + ("slots out of whack")); \ +} while (0) + /* * KSE_CAN_MIGRATE macro returns true if the kse can migrate between * cpus. @@ -789,26 +815,6 @@ } } - /* - * The thread we are about to run needs to be counted as if it had been - * added to the run queue and selected. - * it came from: - * A preemption - * An upcall - * A followon - * Do this before saving curthread so that the slot count - * doesn't give an overly optimistic view when that happens. - */ - if (newtd) { - KASSERT((newtd->td_inhibitors == 0), - ("trying to run inhibitted thread")); - newtd->td_ksegrp->kg_avail_opennings--; - newtd->td_kse->ke_flags |= KEF_DIDRUN; - TD_SET_RUNNING(newtd); - if ((newtd->td_proc->p_flag & P_NOLOAD) == 0) - sched_tdcnt++; - } - td->td_lastcpu = td->td_oncpu; td->td_flags &= ~TDF_NEEDRESCHED; td->td_pflags &= ~TDP_OWEPREEMPT; @@ -822,7 +828,7 @@ if (td == PCPU_GET(idlethread)) TD_SET_CAN_RUN(td); else { - td->td_ksegrp->kg_avail_opennings++; + SLOT_RELEASE(td->td_ksegrp); if (TD_IS_RUNNING(td)) { /* Put us back on the run queue (kse and all). */ setrunqueue(td, SRQ_OURSELF|SRQ_YIELDING); @@ -831,12 +837,32 @@ * We will not be on the run queue. So we must be * sleeping or similar. As it's available, * someone else can use the KSE if they need it. + * It's NOT available if we are about to need it */ - slot_fill(td->td_ksegrp); + if (newtd == NULL || newtd->td_ksegrp != td->td_ksegrp) + slot_fill(td->td_ksegrp); } } - if (newtd == NULL) + if (newtd) { + /* + * The thread we are about to run needs to be counted + * as if it had been added to the run queue and selected. + * It came from: + * * A preemption + * * An upcall + * * A followon + */ + KASSERT((newtd->td_inhibitors == 0), + ("trying to run inhibitted thread")); + SLOT_USE(newtd->td_ksegrp); + newtd->td_kse->ke_flags |= KEF_DIDRUN; + TD_SET_RUNNING(newtd); + if ((newtd->td_proc->p_flag & P_NOLOAD) == 0) + sched_tdcnt++; + } else { newtd = choosethread(); + } + if (td != newtd) cpu_switch(td, newtd); sched_lock.mtx_lock = (uintptr_t)td; @@ -1030,7 +1056,7 @@ } if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt++; - td->td_ksegrp->kg_avail_opennings--; + SLOT_USE(td->td_ksegrp); runq_add(ke->ke_runq, ke); ke->ke_ksegrp->kg_runq_kses++; ke->ke_state = KES_ONRUNQ; @@ -1051,7 +1077,7 @@ if ((td->td_proc->p_flag & P_NOLOAD) == 0) sched_tdcnt--; - td->td_ksegrp->kg_avail_opennings++; + SLOT_RELEASE(td->td_ksegrp); runq_remove(ke->ke_runq, ke); ke->ke_state = KES_THREAD;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200409200726.i8K7QpIv012181>
