/*
 * cpu utilization suppression. 
 *
 * written by Cyrus Patel <cyp@fb14.uni-mainz.de>
 *
*/

#include "nwlemu.h"  /* clib safe: ImportSymbol(), GetNLMHandle(),
                        [Add|Remove]PollingProcedure[RTag]() */
#include "nwcmisc.h" /* nwCliGetPollingProcedureResourceTag() */

static void __ResetPollingLoopCounters(void)
{
  static int (*_MaximumNumberOfPollingLoops) = ((int *)0x01);
  static int (*_NumberOfPollingLoops);
  if (_MaximumNumberOfPollingLoops == ((int *)0x01))
  {
    _NumberOfPollingLoops = 
       (int *)ImportSymbol(GetNLMHandle(), "NumberOfPollingLoops" );
    _MaximumNumberOfPollingLoops = 
         (int *)ImportSymbol(GetNLMHandle(), "MaximumNumberOfPollingLoops" );
  }
  if (_MaximumNumberOfPollingLoops && _NumberOfPollingLoops)
    *_NumberOfPollingLoops = *_MaximumNumberOfPollingLoops;
  return;
}

static void __doNothing(void){}
static void __ResetByAddDelPollingLoop(void)
{
  //if (GetNumberOfRegisteredProcessors() < 2)
  {
    unsigned long plrpResourceTag;
    if ((plrpResourceTag = nwCliGetPollingProcedureResourceTag()) != 0)
    {
      static unsigned long lastResetTime = 0xfffffffful;
      unsigned long currTime = GetCurrentTicks();
      register int needreset = 0;
      #define SECS2TICKS(__t) ((182*(__t))/10)
      if (lastResetTime == 0xfffffffful && currTime > SECS2TICKS(600)) /* begin 20s */
        lastResetTime = ((currTime+SECS2TICKS(20))-SECS2TICKS(600)); /* after first call */
      else if ((currTime < lastResetTime) || ((currTime-lastResetTime) > SECS2TICKS(600)))
        needreset = 1;
      else if ((currTime-lastResetTime) > SECS2TICKS(20)) 
        needreset = (GetProcessorUtilization() > 90);
      if (needreset)
      {
        lastResetTime = currTime;
        if (AddPollingProcedureRTag( __doNothing, plrpResourceTag) == 0)
          RemovePollingProcedure( __doNothing );
      }
    }
  }
  return;
}
  
/* ===================================================================== */

int nwCliUtilSuppressorControl(int dowhat /* >0=initialize,<0=deinitialize */)
{
  static int initialized = -1; /* not initialized */
  if (dowhat > 0 && initialized != 0) /* previous attempt was not failed */
  {
    if ((++initialized) == 0)
    {
      if (nwCliGetUtilizationSupressionFlag()) /* supression wanted */
      {
        ++initialized; /* assume success */
      }
    }
  }
  else if (dowhat < 0 && /* deinitialize */ initialized != 0)
  {
    if ((--initialized) == 0)
    {
      --initialized; /* assume success */
    }
  }
  if (dowhat == 0) /* do supression */
  {
    if (initialized > 0) /* supression wanted */
    {
      __ResetPollingLoopCounters(); /* self initializing */
      __ResetByAddDelPollingLoop(); /* self initializing */
    }
    return 0;
  }
  return -1;
}  
