Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: peter@a59252.upc-a.chello.nl
To: gdb@sourceware.cygnus.com
Subject: Re: configuring gdb 5.x for use with threads
Date: Tue, 06 Nov 2001 21:13:00 -0000	[thread overview]
Message-ID: <20011117142746.A12792@a59252.upc-a.chello.nl> (raw)
In-Reply-To: <20011102102321.D6507@a59252.upc-a.chello.nl>; from peter@a59252.upc-a.chello.nl on Fri, Nov 02, 2001 at 10:23:21AM +0100

[-- Attachment #1: Type: text/plain, Size: 2470 bytes --]

Hi,.

I rebuild my glibc+linuxthreads 2.2.4 agains my linuxkernel 2.4.15-pre5 SMP, a libthread_db-1.0.so was build.
I rebuild gdb 2001-11-16-cvs, it detected thread_db.h, even loads libthread_db.so.1 on startup. However I still can't debug multi-threaded apps. 

here's some output and the programm used to generate it.

can someone please tell me what I've done wrong or point me to the docs, I'll read.

regards,
Peter Zijlstra

---

peter@twins queue $ gcc -ggdb3 -o test test.c queue.c -D_REENTRANT -lpthread
peter@twins queue $ gdb ./test
GNU gdb 2001-11-16-cvs
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) run
Starting program: /home/peter/code/queue/./test 

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) bt
#0  0x40068bc9 in sigsuspend () from /lib/libc.so.6
#1  0x4002d6cf in pthread_getconcurrency () from /lib/libpthread.so.0
#2  0x4002ce99 in pthread_create () from /lib/libpthread.so.0
#3  0x08049206 in queue_create (queue_size_=16, workers_=3, reaper_=0x804890c <my_reaper>) at queue.c:160
#4  0x0804896e in main (argc=1, argv=0xbffff834) at test.c:38
#5  0x40057921 in __libc_start_main () from /lib/libc.so.6
(gdb) cont
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) 
Continuing.
==> starting packet 2, 12582912
==> starting packet 1, 13369344
==> starting packet 3, 12845056
<== ending packet: 2

Program received signal SIG32, Real-time event 32.
0x40068bc9 in sigsuspend () from /lib/libc.so.6
(gdb) ==> starting packet 4, 14155776
<== ending packet: 1
==> starting packet 5, 14417920
<=> wasting packet 1

<snip>

<== ending packet: 15
<=> wasting packet 15
<=> wasting packet 16
Quit
(gdb) info threads
(gdb) cont
Continuing.
==> starting packet 17, 9175040
==> starting packet 19, 8650752
==> starting packet 18, 8388608
<== ending packet: 17

...

