This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

drand48() (and erand48) returns only zeros and pthread application problems


I am working with cygwin environment (Cygwin 1.7.7 + Newlib 1.18)
where drand48 function returns always zero values.

The problem was reported in 2004 at cygwin mailist:
    1) http://cygwin.com/ml/cygwin/2004-11/msg00488.html
    2) http://cygwin.com/ml/cygwin/2004-11/msg00513.html

It seems the problem is at drand48 internal initialization. As a
workaround if srand48 is called at program beginning, future drand48
calls works ok, but this srand48 call is not mandatory.

A main problem related with drand48 returning only zeros are cygwin
pthread applications that uses drand48:
1) We execute srand48 initialization as a workaround of drand48
problems in main function.
2) After this, if we create several threads, the new threads created
in application, has the same zeros problem, but we called srand48 in
main function.

The application behavior in Cygwin is like every thread has its own
"srand48, drand48 and erand48" internal environment and the generated
numbers are isolated. In linux and solaris, generated numbers are
mixed between all threads.

The output is:

==> Cygwin 1.7.7 + Newlib 1.18

./drand48threadtest.exe <seed> <num_threads>

$ ./drand48threadtest.exe 1 5
Init srand48 with: 1
Start main
Main: Creating thread #0 - drand48: 0.041630
Main: Creating thread #1 - drand48: 0.454492
       Executing thread #0.0 - drand48: 0.000000
       Executing thread #1.0 - drand48: 0.000000
Main: Creating thread #2 - drand48: 0.834817
       Executing thread #0.1 - drand48: 0.000000
       Executing thread #1.1 - drand48: 0.000000
Main: Creating thread #3 - drand48: 0.335986
       Executing thread #2.0 - drand48: 0.000000
       Executing thread #0.2 - drand48: 0.000000
       Executing thread #1.2 - drand48: 0.000000
       Executing thread #2.1 - drand48: 0.000000
       Executing thread #3.0 - drand48: 0.000000
Main: Creating thread #4 - drand48: 0.565489
       Executing thread #2.2 - drand48: 0.000000
       Executing thread #3.1 - drand48: 0.000000
       Executing thread #3.2 - drand48: 0.000000
       Executing thread #4.0 - drand48: 0.000000
       Executing thread #4.1 - drand48: 0.000000
       Executing thread #4.2 - drand48: 0.000000
End main

==> Linux and Solaris environments:

./drand48threadtest.exe <seed> <num_threads>

# drand48threadtest 1 5
Init srand48 with: 1
Start main
Main: Creating thread #0 - drand48: 0.041630
Main: Creating thread #1 - drand48: 0.454492
       Executing thread #0.0 - drand48: 0.834817
       Executing thread #0.1 - drand48: 0.335986
       Executing thread #0.2 - drand48: 0.565489
Main: Creating thread #2 - drand48: 0.001767
       Executing thread #1.0 - drand48: 0.187590
       Executing thread #1.1 - drand48: 0.990434
Main: Creating thread #3 - drand48: 0.750497
       Executing thread #2.0 - drand48: 0.351209
       Executing thread #2.1 - drand48: 0.573345
       Executing thread #2.2 - drand48: 0.132554
Main: Creating thread #4 - drand48: 0.064166
       Executing thread #3.0 - drand48: 0.950854
End main
       Executing thread #1.2 - drand48: 0.366274
       Executing thread #4.0 - drand48: 0.584649
       Executing thread #4.1 - drand48: 0.216588
       Executing thread #4.2 - drand48: 0.806502
       Executing thread #3.1 - drand48: 0.153560
       Executing thread #3.2 - drand48: 0.140473

I attach two test program and my cygcheck output.
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int i;
	for(i=0; i<10; i++)
	{
		printf("%i drand48: %f\n",i,drand48());
	}
}
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

int seed=1;
int num_threads=10;

void init_random()
{
	printf("Init srand48 with: %i\n",seed);
	srand48(seed);
}

void *thread_function(void *threadid)
{
	long tid;
	tid = (long)threadid;
	printf("\tExecuting thread #%ld.0 - drand48: %f\n", tid,drand48());
	printf("\tExecuting thread #%ld.1 - drand48: %f\n", tid,drand48());
	printf("\tExecuting thread #%ld.2 - drand48: %f\n", tid,drand48());
	pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
	if(argc!=3)
	{
		printf("%s <seed> <num_threads>\n",argv[0]);
		return;
	}
	else
	{
		seed=atoi(argv[1]);
		num_threads=atoi(argv[2]);
	}
	init_random();
	pthread_t threads[num_threads];
	int rc;
	long t;
	printf("Start main\n");
	for(t=0;t<num_threads;t++)
	{
		printf("Main: Creating thread #%ld - drand48: %f\n", t,drand48());
		rc = pthread_create(&threads[t], NULL, thread_function, (void *)t);
		if (rc)
		{
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
		}
	}
	printf("End main\n");
	pthread_exit(NULL);
}

Attachment: cygcheck.out
Description: Binary data

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

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