1*10dd2532SchristosInstructions for porting top to other architectures. 2*10dd2532Schristos 3*10dd2532SchristosThis is still a preliminary document. Suggestions for improvement are 4*10dd2532Schristosmost welcome. 5*10dd2532Schristos 6*10dd2532SchristosBefore you embark on a port, please send me a mail message telling me 7*10dd2532Schristoswhat platform you are porting top to. There are three reasons for 8*10dd2532Schristosthis: (1) I may already have a port, (2) module naming needs to be 9*10dd2532Schristoscentralized, (3) I want to loosely track the various porting efforts. 10*10dd2532SchristosYou do not need to wait for an "okay", but I do want to know that you 11*10dd2532Schristosare working on it. And of course, once it is finished, please send me 12*10dd2532Schristosthe module files so that I can add them to the main distribution! 13*10dd2532Schristos 14*10dd2532Schristos---------- 15*10dd2532Schristos 16*10dd2532SchristosThere is one set of functions which extract all the information that 17*10dd2532Schristostop needs for display. These functions are collected in to one file. 18*10dd2532SchristosTo make top work on a different architecture simply requires a 19*10dd2532Schristosdifferent implementation of these functions. The functions for a 20*10dd2532Schristosgiven architecture "foo" are stored in a file called "m_foo.c". The 21*10dd2532SchristosConfigure script looks for these files and lets the configurer choose 22*10dd2532Schristosone of them. This file is called a "module". The idea is that making 23*10dd2532Schristostop work on a different machine only requires one additional file and 24*10dd2532Schristosdoes not require changes to any existing files. 25*10dd2532Schristos 26*10dd2532SchristosA module template is included in the distribution, called "m-template". 27*10dd2532SchristosTo write your own module, it is a good idea to start with this template. 28*10dd2532SchristosIf you architecture is similar to one for which a module already 29*10dd2532Schristosexists, then you can start with that module instead. If you do so, 30*10dd2532Schristosremember to change the "AUTHOR" section at the top! 31*10dd2532Schristos 32*10dd2532SchristosThe first comment in a module contains information which is extracted 33*10dd2532Schristosand used by Configure. This information is marked with words in all 34*10dd2532Schristoscapitals (such as "SYNOPSIS:" and "LIBS:"). Go look at m-template: it 35*10dd2532Schristosis fairly self-explanatory. The text after "LIBS:" (on the same line) 36*10dd2532Schristosis extracted and included in the LIBS definition of the Makefile so 37*10dd2532Schristosthat extra libraries which may be necessary on some machines (such as 38*10dd2532Schristos"-lkvm") can be specified in the module. The text after "CFLAGS:" 39*10dd2532Schristos(on the same line) is extracted and included as flags in the "CFLAGS" 40*10dd2532Schristosdefinition of the Makefile (thus in every compilation step). This is 41*10dd2532Schristosused for rare circumstances only: please don't abuse this hook. 42*10dd2532Schristos 43*10dd2532SchristosSome operating systems have idiosyncrasies which will affect the form 44*10dd2532Schristosand/or content of the information top displays. You may wish to 45*10dd2532Schristosdocument such anomalies in the top man page. This can be done by adding 46*10dd2532Schristosa file called m_{modulename}.man (where {modulename} is replaced with 47*10dd2532Schristosthe name of the module). Configure will automatically add this file to 48*10dd2532Schristosthe end of the man page. See m_sunos4.man for an example. 49*10dd2532Schristos 50*10dd2532SchristosA module is concerned with two structures: 51*10dd2532Schristos 52*10dd2532SchristosThe statics struct is filled in by machine_init. Each item is a 53*10dd2532Schristospointer to a list of character pointers. The list is terminated 54*10dd2532Schristoswith a null pointer. 55*10dd2532Schristos 56*10dd2532Schristosstruct statics 57*10dd2532Schristos{ 58*10dd2532Schristos char **procstate_names; /* process state names */ 59*10dd2532Schristos char **cpustate_names; /* cpu state names */ 60*10dd2532Schristos char **memory_names; /* memory information names */ 61*10dd2532Schristos}; 62*10dd2532Schristos 63*10dd2532SchristosThe system_info struct is filled in by get_system_info and 64*10dd2532Schristosget_process_info. 65*10dd2532Schristos 66*10dd2532Schristosstruct system_info 67*10dd2532Schristos{ 68*10dd2532Schristos int last_pid; /* last pid assigned (0 means non-sequential assignment) */ 69*10dd2532Schristos double load_avg[NUM_AVERAGES]; /* see below */ 70*10dd2532Schristos int p_total; /* total number of processes */ 71*10dd2532Schristos int p_active; /* number of procs considered "active" */ 72*10dd2532Schristos int *procstates; /* array of process state counters */ 73*10dd2532Schristos int *cpustates; /* array of cpustate counters */ 74*10dd2532Schristos int *memory; /* memory information */ 75*10dd2532Schristos}; 76*10dd2532Schristos 77*10dd2532SchristosThe last three pointers each point to an array of integers. The 78*10dd2532Schristoslength of the array is determined by the length of the corresponding 79*10dd2532Schristos_names array in the statics structure. Furthermore, if an entry in a 80*10dd2532Schristos_names array is the empty string ("") then the corresponding value in 81*10dd2532Schristosthe value array will be skipped over. The display routine displays, 82*10dd2532Schristosfor example, the string procstate_names[0] then the number 83*10dd2532Schristosprocstates[0], then procstate_names[1], procstates[1], etc. until 84*10dd2532Schristosprocstate_names[N] == NULL. This allows for a tremendous amount of 85*10dd2532Schristosflexibility in labeling the displayed values. 86*10dd2532Schristos 87*10dd2532Schristos"procstates" and "memory" are displayed as straight integer values. 88*10dd2532SchristosValues in "cpustates" are displayed as a percentage * 10. For 89*10dd2532Schristosexample, the (integer) value 105 is displayed as 10.5%. 90*10dd2532Schristos 91*10dd2532SchristosThese routines must be defined by the machine dependent module. 92*10dd2532Schristos 93*10dd2532Schristosint machine_init(struct statics *) 94*10dd2532Schristos 95*10dd2532Schristos returns 0 on success and -1 on failure, 96*10dd2532Schristos prints error messages 97*10dd2532Schristos 98*10dd2532Schristoschar *format_header(char *) 99*10dd2532Schristos 100*10dd2532Schristos Returns a string which should be used as the header for the 101*10dd2532Schristos process display area. The argument is a string used to label 102*10dd2532Schristos the username column (either "USERNAME" or "UID") and is always 103*10dd2532Schristos 8 characters in length. 104*10dd2532Schristos 105*10dd2532Schristosvoid get_system_info(struct system_info *) 106*10dd2532Schristos 107*10dd2532Schristoscaddr_t get_process_info(struct system_info *, int, int, int (*func)()) 108*10dd2532Schristos 109*10dd2532Schristos returns a handle to use with format_next_process 110*10dd2532Schristos 111*10dd2532Schristoschar *format_next_process(caddr_t, char *(*func)()) 112*10dd2532Schristos 113*10dd2532Schristos returns string which describes next process 114*10dd2532Schristos 115*10dd2532Schristosint proc_compare(caddr_t, caddr_t) 116*10dd2532Schristos 117*10dd2532Schristos qsort comparison function 118*10dd2532Schristos 119*10dd2532Schristosuid_t proc_owner(pid_t) 120*10dd2532Schristos 121*10dd2532Schristos Returns the uid owner of the process specified by the pid argument. 122*10dd2532Schristos This function is VERY IMPORTANT. If it fails to do its job, then 123*10dd2532Schristos top may pose a security risk. 124*10dd2532Schristos 125*10dd2532Schristos 126*10dd2532Schristosget_process_info is called immediately after get_system_info. In 127*10dd2532Schristosfact, the two functions could be rolled in to one. The reason they 128*10dd2532Schristosare not is mostly historical. 129*10dd2532Schristos 130*10dd2532SchristosTop relies on the existence of a function called "setpriority" to 131*10dd2532Schristoschange a process's priority. This exists as a kernel call on most 4.3 132*10dd2532SchristosBSD derived Unixes. If neither your operating system nor your C 133*10dd2532Schristoslibrary supplies such a function, then you will need to add one to the 134*10dd2532Schristosmodule. It is defined as follows: 135*10dd2532Schristos 136*10dd2532Schristos int setpriority (int dummy, int who, int niceval) 137*10dd2532Schristos 138*10dd2532Schristos For the purposes of top, the first argument is meaningless. 139*10dd2532Schristos The second is the pid and the third is the new nice value. 140*10dd2532Schristos This function should behave just like a kernel call, setting 141*10dd2532Schristos errno and returning -1 in case of an error. This function MUST 142*10dd2532Schristos check to make sure that a non-root user does not specify a nice 143*10dd2532Schristos value less than the process's current value. If it detects such 144*10dd2532Schristos a condition, it should set errno to EACCES and return -1. 145*10dd2532Schristos Other possible ERRNO values: ESRCH when pid "who" does not exist, 146*10dd2532Schristos EPERM when the invoker is not root and not the same as the 147*10dd2532Schristos process owner. 148*10dd2532Schristos 149*10dd2532SchristosNote that top checks process ownership and should never call setpriority 150*10dd2532Schristoswhen the invoker's uid is not root and not the same as the process's owner 151*10dd2532Schristosuid. 152*10dd2532Schristos 153*10dd2532Schristos 154*10dd2532SchristosThe file "machine.h" contains definitions which are useful to modules 155*10dd2532Schristosand to top.c (such as the structure definitions). You SHOULD NOT need 156*10dd2532Schristosto change it when porting to a new platform. 157*10dd2532Schristos 158*10dd2532SchristosPorting to a new platform should NOT require any changes to existing 159*10dd2532Schristosfiles. You should only need to add m_ files. If you feel you need a 160*10dd2532Schristoschange in one of the existing files, please contact me so that we can 161*10dd2532Schristosdiscuss the details. I want to keep such changes as general as 162*10dd2532Schristospossible. 163*10dd2532Schristos 164*10dd2532Schristos-------- 165*10dd2532Schristos 166*10dd2532SchristosChanges were made to the module interface between 3.5 and 3.6. Here are 167*10dd2532Schristosthe changes that need to be made to port a 3.5 module to 3.6: 168*10dd2532Schristos 169*10dd2532SchristosThe array that stores memory statistics and is passed back in the system 170*10dd2532Schristosinformation structure as "memory" must now be an array of (signed) longs. 171*10dd2532SchristosThis was done to more easily accomodate systems that have gigabytes of 172*10dd2532Schristosmemory. Since the numbers are supposed to be kilobytes, a long can still 173*10dd2532Schristosrepresent up to 2 terabytes. Look for "int memory_stats[X]" (where "X" 174*10dd2532Schristosis some arbitrary number) and change it to "long memory_stats[X]". If 175*10dd2532Schristosthe module support reporting swap information on a separate line, then 176*10dd2532Schristosits "swap_stats" array also needs to be an array of longs. 177*10dd2532Schristos 178*10dd2532SchristosThe argument to proc_owner should be an int, as in "int pid". When it is 179*10dd2532Schristosused in proc_owner it should be cast as necessary. Many operating systems 180*10dd2532Schristoswill require it to be cast to a pid_t before being compared to the appropriate 181*10dd2532Schristoselement in the proc structure. 182*10dd2532Schristos 183*10dd2532SchristosIn the function format_next_process, the last argument in the main call 184*10dd2532Schristosto sprintf is the string that contains the command for the process. 185*10dd2532SchristosMake sure that this last argument is enclosed in a call to "printable". 186*10dd2532SchristosFor example: "printable(MPP(pp, p_comm))". 187*10dd2532Schristos 188*10dd2532SchristosThe third argument to "get_process_info" needs to be changed to an integer, 189*10dd2532Schristostypically "int compare_index". The call to qsort in get_process_info may 190*10dd2532Schristosbe guarded by "if (compare != NULL)". If it is, remove the if statement. 191*10dd2532Schristos 192*10dd2532SchristosThe other changes to get_process_info depends on whether or not the module 193*10dd2532Schristossupports multiple sort orders. 194*10dd2532Schristos 195*10dd2532SchristosTo support multiple keys: 196*10dd2532Schristos 197*10dd2532SchristosCreate an array int (*proc_compares[])() and assign to it the list of 198*10dd2532Schristoscomparison functions, NULL terminated. For example: 199*10dd2532Schristos 200*10dd2532Schristosint (*proc_compares[])() = { 201*10dd2532Schristos compare_cpu, 202*10dd2532Schristos compare_size, 203*10dd2532Schristos compare_res, 204*10dd2532Schristos compare_time, 205*10dd2532Schristos NULL }; 206*10dd2532Schristos 207*10dd2532SchristosIn get_process_info there is a call to qsort which uses one of the 208*10dd2532Schristosfunctions in proc_compares. It should be changed so that its fourth 209*10dd2532Schristosargument is "proc_compares[compare_index]". 210*10dd2532Schristos 211*10dd2532SchristosIf the module contains the function "proc_compare", it should be removed. 212*10dd2532Schristos 213*10dd2532SchristosThere should also be a NULL-terminated array of strings which list the names 214*10dd2532Schristosfor the sort keys, for example: 215*10dd2532Schristos 216*10dd2532Schristoschar *ordernames[] = 217*10dd2532Schristos{"cpu", "size", "res", "time", NULL}; 218*10dd2532Schristos 219*10dd2532SchristosTo indicate that this module supports multiple sort keys, add the following 220*10dd2532Schristosline in machine_init: 221*10dd2532Schristos 222*10dd2532Schristos statics->order_names = ordernames; 223*10dd2532Schristos 224*10dd2532SchristosIf there is no support for multiple keys: 225*10dd2532Schristos 226*10dd2532SchristosLeave statics->order_names alone and call the comparison function of 227*10dd2532Schristosyour choice in get_process_info, ignoring the third argument. 228*10dd2532Schristos 229*10dd2532Schristos 230