Uno scheduler per XEN
questo è uno scheduler (random) per XEN. Il suo valore è semplicemente accademico senza alcuna applicazione pratica.
This is a random scheduler for XEN. I wrote this scheduler for academic purposes only.
/****************************************************************************
* (C) 2010 - Michele Paolino
****************************************************************************
*
* File: common/sched_random.c
* Author: Michele Paolino
*
* Description: Random CPU scheduler
*/
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/time.h>
#include <xen/sched-if.h>
#include <xen/softirq.h>
#include <xen/errno.h>
#include <xen/list.h>
#include <xen/timer.h>
#include <xen/randmd5.h>
int tot_vcpu=0;
MD5_CTX mdContext;
#define RAND_PCPU(_c) ((struct random_pcpu *)per_cpu(schedule_data, _c).sched_priv)
#define RAND_VCPU(_vcpu) ((struct random_vcpu *) (_vcpu)->sched_priv)
#define RUNQ(_cpu) (&(RAND_PCPU(_cpu)->runq))
struct random_pcpu {
struct list_head runq;
};
struct random_vcpu{
struct list_head runq_elem;
struct vcpu *vcpu;
};
static inline void __runq_tickle(unsigned int cpu, struct random_vcpu *new)
{
struct random_vcpu * const cur = RAND_VCPU(per_cpu(schedule_data, cpu).curr);
cpumask_t mask;
ASSERT(cur);
cpus_clear(mask);
printk("\nTickle vcpu %d\n", cur->vcpu->vcpu_id);
if ( vcpu_runnable(cur->vcpu) )
{
cpu_set(cpu, mask);
printk("\nI'm setting the mask for the current vcpu\n");
}
/* Send scheduler interrupts to designated CPUs */
if ( !cpus_empty(mask) ){
printk("\nRaising softirq\n");
cpumask_raise_softirq(mask, SCHEDULE_SOFTIRQ);
}
}
static inline int __vcpu_on_runq(struct random_vcpu *svc)
{
return !list_empty(&svc->runq_elem);
}
static inline void __runq_insert(unsigned int cpu, struct random_vcpu *svc)
{
struct list_head *runq = RUNQ(cpu);
BUG_ON( cpu != svc->vcpu->processor );
if (!__vcpu_on_runq(svc)) list_add(&svc->runq_elem,runq);
return;
}
static inline void __runq_remove(struct random_vcpu *svc)
{
BUG_ON( !__vcpu_on_runq(svc) );
list_del_init(&svc->runq_elem);
}
static inline void __random_vcpu_check(struct vcpu *vc)
{
struct random_vcpu * const svc = RAND_VCPU(vc);
BUG_ON( (svc->vcpu) != vc );
}
static int random_pcpu_init(int cpu)
{
struct random_pcpu *spc;
/* Allocate per-PCPU info */
spc = xmalloc(struct random_pcpu);
if ( spc == NULL )
return -1;
memset(spc, 0, sizeof(*spc));
INIT_LIST_HEAD(&spc->runq);
per_cpu(schedule_data, cpu).sched_priv = spc;
return 0;
}
static int random_vcpu_init(struct vcpu *vc){
struct random_vcpu *svc;
svc = xmalloc(struct random_vcpu);
if ( svc == NULL )
return -1;
memset(svc, 0, sizeof(*svc));
INIT_LIST_HEAD(&svc->runq_elem);
svc->vcpu = vc;
vc->sched_priv = svc;
/* Allocate per-PCPU info */
if ( unlikely(!RAND_PCPU(vc->processor)) )
{
if ( random_pcpu_init(vc->processor) != 0 )
return -1;
}
__random_vcpu_check(vc);
tot_vcpu++;
printk("\nadd VCPU %d tot_vcpu=%d\n", vc->vcpu_id, tot_vcpu);
return 0;
}
static void random_vcpu_destroy(struct vcpu *vc)
{
struct random_vcpu * const svc = RAND_VCPU(vc);
printk("\n\nDestroying vcpu %d\n\n",vc->vcpu_id);
tot_vcpu--;
BUG_ON( !list_empty(&svc->runq_elem) );
list_del(&svc->runq_elem);
xfree(svc);
}
struct task_slice random_schedule(s_time_t now){
const unsigned int cpu = smp_processor_id();
struct list_head * runq = RUNQ(cpu);
struct random_vcpu * const scurr = RAND_VCPU(current);
struct random_vcpu *snext;
struct task_slice ret;
int next_vcpu=0;
next_vcpu = (MD5Final (&mdContext)) % tot_vcpu;
__random_vcpu_check(current);
if ( vcpu_runnable(current) )
__runq_insert(cpu, scurr);
else
BUG_ON( is_idle_vcpu(current) || list_empty(runq) );
while (next_vcpu!=0){
next_vcpu--;
list_move(runq, runq->next);
}
snext = list_entry(runq->next, struct random_vcpu, runq_elem);
__runq_remove(snext);
ret.time = MILLISECS(10);
ret.task=snext->vcpu;
__random_vcpu_check(current);
return ret;
}
static void __random_init(void){
unsigned char digest[16];
int i;
long unsigned int mask= 0xFF;
long unsigned int string_now = NOW();
MD5Init (&mdContext);
for (i=0;i<8;i++){
digest[i]=(char) ((string_now & mask) >> 8*i);
mask <<=8;
}
MD5Update (&mdContext, (unsigned char*)digest, sizeof(s_time_t));
}
static void random_vcpu_wake( struct vcpu *vc){
struct random_vcpu * const svc = RAND_VCPU(vc);
const unsigned int cpu = vc->processor;
BUG_ON ( is_idle_vcpu(vc) );
/* Put the VCPU on the runq and tickle CPUs */
__runq_insert(cpu, svc); //inserisco in coda
__runq_tickle(cpu, svc); // raise softirq
return;
}
static void random_vcpu_sleep(struct vcpu *vc)
{
struct random_vcpu * const svc = RAND_VCPU(vc);
printk("Sleeping..\n");
BUG_ON( is_idle_vcpu(vc) );
if ( per_cpu(schedule_data, vc->processor).curr == vc )
cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ);
else if ( __vcpu_on_runq(svc) )
__runq_remove(svc);
}
static void random_init(void)
{
tot_vcpu=0;
__random_init();
}
struct scheduler sched_rand_def = {
.name = "Random Scheduler",
.opt_name = "random",
.sched_id = 17,
.init_vcpu = random_vcpu_init,
.wake = random_vcpu_wake,
.sleep = random_vcpu_sleep,
.destroy_vcpu = random_vcpu_destroy,
.do_schedule = random_schedule,
.init = random_init,
};
