[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: