> >>>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]