freebsd-ports/lang/ruby18/files/patch-gc.c
2010-01-06 06:31:21 +00:00

176 lines
3.9 KiB
C

--- gc.c.orig 2009-12-24 00:28:08.000000000 -0800
+++ gc.c 2010-01-05 18:02:16.000000000 -0800
@@ -30,6 +30,10 @@
#include <sys/resource.h>
#endif
+#if defined(HAVE_PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
#if defined _WIN32 || defined __CYGWIN__
#include <windows.h>
#endif
@@ -75,6 +79,7 @@
static void run_final();
static VALUE nomem_error;
static void garbage_collect();
+static void set_stack_limit();
int ruby_gc_stress = 0;
@@ -485,6 +490,8 @@
# define STACK_LEVEL_MAX 655300
#endif
+VALUE *stack_bottom_addr = 0x0;
+
#ifdef C_ALLOCA
# define SET_STACK_END VALUE stack_end; alloca(0);
# define STACK_END (&stack_end)
@@ -534,9 +541,22 @@
#define GC_WATER_MARK 512
-#define CHECK_STACK(ret) do {\
+#define CHECK_STACK(ret, prev) do {\
SET_STACK_END;\
- (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
+ ssize_t avail;\
+ if (stack_bottom_addr != 0) {\
+ if (STACK_UPPER(&avail, 1, -1) > 0)\
+ avail = stack_bottom_addr - STACK_END;\
+ else\
+ avail = STACK_END - stack_bottom_addr;\
+ } else {\
+ avail = STACK_LEVEL_MAX + GC_WATER_MARK - STACK_LENGTH;\
+ }\
+ if (avail <= 0 || (prev != 0 && (prev - avail) > avail))\
+ (ret) = 1;\
+ else\
+ (ret) = 0;\
+ (prev) = avail;\
} while (0)
size_t
@@ -552,8 +572,9 @@
ruby_stack_check()
{
int ret;
+ static ssize_t prev = 0;
- CHECK_STACK(ret);
+ CHECK_STACK(ret, prev);
return ret;
}
@@ -1607,18 +1628,72 @@
}
rb_gc_stack_start = addr;
#endif
+ set_stack_limit();
+}
+
+static void set_stack_limit()
+{
+ size_t stacksize = 0;
+
#ifdef HAVE_GETRLIMIT
{
struct rlimit rlim;
- if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- unsigned int space = rlim.rlim_cur/5;
+ if (getrlimit(RLIMIT_STACK, &rlim) == 0)
+ stacksize = rlim.rlim_cur;
+ }
+#elif defined _WIN32
+ {
+ MEMORY_BASIC_INFORMATION mi;
- if (space > 1024*1024) space = 1024*1024;
- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+ if (VirtualQuery(&mi, &mi, sizeof(mi))) {
+ stacksize = (char *)mi.BaseAddress - (char *)mi.AllocationBase;
+ }
+ }
+#endif
+#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
+ {
+ pthread_attr_t attr;
+ size_t size;
+ void *addr;
+
+ pthread_attr_init(&attr);
+ if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
+ pthread_attr_getstack(&attr, &addr, &size);
+ if (stacksize == 0 || size < stacksize)
+ stacksize = size;
+ stack_bottom_addr = addr;
+ }
+ pthread_attr_destroy(&attr);
+ }
+#endif
+ if (stacksize) {
+ unsigned int space = stacksize / 5;
+
+ if (space > 1024*1024)
+ space = 1024*1024;
+ STACK_LEVEL_MAX = (stacksize - space) / sizeof(VALUE);
+#if defined(__FreeBSD__)
+#include <sys/sysctl.h>
+ if (stack_bottom_addr == 0) {
+ size_t len;
+ void *usrstack;
+ int mib[2];
+ int error;
+
+ len = sizeof(usrstack);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_USRSTACK;
+ error = sysctl(mib, 2, &usrstack, &len, NULL, 0);
+ if (error == 0) {
+ if (STACK_UPPER(&avail, 1, -1) > 0)
+ stack_bottom_addr = usrstack + (stacksize - space);
+ else
+ stack_bottom_addr = usrstack - (stacksize - space);
}
}
#endif
+ }
}
void ruby_init_stack(VALUE *addr
@@ -1639,31 +1714,7 @@
rb_gc_register_stack_start = (VALUE*)bsp;
}
#endif
-#ifdef HAVE_GETRLIMIT
- {
- struct rlimit rlim;
-
- if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
- unsigned int space = rlim.rlim_cur/5;
-
- if (space > 1024*1024) space = 1024*1024;
- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
- }
- }
-#elif defined _WIN32
- {
- MEMORY_BASIC_INFORMATION mi;
- DWORD size;
- DWORD space;
-
- if (VirtualQuery(&mi, &mi, sizeof(mi))) {
- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase;
- space = size / 5;
- if (space > 1024*1024) space = 1024*1024;
- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE);
- }
- }
-#endif
+ set_stack_limit();
}
/*