TABLE OF CONTENTS SysInfo.library/--background-- SysInfo.library/AddNotify SysInfo.library/FreeSysInfo SysInfo.library/GetCpuUsage SysInfo.library/GetLoadAverage SysInfo.library/GetNice SysInfo.library/GetPgrp SysInfo.library/GetPid SysInfo.library/GetPpid SysInfo.library/GetTaskCpuUsage SysInfo.library/InitSysInfo SysInfo.library/RemoveNotify SysInfo.library/SetNice SysInfo.library/--background-- SysInfo.library/--background-- PURPOSE SysInfo.library was developed to bring together all the different utility programs that add some new features to Amiga task handling, like CPU usage calculation. SysInfo.library was first developed for Executive, but it's possible to rewrite it to support other similar programs. It's not necessary to support all SysInfo.library functions in all implementations. FEATURES * CPU usage SysInfo.library provides several CPU usage indicators, e.g. total used CPU time, CPU time used during last second, recently used CPU time. Executive will also provide context switch counters. * load averages Load average is the number of tasks ready or running over various periods of time, usually 1, 5 and 15 minutes. A load average 1.0 means that there has been exactly one task running. * PID, PPID and PGRP PID is a process identifier. This is a unique number assigned for each task in the system. PPID is a parent process identifier. It's the PID of the process that has created the current process. PGRP is a process group. Process groups can't be implemented on Amiga at the moment, because it's impossible to distinguish if a task is a child-task or a totally separate task. In Executive process groups mean processes created by a specific task. The PGRP number is the PID of the parent task. By referring to a specific process group, you refer to all tasks created by the parent task. * nice-values Nice-values similar to Amiga priorities, they are used by the scheduler when calculating priorities for different tasks. NOTES If some function can't be implemented, a valid error-value should still be returned. A `server' in this document means the program calculating all this information. SysInfo.library is a standard interface to different servers. AUTHOR Petri Nordlund HISTORY V1.00 First release V1.20 No changes, Executive server modifications required recompilation. V1.30 (Thanks to Bernhard Mollemann ) - Better names for some structures: sysinfo -> SysInfo loadaverage -> SI_LoadAverage loadaverage_fixed -> SI_LoadAverageFixed SysInfo_notify -> SI_Notify cpu_usage -> SI_CpuUsage task_cpu_usage -> SI_TaskCpuUsage - SysInfo was sometimes spelled as sysinfo or Sysinfo. It's now always SysInfo. - sysinfo.fd is now SysInfo_lib.fd - Changed the compiler dependant types: int -> LONG short -> WORD long -> LONG - Removed LOADAVG_FLOAT. - Replaced the `use_messages' parameter in AddNotify() call with `flags'. - Some internal changes to support Executive V1.30 V2.00 Notification using signals now works. SysInfo.library/AddNotify SysInfo.library/AddNotify NAME AddNotify - Add a notification request SYNOPSIS notify = AddNotify(sysinfo,flags,safety_limit); D0 A0 D0 D1 struct SI_Notify *AddNotify(struct SysInfo *, WORD, LONG); FUNCTION Ask the server to notify us after it has updated its information. After the notification, new load average, CPU usage and other information may be requested and they'll be up-to-date. Notification is useful if your application updates its display frequently. You don't end up updating just before the server will calculate new information. The notification will keep your application in sync with the server. There are two ways to notify your task, by signals or messages. Signals are very fast, but they don't queue. The safety_limit variable can be used with messages, it's the maximum number of notification messages that will be sent to you before you reply to them. A good value here is about 10 - 20. This function returns a SI_Notify structure, which you must not modify. If you use messages for notification, it has a pointer to a port where the messages will arrive. Just reply to the messages you get. There may be some internal information in these messages that the server will use so don't modify them. If you have ask for signals to be used for notification, there will be a signal number in the structure. Just Wait() for that signal. Before requesting notification, make sure it's implemented. The SysInfo->notify_sig_implemented is TRUE if you can use signals and the SysInfo->notify_msg_implemented is TRUE if notification with messages is available. A notification happens once every second. INPUTS SysInfo - SysInfo structure returned by InitSysInfo() flags - See safety_limit - maximum number of messages sent to you RESULT notify - SI_Notify structure defined in or NULL if there was an error SEE ALSO RemoveNotify(), SysInfo.library/FreeSysInfo SysInfo.library/FreeSysInfo NAME FreeSysInfo - Finish using the SysInfo.library SYNOPSIS FreeSysInfo(SysInfo); A0 void FreeSysInfo(struct SysInfo *); FUNCTION Declares that you are finished using the services provided by SysInfo.library. The SysInfo structure will be freed. INPUTS SysInfo - structure returned by InitSysInfo() RESULT None SEE ALSO InitSysInfo(), SysInfo.library/GetCpuUsage SysInfo.library/GetCpuUsage NAME GetCpuUsage - Get the current CPU usage values SYNOPSIS GetCpuUsage(sysinfo, cpuusage); A0 A1 void GetCpuUsage(struct SysInfo *, struct SI_CpuUsage *); FUNCTION The SI_CpuUsage structure will be filled with current CPU usage values. The SysInfo->cpu_usage_implemented field indicates what values are implemented in the SysInfo.library. The corresponding bits are defined in : CPU_USAGEF_TOTAL_IMPLEMENTED Total CPU usage. The SI_CpuUsage->total_used_cputime is the CPU time used in seconds. The SI_CpuUsage->total_elapsed_time is the used CPU time plus idle CPU time, i.e. the elapsed time since CPU time calculations began. You can calculate the CPU usage percentage in this way: 100 * total_used_cputime / total_elapsed_time CPU_USAGEF_LASTSEC_IMPLEMENTED CPU time used by all processes during last second. The SI_CpuUsage->used_cputime_lastsec_hz is the number of clock ticks during one second. The SI_CpuUsage->used_cputime_lastsec is the number of ticks used. To calculate the percentage of CPU time used: 100 * used_cputime_lastsec / used_cputime_lastsec_hz CPU_USAGEF_RECENT_IMPLEMENTED The SI_CpuUsage->recent_used_cputime is a decaying average of recent CPU usage. In Executive this is for the last minute. The time in seconds is stored in SI_CpuUsage->recent_seconds. You can calculate recent CPU usage percentage in this way: 100 * recent_used_cputime / recent_used_cputime_hz CPU_USAGEF_IVVOCSW_IMPLEMENTED Some servers can also keep a count of the number of context switches. A context switch happens when one task is switched to another. The SI_CpuUsage->involuntary_csw field indicates the total number of involuntary context switches and the SI_CpuUsage->voluntary_csw field indicates the total number of voluntary context switches. Involuntary context switch happens when the CPU is taken away from a task that has not finished using it. This happens when a higher priority task becomes ready to run. Voluntary context switch happens when task calls Wait() and a lower priority task gets CPU time. CPU_USAGEF_TOTALCSW_IMPLEMENTED In some implementations only the total number of context switches is available. The SI_CpuUsage->total_csw is just involuntary context switches plus voluntary context switches, if specific information is available. CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED Like above, but for the last second. Do all calculations with 32-bits values. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() cpuusage - SI_CpuUsage structure defined in RESULT None SEE ALSO GetTaskCpuUsage(), SysInfo.library/GetLoadAverage SysInfo.library/GetLoadAverage NAME GetLoadAverage - Get load averages SYNOPSIS GetLoadAverage(sysinfo, loadaverage); A0 A1 void GetLoadAverage(struct SysInfo *, struct SI_LoadAverage *); FUNCTION This function fills the SI_LoadAverage structure with current load average values. There are three values which mean the average load for the last few minutes. Usually these are 1, 5 and 15 minutes, but this may vary. The number of seconds each load average means, is stored in SysInfo->loadavg_time[1-3]. Value 0 means that the load average for that time is not implemented. The SysInfo->loadavg_type field indicates the way the load averages are stored in the SI_LoadAverage structure. This can be LOADAVG_NONE, in which case load averages are not available at all. LOADAVG_FIXEDPNT means that the load averages are stored as 32-bit values that have been multiplied with SysInfo->fscale. To get the actual load average, you need to calculate in floating point numbers: (float) loadaverage->lavg_fixed.load1 / (float) SysInfo->fscale INPUTS sysinfo - SysInfo structure returned by InitSysInfo() loadaverage - SI_LoadAverage structure defined in RESULT None SEE ALSO SysInfo.library/GetNice SysInfo.library/GetNice NAME GetNice - get internal priority, nice-value SYNOPSIS nice = GetNice(sysinfo, which, who) D0 A0 D0 D1 LONG GetNice(struct SysInfo *, LONG, LONG); FUNCTION Get a nice-value for a process or group of processes. Nice-value is used when the server also contains a scheduler, like Executive. Nice-value is used when calculating scheduling priorities for tasks. The nice-value that gives most CPU time is available from SysInfo->nicemin (usually -20) and the nice-value that gives least CPU time is in SysInfo->nicemax (usually +20). Which is one of PRIO_PROCESS, PRIO_PGRP, PRIO USER or PRIO_TASK and who is interpreted relative to which (a process identifier for PRIO_PROCESS, process group identifier for PRIO_PGRP, user ID for PRIO_USER and a task address for PRIO_TASK). A zero value of who denotes the current process, process group, user or task. Prio is a value in the range SysInfo->nicemin to SysInfo->nicemax. The GetNice() call returns the highest nice-value (usually lowest numerical value) enjoyed by any of the specified processes. Bits in SysInfo->which_implemented indicate what values you can use for which. If this value is 0, then GetNice() and SetNice() routines are not available. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() which - get priority from which processes who - depends on which-field, 0 means current process, PGRP, user or task RESULT nice - highest nice-value enjoyed by any of the specified processes If an error occurs, -1 is returned. Since -1 is a legitimate value, it is necessary to look at SysInfo->errno. If errno is zero, no error has occurred. Possible errors are: WHICH_ESRCH No process was located using the which and who values specified. WHICH_EINVAL Which was not one of PRIO_PROCESS, PRIO_PGRP, PRIO_USER or PRIO_TASK, or that value is not supported. NOTES The name of this function should have been GetPriority() like in Un*x, but then it might have been confused with Exec priorities. SEE ALSO SysInfo.library/GetPgrp SysInfo.library/GetPgrp NAME GetPgrp - Get a process group identifier SYNOPSIS pgrp = GetPgrp(sysinfo); D0 A0 LONG GetPgrp(struct SysInfo *); FUNCTION The process group of the current process is returned by GetPgrp(). If this function is available, the SysInfo->GetPgrp_implemented field is TRUE. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() RESULT pgrp - process group identifier or -1 if process group is unknown SEE ALSO GetPid(), GetPpid(), SysInfo.library/GetPid SysInfo.library/GetPid NAME GetPid - Get a process identifier SYNOPSIS pid = GetPid(sysinfo); D0 A0 LONG GetPid(struct SysInfo *); FUNCTION GetPid() returns the process ID of the calling task. The ID is guaranteed to be unique and is useful for constructing temporary file names. This routine is always available. If special unique PIDs can't be given, it return the task address, so calling this is equivalent to calling FindTask(NULL). INPUTS sysinfo - SysInfo structure returned by InitSysInfo() RESULT pid - process identifier SEE ALSO GetPgrp(), GetPpid(), SysInfo.library/GetPpid SysInfo.library/GetPpid NAME GetPpid - Get a parent process identifier SYNOPSIS pid = GetPpid(sysinfo); D0 A0 LONG GetPpid(struct SysInfo *); FUNCTION GetPpid() returns the process ID of the parent of the calling task. If this function is available, the SysInfo->GetPpid_implemented field is TRUE. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() RESULT pid - parent process identifier or -1 if parent is unknown SEE ALSO GetPgrp(), GetPid(), SysInfo.library/GetTaskCpuUsage SysInfo.library/GetTaskCpuUsage NAME GetCpuUsage - Get the current CPU usage values for a task SYNOPSIS success = GetTaskCpuUsage(sysinfo, taskcpuusage, task); D0 A0 A1 A2 LONG GetTaskCpuUsage(struct SysInfo *, struct SI_TaskCpuUsage *, struct Task *); FUNCTION The cpu_usage structure will be filled with current CPU usage values for the specified task. Specify NULL for current task. This routine is rather similar to GetCpuUsage, but has some small differences. The SysInfo->task_cpu_usage_implemented field indicates what values are implemented in the SysInfo.library. The corresponding bits are defined in : TASK_CPU_USAGEF_TOTAL_IMPLEMENTED Total CPU usage. The SI_TaskCpuUsage->total_used_time_hz is the number of clock ticks during one second. The SI_TaskCpuUsage-> total_used_cputime is the total number of ticks used. You can calculate the CPU usage percentage in this way: 100 * total_used_cputime / total_used_time_hz The SI_TaskCpuUsage->total_elapsed_time is the used CPU time plus idle CPU time, i.e. the elapsed time since the task was created. You can calculate how many percent of CPU time task has used: 100 * (total_used_cputime / total_used_time_hz) / total_elapsed_time Please remember that this number doesn't mean the percentage of CPU time the task has used from all used CPU time. It's the percentage of CPU time the task has used from the total available CPU time. TASK_CPU_USAGEF_LASTSEC_IMPLEMENTED CPU time used by this task during last second. The SI_TaskCpuUsage->used_cputime_lastsec_hz is the number of clock ticks during one second. The SI_TaskCpuUsage-> used_cputime_lastsec is the number of ticks used. To calculate the percentage of CPU time used: 100 * used_cputime_lastsec / used_cputime_lastsec_hz TASK_CPU_USAGEF_RECENT_IMPLEMENTED The SI_TaskCpuUsage->recent_used_cputime is a decaying average of recent CPU usage. In Executive this is for the last minute. The time in seconds is stored in SI_TaskCpuUsage->recent_seconds. You can calculate recent CPU usage percentage in this way: 100 * recent_used_cputime / recent_used_cputime_hz TASK_CPU_USAGEF_IVVOCSW_IMPLEMENTED Some servers can also keep a count of the number of context switches. A context switch happens when one task is switched to another. The SI_TaskCpuUsage->involuntary_csw field indicates the total number of involuntary context switches for the specified task and the SI_TaskCpuUsage->voluntary_csw field indicates the total numnber of voluntary context switches. Involuntary context switch happens when the CPU is taken away from a task that has not finished using it. This happens when a higher priority task becomes ready to run. Voluntary context switch happens when task calls Wait() and a lower priority task gets CPU time. TASK_CPU_USAGEF_TOTALCSW_IMPLEMENTED In some implementations only the total number of context switches is available. The SI_TaskCpuUsage->total_csw is just involuntary context switches plus voluntary context switches, if specific information is available. TASK_CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED TASK_CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED Like above, but for the last second. Do all calculations with 32-bits values. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() taskcpuusage - SI_TaskCpuUsage structure defined in task - task address, NULL for current task RESULT success - 0 for success, 1 for error SEE ALSO GetCpuUsage(), SysInfo.library/InitSysInfo SysInfo.library/InitSysInfo NAME InitSysInfo - Initialize the SysInfo.library SYNOPSIS SysInfo InitSysInfo(void); D0 struct SysInfo *InitSysInfo(void); FUNCTION This function will initialize the SysInfo.library and possibly make a connection to the server task. It returns a SysInfo structure which you need when requesting information. The structure is read- only and it's size may grow in later versions of the library. INPUTS None RESULT SysInfo - structure defined in SEE ALSO FreeSysInfo(), SysInfo.library/RemoveNotify SysInfo.library/RemoveNotify NAME RemoveNotify - Remove a notification request SYNOPSIS RemoveNotify(sysInfo,notify); A0 A0 void RemoveNotify(struct SysInfo *, struct SI_Notify *); FUNCTION Remove the notification request added with AddNotify(). This function will internally make sure that you won't get any more notification messages and it will clean up the queued messages if any. It will also clear the signal if it was allocated. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() notify - SI_Notify structure you got from AddNotify() RESULT None SEE ALSO AddNotify(), SysInfo.library/SetNice SysInfo.library/SetNice NAME SetNice - set internal priority, nice-value SYNOPSIS success = SetNice(sysinfo, which, who, nice) D0 A0 D0 D1 D2 LONG SetNice(struct SysInfo *, LONG, LONG, LONG); FUNCTION Set a nice-value for a process or group of processes. See GetNice() for more information. INPUTS sysinfo - SysInfo structure returned by InitSysInfo() which - which processes are affected who - depends on which-field, 0 means current process, PGRP, user or task nice - change nice to this value RESULT success - 0 if there is no error, or -1 if there is, in which case the error is in SysInfo->errno: WHICH_ESRCH No process was located using the which and who values specified. WHICH_EINVAL Which was not one of PRIO_PROCESS, PRIO_PGRP, PRIO_USER or PRIO_TASK, or that value is not supported. Some implementations may returns one of these: WHICH_EPERM A process was located, but neither its effective nor real user ID matched the effective user ID of the caller. WHICH_EACCES A non super-user attempted to lower a process priority. NOTES The name of this function should have been SetPriority() like in Un*x, but then it might have been confused with Exec priorities. SEE ALSO .