kern/70502: error in new __thread local storage support

Jake Hamby jhamby at anobject.com
Sun Aug 15 17:30:25 PDT 2004


>Number:         70502
>Category:       kern
>Synopsis:       error in new __thread local storage support
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Aug 16 00:30:24 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Jake Hamby
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
Software Factory x
>Environment:
System: FreeBSD fuji 5.2-CURRENT FreeBSD 5.2-CURRENT #2: Sat Aug 14 19:00:56 PDT 2004 root at fuji:/usr/home/work/sys/FUJI i386
>Description:

The new __thread based TLS code doesn't seem to work beyond a particular size.

>How-To-Repeat:

See the attached test program.  On my machine, it works for NUM_KEYS=6, but
with NUM_KEYS=10 I see data corruption in the TLS area, and with NUM_KEYS=64,
it crashes, so the TLS region is definitely overwriting something important.

$ gcc -O2 -o tls_nptl_test tls_nptl_test.c -lpthread
$ ./tls_nptl_test

Fatal error '_pq_remove: Not in priority queue' at line 144 in file /usr/src/lib/libpthread/thread/thr_priority_queue.c (errno = 0)
Segmentation fault (core dumped)

>Fix:

I don't know the code well enough to suggest a fix.

--- tls_nptl_test.c begins here ---

/*
 * Test of pthreads / TLS storage.
 */

#define _REENTRANT
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <dlfcn.h>

#define NUM_THREADS 64
#define NUM_KEYS 64
static __thread int TLS_keys[NUM_KEYS];
static pthread_t threads[NUM_THREADS];

static void*
start_routine(void *arg)
{
	int thread_num = (int)arg;
	int i, err;
	for(i=0; i<500; i++)
	{
		if (i==17)
		{
		/*	printf("Thread %d: Number 17:  break for debugger\n",
				thread_num); */
		}
		int j;
		for(j=0; j<NUM_KEYS; j++)
		{
			/* verify old key value (except first time through loop) */
			int val = TLS_keys[j];
			if (val != i && (i != 0))
			{
				printf("Thread %d: expected %d for key %d, found %d\n",
					thread_num, i, j, val);
				return (void*)1;
			}
			/* set new key value */
			TLS_keys[j] = i+1;
		}
		/* sleep from 0.1 to 1 sec. */
		struct timespec slptime = {0, 100000000 + random()%900000000};
		/*printf("Thread %d: foo sleep %d\n", thread_num, slptime.tv_nsec);*/
		nanosleep(&slptime, 0);
	}
	return 0;
}

int
main(int argc, char** argv)
{
	int i;
	const char* dlerr = dlerror();
	if (dlerr)
	{
		printf("dlerror: %s\n", dlerr);
		return 1;
	}
	for(i=0; i<NUM_THREADS; i++)
	{
		int err = pthread_create(&threads[i], NULL, start_routine,
					 (void*)i);
		if (err)
		{
			printf("pthread_create error %d for thread %d\n", err, i);
			return 1;
		}
	}
	for(i=0; i<NUM_THREADS; i++)
	{
		void* retval;
		int err = pthread_join(threads[i], &retval);
		if (err)
		{
			printf("pthread_join error %d for thread %d\n", err, i);
			return 1;
		}
	}
	return 0;
}
--- tls_nptl_test.c ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list