'Effective software scheduling

For example in a code like below

while(1){
  task1();
  task2();
}

there should be cooperation between task1() and task2() which are executed in rr fashion. However, if task1() is implemented as follows

task1(){
  while(1);
}

Is there a way to build a scheduler which avoid monopolization of resources by task1() by only relying on software (for example switching tasks each 500 ms)?

Assume to have available only plain C/Assembly, and not rely on external scheduler/OS.



Solution 1:[1]

Is there a way to build a scheduler which avoid monopolization of resources by task1() by only relying on software (for example switching tasks each 500 ms)?

Yes it's possible; but it probably isn't possible in plain C because (at a minimum) you'd need to switch between different stacks during task switches.

However, you should know that just switching tasks every 500 ms is very "not effective". Specifically; when one task has to wait for anything (time delay, data received from network, user input, data to be fetched from disk, a mutex, ...) you want to keep the CPU busy by switching to a different task (if there are any other tasks).

To do that; you either need fully asynchronous interfaces for everything (which C does not have), or you need to control all of the code (e.g. write an OS).

Of course the majority of task switches are caused by "task has to wait for something" or "something task was waiting for occurred"; and switching tasks every 500 ms is relatively irrelevant (it only matters for rare tasks that don't do any IO), and even when it is relevant it's a bad idea (in a "10 half finished jobs vs. 5 finished jobs and 5 unstarted jobs" way).

Solution 2:[2]

one easy way is to use

  1. a hardware timer,
  2. a queue of tasks to run,
  3. a scheduler
  4. and a dispatcher.
  5. a pre-allocated stack for each task

the timer interrupt handler triggers the scheduler. The scheduler determines which task is to run next. The scheduler triggers the dispatcher. The dispatcher performs a 'context' switch between the prior running task and the next task to run, placing the prior running task back into the queue, then restores the 'context' of the next task to run, then transfers execution control to the 'next' task,

The queue is composed of control blocks. The control blocks contain a copy of all the registers and the address of the entry point for the task

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Brendan
Solution 2