#include #include #include #include #include "lve_internal.h" #include "resource.h" #include "lve_debug.h" #include "lve_hooks.h" unsigned long lavenrun[3]; void lve_get_avenrun_trace(unsigned long *loads, unsigned long offset, int shift) { loads[0] = (lavenrun[0] + offset) << shift; loads[1] = (lavenrun[1] + offset) << shift; loads[2] = (lavenrun[2] + offset) << shift; } static void update_loadavg(void) { long count, lcount; struct light_ve *ve; struct lvp_ve_private *lvp = root_lvp; /* do we need other lvps? */ /* Reduce by 1 so as not to account our loadavg thread */ count = 0; down_read(&lvp_tree_lock(lvp)); list_for_each_entry(ve, &lvp->lvp_lve_list, lve_link) { lcount = os_loadavg_count(ve); count += (ve == lvp->lvp_default) ? lcount : !!lcount; LVE_DBG("lve %d count %ld\n", ve->lve_id, lcount); } up_read(&lvp_tree_lock(lvp)); count -= 1; LVE_DBG("total count %ld\n", count); count *= FIXED_1; CALC_LOAD(lavenrun[0], EXP_1, count); CALC_LOAD(lavenrun[1], EXP_5, count); CALC_LOAD(lavenrun[2], EXP_15, count); } int loadavg_thread(void *unused) { while (!kthread_should_stop()) { update_loadavg(); /* * Though we count load average ourselves, the * thread should not appear on the thread list * as non-interruptible, since other ways to * calculate LA will always show at least 1.0 * We are still safe from signals, since this thread * was forked from kthreadd, which called * ignore_signals() and we copied SIG_IGN handlers in * copy_sighand(). */ freezable_schedule_timeout_interruptible(LOAD_FREQ); } return 0; } static struct task_struct *la_thread; int lve_stats_init(void) { la_thread = lve_call(kthread_create(loadavg_thread, NULL, "lve_loadavg"), LVE_FAIL_STATS_CRT_THREAD, ERR_PTR(-ENOMEM)); if (IS_ERR(la_thread)) return -ENOMEM; wake_up_process(la_thread); return 0; } void lve_stats_fini(void) { kthread_stop(la_thread); }