Mondo IT

recensioni, articoli e approfondimenti sul mondo IT

Uno scheduler per XEN

leave a comment »

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,
};
Annunci

Written by Michele Paolino

21/05/2010 a 22:16

Rispondi

Effettua il login con uno di questi metodi per inviare il tuo commento:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: