We've found that on Power some 32-bit binaries, when relinked via
libhugetlbfs, run out of address space. Add some heuristics to warn the
user if the memory size of the segments (plus the size of the largest
segment) exceeds 80% of addressable memory.

Signed-off-by: Nishanth Aravamudan <[EMAIL PROTECTED]>
---
 elflink.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/elflink.c b/elflink.c
index a53c649..bed8ef6 100644
--- a/elflink.c
+++ b/elflink.c
@@ -55,6 +55,9 @@
 #define ELF_ST_TYPE(x)  ELF64_ST_TYPE(x)
 #endif
 
+/* 90% of 32-bit addressable memory */
+#define MEMSZ_THRESHOLD_32     0xCCCCCCCCUL
+
 #ifdef __syscall_return
 #ifdef __i386__
 /* The normal i386 syscall macros don't work with -fPIC :( */
@@ -231,6 +234,63 @@ static void assemble_path(char *dst, const char *fmt, ...)
        }
 }
 
+#if defined(__i386__) || defined(__powerpc32__)
+static long read_vsize()
+{
+       FILE *filp;
+       unsigned long vsize;
+       int ret;
+
+       filp = fopen("/proc/self/stat", "r");
+       if (!filp) {
+               ERROR("Couldn't open /proc/self/stat: %s\n", strerror(errno));
+               return -1;
+       }
+
+       ret = fscanf(filp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u 
%*u %*u %*d %*d %*d %*d %*d %*d %*u %lu", &vsize);
+       if (ret != 1) {
+               ERROR("Couldn't find vsize in /proc/self/stat\n");
+               return -1;
+       }
+       fclose(filp);
+
+       return vsize;
+}
+
+static void check_memsz()
+{
+       int i;
+       unsigned long memsz_total = 0, memsz_max = 0;
+       if (htlb_num_segs == 0)
+               return;
+       if (__debug) {
+               /* parse /proc/self/statm */
+               memsz_total = read_vsize();
+       } else {
+               /*
+                * rough heuristic to see if we'll run out of address
+                * space
+                */
+               for (i = 0; i < htlb_num_segs; i++) {
+                       memsz_total += htlb_seg_table[i].memsz;
+                       if (htlb_seg_table[i].memsz > memsz_max)
+                               memsz_max = htlb_seg_table[i].memsz;
+               }
+       }
+       /* avoid overflow checking by using two checks */
+       if (memsz_total > MEMSZ_THRESHOLD_32 ||
+                       memsz_total + memsz_max > MEMSZ_THRESHOLD_32) {
+               WARNING("The memory requirements of this binary's "
+                               "segments may be too large for a 32-bit "
+                               "address space. This limitation can be "
+                               "removed by rebuilding the binary as "
+                               "64-bit.\n");
+       }
+}
+#else
+static inline void check_memsz() { }
+#endif
+
 /**
  * find_or_create_share_path - obtain a directory to store the shared
  * hugetlbfs files
@@ -568,6 +628,7 @@ static void parse_elf(Elf_Ehdr *ehdr)
                                                        ehdr->e_phnum);
                htlb_num_segs++;
        }
+       check_memsz();
 }
 
 /*

-- 
Nishanth Aravamudan <[EMAIL PROTECTED]>
IBM Linux Technology Center

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Libhugetlbfs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libhugetlbfs-devel

Reply via email to