home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / gnu / make3_60.lzh / MAKE3_60 / LOAD.C < prev    next >
C/C++ Source or Header  |  1993-07-30  |  6KB  |  279 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. #include "make.h"
  19. #include "commands.h"
  20. #include "job.h"
  21.  
  22. #ifdef UMAX
  23.  
  24. #define LDAV_BASED
  25.  
  26. /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
  27.    have a /dev/kmem.  Information about the workings of the running kernel
  28.    can be gathered with inq_stats system calls.  */
  29. #include <stdio.h>
  30. #include <signal.h>
  31.  
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #include <sys/wait.h>
  35. #include <sys/syscall.h>
  36.  
  37. #ifdef    UMAX_43
  38. #include <machine/cpu.h>
  39. #include <inq_stats/statistics.h>
  40. #include <inq_stats/sysstats.h>
  41. #include <inq_stats/cpustats.h>
  42. #include <inq_stats/procstats.h>
  43. #else    /* Not UMAX_43.  */
  44. #include <sys/sysdefs.h>
  45. #include <sys/statistics.h>
  46. #include <sys/sysstats.h>
  47. #include <sys/cpudefs.h>
  48. #include <sys/cpustats.h>
  49. #include <sys/procstats.h>
  50. #endif
  51.  
  52. static double
  53. load_average ()
  54. {
  55.   static unsigned int cpus = 0, samples;
  56.   struct proc_summary proc_sum_data;
  57.   struct stat_descr proc_info;
  58.   double load;
  59.   register unsigned int i, j;
  60.  
  61.   if (cpus == 0)
  62.     {
  63.       register unsigned int c, i;
  64.       struct cpu_config conf;
  65.       struct stat_descr desc;
  66.  
  67.       desc.sd_next = 0;
  68.       desc.sd_subsys = SUBSYS_CPU;
  69.       desc.sd_type = CPUTYPE_CONFIG;
  70.       desc.sd_addr = (char *) &conf;
  71.       desc.sd_size = sizeof conf;
  72.  
  73.       if (inq_stats (1, &desc))
  74.     return 0.0;
  75.  
  76.       c = 0;
  77.       for (i = 0; i < conf.config_maxclass; ++i)
  78.     {
  79.       struct class_stats stats;
  80.       bzero ((char *) &stats, sizeof stats);
  81.  
  82.       desc.sd_type = CPUTYPE_CLASS;
  83.       desc.sd_objid = i;
  84.       desc.sd_addr = (char *) &stats;
  85.       desc.sd_size = sizeof stats;
  86.  
  87.       if (inq_stats (1, &desc))
  88.         return 0.0;
  89.  
  90.       c += stats.class_numcpus;
  91.     }
  92.       cpus = c;
  93.       samples = cpus < 2 ? 3 : (2 * cpus / 3);
  94.     }
  95.   
  96.   proc_info.sd_next = 0;
  97.   proc_info.sd_subsys = SUBSYS_PROC;
  98.   proc_info.sd_type = PROCTYPE_SUMMARY;
  99.   proc_info.sd_addr = (char *) &proc_sum_data;
  100.   proc_info.sd_size = sizeof (struct proc_summary);
  101.   proc_info.sd_sizeused = 0;
  102.   
  103.   if (inq_stats (1, &proc_info) != 0)
  104.     return 0.0;
  105.   
  106.   load = proc_sum_data.ps_nrunnable;
  107.   j = 0;
  108.   for (i = samples - 1; i > 0; --i)
  109.     {
  110.       load += proc_sum_data.ps_nrun[j];
  111.       if (j++ == PS_NRUNSIZE)
  112.     j = 0;
  113.     }
  114.   
  115.   return (load / samples / cpus);
  116. }
  117.  
  118. #else    /* Not UMAX.  */
  119.  
  120. #ifndef NO_LDAV
  121.  
  122. #define LDAV_BASED
  123.  
  124. #if    defined(hp300) && defined(BSD)
  125. #define    LDAV_CVT    (((double) load) / 2048.0)
  126. #endif
  127.  
  128. #ifndef    KERNEL_FILE_NAME
  129. #define KERNEL_FILE_NAME "/vmunix"
  130. #endif
  131. #ifndef    LDAV_SYMBOL
  132. #define LDAV_SYMBOL "_avenrun"
  133. #endif
  134. #ifndef LDAV_TYPE
  135. #define LDAV_TYPE long int
  136. #endif
  137. #ifndef LDAV_CVT
  138. #define LDAV_CVT ((double) load)
  139. #endif
  140.  
  141. #include <nlist.h>
  142. #ifdef    NLIST_NAME_UNION
  143. #define    nl_name    n_un.n_name
  144. #else
  145. #define    nl_name    n_name
  146. #endif
  147.  
  148. #ifdef    USG
  149. #include <fcntl.h>
  150. #else
  151. #include <sys/file.h>
  152. #endif
  153.  
  154. /* Return the current load average as a double.  */
  155.  
  156. static double
  157. load_average ()
  158. {
  159.   extern int nlist ();
  160.   LDAV_TYPE load;
  161.   static int complained = 0;
  162.   static int kmem = -1;
  163.   static unsigned long int offset = 0;
  164.  
  165.   if (kmem < 0)
  166.     {
  167.       kmem = open ("/dev/kmem", O_RDONLY);
  168.       if (kmem < 0)
  169.     {
  170.       if (!complained)
  171.         perror_with_name ("open: ", "/dev/kmem");
  172.       goto lose;
  173.     }
  174.     }
  175.  
  176.   if (offset == 0)
  177.     {
  178.       struct nlist nl[2];
  179.  
  180. #ifdef    NLIST_NAME_ARRAY
  181.       strcpy (nl[0].nl_name, LDAV_SYMBOL);
  182.       strcpy (nl[1].nl_name, "");
  183. #else    /* Not NLIST_NAME_ARRAY.  */
  184.       nl[0].nl_name = LDAV_SYMBOL;
  185.       nl[1].nl_name = 0;
  186. #endif    /* NLIST_NAME_ARRAY.  */
  187.  
  188.       if (nlist (KERNEL_FILE_NAME, nl) < 0 || nl[0].n_type == 0)
  189.     {
  190.       if (!complained)
  191.         perror_with_name ("nlist: ", KERNEL_FILE_NAME);
  192.       goto lose;
  193.     }
  194.       offset = nl[0].n_value;
  195.     }
  196.  
  197.   if (lseek (kmem, offset, 0) == -1L)
  198.     {
  199.       if (!complained)
  200.     perror_with_name ("lseek: ", "/dev/kmem");
  201.       goto lose;
  202.     }
  203.   if (read (kmem, &load, sizeof load) < 0)
  204.     {
  205.       if (!complained)
  206.     perror_with_name ("read: ", "/dev/kmem");
  207.       goto lose;
  208.     }
  209.  
  210.   if (complained)
  211.     {
  212.       error ("Load average limits will be enforced again.");
  213.       complained = 0;
  214.     }
  215.   return LDAV_CVT;
  216.  
  217.  lose:;
  218.   if (!complained)
  219.     {
  220.       error ("Load average limits will not be enforced.");
  221.       complained = 1;
  222.     }
  223.   return 0.0;
  224. }
  225.  
  226. #endif    /* Not NO_LDAV.  */
  227.  
  228. #endif    /* UMAX.  */
  229.  
  230.  
  231. #ifdef LDAV_BASED
  232.  
  233. extern unsigned int job_slots_used;
  234.  
  235. extern unsigned int sleep ();
  236.  
  237. /* Don't return until a job should be started.  */
  238.  
  239. void
  240. wait_to_start_job ()
  241. {
  242.   register unsigned int loops = 0;
  243.  
  244.   if (max_load_average < 0.0)
  245.     return;
  246.  
  247.   while (job_slots_used > 0)
  248.     {
  249.       double load = load_average ();
  250.  
  251.       if (load < max_load_average)
  252.     return;
  253.  
  254.       ++loops;
  255.       if (loops == 5 || load > max_load_average * 2)
  256.     {
  257.       /* If the load is still too high after five loops or it is very
  258.          high, just wait for a child to die before checking again.  */
  259.       loops = 0;
  260.       wait_for_children (1, 0);
  261.     }
  262.       else
  263.     /* Don't check the load again immediately, because that will
  264.        just worsen the load.  Check it progressively more slowly.  */
  265.     sleep (loops);
  266.     }
  267. }
  268.  
  269. #else    /* Not LDAV_BASED.  */
  270.  
  271. /* How else to do it?  */
  272.  
  273. void
  274. wait_to_start_job ()
  275. {
  276.   return;
  277. }
  278. #endif    /* LDAV_BASED.  */
  279.