Bug#503162: libc6: Doubt with nptl
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;
}
Reply to: