bitkeeper revision 1.1389.5.37 (427f9fd5lvofpMsmBQ2h16fsuXQH6Q)

Manual merge.
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-05-09 17:37:25 +00:00
commit bb5ae6b5cc
15 files changed
+1929 -19

No files matched your search

+4
View File
@@ -21,6 +21,7 @@
412f4bd9sm5mCQ8BkrgKcAKZGadq7Q docs/misc/blkif-drivers-explained.txt
420b949cy9ZGzED74Fz_DaWlK7tT4g docs/misc/crashdb.txt
4251a1f82AexscYEiF4Iku8Gc_kWfQ docs/misc/grant-tables.txt
424d462b5GuApQ_NyMsRFt9LbrsWow docs/misc/sedf_scheduler_mini-HOWTO.txt
40d6ccbfKKBq8jE0ula4eHEzBiQuDA docs/misc/xen_config.html
410a4c2bAO_m_l4RsiiPHnZ4ixHWbQ docs/misc/xend.tex
3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/src/interface.tex
@@ -742,6 +743,7 @@
3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/xc_private.h
42337174PxyzzPk62raDiYCIsfStDg tools/libxc/xc_ptrace.c
4273458duzL--nsTfT6e_q6Kfij48g tools/libxc/xc_ptrace_core.c
41ebbfe9U0b0kI-HgjK7VEY4EvW7_w tools/libxc/xc_sedf.c
41dde8b0pLfAKMs_L9Uri2hnzHiCRQ tools/libxc/xc_vmx_build.c
40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
@@ -1261,6 +1263,7 @@
3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c
40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
41ebbfe9oF1BF3cH5v7yE3eOL9uPbA xen/common/sched_sedf.c
3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
3ddb79bd0gVQYmL2zvuJnldvD0AGxQ xen/common/softirq.c
3e7f358awXBC3Vw-wFRwPw18qL1khg xen/common/string.c
@@ -1409,6 +1412,7 @@
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h
3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h
40715b2epYl2jBbxzz9CI2rgIca7Zg xen/include/xen/acpi.h
422f0995xCgnbsVhTjSncnqIABs64g xen/include/xen/adv_sched_hist.h
3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xen/cache.h
41f2cea7Yna7xc0X9fyavIjoSFFeVg xen/include/xen/compile.h.in
3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/include/xen/compiler.h
+44
View File
@@ -0,0 +1,44 @@
sEDF scheduler
--------------
Author:
Stephan.Diestelhorst@{cl.cam.ac.uk, inf.tu-dresden.de}
Overview:
This scheduler provides weighted CPU sharing in an intuitive way and
uses realtime-algorithms to ensure time guarantees.
Usage:
   -add "sched=sedf" on Xen's boot command-line
   -create domains as usual
   -use "xm sedf <dom-id> <period> <slice> <latency-hint> <extra> <weight>"
  Where:
  -period/slice are the normal EDF scheduling parameters in nanosecs
  -latency-hint is the scaled period in case the domain is doing heavy I/O
(unused by the currently compiled version)
  -extra is a flag (0/1), which controls whether the domain can run in
extra-time
  -weight is mutually exclusive with period/slice and specifies another
way of setting a domains cpu slice
Examples:
 normal EDF (20ms/5ms):
  xm sedf <dom-id> 20000000 5000000 0 0 0
 best-effort domains (i.e. non-realtime):
  xm sedf <dom-id> 20000000 0 0 1 0
 
normal EDF (20ms/5ms) + share of extra-time:
  xm sedf <dom-id> 20000000 5000000 0 1 0
 4 domains with weights 2:3:4:2
  xm sedf <d1> 0 0 0 0 2
  xm sedf <d2> 0 0 0 0 3
  xm sedf <d3> 0 0 0 0 4
  xm sedf <d4> 0 0 0 0 2
 1 fully-specified (10ms/3ms) domain, 3 other domains share
 available rest in 2:7:3 ratio:
  xm sedf <d1> 10000000 3000000 0 0 0
  xm sedf <d2> 0 0 0 0 2
  xm sedf <d3> 0 0 0 0 7
  xm sedf <d4> 0 0 0 0 3
+1
View File
@@ -16,6 +16,7 @@ vpath %c $(XEN_LIBXUTIL)
INCLUDES += -I $(XEN_LIBXUTIL)
SRCS :=
SRCS += xc_sedf.c
SRCS += xc_bvtsched.c
SRCS += xc_core.c
SRCS += xc_domain.c
+8
View File
@@ -296,6 +296,14 @@ int xc_bvtsched_domain_get(int xc_handle,
long long *warpl,
long long *warpu);
int xc_sedf_domain_set(int xc_handle,
u32 domid,
u64 period, u64 slice, u64 latency, u16 extratime, u16 weight);
int xc_sedf_domain_get(int xc_handle,
u32 domid,
u64* period, u64 *slice, u64 *latency, u16 *extratime, u16* weight);
typedef evtchn_status_t xc_evtchn_status_t;
/*
+51
View File
@@ -0,0 +1,51 @@
/******************************************************************************
* xc_sedf.c
*
* API for manipulating parameters of the Simple EDF scheduler.
*
* changes by Stephan Diestelhorst
* based on code
* by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
*/
#include "xc_private.h"
int xc_sedf_domain_set(int xc_handle,
u32 domid, u64 period, u64 slice,u64 latency, u16 extratime,u16 weight)
{
dom0_op_t op;
struct sedf_adjdom *p = &op.u.adjustdom.u.sedf;
op.cmd = DOM0_ADJUSTDOM;
op.u.adjustdom.domain = (domid_t)domid;
op.u.adjustdom.sched_id = SCHED_SEDF;
op.u.adjustdom.direction = SCHED_INFO_PUT;
p->period = period;
p->slice = slice;
p->latency = latency;
p->extratime = extratime;
p->weight = weight;
return do_dom0_op(xc_handle, &op);
}
int xc_sedf_domain_get(int xc_handle, u32 domid, u64 *period, u64 *slice, u64* latency, u16* extratime, u16* weight)
{
dom0_op_t op;
int ret;
struct sedf_adjdom *p = &op.u.adjustdom.u.sedf;
op.cmd = DOM0_ADJUSTDOM;
op.u.adjustdom.domain = (domid_t)domid;
op.u.adjustdom.sched_id = SCHED_SEDF;
op.u.adjustdom.direction = SCHED_INFO_GET;
ret = do_dom0_op(xc_handle, &op);
*period = p->period;
*slice = p->slice;
*latency = p->latency;
*extratime = p->extratime;
*weight = p->weight;
return ret;
}
+70
View File
@@ -827,6 +827,52 @@ static PyObject *pyxc_physinfo(PyObject *self,
"cpu_khz", info.cpu_khz);
}
static PyObject *pyxc_sedf_domain_set(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 domid;
u64 period, slice, latency;
u16 extratime, weight;
static char *kwd_list[] = { "dom", "period", "slice", "latency", "extratime", "weight",NULL };
if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list, &domid,
&period, &slice, &latency, &extratime, &weight) )
return NULL;
if ( xc_sedf_domain_set(xc->xc_handle, domid, period, slice, latency, extratime,weight) != 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
return zero;
}
static PyObject *pyxc_sedf_domain_get(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 domid;
u64 period, slice,latency;
u16 weight, extratime;
static char *kwd_list[] = { "dom", NULL };
if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
return NULL;
if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
&slice,&latency,&extratime,&weight) )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
"domain", domid,
"period", period,
"slice", slice,
"latency", latency,
"extratime", extratime);
}
static PyObject *pyxc_shadow_control(PyObject *self,
PyObject *args,
PyObject *kwds)
@@ -1027,6 +1073,30 @@ static PyMethodDef pyxc_methods[] = {
" warpu [long]: Unwarp requirement.\n"
" warpl [long]: Warp limit,\n"
},
{ "sedf_domain_set",
(PyCFunction)pyxc_sedf_domain_set,
METH_KEYWORDS, "\n"
"Set the scheduling parameters for a domain when running with Atropos.\n"
" dom [int]: domain to set\n"
" period [long]: domain's scheduling period\n"
" slice [long]: domain's slice per period\n"
" latency [long]: domain's wakeup latency hint\n"
" extratime [int]: domain aware of extratime?\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "sedf_domain_get",
(PyCFunction)pyxc_sedf_domain_get,
METH_KEYWORDS, "\n"
"Get the current scheduling parameters for a domain when running with\n"
"the Atropos scheduler."
" dom [int]: domain to query\n"
"Returns: [dict]\n"
" domain [int]: domain ID\n"
" period [long]: scheduler period\n"
" slice [long]: CPU reservation per period\n"
" latency [long]: domain's wakeup latency hint\n"
" extratime [int]: domain aware of extratime?\n"},
{ "evtchn_alloc_unbound",
(PyCFunction)pyxc_evtchn_alloc_unbound,
+9
View File
@@ -260,6 +260,15 @@ class Xend:
'warpl' : warpl,
'warpu' : warpu })
def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
return self.xendPost(self.domainurl(id),
{'op' : 'cpu_sedf_set',
'period' : period,
'slice' : slice,
'latency' : latency,
'extratime' : extratime,
'weight' : weight })
def xend_domain_maxmem_set(self, id, memory):
return self.xendPost(self.domainurl(id),
{ 'op' : 'maxmem_set',
+18
View File
@@ -644,6 +644,24 @@ class XendDomain:
except Exception, ex:
raise XendError(str(ex))
def domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
"""Set Simple EDF scheduler parameters for a domain.
"""
dominfo = self.domain_lookup(id)
try:
return xc.sedf_domain_set(dominfo.dom, period, slice, latency, extratime, weight)
except Exception, ex:
raise XendError(str(ex))
def domain_cpu_sedf_get(self, id):
"""Get Atropos scheduler parameters for a domain.
"""
dominfo = self.domain_lookup(id)
try:
return xc.sedf_domain_get(dominfo.dom)
except Exception, ex:
raise XendError(str(ex))
def domain_device_create(self, id, devconfig):
"""Create a new device for a domain.
+12
View File
@@ -107,6 +107,18 @@ class SrvDomain(SrvDir):
val = fn(req.args, {'dom': self.dom.id})
return val
def op_cpu_sedf_set(self, op, req):
fn = FormFn(self.xd.domain_cpu_sedf_set,
[['dom', 'str'],
['period', 'int'],
['slice', 'int'],
['latency', 'int'],
['extratime', 'int'],
['weight', 'int']])
val = fn(req.args, {'dom': self.dom.id})
return val
def op_maxmem_set(self, op, req):
fn = FormFn(self.xd.domain_maxmem_set,
[['dom', 'str'],
+17
View File
@@ -591,6 +591,23 @@ class ProgBvtslice(Prog):
xm.prog(ProgBvtslice)
class ProgSedf(Prog):
group = 'scheduler'
name= "sedf"
info = """Set simple EDF parameters."""
def help(self, args):
print args[0], "DOM PERIOD SLICE LATENCY EXTRATIME WEIGHT"
print "\nSet simple EDF parameters."
def main(self, args):
if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
dom = args[1]
v = map(int, args[2:7])
server.xend_domain_cpu_sedf_set(dom, *v)
xm.prog(ProgSedf)
class ProgInfo(Prog):
group = 'host'
name = "info"
File diff suppressed because it is too large. Load diff
+143 -6
View File
@@ -40,6 +40,17 @@
static char opt_sched[10] = "bvt";
string_param("sched", opt_sched);
/*#define WAKE_HISTO*/
/*#define BLOCKTIME_HISTO*/
/*#define ADV_SCHED_HISTO*/
//#include <xen/adv_sched_hist.h>
#if defined(WAKE_HISTO)
#define BUCKETS 31
#elif defined(BLOCKTIME_HISTO)
#define BUCKETS 200
#endif
#define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */
/* Various timer handlers. */
@@ -51,8 +62,10 @@ static void dom_timer_fn(unsigned long data);
struct schedule_data schedule_data[NR_CPUS];
extern struct scheduler sched_bvt_def;
extern struct scheduler sched_sedf_def;
static struct scheduler *schedulers[] = {
&sched_bvt_def,
&sched_sedf_def,
NULL
};
@@ -226,6 +239,10 @@ long do_block(void)
{
struct exec_domain *ed = current;
#ifdef ADV_SCHED_HISTO
adv_sched_hist_start(current->processor);
#endif
ed->vcpu_info->evtchn_upcall_mask = 0;
set_bit(EDF_BLOCKED, &ed->flags);
@@ -246,6 +263,10 @@ long do_block(void)
/* Voluntarily yield the processor for this allocation. */
static long do_yield(void)
{
#ifdef ADV_SCHED_HISTO
adv_sched_hist_start(current->processor);
#endif
TRACE_2D(TRC_SCHED_YIELD, current->domain->id, current->id);
__enter_scheduler();
return 0;
@@ -275,6 +296,7 @@ long do_sched_op(unsigned long op)
case SCHEDOP_shutdown:
{
TRACE_3D(TRC_SCHED_SHUTDOWN, current->domain->id, current->id,
TRACE_3D(TRC_SCHED_SHUTDOWN, current->domain->id, current->id,
(op >> SCHEDOP_reasonshift));
domain_shutdown((u8)(op >> SCHEDOP_reasonshift));
@@ -322,10 +344,22 @@ long sched_ctl(struct sched_ctl_cmd *cmd)
long sched_adjdom(struct sched_adjdom_cmd *cmd)
{
struct domain *d;
struct exec_domain *ed;
int cpu;
#if NR_CPUS <=32
unsigned long have_lock;
#else
unsigned long long have_lock;
#endif
int succ;
#define __set_cpu_bit(cpu, data) data |= ((typeof(data))1)<<cpu
#define __get_cpu_bit(cpu, data) (data & ((typeof(data))1)<<cpu)
#define __clear_cpu_bits(data) data = ((typeof(data))0)
if ( cmd->sched_id != ops.sched_id )
return -EINVAL;
if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET )
return -EINVAL;
@@ -333,9 +367,38 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd)
if ( d == NULL )
return -ESRCH;
spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
/* acquire locks on all CPUs on which exec_domains of this domain run */
do {
succ = 0;
__clear_cpu_bits(have_lock);
for_each_exec_domain(d, ed) {
cpu = ed->processor;
if (!__get_cpu_bit(cpu, have_lock)) {
/* if we don't have a lock on this CPU: acquire it*/
if (spin_trylock(&schedule_data[cpu].schedule_lock)) {
/*we have this lock!*/
__set_cpu_bit(cpu, have_lock);
succ = 1;
} else {
/*we didn,t get this lock -> free all other locks too!*/
for (cpu = 0; cpu < NR_CPUS; cpu++)
if (__get_cpu_bit(cpu, have_lock))
spin_unlock(&schedule_data[cpu].schedule_lock);
/* and start from the beginning! */
succ = 0;
/* leave the "for_each_domain_loop" */
break;
}
}
}
} while (!succ);
//spin_lock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
SCHED_OP(adjdom, d, cmd);
spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
//spin_unlock_irq(&schedule_data[d->exec_domain[0]->processor].schedule_lock);
for (cpu = 0; cpu < NR_CPUS; cpu++)
if (__get_cpu_bit(cpu, have_lock))
spin_unlock(&schedule_data[cpu].schedule_lock);
__clear_cpu_bits(have_lock);
TRACE_1D(TRC_SCHED_ADJDOM, d->id);
put_domain(d);
@@ -358,8 +421,14 @@ static void __enter_scheduler(void)
perfc_incrc(sched_run);
spin_lock_irq(&schedule_data[cpu].schedule_lock);
#ifdef ADV_SCHED_HISTO
adv_sched_hist_from_stop(cpu);
#endif
now = NOW();
#ifdef ADV_SCHED_HISTO
adv_sched_hist_start(cpu);
#endif
rem_ac_timer(&schedule_data[cpu].s_timer);
@@ -386,9 +455,12 @@ static void __enter_scheduler(void)
spin_unlock_irq(&schedule_data[cpu].schedule_lock);
if ( unlikely(prev == next) )
if ( unlikely(prev == next) ) {
#ifdef ADV_SCHED_HISTO
adv_sched_hist_to_stop(cpu);
#endif
return continue_running(prev);
}
perfc_incrc(sched_ctx);
#if defined(WAKE_HISTO)
@@ -423,6 +495,10 @@ static void __enter_scheduler(void)
prev->domain->id, prev->id,
next->domain->id, next->id);
#ifdef ADV_SCHED_HISTO
adv_sched_hist_to_stop(cpu);
#endif
context_switch(prev, next);
}
@@ -444,6 +520,10 @@ int idle_cpu(int cpu)
/* The scheduler timer: force a run through the scheduler */
static void s_timer_fn(unsigned long unused)
{
#ifdef ADV_SCHED_HISTO
adv_sched_hist_start(current->processor);
#endif
raise_softirq(SCHEDULE_SOFTIRQ);
perfc_incrc(sched_irq);
}
@@ -587,9 +667,66 @@ void reset_sched_histo(unsigned char key)
schedule_data[j].hist[i] = 0;
}
#else
#if defined(ADV_SCHED_HISTO)
void print_sched_histo(unsigned char key)
{
int i, j, k,t;
printf("Hello!\n");
for ( k = 0; k < smp_num_cpus; k++ )
{
j = 0;
t = 0;
printf ("CPU[%02d]: scheduler latency histogram FROM (ms:[count])\n", k);
for ( i = 0; i < BUCKETS; i++ )
{
//if ( schedule_data[k].hist[i] != 0 )
{
t += schedule_data[k].from_hist[i];
if ( i < BUCKETS-1 )
printk("%3d:[%7u] ", i, schedule_data[k].from_hist[i]);
else
printk(" >:[%7u] ", schedule_data[k].from_hist[i]);
//if ( !(++j % 5) )
printk("\n");
}
}
printk("\nTotal: %i\n",t);
}
for ( k = 0; k < smp_num_cpus; k++ )
{
j = 0; t = 0;
printf ("CPU[%02d]: scheduler latency histogram TO (ms:[count])\n", k);
for ( i = 0; i < BUCKETS; i++ )
{
//if ( schedule_data[k].hist[i] != 0 )
{
t += schedule_data[k].from_hist[i];
if ( i < BUCKETS-1 )
printk("%3d:[%7u] ", i, schedule_data[k].to_hist[i]);
else
printk(" >:[%7u] ", schedule_data[k].to_hist[i]);
//if ( !(++j % 5) )
printk("\n");
}
}
printk("\nTotal: %i\n",t);
}
}
void reset_sched_histo(unsigned char key)
{
int i, j;
for ( j = 0; j < smp_num_cpus; j++ ) {
for ( i=0; i < BUCKETS; i++ )
schedule_data[j].to_hist[i] = schedule_data[j].from_hist[i] = 0;
schedule_data[j].save_tsc = 0;
}
}
#else
void print_sched_histo(unsigned char key) { }
void reset_sched_histo(unsigned char key) { }
#endif
#endif
/*
* Local variables:
+27 -13
View File
@@ -9,6 +9,7 @@
/* Scheduler types. */
#define SCHED_BVT 0
#define SCHED_SEDF 4
/* Set or get info? */
#define SCHED_INFO_PUT 0
@@ -31,18 +32,31 @@ struct sched_ctl_cmd
struct sched_adjdom_cmd
{
u32 sched_id;
u32 direction;
domid_t domain;
union {
struct bvt_adjdom {
u32 mcu_adv; /* mcu advance: inverse of weight */
u32 warpback; /* warp? */
s32 warpvalue; /* warp value */
long long warpl; /* warp limit */
long long warpu; /* unwarp time requirement */
} bvt;
} u;
};
u32 sched_id; /* 0 */
u32 direction; /* 4 */
domid_t domain; /* 8 */
u16 __pad0;
u32 __pad1;
union { /* 16 */
struct bvt_adjdom
{
u32 mcu_adv; /* 16: mcu advance: inverse of weight */
u32 warpback; /* 20: warp? */
s32 warpvalue; /* 24: warp value */
long long warpl; /* 32: warp limit */
long long warpu; /* 40: unwarp time requirement */
} PACKED bvt;
struct sedf_adjdom
{
u64 period; /* 16 */
u64 slice; /* 24 */
u64 latency; /* 32 */
u16 extratime; /* 36 */
u16 weight; /* 38 */
} PACKED sedf;
} PACKED u;
} PACKED; /* 40 bytes */
#endif /* __XEN_PUBLIC_SCHED_CTL_H__ */
+40
View File
@@ -0,0 +1,40 @@
/* Some functions to suport advanced scheduler histograms
Author: Stephan.Diestelhorst@cl.cam.ac.uk */
//#include <xen/sched.h>
//#include <xen/sched-if.h>
#include <asm/msr.h>
#define ADV_SCHED_HISTO
static inline void adv_sched_hist_start(int cpu) {
u64 now;
rdtscll(now);
if (!schedule_data[cpu].save_tsc)
schedule_data[cpu].save_tsc = now;
}
static inline void adv_sched_hist_from_stop(int cpu) {
u64 now;
rdtscll(now);
if (schedule_data[cpu].save_tsc) {
now -= schedule_data[cpu].save_tsc;
now /= 7;
if (now < BUCKETS-1)
schedule_data[cpu].from_hist[now]++;
else
schedule_data[cpu].from_hist[BUCKETS-1]++;
schedule_data[cpu].save_tsc = 0;
}
}
static inline void adv_sched_hist_to_stop(int cpu) {
u64 now;
rdtscll(now);
if (schedule_data[cpu].save_tsc) {
now -= schedule_data[cpu].save_tsc;
now /= 24;
if (now < BUCKETS-1)
schedule_data[cpu].to_hist[now]++;
else
schedule_data[cpu].to_hist[BUCKETS-1]++;
schedule_data[cpu].save_tsc = 0;
}
}
+9
View File
@@ -8,6 +8,10 @@
#ifndef __XEN_SCHED_IF_H__
#define __XEN_SCHED_IF_H__
//#define ADV_SCHED_HISTO
#define BUCKETS 10
/*300*/
struct schedule_data {
spinlock_t schedule_lock; /* spinlock protecting curr */
struct exec_domain *curr; /* current task */
@@ -15,6 +19,11 @@ struct schedule_data {
void *sched_priv;
struct ac_timer s_timer; /* scheduling timer */
unsigned long tick; /* current periodic 'tick' */
#ifdef ADV_SCHED_HISTO
u32 to_hist[BUCKETS];
u32 from_hist[BUCKETS];
u64 save_tsc;
#endif
#ifdef BUCKETS
u32 hist[BUCKETS]; /* for scheduler latency histogram */
#endif
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.