Follow-up Comment #3, bug #52697 (project make): I'm pretty sure something like this was already proposed, discussed and/or even implemented somewhere, but anyway:
here is a quick and dirty hack I'm using to successfully compile gcc (together with some other required measures) on my raspberry pi which has four cores but 'only' 1 GB of RAM: an -M [minavail] option, similar to -l [load]. Specifying this option will inhibit launching new jobs until there is at least MINAVAIL megabytes of RAM is available. Works only on Linux by scanning /proc/meminfo for MemAvailable string. --- job.c | 38 +++++++++++++++++++++++++++++++++++++- main.c | 7 +++++++ makeint.h | 2 ++ 3 files changed, 46 insertions(+), 1 deletion(-) Index: make-4.2.1/job.c =================================================================== --- make-4.2.1.orig/job.c +++ make-4.2.1/job.c @@ -214,6 +214,7 @@ int getloadavg (double loadavg[], int ne static void free_child (struct child *); static void start_job_command (struct child *child); static int load_too_high (void); +static int memory_load_high (void); static int job_next_command (struct child *); static int start_waiting_job (struct child *); @@ -1557,7 +1558,7 @@ start_waiting_job (struct child *c) /* If we are running at least one job already and the load average is too high, make this one wait. */ if (!c->remote - && ((job_slots_used > 0 && load_too_high ()) + && ((job_slots_used > 0 && (load_too_high () || memory_load_high ())) #ifdef WINDOWS32 || (process_used_slots () >= MAXIMUM_WAIT_OBJECTS) #endif @@ -1882,6 +1883,41 @@ job_next_command (struct child *child) return 1; } +static int +get_mem_avail (void) +{ + FILE *fp; + char s [64]; + long m = 0; + int n; + + fp = fopen ("/proc/meminfo", "r"); + if (fp == NULL) + return 0; // out of memory already or no /proc, huh + + while (!feof (fp)) + { + if (!fgets (s, 64, fp)) + break; + + n = sscanf (s, "MemAvailable: %ld kB", &m); + if (n == 1) + break; + } + fclose (fp); + + return m / 1024; +} + +static int +memory_load_high (void) +{ + if (mem_limit && get_mem_avail () < mem_limit) + return 1; + else + return 0; +} + /* Determine if the load average on the system is too high to start a new job. The real system load average is only recomputed once a second. However, a very parallel make can easily start tens or even hundreds of jobs in a Index: make-4.2.1/main.c =================================================================== --- make-4.2.1.orig/main.c +++ make-4.2.1/main.c @@ -282,6 +282,11 @@ int max_load_average = -1; int default_load_average = -1; #endif +/* Minimum memory available (megabytes) required before starting job. + Zero means unlimited. */ +int mem_limit = 0; +static int default_mem_limit = 0; + /* List of directories given with -C switches. */ static struct stringlist *directories = 0; @@ -457,6 +462,8 @@ static const struct command_switch switc { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #endif + { 'M', positive_int, &mem_limit, 1, 1, 0, &default_mem_limit, + &default_mem_limit, "mem-limit" }, { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" }, { 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync" }, { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" }, Index: make-4.2.1/makeint.h =================================================================== --- make-4.2.1.orig/makeint.h +++ make-4.2.1/makeint.h @@ -666,6 +666,8 @@ extern double max_load_average; extern int max_load_average; #endif +extern int mem_limit; + #ifdef WINDOWS32 extern char *program; #else _______________________________________________________ Reply to this item at: <http://savannah.gnu.org/bugs/?52697> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/ _______________________________________________ Bug-make mailing list Bug-make@gnu.org https://lists.gnu.org/mailman/listinfo/bug-make