uclibc-0.9.30.1-pthread_getattr_np.patch 4.48 KB
Newer Older
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 128 129 130 131 132 133 134 135 136 137
--- uClibc-0.9.30.1.orig/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h	2009-03-30 15:01:48.000000000 +0000
+++ uClibc-0.9.30.1/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h	2009-03-30 15:48:16.000000000 +0000
@@ -288,16 +288,12 @@
 				      __attr, size_t *__restrict __stacksize)
      __THROW;
 
-#if 0
-/* Not yet implemented in uClibc! */
-
 #ifdef __USE_GNU
 /* Initialize thread attribute *ATTR with attributes corresponding to the
    already running thread TH.  It shall be called on uninitialized ATTR
    and destroyed with pthread_attr_destroy when no longer needed.  */
 extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW;
 #endif
-#endif
 
 /* Functions for scheduling control.  */
 
@@ -599,6 +595,11 @@
    cancelled.  */
 extern void pthread_testcancel (void);
 
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr,
+				  void **__restrict __stackaddr,
+				  size_t *__restrict __stacksize) __THROW;
+
 
 /* Install a cleanup handler: ROUTINE will be called with arguments ARG
    when the thread is cancelled or calls pthread_exit.  ROUTINE will also
--- a/libpthread/linuxthreads.old/attr.c.orig	2007-11-22 16:55:08.000000000 +0000
+++ b/libpthread/linuxthreads.old/attr.c	2009-03-30 19:15:51.000000000 +0000
@@ -38,6 +38,14 @@
 libpthread_hidden_proto(pthread_attr_getscope)
 libpthread_hidden_proto(pthread_attr_setscope)
 
+#include <sys/resource.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+
 /* NOTE: With uClibc I don't think we need this versioning stuff.
  * Therefore, define the function pthread_attr_init() here using
  * a strong symbol. */
@@ -235,4 +243,88 @@
   *stacksize = attr->__stacksize;
   return 0;
 }
+
+
+extern int *__libc_stack_end;
+
 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
+int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr)
+{
+    static void *stackBase = 0;
+    static size_t stackSize = 0;
+    int ret = 0;
+    /* Stack size limit.  */
+    struct rlimit rl;
+
+    /* The safest way to get the top of the stack is to read
+    /proc/self/maps and locate the line into which
+    __libc_stack_end falls.  */
+    FILE *fp = fopen("/proc/self/maps", "rc");
+    if (fp == NULL)
+        ret = errno;
+    /* We need the limit of the stack in any case.  */
+    else if (getrlimit (RLIMIT_STACK, &rl) != 0)
+        ret = errno;
+    else {
+        /* We need no locking.  */
+        __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+        /* Until we found an entry (which should always be the case)
+        mark the result as a failure.  */
+        ret = ENOENT;
+
+        char *line = NULL;
+        size_t linelen = 0;
+        uintptr_t last_to = 0;
+
+        while (! feof_unlocked (fp)) {
+            if (getdelim (&line, &linelen, '\n', fp) <= 0)
+                break;
+
+            uintptr_t from;
+            uintptr_t to;
+            if (sscanf (line, "%x-%x", &from, &to) != 2)
+                continue;
+            if (from <= (uintptr_t) __libc_stack_end
+            && (uintptr_t) __libc_stack_end < to) {
+                /* Found the entry.  Now we have the info we need.  */
+                attr->__stacksize = rl.rlim_cur;
+#ifdef _STACK_GROWS_UP
+                /* Don't check to enforce a limit on the __stacksize */
+                attr->__stackaddr = (void *) from;
+#else
+                attr->__stackaddr = (void *) to;
+
+                /* The limit might be too high.  */
+                if ((size_t) attr->__stacksize > (size_t) attr->__stackaddr - last_to)
+                    attr->__stacksize = (size_t) attr->__stackaddr - last_to;
+#endif
+
+                /* We succeed and no need to look further.  */
+                ret = 0;
+                break;
+            }
+            last_to = to;
+        }
+
+        fclose (fp);
+        free (line);
+    }
+    return ret;
+}
+
+int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
+			     size_t *stacksize)
+{
+  /* XXX This function has a stupid definition.  The standard specifies
+     no error value but what is if no stack address was set?  We simply
+     return the value we have in the member.  */
+#ifndef _STACK_GROWS_UP
+  *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
+#else
+  *stackaddr = attr->__stackaddr;
+#endif
+  *stacksize = attr->__stacksize;
+  return 0;
+}
+weak_alias (__pthread_attr_getstack, pthread_attr_getstack)