/* ** $RCSfile: Timer.c,v $ ** $Filename: Timer.c $ ** $Revision: 1.1 $ ** $Date: 2001/04/28 17:30:19 $ ** ** sysmon command timer (version 1.1) ** ** (C) Copyright 1995-2001 by Etienne Vogt */ #include #include #include #include #include #define __USE_SYSBASE #include #include #include #include #include #include #include "sysmon.h" #include "sysmon_protos.h" #include "sysmon_pragmas.h" struct Library *SysmonBase; struct Device *TimerBase; static struct RDArgs *myrda; static struct WBStartup *wbmsg; static struct timerequest mytimereq; int main(void); static void cleanexit(int rc); static struct EClockVal subEClockVal(struct EClockVal e2, struct EClockVal e1); static char *uptimestr(struct EClockVal *clockval, ULONG clockrate); static char *cputimestr(struct EClockVal *clockval, ULONG clockrate); static char *cpuloadstr(struct EClockVal *cpu, struct EClockVal *time); static ULONG EClockDivide(struct EClockVal *numerator, ULONG denominator, ULONG *remainder); static __inline APTR SPrintf(STRPTR buffer, STRPTR format, ...); void __asm __saveds comExit(register __d0 int rc, register __d1 struct EClockVal *data); static UBYTE template[] = "COMMAND/F/A"; static UBYTE version[] = "$VER: Timer 1.1 (28.4.2001)"; #define OPT_COMMAND 0 #define OPTMAX 1 int main(void) { LONG opts[OPTMAX]; struct CommandLineInterface *mycli; SysmonBase = NULL; TimerBase = NULL; wbmsg = NULL; myrda = NULL; if (DOSBase->dl_lib.lib_Version < 37) { Printf("Requires AmigaOS V37 or higher.\n"); exit(30); } if (!(mycli = Cli())) cleanexit(20); /* If started from WB, exit cleanly */ else { struct EClockVal StartTime, EndTime, ElapsedTime; static struct EClockVal ElapsedCPU; ULONG EClockRate; memset((char *)opts, 0, sizeof(opts)); if ((myrda = ReadArgs(template, opts, NULL)) == NULL) { PrintFault(IoErr(),NULL); cleanexit(20); } if ((SysmonBase = OpenLibrary("sysmon.library",0)) == NULL) { PutStr("timer : Couldn't open sysmon.library\n"); cleanexit(20); } if (OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)&mytimereq, 0L)) cleanexit(100); TimerBase = mytimereq.tr_node.io_Device; EClockRate = ReadEClock(&StartTime); if (SystemTags((STRPTR)opts[OPT_COMMAND], SYS_UserShell, TRUE, NP_StackSize, mycli->cli_DefaultStack << 2, NP_ExitCode, comExit, NP_ExitData, &ElapsedCPU, TAG_DONE )) { PrintFault(IoErr(), "Error starting command"); cleanexit(10); } ReadEClock(&EndTime); ElapsedTime = subEClockVal(EndTime, StartTime); Printf("Elapsed Time: %s , CPU Time: %s , CPU Load: %s\n", uptimestr(&ElapsedTime, EClockRate), cputimestr(&ElapsedCPU, EClockRate), cpuloadstr(&ElapsedCPU, &ElapsedTime)); } cleanexit(0); } static void cleanexit(int rc) { if (SysmonBase) CloseLibrary(SysmonBase); if (TimerBase) CloseDevice((struct IORequest *)&mytimereq); if (myrda) FreeArgs(myrda); exit(rc); } static struct EClockVal subEClockVal(struct EClockVal e2, struct EClockVal e1) { BOOL carry = (e1.ev_lo > e2.ev_lo); e2.ev_lo -= e1.ev_lo; e2.ev_hi -= e1.ev_hi; if (carry) e2.ev_hi -= 1; return e2; } static char *uptimestr(struct EClockVal *clockval, ULONG clockrate) { static char buffer[16]; ULONG seconds; UWORD updays, uphours, upminutes, upseconds; seconds = EClockDivide(clockval, clockrate, NULL); updays = seconds / (24*60*60); seconds %= 24*60*60; uphours = seconds / (60*60); seconds %= 60*60; upminutes = seconds / 60; upseconds = seconds % 60; SPrintf(buffer, "%3lu-%02lu:%02lu:%02lu", updays, uphours, upminutes, upseconds); return buffer; } static char *cputimestr(struct EClockVal *clockval, ULONG clockrate) { static char buffer[18]; ULONG seconds, clockremain; UWORD cpudays, cpuhours, cpuminutes, cpuseconds, cpumillis; seconds = EClockDivide(clockval, clockrate, &clockremain); cpudays = seconds / (24*60*60); seconds %= 24*60*60; cpuhours = seconds / (60*60); seconds %= 60*60; cpuminutes = seconds / 60; cpuseconds = seconds % 60; cpumillis = clockremain / (clockrate / 1000); if (cpumillis == 1000) cpumillis--; SPrintf(buffer, "%3lu-%02lu:%02lu:%02lu.%03lu", cpudays, cpuhours, cpuminutes, cpuseconds, cpumillis); return buffer; } static ULONG EClockDivide(struct EClockVal *numerator, ULONG denominator, ULONG *remainder) { int bits; ULONG d1,d2,d3; d1 = 0x0; d2 = numerator->ev_hi; d3 = numerator->ev_lo; for (bits = 0; bits < 64; bits++) { /* now left-shift d1,d2,d3 */ d1 <<= 1; if (d2 & 0x80000000) d1 |= 0x1; d2 <<= 1; if (d3 & 0x80000000) d2 |= 0x1; d3 <<= 1; if (d1 >= denominator) { d1 -= denominator; d3 |= 0x1; } } /* fill in the remainder */ if (remainder) *remainder = d1; /* return the quotient, or the low part of it, at least */ return d3; } static char *cpuloadstr(struct EClockVal *cpu, struct EClockVal *time) { static char buffer[10]; double cpuload; cpuload = 100.0 * (cpu->ev_hi * 4294967296.0 + cpu->ev_lo) / (time->ev_hi * 4294967296.0 + time->ev_lo); sprintf(buffer, "%5.1f %%", cpuload); return buffer; } static __inline APTR SPrintf(STRPTR buffer, STRPTR format, ...) { return smVSPrintf(buffer, format, &format + 1); } void __asm __saveds comExit(register __d0 int rc, register __d1 struct EClockVal *data) { struct TaskInfo *mytinfo; mytinfo = smFindTaskInfo(NULL); *data = mytinfo->ti_CPUTime; }