This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Testcase for pthread_join() with user-defined stacks


Hello,

Below is a testcase exercising the problem with pthread_join() on
threads with user-defined stacks.  On all versions of glibc that I am
aware of, this test hangs or crashes sooner or later.

The patch that I just sent under `Re: Re-use of user-defined stacks
for threads' is meant to address the problem, with it applied the
testcase runs fine on my machine.

Regards,
Wolfram.

/*
 * Testcase for pthread_join() with user-defined stacks
 * by Wolfram Gloger <wg@malloc.de> 2000
 */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>

#define NT_MAX   100
#define NT_TOTAL 200
#define MAX_USEC 400
#define STACKSIZE 65536
#ifndef USERSTACKS
#define USERSTACKS 1
#endif

struct thread_t {
    char* sp;
    pthread_t pt;
    int done;
};

pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;

static void*
t_entry(void* ptr)
{
    struct thread_t* tt = (struct thread_t*)ptr;
    long r;
    struct timeval tv;

    printf("start %p\n", tt->sp);
    r = random()%1000;
    tv.tv_sec = 0;
    tv.tv_usec = r*MAX_USEC;
    select(0, 0, 0, 0, &tv);
    pthread_mutex_lock(&finish_mutex);
    tt->done = 1;
    pthread_mutex_unlock(&finish_mutex);
    pthread_cond_signal(&finish_cond);
    return 0;
}

int
main(int argc, char* argv[])
{
    int completed, running = 0;
    int i, nt = 8, nt_total = NT_TOTAL;
    struct thread_t tt[NT_MAX];
    pthread_attr_t pa;

    if(argc > 1) {
	nt = atoi(argv[1]);
	if(argc > 2)
	    nt_total = atoi(argv[2]);
    }
    if(nt > NT_MAX)
	nt = NT_MAX;

    for(i=0; i<nt; i++) {
	tt[i].sp = malloc(STACKSIZE+16);
	tt[i].done = 0;
	pthread_attr_init(&pa);
	pthread_attr_setstacksize(&pa, STACKSIZE);
	pthread_attr_setstackaddr(&pa, tt[i].sp + STACKSIZE);
	if(pthread_create(&tt[i].pt, USERSTACKS ? &pa : 0, t_entry, &tt[i])) {
	    fprintf(stderr, "can't create\n");
	    pthread_attr_destroy(&pa);
	    break;
	}
	pthread_attr_destroy(&pa);
	++running;
    }
    nt = i;
    for(completed=0; running>0;) {
	pthread_mutex_lock(&finish_mutex);
	pthread_cond_wait(&finish_cond, &finish_mutex);
	for(i=0; i<nt; i++) {
	    if(tt[i].done) {
		printf("join %p\n", tt[i].sp);
		pthread_join(tt[i].pt, NULL);
		printf("done %p (%d)\n", tt[i].sp, i);
		++completed;
		printf("comp=%d run=%d\n", completed, running);
		tt[i].done = 0;
		if(completed+running < nt_total) {
		    pthread_attr_init(&pa);
		    pthread_attr_setstacksize(&pa, STACKSIZE);
		    pthread_attr_setstackaddr(&pa, tt[i].sp + STACKSIZE);
		    if(pthread_create(&tt[i].pt, USERSTACKS ? &pa : 0, t_entry,
				      &tt[i])) {
			fprintf(stderr, "can't create\n");
			pthread_attr_destroy(&pa);
			--running;
			break;
		    }
		    pthread_attr_destroy(&pa);
		} else
		    --running;
	    }
	}
	pthread_mutex_unlock(&finish_mutex);
    }
    fprintf(stderr, "Done\n");
    for(i=0; i<nt; i++) {
	free(tt[i].sp);
    }
    return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]