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
next parent 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