tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

swapcontext() vs pthread bug



Emmanuel Dreyfus <manu%netbsd.org@localhost> wrote:

> I observed an interesting thing: in my test case, pthread_self() reports
> that we changed thread, but ktrace shows the same lwp id, therefore
> swapcontext() would not preempt anything?

I am now convinced NetBSD swapcontext() behavior is buggy. Below is a test
case that shows how swapcontext() can make two different threads report the
same pthread_self() while both are running:

# ./tss 
thread 1 self = 0xbfa00000
before swapcontext self = 0xbb600000
after swapcontext self = 0xbfa00000
thread 2 self = 0xbfa00000
thread 1 self = 0xbfa00000
thread 2 self = 0xbfa00000
thread 1 self = 0xbfa00000
thread 2 self = 0xbfa00000

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <err.h>
#include <sysexits.h>
#include <signal.h>
#ifdef __linux__
#include <bits/sigstack.h>
#endif
#include <ucontext.h>

char stack[66536];
ucontext_t ctx;
ucontext_t octx;

void wrap(int);
void *thread1(void *);

void
wrap(cookie)
        int cookie;
{
        printf("after swapcontext self = %p\n", (void *)pthread_self());

        do {
                printf("thread 2 self = %p\n", (void *)pthread_self()); 
                sleep (1);
        } while (1 /* CONSTCOND */);    


        return;
}

void *
thread1(arg)
        void *arg;
{

        usleep(50);

        ctx.uc_stack.ss_sp = stack;
        ctx.uc_stack.ss_size = sizeof(stack);
        
        makecontext(&ctx, (void *)*wrap, 2, (int)0xdeadbeef);

        printf("before swapcontext self = %p\n", (void *)pthread_self());
        if (swapcontext(&octx, &ctx) != 0)
                err(EX_OSERR, "swapcontext failed");
        

        errx(EX_SOFTWARE, "swapcontext returned");
        /* NOTREACHED */
        return NULL;
}


int
main(argc, argv)
        int argc;
        char **argv;
{
        int error;
        pthread_t th;

        if ((error = pthread_create(&th, NULL, *thread1, NULL)) != 0)
                err(EX_OSERR, "pthread_create returns error = %d", error);

        if (getcontext(&ctx) != 0)
                err(EX_OSERR, "getcontext failed");

        do {
                printf("thread 1 self = %p\n", (void *)pthread_self()); 
                sleep (1);
        } while (1 /* CONSTCOND */);    

        /* NOTREACHED */
        return EX_OK;
}


-- 
Emmanuel Dreyfus
http://hcpnet.free.fr/pubz
manu%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index