Проблемы синхронизации в C с использованием мьютексов pthreads - PullRequest
0 голосов
/ 01 апреля 2011

Я использую простую реализацию очереди и пытаюсь создать простую программу, которая имеет два потока: первый в очереди событий в очереди, а второй обрабатывает их.Я использую мьютексы, чтобы избежать проблем с синхронизацией.Тем не менее, я все еще получаю довольно часто (не всегда) ошибки сегментации.

Имейте в виду, я также создал свои коды, используя опцию -D_REENTRANT.Кроме того, код прекрасно работает, если очередь / очередь вызывается только из одного потока.

Вот простой код, который показывает, как я синхронизирую вещи:

int main(void) {
    init_queue(&my_queue);

    pthread_t thread_queue, thread_process;
    int iret1, iret2;

    iret1 = pthread_create( &thread_queue, NULL, svetlin_queue_events, (void*) NULL);
    iret2 = pthread_create( &thread_process, NULL, svetling_process_events, (void*) fb);

    pthread_join(thread_queue, NULL);
    pthread_join(thread_process, NULL);
}

функция очереди:

void svetlin_queue_events(void * v) {
    int fd;
    if ((fd = open("/dev/input/mouse1", O_RDONLY)) == -1) {
        printf("error with touchscreen device\n");
        exit(1);
    }

    struct input_event ev;
    struct input_event *being_sent;
    int rd;

    while (1) {
        read(fd, &ev, sizeof(struct input_event));

        being_sent = malloc(sizeof(struct input_event));
        memcpy(being_sent, &ev, sizeof(struct input_event));

        pthread_mutex_lock(&my_mutex);
        enqueue(&my_queue, being_sent);
        pthread_mutex_unlock(&my_mutex);

        printf("enqueueing...\n");
    }
}

и функция обработки:

void svetling_process_events(void *v) {

    printf("FB pointer is: %p\n", fb);

    int x, y = 0;
    int has_item = 0;
    struct input_event **being_fetched;
    struct input_event *ev;

    while(1) {

        pthread_mutex_lock(&my_mutex);
        has_item = dequeue(&my_queue, being_fetched);
        pthread_mutex_unlock(&my_mutex);

        if (has_item) {
            ev = *being_fetched;
            printf("dequeueing...\n");
            if (ev->type == 3) {
                if (ev->code == 0) {
                    x = ev->value;
                }

                if (ev->code == 1) {
                    y = ev->value;
                }
            }
        }
    }
}

Надеюсь, я не перегружаю вас большим количеством кода, но на самом деле это нечто простое.

Так что мойВопрос в том, что касается синхронизации, я делаю неправильно?

Спасибо!

ОБНОВЛЕНИЕ

Вот реализация очереди:

struct queue_node
{
    struct queue_node *next;
    void *data;
};

struct queue
{
    struct queue_node *first;
    struct queue_node *last;
};

int enqueue(struct queue *q, void * const value)
{
    struct queue_node *node = malloc(sizeof(struct queue_node));

    if (node == NULL) {
        errno = ENOMEM;
        return 1;
    }

    node->data = value;

    if (q->first == NULL) {
        q->first = q->last = node;
    } else {
        q->last->next = node;
        q->last = node;
    }

    node->next = NULL;
    return 0;
}

int dequeue(struct queue *q, void **value)
{
    if (!q->first) {
        value = NULL;
        return 0;
    }
    *value = q->first->data;
    q->first = q->first->next;
    return 1;
}

void init_queue(struct queue *q)
{
    q->first = q->last = NULL;
}

int queue_empty_p(const struct queue *q)
{
    return q->first == NULL;
}

Это segfaults на линии*value = q->first->data; в dequeue.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 01 апреля 2011

Одна небольшая проблема:

if (!q->first) {
    *value = NULL;
    return 0;
}

(обратите внимание на добавленную звездочку).

Основная проблема, как представляется, заключается в том, что вы не выделяете память для *being_fetched в process_eventsfunction.

Если честно, я бы изменил тип этой переменной на struct input_event *being_fetched и просто передал бы ее адрес dequeue: has_item = dequeue(&my_queue, &being_fetched).Это также позволит вам избавиться от ev как отдельной переменной.

1 голос
/ 01 апреля 2011

Как сказал Экс, вы не инициировали * будучи_полученным. Но я думаю, что вам лучше определить это по-другому:

struct input_event *being_fetched;
...
has_item = dequeue(&my_queue, &being_fetched);
...
ev = being_fetched;

И затем убедитесь, что вы исправили другую ошибку, о которой упоминает aix, иначе вы не получите нулевой указатель обратно из функции.

...