This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
pthread_rwlock problem
- From: "Alexey Salmin" <alexey dot salmin at gmail dot com>
- To: gcc-help at gcc dot gnu dot org
- Date: Sun, 19 Oct 2008 17:58:46 +0700
- Subject: pthread_rwlock problem
Hello!
I'm not quite sure this mail was sent to a proper place but anyway I
hope I'll get some help :)
Trying to understand the way NPTL works I wrote a simple program which
uses the base
pthread_rwlock functionality (see the attached file). But it doesn't
work and I have no idea why.
My program contains an integer variable protected with pthread_rwlock.
It can execute two
simple command: "r" and "w NNN", where NNN is an integer value. When
you type 'r' symbol
to it's stdin pthread_rwlock_rdlock is being hold for 5 seconds and
stored value is being
written to the stdout. "w" command holds pthread_rwlock_wrlock for 5
second and changes
the data. Here's the text from the pthread_rwlock_rdlock manual :"The
pthread_rwlock_rdlock()
function shall apply a read lock to the read-write lock referenced by
rwlock. The calling thread
acquires the read lock if a writer does not hold the lock and (!)
there are no writers blocked on the lock (!)."
So the expected result for the "r w 10 r" command string is "0 10".
But actually it is "0 0".
It means that the second "r" command get the lock while the "w"
operation is being blocked.
I compile my program this way: "gcc main.c -o main -l pthread -std=gnu99"
My system info:
salmin@salmin:~$ uname -a
Linux salmin 2.6.26-1-amd64 #1 SMP Wed Sep 24 13:59:41 UTC 2008 x86_64 GNU/Linux
ii gcc 4:4.3.2-2 The GNU C compiler
ii libc6 2.7-15 GNU C Library:
Shared libraries
PS Sorry for my language :)
Alexey
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
extern char *strerror(int errnum);
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;
typedef struct query_t_ {
query_type_t type;
int a; // if type == Q_WRITE contains data to be written
data_t *data;
} 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_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;
}