diff --git a/Makefile b/Makefile index 09d790cf63..58f3b75885 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ OBJS = \ uart.o\ vectors.o\ vm.o\ + rand.o\ # Cross-compiling (e.g., on Mac OS X) # TOOLPREFIX = i386-jos-elf diff --git a/proc.c b/proc.c index 806b1b184b..d128a27a18 100644 --- a/proc.c +++ b/proc.c @@ -6,6 +6,7 @@ #include "x86.h" #include "proc.h" #include "spinlock.h" +#include "rand.h" struct { struct spinlock lock; @@ -70,16 +71,17 @@ myproc(void) { // If found, change state to EMBRYO and initialize // state required to run in the kernel. // Otherwise return 0. -static struct proc* +static struct proc * allocproc(void) { struct proc *p; char *sp; + static int count = 0; acquire(&ptable.lock); - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) - if(p->state == UNUSED) + for (p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if (p->state == UNUSED) goto found; release(&ptable.lock); @@ -88,11 +90,13 @@ allocproc(void) found: p->state = EMBRYO; p->pid = nextpid++; + p->tickets = count++ + (nextpid * 10) / 5; release(&ptable.lock); // Allocate kernel stack. - if((p->kstack = kalloc()) == 0){ + if ((p->kstack = kalloc()) == 0) + { p->state = UNUSED; return 0; } @@ -100,15 +104,15 @@ allocproc(void) // Leave room for trap frame. sp -= sizeof *p->tf; - p->tf = (struct trapframe*)sp; + p->tf = (struct trapframe *)sp; // Set up new context to start executing at forkret, // which returns to trapret. sp -= 4; - *(uint*)sp = (uint)trapret; + *(uint *)sp = (uint)trapret; sp -= sizeof *p->context; - p->context = (struct context*)sp; + p->context = (struct context *)sp; memset(p->context, 0, sizeof *p->context); p->context->eip = (uint)forkret; @@ -319,22 +323,47 @@ wait(void) // - swtch to start running that process // - eventually that process transfers control // via swtch back to the scheduler. -void -scheduler(void) +void scheduler(void) { struct proc *p; struct cpu *c = mycpu(); c->proc = 0; - - for(;;){ + + for (;;) + { // Enable interrupts on this processor. sti(); + int tickets_passed = 0; + int number_tickets = 0; + + //cuenta el total de tickets + for (p = ptable.proc; p < &ptable.proc[NPROC]; p++) + { + if (p->state != RUNNABLE) + continue; + number_tickets = number_tickets + p->tickets; + } + + long winner = random_tickets(number_tickets); + // Loop over process table looking for process to run. acquire(&ptable.lock); - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->state != RUNNABLE) + for (p = ptable.proc; p < &ptable.proc[NPROC]; p++) + { + if (p->state != RUNNABLE) continue; + tickets_passed += p->tickets; + if (tickets_passed < winner) + { + continue; + } + if (tickets_passed == winner) //Estas 3 lineas eran para verificar que funcionaba el Lottery Scheduler + { + cprintf("\t\tTickets Passed: %d\n", tickets_passed); + cprintf("\t\tProcess Winner: %s\n", p->name); + cprintf("\t\tProcess Tickets: %d\n", p->tickets); + } // Switch to chosen process. It is the process's job // to release ptable.lock and then reacquire it @@ -349,9 +378,9 @@ scheduler(void) // Process is done running for now. // It should have changed its p->state before coming back. c->proc = 0; + break; } release(&ptable.lock); - } } diff --git a/proc.h b/proc.h index 1647114179..421dd72d22 100644 --- a/proc.h +++ b/proc.h @@ -49,6 +49,7 @@ struct proc { struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) + int tickets; }; // Process memory is laid out contiguously, low addresses first: diff --git a/rand.c b/rand.c new file mode 100644 index 0000000000..b4c24d7634 --- /dev/null +++ b/rand.c @@ -0,0 +1,120 @@ +/* A C-program for MT19937: Real number version */ +/* genrand() generates one pseudorandom real number (double) */ +/* which is uniformly distributed on [0,1]-interval, for each */ +/* call. sgenrand(seed) set initial values to the working area */ +/* of 624 words. Before genrand(), sgenrand(seed) must be */ +/* called once. (seed is any 32-bit integer except for 0). */ +/* Integer generator is obtained by modifying two lines. */ +/* Coded by Takuji Nishimura, considering the suggestions by */ +/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ + +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later */ +/* version. */ +/* This library is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +/* See the GNU Library General Public License for more details. */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ +/* 02111-1307 USA */ + +/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ +/* Any feedback is very welcome. For any question, comments, */ +/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */ +/* matumoto@math.keio.ac.jp */ + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0df /* constant vector a */ +#define UPPER_MASK 0x80000000 /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffff /* least significant r bits */ + +/* Tempering parameters */ +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define TEMPERING_SHIFT_U(y) (y >> 11) +#define TEMPERING_SHIFT_S(y) (y << 7) +#define TEMPERING_SHIFT_T(y) (y << 15) +#define TEMPERING_SHIFT_L(y) (y >> 18) + +#define RAND_MAX 0x7fffffff + +static unsigned long mt[N]; /* the array for the state vector */ +static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializing the array with a NONZERO seed */ +void +sgenrand(unsigned long seed) +{ + /* setting initial seeds to mt[N] using */ + /* the generator Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming */ + /* Vol. 2 (2nd Ed.), pp102] */ + mt[0]= seed & 0xffffffff; + for (mti=1; mti= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if sgenrand() has not been called, */ + sgenrand(4357); /* a default initial seed is used */ + + for (kk=0;kk> 1) ^ mag01[y & 0x1]; + } + for (;kk> 1) ^ mag01[y & 0x1]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + + mti = 0; + } + + y = mt[mti++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y ^= TEMPERING_SHIFT_L(y); + + // Strip off uppermost bit because we want a long, + // not an unsigned long + return y & RAND_MAX; +} + +// Assumes 0 <= max <= RAND_MAX +// Returns in the half-open interval [0, max] +long random_tickets(long max) { + unsigned long + // max <= RAND_MAX < ULONG_MAX, so this is okay. + num_bins = (unsigned long) max + 1, + num_rand = (unsigned long) RAND_MAX + 1, + bin_size = num_rand / num_bins, + defect = num_rand % num_bins; + + long x; + do { + x = genrand(); + } + // This is carefully written not to overflow + while (num_rand - defect <= (unsigned long)x); + + // Truncated division is intentional + return x/bin_size; +} \ No newline at end of file diff --git a/rand.h b/rand.h new file mode 100644 index 0000000000..b3e9fb82aa --- /dev/null +++ b/rand.h @@ -0,0 +1,3 @@ +void sgenrand(unsigned long); +long genrand(void); +long random_tickets(long); \ No newline at end of file diff --git a/syscall.h b/syscall.h index bc5f35651c..16a1a01780 100644 --- a/syscall.h +++ b/syscall.h @@ -19,4 +19,4 @@ #define SYS_unlink 18 #define SYS_link 19 #define SYS_mkdir 20 -#define SYS_close 21 +#define SYS_close 21 \ No newline at end of file