> >>>Does Red Hat have some kind of userland address space hack that > >>>we're not aware of? > >> > >>Do you have any special kernel config options that you did not use before?
> > the thread stacks are 2MB apiece (bf601000-bf800000 is > > 2093056 bytes, or 2044kB)! Yet: > > > > # mysql -e 'show variables' | grep thread_stack > > thread_stack 196608 > > > > It seems like the setting does nothing for us. We top out at > > exactly 256 threads. > Ok, that's the problem. Thread stack on older glibc versions is hard-coded. > Newer versions (at least 2.3.2) will have a truly adjustable stack size if it is > compiled with FLOATING_STACKS defined, which is off by default. One possibility > is that the MySQL build team moved to linking against glibc 2.3.2, but did not > enable floating stacks in it. Maybe Lenz can comment on it. We wrote a wrapper with LD_PRELOAD. When mysqld does pthread_attr_setstacksize() we translate it into an anonymous mmap() and use pthread_attr_setstackaddr() instead. It's the equivalent of FLOATING_STACKS. ;) Our mysqld (which is running as slave) will seg fault if we set the thread_stack to 256k. Running it with thread_stack set to 2MB works flawlessly (that is until we allocate 256 threads). mysql 3.23.58 doesn't like <2MB thread stacks in our environment. Is this normal? Here's the code if you want to see for yourself. Build with: gcc -Wall -shared -o pthread_preload.so pthread_preload.c -lpthread -ldl Ignore the deprecated warnings (ergo the glibc comment below). Run LD_PRELOAD=pthread_preload.so before launching mysqld. --- pthread_preload.c --- /* Copyright (C) Netgraft Corp 2004 GPL license */ #include <stdio.h> #include <limits.h> #include <pthread.h> #include <sys/mman.h> #define __USE_GNU 1 #include <dlfcn.h> #define PAGE_SIZE 4096 /* size of crash zone at end of stack */ /* XXX: this assumes that the stacks grow towards decreasing addresses! */ extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, size_t __stacksize); int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { static void *start = NULL, *stop = NULL; static int (*parent)(pthread_attr_t *,size_t) = NULL; static FILE *dbg = NULL; if (!parent) { parent = dlsym(RTLD_NEXT, "pthread_attr_setstacksize"); if (parent == pthread_attr_setstacksize) { parent = NULL; } } if (!dbg) dbg = fopen("/tmp/buh","w"); if (dbg) { fprintf(dbg,"buh:%d,%p\n",(int)stacksize,parent); fflush(dbg); } if (stacksize <= PTHREAD_STACK_MIN) stacksize = PTHREAD_STACK_MIN; if (stacksize >= 2*1024*1024 && parent) { /* big stack, let the parent do this */ return parent(attr, stacksize); } if (((int)start=mmap(NULL, stacksize+PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == -1) { if (parent) { return parent(attr, stacksize); } else { return -1; } } /* unmap the lowest addresses of the stack for overflow */ mprotect(start, PAGE_SIZE, PROT_NONE); start += PAGE_SIZE; /* stop is the highest address in the stack, * actually just beyond it */ stop = start + stacksize; if (parent) { int ret; if (dbg) { fprintf(dbg,"stacksize...\n"); fflush(dbg); } ret = parent(attr,stacksize); if (ret) return ret; if (dbg) { fprintf(dbg,"stackaddr(%p-%p)...\n",start,stop); fflush(dbg); } ret = pthread_attr_setstackaddr(attr, stop); if (dbg) { fprintf(dbg,"ret=%d...\n",ret); fflush(dbg); } return ret; } else { /* this doesn't work because the glibc people should be shot */ /* so preferentially use the setstacksize/addr interface */ pthread_attr_setstack(attr, stop, stacksize); } return 0; } -- MySQL General Mailing List For list archives: http://lists.mysql.com/mysql To unsubscribe: http://lists.mysql.com/[EMAIL PROTECTED]