Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jun 2005 13:18:35 -0400
From:      John Baldwin <jhb@FreeBSD.org>
To:        freebsd-hackers@freebsd.org, Pablo Mora <fbsd.hackers@gmail.com>
Subject:   Re: problem handling POSIX thread on FreeBSD
Message-ID:  <200506271318.36748.jhb@FreeBSD.org>
In-Reply-To: <a9e342b505062622321b949ebb@mail.gmail.com>
References:  <a9e342b5050626200472f78ea5@mail.gmail.com> <a9e342b505062622103e90d241@mail.gmail.com> <a9e342b505062622321b949ebb@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 27 June 2005 01:32 am, Pablo Mora wrote:
> /* file: test.c */
> #include<stdio.h>
> #include<pthread.h>
> #include<string.h>
> #include<unistd.h>
> #include<stdlib.h>
>
> char buffer[512];
> pthread_mutex_t mutex, mutex2;
> pthread_t hilo1, hilo2;
>
> void f1(void* ptr)
> {
> 	int i,n=10;
> 	int valor=0;
> 	char*p=(char*)ptr;
>
> 	for(i=0;i<n;i++)
> 	{
> 		pthread_mutex_lock(&mutex);
> 		sscanf(p,"%d",&valor);
> 		printf("\thilo1: puntero contiene %d\n", valor);
> 		valor=i*3;
> 		sprintf(p, "%d",valor);
>
> 		pthread_mutex_unlock(&mutex2);
> 	}
> 	valor=(int)pthread_self();
> 	printf("finaliza hilo1 con id %d\n", valor);
> 	pthread_exit(&valor);
> }
> void f2(void* ptr)
> {
> 	int i,n=10;
> 	int valor=0;
> 	char*p=(char*)ptr;
> 	for(i=0;i<n;i++)
> 	{
> 		pthread_mutex_lock(&mutex2);
> 		sscanf(p,"%d",&valor);
> 		printf("hilo2: puntero contiene %d\n", valor);
> 		valor=i*2;
>
> 		sprintf(p, "%d",valor);
> 		pthread_mutex_unlock(&mutex);
> 	}
> 	valor=(int)pthread_self();
> 	printf("finaliza hilo2 con id %d\n", valor);
> 	pthread_exit(&valor);
> }

This code is nuts.  You can't unlock a mutex that you don't own.  You probably 
want to be using semaphores I think.  However, even then that doesn't really 
make sense.  Replace 'mutex2' with 'mutex' in the f1() and f2() functions and 
get rid of mutex2 and try it again.  However, with that change, f1() is free 
to run to completion before f2() will start.  If you want to enforce ping 
ponging, you need to use a condition variable to synchronize.  Something 
like:

pthread_cond_t condvar;

f1()
{
	...
	pthread_mutex_lock(&mutex);
	for (i = 0; i < n; i++) {
		sscanf(...)
		printf(...)
		valor = i * 3;
		sprintf(...)
		pthread_cond_wait(&condvar, &mutex);
	}
	pthread_mutex_unlock(&mutex);
	valor = (int)pthread_self();
	...
}

and f2() is similar except s/3/2/.  This will cause the threads to ping pong 
where one thread waits for the other to run after each cycle.  You might also 
want to read up on how synchronization with multiple threads works.  
"Programming with POSIX Threads" is a decent book, and Tannebaum's "Modern 
Operating Systems" has a decent section on various synchronization primitives 
such as mutexes, semaphores, etc.  Also, if you have thread specific 
questions, there is a freebsd-threads@ mailing list that is probably a better 
place to ask them on.

> int main()
> {
> 	pthread_attr_t atributos;
> 	//pthread_mutexattr_t mutexattr; - solaris
>
> 	memset(buffer, '\0', sizeof(buffer));
> 	/*
>
> if(pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_PRIVATE)!=0)
> //solaris
> 	{
> 		perror("pthread_mutexattr_setpshared");
> 		exit(-12);
> 	}
>     */
>
> 	pthread_mutex_init(&mutex, NULL); //linux
> 	pthread_mutex_init(&mutex2, NULL); //linux
>
> 	pthread_mutex_lock(&mutex2); /
>
> 	/*if(pthread_mutex_init(&mutex, &mutexattr)!=0) //solaris
> 	{
> 		perror("pthread_mutex_init");
> 		exit(-2);
> 	}*/
>
> 	if(pthread_attr_init(&atributos) < 0)
> 	{
> 		perror("pthread_attr_init");
> 		exit(-1);
> 	}
> 		if(pthread_attr_setscope(&atributos,PTHREAD_SCOPE_PROCESS) < 0)
> 	{
> 		perror("pthread_attr_setscope");
> 		exit(-2);
> 	}
> 	if(pthread_create (&hilo1, &atributos, (void*)&f1, (void*)buffer)<0)
> 	{
> 		perror("pthread_create hilo1");
> 		exit(-2);
> 	}
> 	if(pthread_create(&hilo2, &atributos, (void*)&f2, (void*)buffer)<0)
> 	{
> 		perror("pthread_create hilo2");
> 		exit(-2);
> 	}
>
>
> 	if(pthread_join(hilo2, NULL)<0)
> 	{
> 		perror("pthread_join hilo1 ");
> 		exit(-3);
> 	}
> 	puts("fin hilo 2");
> 	/*if(pthread_join(hilo1, NULL)<0)
> 	{
> 		perror("pthread_join hilo2 ");
> 		exit(-3);
> 	}*/
>
>
> 	pthread_mutex_destroy(&mutex);
> 	exit(0);
> }
>
> output in solaris and linux: (gcc test.c -lpthread)
>
>                 hilo1: puntero contiene 0
>        hilo2: puntero contiene 0
>                hilo1: puntero contiene 0
>        hilo2: puntero contiene 3
>                hilo1: puntero contiene 2
>        hilo2: puntero contiene 6
>                hilo1: puntero contiene 4
>       hilo2: puntero contiene 9
>               hilo1: puntero contiene 6
>       hilo2: puntero contiene 12
>               hilo1: puntero contiene 8
>       hilo2: puntero contiene 15
>               hilo1: puntero contiene 10
>       hilo2: puntero contiene 18
>               hilo1: puntero contiene 12
>       hilo2: puntero contiene 21
>               hilo1: puntero contiene 14
>       hilo2: puntero contiene 24
>               hilo1: puntero contiene 16
>       finaliza hilo1 con id 1082231728
>       hilo2: puntero contiene 27
>       finaliza hilo2 con id 1090624432
>       fin hilo 2
>
> output on FreeBSD v4.11 STABLE (gcc test.c -pthread):
>
>         hilo1: puntero contiene 0
>         hilo1: puntero contiene 0
>         hilo1: puntero contiene 3
>         hilo1: puntero contiene 6
>         hilo1: puntero contiene 9
>         hilo1: puntero contiene 12
>         hilo1: puntero contiene 15
>         hilo1: puntero contiene 18
>         hilo1: puntero contiene 21
>         hilo1: puntero contiene 24
> finaliza hilo1 con id 134534144
>
> why ??
>
> help me please :-).

-- 
John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200506271318.36748.jhb>