2011-02-10 14 views
0

私はpthreadライブラリを使って素数を計算するプログラムを作った。 プログラムはcygwinとlinuxではうまく動作しますが、FreeBSDでは動作しません。ここでFreeBSDのpthreads

はプログラム

#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 

とfinaly 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のは、このエラーが発生しているようですが、私は修正する方法を見つけ出すことはできませんですそれ。 誰も助けることができますか?

+0

プログラムを静的にリンクしようとしましたか?おそらく、ライブラリのバージョン管理エラーです。 –

答えて

0

私は正確に覚えておらず、すぐにFreeBSDを持っていませんが、-pthreadフラグでコンパイルしてみてください。

+0

それは役に立たなかった。問題は残っている。 – wallee

+0

@wallee:今すぐプログラムをコンパイルするために使用するコマンドを提供してもらえますか( 'make'によって出力されます)。また、pthread_t構造体(私はそれが構造体であるかどうか覚えていません)が(誰かがメモリにぶつかっているかどうかに関わらず)mangledされているかどうかを確認できますか? –

2

ソースコードの詳細を確認せずに、あなたがどこかであなたのメモリを破壊している可能性があります - それは奇妙なSIGSEGVを説明するでしょう。それ以外の場合は、pthread_mutex_unlock()がコアダンプを行う理由はありません。

多分、すべてのアレイ操作を試して削除しますか?またはそこにいくつかの余分な境界をチェックしますか?

+0

それが問題でした。いくつかの反復の後、私は範囲外の値を読んでいました。 – wallee