[-- Attachment #2: test.c --]
[-- Type: text/plain, Size: 977 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


#include "queue.h"

typedef struct {
	long long		wait;
	int		seq;
} my_data_t;

void my_processor( void * arg_) {
	my_data_t * data = (my_data_t *)arg_;

	if ( !data) return;

	printf( "==> starting packet %d, %lld\n", data->seq, data->wait);
	fflush( stdout);
	while ( --data->wait);
	printf( "<== ending packet: %d\n", data->seq);
	fflush( stdout);
}

void my_reaper( void * arg_) {
	my_data_t * data = (my_data_t *)arg_;

	printf( "<=> wasting packet %d\n", data->seq);
	fflush( stdout);

	free( arg_);
}

int main( int argc, char ** argv) {
	queue_t * work;
	int i;

	work = queue_create( 16, 3, my_reaper);

	sleep(1);

	for ( i=1; i<50; i++) {
		my_data_t * data = (my_data_t *)malloc( sizeof( my_data_t));
		data->seq = i;
		data->wait = (long long)(50^i) << 18;

		queue_insert( work, my_processor, (void *)data);
	}

	queue_insert_last( work);
	queue_wait_last( work);
	queue_destruct( work);

	return 0;
}

[-- Attachment #3: queue.c --]
[-- Type: text/plain, Size: 4713 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "queue.h"

//#define INC( q, x)	++(x) %= (q)->_queue_size;
#define INC( q, x)	({ ++(x); (x) %= (q)->_queue_size; (x); })

//#define pthread_mutex_lock( a) { pthread_mutex_lock( a); printf( "%p: got mutex\n", pthread_self()); fflush( stdout); }

static queue_elem_t * queue_create_elem( process_func_t func_, void * data_) {
	queue_elem_t * qe = (queue_elem_t *)malloc( sizeof( queue_elem_t));
	if ( !qe) return NULL;

	qe->_data = data_;
	qe->_process = func_;
	qe->_done = 0;

	pthread_mutex_init( &qe->_elem_lock, NULL);

	return qe;
}

static queue_elem_t * queue_get_next( queue_t * q_) {
	size_t head;
	queue_elem_t * qe = NULL;
	
	pthread_mutex_lock( &q_->_queue_lock);
	while ( q_->_size != q_->_queue_size && 
			q_->_next == q_->_head && 
			!q_->_quit)
		pthread_cond_wait( &q_->_queue_insert, &q_->_queue_lock);
	if ( !q_->_quit) {
		qe = q_->_queue[ q_->_next];
		INC( q_, q_->_next);
	}
	pthread_mutex_unlock( &q_->_queue_lock);

	return qe;
}

static void * queue_worker( void * arg_) {
	queue_t * q = (queue_t *)arg_;

	while ( !q->_quit) {
		queue_elem_t * qe = queue_get_next( q);
		if ( !qe) continue;
		pthread_mutex_lock( &qe->_elem_lock);
		if ( qe->_process && qe->_data)
			qe->_process( qe->_data);
		qe->_done = 1;
		pthread_cond_signal( &q->_elem_done);
		pthread_mutex_unlock( &qe->_elem_lock);
	}

	return NULL;
}

static void * queue_reaper( void * arg_) {
	queue_t * q = (queue_t *)arg_;

	while ( !q->_quit) {
		queue_elem_t * qe = NULL;
		pthread_mutex_lock( &q->_queue_lock);
		while ( q->_tail == q->_next && !q->_quit)
			pthread_cond_wait( &q->_elem_done, &q->_queue_lock);
		if ( !q->_quit) {
			qe = q->_queue[ q->_tail];
			q->_queue[ q->_tail] = NULL;
			INC( q, q->_tail);
			--q->_size;
			pthread_cond_signal( &q->_queue_remove);
		}
		pthread_mutex_unlock( &q->_queue_lock);
		if ( !qe) continue;

		// XXX: should sync if _elem_done was not tail elem.
		pthread_mutex_lock( &qe->_elem_lock);
		assert( qe->_done);
		if ( !qe->_process && !qe->_data) q->_last = 1;
		else q->_reap( qe->_data);
		pthread_mutex_unlock( &qe->_elem_lock);
	}

	return NULL;
}

void queue_insert( queue_t * q_, process_func_t func_, void * data_) {
	size_t head;
	queue_elem_t * qe = queue_create_elem( func_, data_);
	if ( !qe) return;

	pthread_mutex_lock( &q_->_queue_lock);
	while ( q_->_size && q_->_tail == q_->_head && !q_->_quit)
		pthread_cond_wait( &q_->_queue_remove, &q_->_queue_lock);
	if ( !q_->_quit) {
		q_->_last = 0;
		assert( q_->_queue[ q_->_head] == NULL);
		q_->_queue[ q_->_head] = qe;
		INC( q_, q_->_head);
		++q_->_size;
		pthread_cond_signal( &q_->_queue_insert);
	}
	pthread_mutex_unlock( &q_->_queue_lock);
}

void queue_insert_last( queue_t * q_) {
	queue_insert( q_, NULL, NULL);
}

void queue_wait_last( queue_t * q_) {
	pthread_mutex_lock( &q_->_queue_lock);
	while ( !q_->_last)
		pthread_cond_wait( &q_->_queue_remove, &q_->_queue_lock);
	pthread_mutex_unlock( &q_->_queue_lock);
}

queue_t * queue_create( size_t queue_size_, size_t workers_, process_func_t reaper_) {
	queue_t * q;
	int i;
	int rc;

	if ( workers_ < 1 || queue_size_ < workers_ || !reaper_)
		return NULL;

	q = (queue_t *)malloc( sizeof( queue_t));
	if ( !q) return NULL;
	
	q->_queue_size = queue_size_;
	q->_queue = (queue_elem_t **)malloc( queue_size_ * sizeof( queue_elem_t *));
	if ( !q->_queue) {
		free( q);
		return NULL;
	}
	for ( i=0; i<queue_size_; i++)
		q->_queue[i] = NULL;

	q->_head = q->_tail = q->_next = q->_size = 0;

	q->_quit = 0;
	q->_reap = reaper_;
	q->_last = 0;

	pthread_mutex_init( &q->_queue_lock, NULL);
	pthread_cond_init( &q->_queue_insert, NULL);
	pthread_cond_init( &q->_queue_remove, NULL);
	pthread_cond_init( &q->_elem_done, NULL);

	q->_workers = workers_;
	q->_tid_workers = (pthread_t *)malloc( workers_ * sizeof( pthread_t));
	if ( !q->_tid_workers) {
		free( q->_queue);
		free( q);
		return NULL;
	}

	pthread_mutex_lock( &q->_queue_lock);
	for ( i=0; i<workers_; i++)
		pthread_create( &q->_tid_workers[i], NULL, queue_worker, (void *)q);

	pthread_create( &q->_tid_reaper, NULL, queue_reaper, (void *)q);
	pthread_mutex_unlock( &q->_queue_lock);

	return q;
}

void queue_destruct( queue_t * q_) {
	int i;
	
	q_->_quit = 1;
	
	for ( i=0; i<q_->_workers; i++) {
		pthread_cond_broadcast( &q_->_queue_insert);
		pthread_join( q_->_tid_workers[i], NULL);
	}

	pthread_cond_signal( &q_->_elem_done);
	pthread_join( q_->_tid_reaper, NULL);

	pthread_mutex_destroy( &q_->_queue_lock);
	pthread_cond_destroy( &q_->_queue_insert);
	pthread_cond_destroy( &q_->_queue_remove);
	pthread_cond_destroy( &q_->_elem_done);
	
	free( q_->_tid_workers);
	free( q_->_queue);
	free( q_);
}

[-- Attachment #4: queue.h --]
[-- Type: text/plain, Size: 1510 bytes --]

#ifndef __QUEUE_INCLUDED
#define __QUEUE_INCLUDED

#include <pthread.h>

typedef void (*process_func_t)( void *);

typedef struct {
	void *			_data;
	process_func_t	_process;
	volatile int	_done;

	pthread_mutex_t	_elem_lock;
} queue_elem_t;

typedef struct {
	size_t			_queue_size;
	queue_elem_t **	_queue;
	volatile size_t	_head, _tail, _next, _size;

	volatile int	_quit;
	process_func_t	_reap;
	volatile int	_last;

	pthread_mutex_t	_queue_lock;
	pthread_cond_t	_queue_insert, _queue_remove;
	pthread_cond_t	_elem_done;

	size_t			_workers;
	pthread_t *		_tid_workers;
	pthread_t		_tid_reaper;
} queue_t;

/*
	queue_insert( queue_t *, process_func_t func, void * data) 
		inserts a job into the queue; executes: func( data)
*/
void queue_insert( queue_t *, process_func_t, void *);

/*
	queue_insert_last( queue_t *); same as queue_insert( queue_t *, NULL, NULL)
*/
void queue_insert_last( queue_t *);

/*
	queue_wait_last( queue_t *)
		waits for a (NULL,NULL) job to be processed

	XXX: queue_insert resets the last flag; 
*/
void queue_wait_last( queue_t *);

/*
	queue_create( size_t queue_size, size_t workers, process_func_t reaper)
	
	creates a queue of size #queue_size with #workers workers
	and calls reaper( job.data) for each enqueued job when done
	and in sequence

	returns: queue_t * on success; NULL on error;
*/
queue_t * queue_create( size_t, size_t, process_func_t);

/*
	queue_destruct( queue_t *)

	frees resources allocated by queue_create;
*/
void queue_destruct( queue_t *);

#endif

       reply	other threads:[~2001-11-17 13:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20011102102321.D6507@a59252.upc-a.chello.nl>
2001-11-06 21:13 ` peter [this message]
2001-11-07  2:30   ` Kevin Buettner
2001-11-08  7:09     ` peter
2001-11-08  7:53       ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20011117142746.A12792@a59252.upc-a.chello.nl \
    --to=peter@a59252.upc-a.chello.nl \
    --cc=gdb@sourceware.cygnus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox