//-------------------------------------------------
//          TestSuite: Termination
//-------------------------------------------------

#include "lcd.h"
#include "util.h"
#include "os_core.h"
#include "os_scheduler.h"
#include "os_memory.h"

#include <avr/interrupt.h>

#define DELAY 100

uint16_t volatile spawns = 2;

void test(uint8_t me) {
  delayMs(DELAY);
  // The crit. sec. makes sure, that we do not start a fork-bomb.
  // The dispatcher should make sure, to clean this up (if you have os_yield implemented, this will do the trick).
  os_enterCriticalSection();
  os_exec(me,DEFAULT_PRIORITY);
  spawns++;
}

PROGRAM(1, AUTOSTART) {
  if (MAX_NUMBER_OF_PROCESSES < 5) {
    cli();
    lcd_clear();
    lcd_writeProgString(PSTR("E: Max.Num.Proc is less than 5"));
  }
  ProcessID p2pid = 0;
  for (;;) {
    lcd_line1();
    lcd_writeProgString(PSTR("Act.P.: "));
    lcd_writeDec(os_getNumberOfActiveProcs());
    lcd_writeChar('/');
    lcd_writeDec(MAX_NUMBER_OF_PROCESSES);
    lcd_line2();
    lcd_writeProgString(PSTR("Spawns: "));
    lcd_writeDec(spawns);
    if (p2pid) {
      os_kill(p2pid);
      p2pid = 0;
    } else {
      p2pid = os_exec(2,1);
    }
  }
}

// we need 3 slots
PROGRAM(2, DONTSTART) {
  spawns++;
  for (;;)
    delayMs(DELAY);
}

// we need 5 slots
PROGRAM(3, AUTOSTART) {
  test(3);
}

#if MAX_NUMBER_OF_PROCESSES > 5
PROGRAM(4, AUTOSTART) {
  test(4);
}
#endif

#if MAX_NUMBER_OF_PROCESSES > 6
PROGRAM(5, AUTOSTART) {
  test(5);
}
#endif

#if MAX_NUMBER_OF_PROCESSES > 7
PROGRAM(6, AUTOSTART) {
  test(6);
}
#endif
