If I understand the logic this is the BOINC client in a nutshell.

GLOBAL List
	task-list						// list of all tasks, unknown order
	task-queue 					// tasks in ordered list, highest priority task first
	projects-with-tasks-running 	// list of projects with tasks running
	projects-with-tasks-queued	// list of projects with tasks queued
	task-completion-interval		// the running average of time between task completions
	task-checkpoint-interval		// the running average of time between task checkpoints
	rs-scoreboard					// scoreboard of time spent per project vs. time
									// that should be spent on a project on a per unit time basis
									// shortfalls would increase the priority of the tasks in the task-queue

main ()
	begin
		initialize
		loop forever
			do what needs to be done
			detect-events;
			if events 
				if number of resources < 4 then
					use old scheduler
				else
					schedule-resources (event list)
			do whatever else needs to be done
			sleep; // isn't this where the 60 second limit should occur?
		end loop; // forever
	end // main

The new routines would look something like this:

schedule-resources (event list)
	iterate through event list

		// note first for speed
		case checkpointing:
			if task.runtime < TSI
				do nothing
			else
				halt task
				update projects-with-tasks-running
				update rs-scoreboard
				do update-task-queue
				do schedule-task-to-resource
				update task-checkpoint-interval

		case task complete:
			update projects-with-tasks-running
			update task-completion-interval
			update rs-scoreboard
			do schedule-task-to-resource

		case download complete:
			do update-task-queue // did we create deadline peril?

		case project/task resume/suspend
			do update-task-queue // did we create deadline peril?

		case RPC complete:
			if server asks to drop WU
				if task not started 
					drop task (this may logically belong in update-task-queue)
					do update-task-queue
				else
					do nothing

		case deadline-peril:
			// on a nominal system this case should never occur
			// because queues are reasonable and speed / width 
			// allows deliberative scheduling
			// this event is raised in update-task-queue
			do determine-task-to-preempt
			preempt task  // frees resource
			update projects-with-tasks-running
			do schedule-task-to-resource
			
	end iterate // event list
end schedule-resources

update-task-queue

	iterate through task-list
		update information using best available estimates and rs-scoreboard
		// establishes the baselines on each task for priority ranking later
		// I would not use rr-sim for rs-scoreboarding

	drop task-queue
	iterate through task-list
		if task is running mark task as queued
		// no need to queue already running tasks
		if task was preempted insert it into the task queue and mark as queued

	loop until all tasks queued
		iterate through task-list
			find the highest priority (deadline order essentially) task
		insert into task-queue
		mark task as queued
	end loop // all tasks queued

	test head task for deadline peril
	// test will calculate based on task-completion-interval and task-checkpoint-interval
	// estimated task run time, safety margin, etc. My current bad example of IBERCIVIS tasks
	// would not raise DP events, but would merely increase the task priority
	if deadline peril exists
		raise deadline-peril event

end update-task-queue

schedule-task-to-resource

	if deadline-peril
		assign task-queue.head-task to available resource
		update projects-with-tasks-running
	else
		// try to keep work mix "interesting"
		compare projects-with-tasks-running to projects-with-tasks-queued
			assign highest priority task where task.project not in projects-with-tasks-running to the available resource
			// this is the most likely route for tasks with long deadlines will be scheduled as 
			// their rs-scoreboard allocation of time shows a shortfall
		else 
			assign task-queue.head-task to available resource
				
end schedule-task-to-resource

determine-task-to-preempt

	iterate running tasks
		find task with longest time to completion and deadline
		mark as preempted
end determine-task-to-preempt