From owner-svn-soc-all@FreeBSD.ORG Sun Jul 31 21:43:15 2011 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 48B1A106566B for ; Sun, 31 Jul 2011 21:43:13 +0000 (UTC) (envelope-from rudot@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Sun, 31 Jul 2011 21:43:13 +0000 Date: Sun, 31 Jul 2011 21:43:13 +0000 From: rudot@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20110731214313.48B1A106566B@hub.freebsd.org> Cc: Subject: socsvn commit: r224784 - soc2011/rudot/kern X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 31 Jul 2011 21:43:15 -0000 Author: rudot Date: Sun Jul 31 21:43:13 2011 New Revision: 224784 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=224784 Log: per-process cpu accounting added Modified: soc2011/rudot/kern/sched_fbfs.c Modified: soc2011/rudot/kern/sched_fbfs.c ============================================================================== --- soc2011/rudot/kern/sched_fbfs.c Sun Jul 31 20:06:11 2011 (r224783) +++ soc2011/rudot/kern/sched_fbfs.c Sun Jul 31 21:43:13 2011 (r224784) @@ -74,17 +74,22 @@ static int sched_slice = 1; /* + * The time window size over which we compute the CPU utilization percentage. + */ +#define PCT_WINDOW 5 + +/* * The schedulable entity that runs a context. * This is an extension to the thread structure and is tailored to * the requirements of this scheduler */ struct td_sched { - fixpt_t ts_pctcpu; /* (j) %cpu during p_swtime. */ - int ts_cpticks; /* (j) Ticks of cpu time. */ - int ts_slptime; /* (j) Seconds !RUNNING. */ int ts_flags; int ts_vdeadline; /* virtual deadline. */ int ts_slice; /* Remaining slice in number of ticks */ + int ts_cswtick; + int ts_incrtick; + int ts_used; struct runq *ts_runq; /* runq the thread is currently on */ #ifdef KTR char ts_name[TS_NAME_LEN]; @@ -165,13 +170,6 @@ KTR_COUNTER0(KTR_SCHED, "load", "global load", sched_tdcnt); } -/* - * This function is called when a thread is about to be put on run queue - * because it has been made runnable or its priority has been adjusted. It - * determines if the new thread should be immediately preempted to. If so, - * it switches to it and eventually returns true. If not, it returns false - * so that the caller may place the thread on an appropriate run queue. - */ int maybe_preempt(struct thread *td) { @@ -236,6 +234,7 @@ thread0.td_sched = &td_sched0; thread0.td_lock = &sched_lock; mtx_init(&sched_lock, "sched lock", NULL, MTX_SPIN | MTX_RECURSE); + td_sched0.ts_used = 0; td_sched0.ts_slice = sched_slice; } @@ -259,8 +258,6 @@ THREAD_LOCK_ASSERT(td, MA_OWNED); ts = td->td_sched; - ts->ts_cpticks++; - if (--ts->ts_slice > 0) return; @@ -299,8 +296,6 @@ KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "exit", "prio:%d", child->td_priority); - thread_lock(td); - thread_unlock(td); mtx_lock_spin(&sched_lock); if ((child->td_proc->p_flag & P_NOLOAD) == 0) sched_load_rem(); @@ -326,6 +321,7 @@ ts->ts_flags |= (td->td_sched->ts_flags & TSF_AFFINITY); ts->ts_vdeadline = td->td_sched->ts_vdeadline; ts->ts_slice = td->td_sched->ts_slice; + ts->ts_used = td->td_sched->ts_used; } void @@ -472,7 +468,6 @@ THREAD_LOCK_ASSERT(td, MA_OWNED); td->td_slptick = ticks; - td->td_sched->ts_slptime = 0; if (pri) sched_prio(td, pri); if (TD_IS_SUSPENDED(td) || pri >= PSOCK) @@ -485,6 +480,7 @@ struct mtx *tmtx; struct td_sched *ts; struct proc *p; + int time_passed; tmtx = NULL; ts = td->td_sched; @@ -571,6 +567,7 @@ (*dtrace_vtime_switch_func)(newtd); #endif + ts->ts_cswtick = ticks; cpu_switch(td, newtd, tmtx != NULL ? tmtx : td->td_lock); lock_profile_obtain_lock_success(&sched_lock.lock_object, 0, 0, __FILE__, __LINE__); @@ -590,6 +587,9 @@ * needed to, or the thread_wait() or wait() will * need to reap it. */ + time_passed = ticks - ts->ts_cswtick; + ts->ts_used = imax(ts->ts_used - time_passed, 0); + if (ts->ts_used < 0) panic("Negative ts_used value\n"); #ifdef HWPMC_HOOKS if (PMC_PROC_IS_USING_PMCS(td->td_proc)) PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_IN); @@ -666,6 +666,7 @@ u_char max_prio; max_thread = curthread; + MPASS(max_thread != NULL); max_prio = max_thread->td_priority; ts = max_thread->td_sched; SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { @@ -685,7 +686,7 @@ } } } - + MPASS(max_thread != NULL); return (max_thread); } @@ -702,7 +703,6 @@ ts = td->td_sched; td->td_flags &= ~TDF_CANSWAP; td->td_slptick = 0; - ts->ts_slptime = 0; sched_add(td, SRQ_BORING); me = PCPU_GET(cpumask); @@ -736,6 +736,7 @@ * We did not wake lastcpu and there is no suitable idle cpu */ thr_worst = worst_running_thread(); + MPASS(thr_worst != NULL); c = thr_worst->td_oncpu; if (thr_worst->td_priority < td->td_priority) return; @@ -821,6 +822,8 @@ int deadline_min; td = td_min = TAILQ_FIRST(rqh); + MPASS(td != NULL); + MPASS(td_min != NULL); deadline_min = td_min->td_sched->ts_vdeadline; td = TAILQ_NEXT(td, td_runq); @@ -833,6 +836,7 @@ td = TAILQ_NEXT(td, td_runq); } + MPASS(td_min != NULL); return (td_min); } @@ -852,6 +856,7 @@ pri = RQB_FFS(rqb->rqb_bits[i]) + (i << RQB_L2BPW); if ((pri == RQ_TIMESHARE) || (pri == RQ_IDLE)) { td = edf_choose(&rq->rq_queues[pri]); + KASSERT(td != NULL, "runq_choose_bfs: no thread on busy queue"); return (td); } rqh = &rq->rq_queues[pri]; @@ -881,7 +886,7 @@ rq = &runq; td = runq_choose_bfs(&runq); - if (td) { + if (td != NULL) { runq_remove(rq, td); td->td_flags |= TDF_DIDRUN; @@ -989,15 +994,44 @@ sched_pctcpu(struct thread *td) { struct td_sched *ts; + int time_passed; + int nticks; + fixpt_t pct; THREAD_LOCK_ASSERT(td, MA_OWNED); ts = td->td_sched; - return (ts->ts_pctcpu); + + switch (td->td_state) { + case TDS_RUNNING: + if (ts->ts_used < 0) panic("Bad ts_used value\n"); + nticks = ts->ts_used; + default: + time_passed = ticks - ts->ts_cswtick; + nticks = imax(ts->ts_used - time_passed, 0); + } + nticks /= PCT_WINDOW; + + if (nticks > hz) panic("too big nticks value.\n"); + if (nticks < 0) panic("bad nticks value.\n"); + + pct = (FSCALE * ((FSCALE * nticks) / hz)) >> FSHIFT; + + return (pct); } void sched_tick(void) { + struct td_sched *ts; + + THREAD_LOCK_ASSERT(curthread, MA_OWNED); + ts = curthread->td_sched; + if (ts->ts_incrtick == ticks) + return; + if (ts->ts_used < (hz * PCT_WINDOW)) { + ts->ts_used += 1; + ts->ts_incrtick = ticks; + } } /*