  STATIC ptr_t GC_linux_main_stack_base(void)
  {
    /* We read the stack base value from /proc/self/stat.  We do this   */
    /* using direct I/O system calls in order to avoid calling malloc   */
    /* in case REDIRECT_MALLOC is defined.                              */
#   ifndef STAT_READ
      /* Also defined in pthread_support.c. */
#     define STAT_BUF_SIZE 4096
#     define STAT_READ read
#   endif
          /* Should probably call the real read, if read is wrapped.    */
    char stat_buf[STAT_BUF_SIZE];
    int f;
    word result;
    int i, buf_offset = 0, len;

    /* First try the easy way.  This should work for glibc 2.2  */
    /* This fails in a prelinked ("prelink" command) executable */
    /* since the correct value of __libc_stack_end never        */
    /* becomes visible to us.  The second test works around     */
    /* this.                                                    */
#   ifdef USE_LIBC_PRIVATES
      if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
#       if defined(IA64)
          /* Some versions of glibc set the address 16 bytes too        */
          /* low while the initialization code is running.              */
          if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
            return __libc_stack_end + 0x10;
          } /* Otherwise it's not safe to add 16 bytes and we fall      */
            /* back to using /proc.                                     */
#       elif defined(SPARC)
          /* Older versions of glibc for 64-bit SPARC do not set this   */
          /* variable correctly, it gets set to either zero or one.     */
          if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
            return __libc_stack_end;
#       else
          return __libc_stack_end;
#       endif
      }
#   endif
    f = open("/proc/self/stat", O_RDONLY);
    if (f < 0)
      ABORT("Couldn't read /proc/self/stat");
    len = STAT_READ(f, stat_buf, STAT_BUF_SIZE);
    close(f);

    /* Skip the required number of fields.  This number is hopefully    */
    /* constant across all Linux implementations.                       */
    for (i = 0; i < STAT_SKIP; ++i) {
      while (buf_offset < len && isspace(stat_buf[buf_offset++])) {
        /* empty */
      }
      while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {
        /* empty */
      }
    }
    /* Skip spaces.     */
    while (buf_offset < len && isspace(stat_buf[buf_offset])) {
      buf_offset++;
    }
    /* Find the end of the number and cut the buffer there.     */
    for (i = 0; buf_offset + i < len; i++) {
      if (!isdigit(stat_buf[buf_offset + i])) break;
    }
    if (buf_offset + i >= len) ABORT("Could not parse /proc/self/stat");
    stat_buf[buf_offset + i] = '\0';

    result = (word)STRTOULL(&stat_buf[buf_offset], NULL, 10);
    if (result < 0x100000 || (result & (sizeof(word) - 1)) != 0)
      ABORT("Absurd stack bottom value");
    return (ptr_t)result;
  }
  STATIC ptr_t GC_linux_main_stack_base(void)
  {
     
     
     
#   ifndef STAT_READ
       
#     define STAT_BUF_SIZE 4096
#     define STAT_READ read
#   endif
           
    char stat_buf[STAT_BUF_SIZE];
    int f;
    word result;
    int i, buf_offset = 0, len;

     
     
     
     
     
#   ifdef USE_LIBC_PRIVATES
      if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
#       if defined(IA64)
           
           
          if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
            return __libc_stack_end + 0x10;
          }  
             
#       elif defined(SPARC)
           
           
          if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
            return __libc_stack_end;
#       else
          return __libc_stack_end;
#       endif
      }
#   endif
    f = open("/proc/self/stat", O_RDONLY);
    if (f < 0)
      ABORT("Couldn't read /proc/self/stat");
    len = STAT_READ(f, stat_buf, STAT_BUF_SIZE);
    close(f);

     
     
    for (i = 0; i < STAT_SKIP; ++i) {
      while (buf_offset < len && isspace(stat_buf[buf_offset++])) {
         
      }
      while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {
         
      }
    }
     
    while (buf_offset < len && isspace(stat_buf[buf_offset])) {
      buf_offset++;
    }
     
    for (i = 0; buf_offset + i < len; i++) {
      if (!isdigit(stat_buf[buf_offset + i])) break;
    }
    if (buf_offset + i >= len) ABORT("Could not parse /proc/self/stat");
    stat_buf[buf_offset + i] = '\0';

    result = (word)STRTOULL(&stat_buf[buf_offset], NULL, 10);
    if (result < 0x100000 || (result & (sizeof(word) - 1)) != 0)
      ABORT("Absurd stack bottom value");
    return (ptr_t)result;
  }