2017-10-18 12 views
0

私は、ミューテックスロックを実装するための大学の割り当てを忙しく待つことなく得ました。私はそれを実装しようとしていますが、多くの成功はありません。ときどき、セグメンテーションのオーバーフローが発生することもありますが、gdbで実行すると、毎回完全に実行されます。ビジー待機なしでのミューテックスロックの実装

mutex.c

#define _GNU_SOURCE 

#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <signal.h> 
#include <stdbool.h> 
#include <sys/syscall.h> 
#include "stack.h" 

#define NUM_THREADS 2 

// shared data structure 
int sum = 0; 

struct Stack waiting_q; 

bool mutex_locked = false; 

void * got_signal(int x) { return NULL; } 

void acquire() 
{ 
    bool first_time = true; 
    while (!__sync_bool_compare_and_swap(&mutex_locked, false, true)) 
    { 
     if (first_time) 
     { 
      push(&waiting_q, pthread_self()); 
      first_time = false; 
     } 
     printf("%ld is waiting for mutex\n", syscall(SYS_gettid)); 
     pause(); 
    } 
    printf("Mutex acquired by %ld\n", syscall(SYS_gettid)); 
} 

void release() 
{ 
    int thread_r = pop(&waiting_q); 
    if (waiting_q.size != 0 && thread_r != INT_MIN) 
     pthread_kill(thread_r, SIGCONT); 

    mutex_locked = false; 
    printf("Mutex released by = %ld\n", syscall(SYS_gettid)); 
} 

void * work() 
{ 
    acquire(); 

    for (int i = 0; i < 10000; i++) 
    { 
     sum = sum + 1; 
    } 
    release(); 
    return NULL; 
} 

int main() 
{ 
    init_stack(&waiting_q); 
    pthread_t threads[NUM_THREADS]; 
    for (int i = 0; i < NUM_THREADS; i++) 
    { 
     int rc = pthread_create(&threads[i], NULL, work, NULL); 
     if (rc != 0) 
      printf("Error creating thread\n"); 
    } 

    for (int i = 0; i < NUM_THREADS; i++) 
    { 
     pthread_join(threads[i], NULL); 
    } 

    printf("Value of Sum = %d\n", sum); 
    return 0; 
} 

stack.h

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

struct Node{ 
    struct Node * next; 
    pthread_t x; 
}; 

struct Stack{ 
    struct Node * head; 
    int size; 
}; 

void push(struct Stack * s, pthread_t n) 
{ 
    struct Node * new_head = malloc(sizeof(struct Node)); 
    new_head->next = s->head; 
    new_head->x = n; 
    s->head = new_head; 
    s->size++; 
} 

pthread_t pop(struct Stack * s) 
{ 
    pthread_t rc = INT_MIN; 
    if (s->head != NULL) 
    { 
     rc = s->head->x; 
     struct Node * next = s->head->next; 
     free(s->head); 
     s->head = next; 
     return rc; 
    } 
    s->size--; 
    return rc; 
} 

void init_stack(struct Stack * s) 
{ 
    s->head = 0; 
    s->size = 0; 
} 
+0

'-fsanitize = undefined、address'をコンパイラとリンカに渡してみてください。あなたが運が良ければ、より有用な出力が得られます。 – nwp

+0

@nwpこれは完全にハングアップするか正しく動作します。 – AhmedBilal

+1

'while'ループの中に' push'を置くと、膨大な量のプッシュが生成される可能性があります。また、 'push'と' pop'のコードはスレッドセーフではないようです。他のスレッドが新しい 'head'を追加するのと同じように' free(s-> head) 'を実行するとどうなりますか? –

答えて

0

ミューテックスの実装からごStackデータ構造へのアクセスは同期されません。

複数のスレッドが同じ時刻にacquireのmutexを試行して、同時にwaiting_qにアクセスする可能性があります。同様に、解放スレッドのpop()へのアクセスは、獲得スレッドからのpush()アクセスと同期しません。

Stackのこのデータ競争は、おそらくsegfaultを引き起こしている可能性が高いです。

+0

実際には、どのようなデータ構造も機能します。私はちょうど私が後でそれらを目を覚ますために一時停止したスレッドを追跡したい。 – AhmedBilal

+0

@AhmedBilal問題はデータ構造ではなく、同期の欠如です。他の(スレッドセーフでない)データ構造でも同様のクラッシュが発生します。 – ComicSansMS

+0

これをどのように修正できますか? – AhmedBilal

関連する問題