This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Testcase for pthread_join() with user-defined stacks
- To: drepper at cygnus dot com, libc-alpha at sources dot redhat dot com
- Subject: Testcase for pthread_join() with user-defined stacks
- From: Wolfram Gloger <Wolfram dot Gloger at dent dot med dot uni-muenchen dot de>
- Date: Mon, 11 Dec 2000 12:24:48 +0100 ("MET)
- References: <20001125113341.29693.qmail@md.dent.med.uni-muenchen.de> <m3n1ejst6b.fsf@otr.mynet.cygnus.com> <20001203122833.8621.qmail@md.dent.med.uni-muenchen.de>
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;
}