/*
 * Test-program for some SysInfo.library features
 *
 * This file is public domain.
 *
 * Author: Petri Nordlund <petrin@megabaud.fi>
 *
 * $Id: test.c 1.5 1996/10/01 23:04:02 petrin Exp petrin $
 *
 */

#include "defs.h"
#include <proto/SysInfo.h>
#include <libraries/SysInfo.h>


/** VARIABLES **/
struct SysInfo *si = NULL;
struct Library *SysInfoBase = NULL;



int
main(int argc, char **argv)
{
	if(!(SysInfoBase = OpenLibrary(SYSINFONAME, SYSINFOVERSION)))
	{
		puts("Can't open SysInfo.library");
		exit(RETURN_FAIL);
	}


/**
 ** Initialize the SysInfo.library, this will make connection to the
 ** server-process and allocate the SysInfo-structure.
 **
 **/

	if(!(si = InitSysInfo()))
	{
		puts("Can't initialize SysInfo");
		CloseLibrary(SysInfoBase);
		exit(RETURN_FAIL);
	}


/**
 ** Print this task's pid, ppid and pgrp.
 **
 **/

	printf("pid:  %d\n",GetPid(si));

	if(si->GetPpid_implemented)
	{
		LONG p = GetPpid(si);
		if(p != -1)
			printf("ppid: %d\n",p);
		else
			printf("ppid: unknown\n");
	}

	if(si->GetPgrp_implemented)
	{
		LONG p = GetPgrp(si);
		if(p != -1)
			printf("pgrp: %d\n",p);
		else
			printf("pgrp: unknown\n");
	}


/**
 ** If si->which_implemented is 0, then GetNice() and SetNice() are not
 ** available. We'll also make sure that the search methods we need have
 ** been implemented.
 **
 **/

	if(si->which_implemented && (si->which_implemented & (WHICHF_PRIO_TASK | WHICH_PRIO_PROCESS)))
	{
		LONG nice;

		/** Display the nice-value for this task **/
		nice=GetNice(si,WHICH_PRIO_TASK,0);
		if(nice == -1)
		{
			if(si->errno)
				printf("GetNice() failed, errno: %d\n",si->errno);
			else
				printf("nice: %d\n",nice);
		}
		else
			printf("nice: %d\n",nice);

		/** Set our nice-value to +5 **/
		if(SetNice(si,WHICH_PRIO_PROCESS,GetPid(si),5))
			printf("SetNice() failed, errno: %d\n",si->errno);
	}


/**
 ** Ask for notification and output load averages every second for
 ** 10 seconds.
 **
 **/

	if(si->loadavg_type != LOADAVG_NONE)
	{
		struct SI_Notify *not;
		struct Message *msg;
		short i;

		if(si->notify_msg_implemented && (not=AddNotify(si,AN_USE_MESSAGES,10)))
		{
			printf("load averages (%d.%02d, %d.%02d, %d.%02d minutes):\n",
				si->loadavg_time1/60, si->loadavg_time1%60,
				si->loadavg_time2/60, si->loadavg_time2%60,
				si->loadavg_time3/60, si->loadavg_time3%60);

			for(i=0;i<10;i++)
			{
				/**
				 ** We'll get a message every second. There may be more than
				 ** one message in the port at once.
				 **
				 **/

				Wait(1L<<not->notify_port->mp_SigBit);

				while(msg = GetMsg(not->notify_port))
				{
					/** This will be filled by GetLoadAverage() **/
					struct SI_LoadAverage load;

					ReplyMsg(msg);

					/** Ask SysInfo.library for current load averages **/
					GetLoadAverage(si, &load);

					printf("load average:");

					if(si->loadavg_type == LOADAVG_FIXEDPNT)
					{
						/** Convert fixed point values to floating point values **/

						if(si->loadavg_time1)
							printf(" %.2f",(float) load.lavg_fixed.load1 / (float) si->fscale);
						else
							printf(" N/A");

						if(si->loadavg_time2)
							printf(" %.2f",(float) load.lavg_fixed.load2 / (float) si->fscale);
						else
							printf(" N/A");

						if(si->loadavg_time3)
							printf(" %.2f\n",(float) load.lavg_fixed.load3 / (float) si->fscale);
						else
							printf(" N/A\n");
					}
				}
			}
			RemoveNotify(si,not);
		}
		else
			printf("Can't use notification.\n");
	}
	else
		printf("Load averages are not supported.\n");


/**
 ** Output CPU usage values.
 **
 **/

	{
		struct SI_CpuUsage cu;

		GetCpuUsage(si,&cu);

		printf("cpu time:                 ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTAL_IMPLEMENTED)
			printf("%d seconds used, %d seconds idle\n",cu.total_used_cputime, cu.total_elapsed_time - cu.total_used_cputime);
		else
			printf("N/A\n");

		printf("cpu usage:                ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTAL_IMPLEMENTED)
			printf("%.2f%%\n",((float) cu.total_used_cputime * 100.0) / (float) cu.total_elapsed_time);
		else
			printf("N/A\n");

		printf("current cpu usage:        ");
		if(si->cpu_usage_implemented & CPU_USAGEF_LASTSEC_IMPLEMENTED)
			printf("%.2f%%\n",((float) cu.used_cputime_lastsec * 100.0) / (float) cu.used_cputime_lastsec_hz);
		else
			printf("N/A\n");

		printf("recent cpu usage:         ");
		if(si->cpu_usage_implemented & CPU_USAGEF_RECENT_IMPLEMENTED)
			printf("%.2f%% (%d seconds)\n",((float) cu.recent_used_cputime * 100.0) / (float) cu.recent_used_cputime_hz, cu.recent_seconds);
		else
			printf("N/A\n");

		printf("context switches:         ");
		if(si->cpu_usage_implemented & CPU_USAGEF_IVVOCSW_IMPLEMENTED)
			printf("%d involuntary, %d voluntary\n", cu.involuntary_csw, cu.voluntary_csw);
		else
			printf("N/A\n");

		printf("total context switches:   ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTALCSW_IMPLEMENTED)
			printf("%d\n", cu.total_csw);
		else
			printf("N/A\n");

		printf("current context switches: ");
		if(si->cpu_usage_implemented & CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED)
			printf("%d involuntary, %d voluntary\n", cu.involuntary_csw_lastsec, cu.voluntary_csw_lastsec);
		else
			printf("N/A\n");

		printf("current total csws:       ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED)
			printf("%d\n", cu.total_csw_lastsec);
		else
			printf("N/A\n");
	}


/**
 ** Output CPU usage values for this task.
 **
 **/

	{
		struct SI_TaskCpuUsage cu;

		if(!GetTaskCpuUsage(si,&cu,0))
		{
			printf("This task:\n");

			printf("cpu time:                   ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTAL_IMPLEMENTED)
				printf("%d.%d seconds\n",cu.total_used_cputime / cu.total_used_time_hz, cu.total_used_cputime % cu.total_used_time_hz);
			else
				printf("N/A\n");

			printf("cpu usage:                  ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTAL_IMPLEMENTED)
				printf("%.2f%%\n",(((float) cu.total_used_cputime) / ((float) cu.total_used_time_hz) * 100.0) / (float) cu.total_elapsed_time);
			else
				printf("N/A\n");

			printf("current cpu usage:          ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_LASTSEC_IMPLEMENTED)
				printf("%.2f%%\n",((float) cu.used_cputime_lastsec * 100.0) / (float) cu.used_cputime_lastsec_hz);
			else
				printf("N/A\n");

			printf("recent cpu usage:           ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_RECENT_IMPLEMENTED)
				printf("%.2f%% (%d seconds)\n",((float) cu.recent_used_cputime * 100.0) / (float) cu.recent_used_cputime_hz, cu.recent_seconds);
			else
				printf("N/A\n");

			printf("context switches:           ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_IVVOCSW_IMPLEMENTED)
				printf("%d involuntary, %d voluntary\n", cu.involuntary_csw, cu.voluntary_csw);
			else
				printf("N/A\n");

			printf("total context switches:     ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTALCSW_IMPLEMENTED)
				printf("%d\n", cu.total_csw);
			else
				printf("N/A\n");

			printf("context switches (ps):      ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED)
				printf("%d involuntary, %d voluntary\n", cu.involuntary_csw_lastsec, cu.voluntary_csw_lastsec);
			else
				printf("N/A\n");

			printf("total context switches (ps):");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED)
				printf("%d\n", cu.total_csw_lastsec);
			else
				printf("N/A\n");
		}
		else
			printf("Can't get CPU usage for this task.\n");
	}

	if(si)
		FreeSysInfo(si);

	if(SysInfoBase)
		CloseLibrary(SysInfoBase);

	return(RETURN_OK);
}
