home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / MAK358AS.ZIP / LOAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-22  |  6.4 KB  |  295 lines

  1. /* Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  2. This file is part of GNU Make.
  3.  
  4. GNU Make is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8.  
  9. GNU Make is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with GNU Make; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * MS-DOS port (c) 1990 by Thorsten Ohl <ohl@gnu.ai.mit.edu>
  20.  *
  21.  * To this port, the same copying conditions apply as to the
  22.  * original release.
  23.  *
  24.  * IMPORTANT:
  25.  * This file is not identical to the original GNU release!
  26.  * You should have received this code as patch to the official
  27.  * GNU release.
  28.  *
  29.  * MORE IMPORTANT:
  30.  * This port comes with ABSOLUTELY NO WARRANTY.
  31.  *
  32.  * $Header: e:/gnu/make/RCS/load.c'v 3.58.0.1 90/07/17 00:59:28 tho Exp $
  33.  */
  34.  
  35. #include "make.h"
  36. #include "commands.h"
  37. #include "job.h"
  38.  
  39. #ifdef UMAX
  40.  
  41. #define LDAV_BASED
  42.  
  43. /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
  44.    have a /dev/kmem.  Information about the workings of the running kernel
  45.    can be gathered with inq_stats system calls.  */
  46. #include <stdio.h>
  47. #include <signal.h>
  48.  
  49. #include <sys/time.h>
  50. #include <sys/types.h>
  51. #include <sys/wait.h>
  52. #include <sys/sysdefs.h>
  53. #include <sys/syscall.h>
  54.  
  55. #ifdef    UMAX_43
  56. #include <machine/cpu.h>
  57. #include <inq_stats/statistics.h>
  58. #include <inq_stats/sysstats.h>
  59. #include <inq_stats/cpustats.h>
  60. #include <inq_stats/procstats.h>
  61. #else    /* Not UMAX_43.  */
  62. #include <sys/statistics.h>
  63. #include <sys/sysstats.h>
  64. #include <sys/cpudefs.h>
  65. #include <sys/cpustats.h>
  66. #include <sys/procstats.h>
  67. #endif
  68.  
  69. static double
  70. load_average ()
  71. {
  72.   static unsigned int cpus = 0, samples;
  73.   struct proc_summary proc_sum_data;
  74.   struct stat_descr proc_info;
  75.   double load;
  76.   register unsigned int i, j;
  77.  
  78.   if (cpus == 0)
  79.     {
  80.       register unsigned int c, i;
  81.       struct cpu_config conf;
  82.       struct stat_descr desc;
  83.  
  84.       desc.sd_next = 0;
  85.       desc.sd_subsys = SUBSYS_CPU;
  86.       desc.sd_type = CPUTYPE_CONFIG;
  87.       desc.sd_addr = (char *) &conf;
  88.       desc.sd_size = sizeof conf;
  89.  
  90.       if (inq_stats (1, &desc))
  91.     return 0.0;
  92.  
  93.       c = 0;
  94.       for (i = 0; i < conf.config_maxclass; ++i)
  95.     {
  96.       struct class_stats stats;
  97.       bzero ((char *) &stats, sizeof stats);
  98.  
  99.       desc.sd_type = CPUTYPE_CLASS;
  100.       desc.sd_objid = i;
  101.       desc.sd_addr = (char *) &stats;
  102.       desc.sd_size = sizeof stats;
  103.  
  104.       if (inq_stats (1, &desc))
  105.         return 0.0;
  106.  
  107.       c += stats.class_numcpus;
  108.     }
  109.       cpus = c;
  110.       samples = cpus < 2 ? 3 : (2 * cpus / 3);
  111.     }
  112.   
  113.   proc_info.sd_next = 0;
  114.   proc_info.sd_subsys = SUBSYS_PROC;
  115.   proc_info.sd_type = PROCTYPE_SUMMARY;
  116.   proc_info.sd_addr = (char *) &proc_sum_data;
  117.   proc_info.sd_size = sizeof (struct proc_summary);
  118.   proc_info.sd_sizeused = 0;
  119.   
  120.   if (inq_stats (1, &proc_info) != 0)
  121.     return 0.0;
  122.   
  123.   load = proc_sum_data.ps_nrunnable;
  124.   j = 0;
  125.   for (i = samples - 1; i > 0; --i)
  126.     {
  127.       load += proc_sum_data.ps_nrun[j];
  128.       if (j++ == PS_NRUNSIZE)
  129.     j = 0;
  130.     }
  131.   
  132.   return (load / samples / cpus);
  133. }
  134.  
  135. #else    /* Not UMAX.  */
  136.  
  137. #ifndef NO_LDAV
  138.  
  139. #define LDAV_BASED
  140.  
  141. #ifndef    KERNEL_FILE_NAME
  142. #define KERNEL_FILE_NAME "/vmunix"
  143. #endif
  144. #ifndef    LDAV_SYMBOL
  145. #define LDAV_SYMBOL "_avenrun"
  146. #endif
  147. #ifndef LDAV_TYPE
  148. #define LDAV_TYPE long int
  149. #endif
  150. #ifndef LDAV_CVT
  151. #define LDAV_CVT ((double) load)
  152. #endif
  153.  
  154. #ifndef MSDOS
  155. #include <nlist.h>
  156. #include <nlist.h>
  157. #ifdef    NLIST_NAME_UNION
  158. #define    nl_name    n_un.n_name
  159. #else
  160. #define    nl_name    n_name
  161. #endif
  162. #endif /* not MSDOS */
  163.  
  164. #ifdef    USG
  165. #include <fcntl.h>
  166. #else
  167. #include <sys/file.h>
  168. #endif
  169.  
  170. /* Return the current load average as a double.  */
  171.  
  172. static double
  173. load_average ()
  174. {
  175.   extern int nlist ();
  176.   LDAV_TYPE load;
  177.   static int complained = 0;
  178.   static int kmem = -1;
  179.   static unsigned long int offset = 0;
  180.  
  181.   if (kmem < 0)
  182.     {
  183.       kmem = open ("/dev/kmem", O_RDONLY);
  184.       if (kmem < 0)
  185.     {
  186.       if (!complained)
  187.         perror_with_name ("open: ", "/dev/kmem");
  188.       goto lose;
  189.     }
  190.     }
  191.  
  192.   if (offset == 0)
  193.     {
  194.       struct nlist nl[2];
  195.  
  196. #ifdef    NLIST_NAME_ARRAY
  197.       strcpy (nl[0].nl_name, LDAV_SYMBOL);
  198.       strcpy (nl[1].nl_name, "");
  199. #else    /* Not NLIST_NAME_ARRAY.  */
  200.       nl[0].nl_name = LDAV_SYMBOL;
  201.       nl[1].nl_name = 0;
  202. #endif    /* NLIST_NAME_ARRAY.  */
  203.  
  204.       if (nlist (KERNEL_FILE_NAME, nl) < 0 || nl[0].n_type == 0)
  205.     {
  206.       if (!complained)
  207.         perror_with_name ("nlist: ", KERNEL_FILE_NAME);
  208.       goto lose;
  209.     }
  210.       offset = nl[0].n_value;
  211.     }
  212.  
  213.   if (lseek (kmem, offset, 0) == -1L)
  214.     {
  215.       if (!complained)
  216.     perror_with_name ("lseek: ", "/dev/kmem");
  217.       goto lose;
  218.     }
  219.   if (read (kmem, &load, sizeof load) < 0)
  220.     {
  221.       if (!complained)
  222.     perror_with_name ("read: ", "/dev/kmem");
  223.       goto lose;
  224.     }
  225.  
  226.   if (complained)
  227.     {
  228.       error ("Load average limits will be enforced again.");
  229.       complained = 0;
  230.     }
  231.   return LDAV_CVT;
  232.  
  233.  lose:;
  234.   if (!complained)
  235.     {
  236.       error ("Load average limits will not be enforced.");
  237.       complained = 1;
  238.     }
  239.   return 0.0;
  240. }
  241.  
  242. #endif    /* Not NO_LDAV.  */
  243.  
  244. #endif    /* UMAX.  */
  245.  
  246.  
  247. #ifdef LDAV_BASED
  248.  
  249. extern unsigned int job_slots_used;
  250.  
  251. extern int sleep ();
  252.  
  253. /* Don't return until a job should be started.  */
  254.  
  255. void
  256. wait_to_start_job ()
  257. {
  258.   register unsigned int loops = 0;
  259.  
  260.   if (max_load_average < 0.0)
  261.     return;
  262.  
  263.   while (job_slots_used > 0)
  264.     {
  265.       double load = load_average ();
  266.  
  267.       if (load < max_load_average)
  268.     return;
  269.  
  270.       ++loops;
  271.       if (loops == 5 || load > max_load_average * 2)
  272.     {
  273.       /* If the load is still too high after five loops or it is very
  274.          high, just wait for a child to die before checking again.  */
  275.       loops = 0;
  276.       wait_for_children (1, 0);
  277.     }
  278.       else
  279.     /* Don't check the load again immediately, because that will
  280.        just worsen the load.  Check it progressively more slowly.  */
  281.     sleep (loops);
  282.     }
  283. }
  284.  
  285. #else    /* Not LDAV_BASED.  */
  286.  
  287. /* How else to do it?  */
  288.  
  289. void
  290. wait_to_start_job ()
  291. {
  292.   return;
  293. }
  294. #endif    /* LDAV_BASED.  */
  295.