#include <inc/assert.h>

#include <kern/env.h>
#include <kern/pmap.h>
#include <kern/monitor.h>


// Choose a user environment to run and run it.
void
sched_yield(void)
{
	// Implement simple round-robin scheduling.
	// Search through 'envs' for a runnable environment,
	// in circular fashion starting after the previously running env,
	// and switch to the first such environment found.
	// It's OK to choose the previously running env if no other env
	// is runnable.
	// But never choose envs[0], the idle environment,
	// unless NOTHING else is runnable.

	// LAB 4: Your code here.

	struct Env *start;
	struct Env *ec;
	
	if (curenv) {
		start = curenv;
	} else {
	    start = &envs[0];
	}
	ec = start+1;
	
	while(ec != start) {
		if ((ec->env_status == ENV_RUNNABLE)&&(ec!=&envs[0])){
        	env_run(ec);
        }
		ec++;
		if (ec == &envs[NENV]) 
			ec = &envs[0];
	}

	if (start->env_status == ENV_RUNNABLE)
		env_run(start);

	// Run the special idle environment when nothing else is runnable.
	if (envs[0].env_status == ENV_RUNNABLE) {
		cprintf("running idle process\n");
		env_run(&envs[0]);
	} else {
		cprintf("Destroyed all environments - nothing more to do!\n");
		while (1)
			monitor(NULL);
	}
}
