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

Reply via email to