Package: libc6 Version: 2.7-15 Severity: normal *** Please type your report below this line ***
Hello! At first I want to say that I'm not sure that debian tracking system is a right place for my question and I apologize if it really is not. I already sent it to the gcc-help mailing list but got no response. I have problems using the pthread_rwlock. It means that it's broken or I have some global misunderstanding of the read-write lock idea. The attached program simply uses the main functionality of the pthread_rwlock: there is an integer variable which can be accessed simultaneously. Every time you type a command ("r" or "w X", where X is an integer value) a new thread is being launched. It locks the variable for 5 seconds and executes your query. The problem is: if you type "r w 10 r" you'll get "0 0" instead of "0 10". But if you wait for some time and type "r" again you'll get "10". I means that the second "r" query acquired the read lock while the "w" query was blocked. It contradicts the statement you can see in the "pthread_rwlock_rdlock" manual: "The calling thread acquires the read lock if a writer does not hold the lock and there are no writers blocked on the lock." The program can be compiled with "gcc main.c -o main -std=gnu99 -l pthread" Alexey Salmin -- System Information: Debian Release: lenny/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 2.6.26-1-amd64 (SMP w/1 CPU core) Locale: LANG=ru_RU.KOI8-R, LC_CTYPE=ru_RU.KOI8-R (charmap=KOI8-R) (ignored: LC_ALL set to ru_RU.KOI8-R) Shell: /bin/sh linked to /bin/bash Versions of packages libc6 depends on: ii libgcc1 1:4.3.2-1 GCC support library libc6 recommends no packages. Versions of packages libc6 suggests: pn glibc-doc <none> (no description available) ii locales 2.7-15 GNU C Library: National Language ( -- debconf information excluded
#include <stdio.h> #include <pthread.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <sched.h> extern char *strerror(int errnum); /* An integer variable protected with rwlock. */ typedef struct data_t_ { int a; pthread_rwlock_t *restrict rwlock; } data_t; typedef enum query_type_t_ { Q_READ, Q_WRITE, } query_type_t; /* A query passed to the thread_func. */ typedef struct query_t_ { query_type_t type; int a; // if (type == Q_WRITE) then "a" contains value to be written data_t *data; // data to be modified } query_t; void *thread_func(void *arg) { query_t *q = (query_t *)arg; int err; if (q->type == Q_READ) { if (err = pthread_rwlock_rdlock(q->data->rwlock)) { fprintf(stderr, "Can't get read lock: %s\n", strerror(err)); free(q); return (void *)(-1); } printf("%d\n", q->data->a); } else { // q->type == Q_WRITE if (err = pthread_rwlock_wrlock(q->data->rwlock)) { fprintf(stderr, "Can't get write lock: %s\n", strerror(err)); free(q); return (void *)(-1); } q->data->a = q->a; } sleep(5); free(q); if (err = pthread_rwlock_unlock(q->data->rwlock)) { fprintf(stderr, "Error during unlocking: %s\n", strerror(err)); return (void *)(-1); } return 0; } int main() { int err; data_t data; data.a = 0; data.rwlock = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)); if (err = pthread_rwlock_init(data.rwlock, 0)) { fprintf(stderr, "Can't initialize rwlock structure: %s\n", strerror(err)); exit(1); } while (1) { char c; pthread_t pthread; pthread_attr_t pthread_attr; query_t *q = (query_t *)malloc(sizeof(query_t)); q->data = &data; if (scanf("\n%c", &c) != 1 || c == 'q') { break; } if (c == 'r') { q->type = Q_READ; } else if (c == 'w') { int a; q->type = Q_WRITE; if (scanf("%d", &a) != 1) { printf("Numeric data expected\n"); free(q); continue; } q->a = a; } else { printf("Unknown command: %c\n", c); free(q); continue; } if (err = pthread_attr_init(&pthread_attr)) { fprintf(stderr, "Can't initialize pthread_attr structure: %s\n", strerror(err)); exit(1); } /*if (err = pthread_attr_setschedpolicy(&pthread_attr, SCHED_OTHER)) { fprintf(stderr, "Can't set sched policy: %s\n", strerror(err)); exit(1); }*/ if (err = pthread_create(&pthread, &pthread_attr, thread_func, q)) { fprintf(stderr, "Can't create thread: %s\n", strerror(err)); exit(1); } } return 0; }