1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#define import_kernel
#define import_knames
#define import_spp
#include <iraf.h>
#define PCT_RESERVE 10 /* percent */
#define MIN_RESERVE 50 /* megabytes */
#define MIN_WORKSET 32 /* megabytes */
#define ENV_DEBUG "ZAWSET_DEBUG"
#define MB (1024*1024)
#define KB 1024
/* Kernel default working set values in bytes. */
unsigned int defworkset = SZ_DEFWORKSET;
unsigned int maxworkset = SZ_MAXWORKSET;
static unsigned int max_wss = 0;
/* ZAWSET -- Adjust or query the "working set", i.e., the maximum amount of
* physical memory allocated to the process.
*/
int
ZAWSET (
XINT *best_size, /* requested working set size, bytes. */
XINT *new_size,
XINT *old_size, /* actual new and old sizes, bytes. */
XINT *max_size /* max working set size, bytes */
)
{
int physmem=0, kb_page;
int debug = (getenv(ENV_DEBUG) != NULL);
char *s;
unsigned int working_set_size;
struct rlimit rlp;
/* Get the page size in kilobytes. */
kb_page = getpagesize() / KB;
#ifdef _SC_PHYS_PAGES
/* On recent POSIX systems (including Solaris, Linux, and maybe
* others) we can use sysconf to get the actual system memory size.
* The computation is done in KB to avoid integer overflow.
*/
physmem = sysconf(_SC_PHYS_PAGES) * kb_page;
if (physmem > 0) {
maxworkset = min (MAX_LONG / KB, physmem);
/* Don't try to use all of physical memory. */
if (maxworkset == physmem) {
maxworkset -= (max ((MIN_RESERVE*MB)/KB,
physmem * PCT_RESERVE / 100));
if (maxworkset <= 0)
maxworkset = (MIN_WORKSET * MB) / KB;
}
/* Now convert back to bytes. */
maxworkset *= 1024;
}
#endif
/* The hard upper limit on memory utilization defined by the unix
* kernel can be limited either by the value compiled into the IRAF
* kernel, or by the value set in the user environment variable
* MAXWORKSET, given in units of Mb.
*/
if (!max_wss) {
if ( (s = getenv ("MAXWORKSET")) ) {
max_wss = atoi(s) * 1024*1024;
if (max_wss < 1024*1024)
max_wss = maxworkset;
} else
max_wss = maxworkset;
}
if (debug)
fprintf(stderr,"zawset: physmem=%dm, maxworkset=%dm max_wss=%dm\n",
physmem / KB, maxworkset / MB, max_wss / MB);
getrlimit (RLIMIT_RSS, &rlp);
if (debug)
fprintf (stderr, "zawset: starting rlimit cur=%ldm, max=%ldm\n",
(long)(rlp.rlim_cur == RLIM_INFINITY ? 0 : rlp.rlim_cur) / MB,
(long)(rlp.rlim_max == RLIM_INFINITY ? 0 : rlp.rlim_max) / MB);
working_set_size = min (max_wss,
rlp.rlim_cur == RLIM_INFINITY ? max_wss : rlp.rlim_cur);
/* Now try to set the size requested by our caller. If bestsize was
* given as zero, merely return the status values.
*/
(*max_size) = min (max_wss,
rlp.rlim_max == RLIM_INFINITY ? max_wss : rlp.rlim_max);
if (*best_size <= 0)
*new_size = *old_size = working_set_size;
else {
rlp.rlim_cur = min (*best_size, *max_size);
if (rlp.rlim_cur > working_set_size)
setrlimit (RLIMIT_RSS, &rlp);
getrlimit (RLIMIT_RSS, &rlp);
*old_size = working_set_size;
*new_size = min(*best_size, min(max_wss,
rlp.rlim_cur == RLIM_INFINITY ? max_wss : rlp.rlim_cur));
}
if (debug)
fprintf (stderr, "zawset: adjusted rlimit cur=%ldm, max=%ldm\n",
(long)(rlp.rlim_cur == RLIM_INFINITY ? 0 : rlp.rlim_cur) / MB,
(long)(rlp.rlim_max == RLIM_INFINITY ? 0 : rlp.rlim_max) / MB);
if (debug)
fprintf (stderr, "zawset: best=%ldm old=%ldm new=%ldm max=%ldm\n",
(long)*best_size/MB, (long)*old_size/MB,
(long)*new_size/MB, (long)*max_size/MB);
return (XOK);
}
|