/* WarpOS tool program which displays task statistics
   If an argument is passed, it's threated as filter value to
   produce more stable timing values. Default is 10, Max. is 20
   1.3.1998 by Sam Jordan */

#define MAXCOUNT 20
#define MAXTASKS 100            /* probably enough for a while */

#include <stdio.h>
#include <string.h>
#include <exec/libraries.h>
#include <dos/rdargs.h>
#include <utility/tagitem.h>
#include <powerpc/powerpc.h>
#include <powerpc/tasksppc.h>
#include <clib/dos_protos.h>
#include <clib/powerpc_protos.h>

extern struct Library* PowerPCBase;
int taskcount = 0;

struct sysinfo_s
{
	int     CPUload;
	int     Systemload;
} sysinfo[MAXCOUNT];

struct taskstat_s
{
	short CPUusage;
	short Busy;
	short Activity;
};

struct taskinfo_s
{
	char*   name;
	int     id;
	int     nice;
	struct taskstat_s taskstat[MAXCOUNT];
	float   FinalCPUusage;
	float   FinalBusy;
	float   FinalActivity;
} taskinfo[MAXTASKS];

struct TagItem Infotags[3] = {GETINFO_CPULOAD,0,
			      GETINFO_SYSTEMLOAD,0,
			      TAG_DONE,0};

struct taskinfo_s* FindTaskEntry(struct TaskPPC* task)
{
	int i;
	for (i=0;i<taskcount;i++)
	{
		if (taskinfo[i].id == task->tp_Id)
			return(&(taskinfo[i]));
	}
	taskinfo[taskcount].name = task->tp_Task.tc_Node.ln_Name;
	taskinfo[taskcount].id = task->tp_Id;
	taskinfo[taskcount].nice = task->tp_Nice;
	taskcount++;
	return(&(taskinfo[taskcount-1]));
}

void GetSysInfo(int index)
{
	GetInfo(Infotags);
	sysinfo[index].CPUload = Infotags[0].ti_Data;
	sysinfo[index].Systemload = Infotags[1].ti_Data;
}

void GetStats(int index)
{
	struct TaskPtr* ptr;
	struct TaskPPC* task;
	struct taskinfo_s* tinfo;

	ptr = LockTaskList();
	while ((struct TaskPtr *)(ptr->tptr_Node.ln_Succ))
	{
		task = ptr->tptr_Task;
		tinfo = FindTaskEntry(task);
		tinfo->taskstat[index].CPUusage = task->tp_CPUusage;
		tinfo->taskstat[index].Busy = task->tp_Busy;
		tinfo->taskstat[index].Activity = task->tp_Activity;
		ptr = (struct TaskPtr *)(ptr->tptr_Node.ln_Succ);
	}
	UnLockTaskList(ptr);
}

void main(void)
{
	int i,j;
	int filtercount = 10;
	float   FinalCPUload=0.0;
	float   FinalSystemload=0.0;
	char template[] = "FILTER/N";
	int* array = NULL;
	struct RDArgs* result;

	if (PowerPCBase->lib_Version < 14)
	{
		printf("Error: powerpc.library V14+ required");
		return;
	}
	if ((result = ReadArgs(template,(LONG *)&array,NULL)) == NULL)
	{
		printf("Error: dos/ReadArgs failed\n");
		return;
	}
	if (array)
		filtercount = *array;
	filtercount = (filtercount < 1) ? 1 : filtercount;
	filtercount = (filtercount > MAXCOUNT) ? MAXCOUNT : filtercount;
	FreeArgs(result);
	GetSysInfo(0);
	GetStats(0);
	for (i=1;i<filtercount;i++)
	{
		WaitTime(0,100000);     /* 100ms */
		GetSysInfo(i);
		GetStats(i);
	}
	for (i=0;i<filtercount;i++)
	{
		FinalCPUload += (float)sysinfo[i].CPUload;
		FinalSystemload += (float)sysinfo[i].Systemload;
	}
	FinalCPUload = FinalCPUload / (100*filtercount);
	FinalSystemload = FinalSystemload / (100*filtercount);
	for (i=0;i<taskcount;i++)
	{
		int a=0,b=0,c=0;

		for (j=0;j<filtercount;j++)
		{
			a += taskinfo[i].taskstat[j].CPUusage;
			b += taskinfo[i].taskstat[j].Busy;
			c += taskinfo[i].taskstat[j].Activity;
		}
		taskinfo[i].FinalCPUusage = (float)a/(100*filtercount);
		taskinfo[i].FinalBusy = (float)b/(100*filtercount);
		taskinfo[i].FinalActivity = (float)c/(100*filtercount);
	}
	printf("\nTask statistics:\n\n");
	printf("Task name                 ID     NICE  CPUusage  Busy      Activity\n");
	printf("-------------------------------------------------------------------\n");
	for (i=0;i<taskcount;i++)
	{
		printf("%-25.25s %5d   %3d   %6.2f%%   %6.2f%%   %6.2f%%\n",
			taskinfo[i].name,taskinfo[i].id,taskinfo[i].nice,
			taskinfo[i].FinalCPUusage,taskinfo[i].FinalBusy,
			taskinfo[i].FinalActivity);
	}
	printf("\n");
	printf("CPU load:    %9.2f%%\n",FinalCPUload);
	printf("System load: %9.2f%%\n",FinalSystemload);
	printf("\n");
}
