pthreads на FreeBSD - PullRequest
       31

pthreads на FreeBSD

0 голосов
/ 10 февраля 2011

Я создал программу, которая вычисляет простые числа, используя библиотеку pthread.Программа хорошо работает в Cygwin и Linux, но не во FreeBSD.

Вот программа

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>

#define NUMTHREADS 5 
#define N 10000 

typedef struct
{
    int start;
    int end;
}DISTANCE;

int arr[N];

pthread_mutex_t mutex;

void *sieve(void* s)
{
    int start,end,k,i,j;
    DISTANCE* d = (DISTANCE*)s;
    start = d->start;
    end = d->end;   
    for(i=start;i<end;i++)
    {

        if(arr[i]==0)
        {
            k = i;
            for(j=2*k;j<N+1;j+=i)
            {

                    pthread_mutex_lock(&mutex);
                    arr[j] = 1;
                    pthread_mutex_unlock(&mutex);

            }
        }
    }
    pthread_exit(NULL);
}
void *fill_array(void* f)
{
    int i;
    arr[0] = 1;
    arr[1] = 1;

    for(i=2;i<N;i++)
    {
        arr[i] = 0;
    }
    pthread_exit(NULL);
}
int main(int argc, char **argv)
{

    int div;
    int status;
    int i;
    int count = 0;
    int nums = 0;   

    pthread_t threads[NUMTHREADS];
    DISTANCE dist[NUMTHREADS];

    #ifdef NORMAL_FILL_ARRAY
    arr[0] = 1;
    arr[1] = 1;

    for(i=2;i<N;i++)
    {
        arr[i] = 0;
    }
    #endif

    #ifdef THREAD_FILL_ARRAY
    pthread_t p_arr;
    pthread_create(&p_arr, NULL, fill_array, (void *) NULL);
    pthread_join(p_arr,NULL);
    #endif

    div = ((int)sqrt(N)+1)/NUMTHREADS;
    pthread_mutex_init(&mutex, NULL);

    for(i=0;i<NUMTHREADS;i++)
    {
        if(i==0)
        {
            dist[i].start = 2;
            dist[i].end = 2 + div;
        }
        else if(i==NUMTHREADS-1)
        {
            dist[i].start = dist[i-1].end;
            dist[i].end = (int)sqrt(N)+1;
        }
        else
        {
            dist[i].start = dist[i-1].end;
            dist[i].end = dist[i].start + div;
        }
        pthread_create(&threads[i],NULL,sieve,(void *)&dist[i]);
    }

    for(i=0;i<NUMTHREADS;i++)
    {
        if(pthread_join(threads[i],(void **)&status)!=0)
            printf("pthread_join error");
    }   
    pthread_mutex_destroy(&mutex);

    /*slower with print*/
    for(i=0;i<N;i++)
        {
                if(arr[i]==0)
                {
                        #ifdef PRINT
                        printf("%d\t",i);
                        count++;
                        #endif
                        nums++;
                }
                #ifdef PRINT
                if(count==10)
                {
                        printf("\n");
                        count = 0;
                }
                #endif
        }
        #ifdef PRINT
        printf("\n");
        #endif
    printf("%d: prime numbers found!\n",nums);
    pthread_exit(NULL);
    return 0;
}

Makefile

COMPILER=gcc
LIBS=-lpthread -lm
PRINT=-D PRINT
NORMAL=-D NORMAL_FILL_ARRAY
THREAD=-D THREAD_FILL_ARRAY

default:
    $(COMPILER) $(NORMAL) p_sieve.c -o p_sieve $(LIBS)
threadfill:
    $(COMPILER) $(THREAD) p_sieve.c -o p_sieve $(LIBS)
default_p:
    $(COMPILER) $(NORMAL) $(PRINT) p_sieve.c -o p_sieve $(LIBS)
threadfill_p:
    $(COMPILER) $(NORMAL) $(PRINT) p_sieve.c -o p_sieve $(LIBS)
debug:
    $(COMPILER) $(NORMAL) -g p_sieve.c -o p_sieve $(LIBS)
clean:
    rm p_sieve

и, наконец, вывод GDB

This GDB was configured as "i386-marcel-freebsd"...
(gdb) r
Starting program: /root/lab/src/sieve/p_sieve 
[New LWP 100060]
[New Thread 28201140 (LWP 100060)]
[New Thread 28218140 (LWP 100085)]
[New Thread 28217ec0 (LWP 100090)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 28218140 (LWP 100085)]
0x28098f1f in pthread_mutex_unlock () from /lib/libthr.so.3

Кажется, что pthread_mutex_unlock выдает эту ошибку, но я не могу понять, как ее исправить.Кто-нибудь может помочь?

Ответы [ 2 ]

2 голосов
/ 14 февраля 2011

Без проверки деталей вашего исходного кода - возможно ли, что вы где-то повреждаете свою память - это могло бы объяснить странный SIGSEGV. В противном случае, я не вижу причины, по которой pthread_mutex_unlock () может создать дамп памяти.

Может быть, попытаться удалить все ваши операции с массивами? Или поставить какие-то дополнительные проверки границ там

0 голосов
/ 10 февраля 2011

Я точно не помню и у меня нет FreeBSD, но попробуйте скомпилировать с флагом -pthread.

...