Update.
* internals.h: Declare __pthread_last_event. * manager.c: Define __pthread_last_event. (pthread_handle_create): Set __pthread_last_event. (pthread_exited): Likewise. * join.c (pthread_exit): Likewise.
This commit is contained in:
parent
dbd3e8629f
commit
ab86fbb1d2
|
@ -1,5 +1,11 @@
|
||||||
1999-11-02 Ulrich Drepper <drepper@cygnus.com>
|
1999-11-02 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
|
* internals.h: Declare __pthread_last_event.
|
||||||
|
* manager.c: Define __pthread_last_event.
|
||||||
|
(pthread_handle_create): Set __pthread_last_event.
|
||||||
|
(pthread_exited): Likewise.
|
||||||
|
* join.c (pthread_exit): Likewise.
|
||||||
|
|
||||||
* Makefile (libpthread-routines): Add events.
|
* Makefile (libpthread-routines): Add events.
|
||||||
* events.c: New file.
|
* events.c: New file.
|
||||||
* internals.h: Protect against multiple inclusion.
|
* internals.h: Protect against multiple inclusion.
|
||||||
|
|
|
@ -229,6 +229,9 @@ extern volatile int __pthread_threads_debug;
|
||||||
/* Globally enabled events. */
|
/* Globally enabled events. */
|
||||||
extern volatile td_thr_events_t __pthread_threads_events;
|
extern volatile td_thr_events_t __pthread_threads_events;
|
||||||
|
|
||||||
|
/* Pointer to descriptor of thread with last event. */
|
||||||
|
extern volatile pthread_descr __pthread_last_event;
|
||||||
|
|
||||||
/* Return the handle corresponding to a thread id */
|
/* Return the handle corresponding to a thread id */
|
||||||
|
|
||||||
static inline pthread_handle thread_handle(pthread_t id)
|
static inline pthread_handle thread_handle(pthread_t id)
|
||||||
|
|
|
@ -54,6 +54,7 @@ void pthread_exit(void * retval)
|
||||||
/* Yep, we have to signal the death. */
|
/* Yep, we have to signal the death. */
|
||||||
THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
|
THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
|
||||||
THREAD_SETMEM(self, p_eventbuf.eventdata, self);
|
THREAD_SETMEM(self, p_eventbuf.eventdata, self);
|
||||||
|
__pthread_last_event = self;
|
||||||
|
|
||||||
/* Now call the function to signal the event. */
|
/* Now call the function to signal the event. */
|
||||||
__linuxthreads_death_event();
|
__linuxthreads_death_event();
|
||||||
|
|
|
@ -55,6 +55,9 @@ volatile int __pthread_threads_debug;
|
||||||
/* Globally enabled events. */
|
/* Globally enabled events. */
|
||||||
volatile td_thr_events_t __pthread_threads_events;
|
volatile td_thr_events_t __pthread_threads_events;
|
||||||
|
|
||||||
|
/* Pointer to thread descriptor with last event. */
|
||||||
|
volatile pthread_descr __pthread_last_event;
|
||||||
|
|
||||||
/* Mapping from stack segment to thread descriptor. */
|
/* Mapping from stack segment to thread descriptor. */
|
||||||
/* Stack segment numbers are also indices into the __pthread_handles array. */
|
/* Stack segment numbers are also indices into the __pthread_handles array. */
|
||||||
/* Stack segment number 0 is reserved for the initial thread. */
|
/* Stack segment number 0 is reserved for the initial thread. */
|
||||||
|
@ -422,6 +425,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
already scheduled when we send the event. */
|
already scheduled when we send the event. */
|
||||||
new_thread->p_eventbuf.eventdata = new_thread;
|
new_thread->p_eventbuf.eventdata = new_thread;
|
||||||
new_thread->p_eventbuf.eventnum = TD_CREATE;
|
new_thread->p_eventbuf.eventnum = TD_CREATE;
|
||||||
|
__pthread_last_event = new_thread;
|
||||||
|
|
||||||
/* Now call the function which signals the event. */
|
/* Now call the function which signals the event. */
|
||||||
__linuxthreads_create_event ();
|
__linuxthreads_create_event ();
|
||||||
|
@ -523,6 +527,7 @@ static void pthread_exited(pid_t pid)
|
||||||
/* Yep, we have to signal the death. */
|
/* Yep, we have to signal the death. */
|
||||||
th->p_eventbuf.eventnum = TD_DEATH;
|
th->p_eventbuf.eventnum = TD_DEATH;
|
||||||
th->p_eventbuf.eventdata = th;
|
th->p_eventbuf.eventdata = th;
|
||||||
|
__pthread_last_event = th;
|
||||||
|
|
||||||
/* Now call the function to signal the event. */
|
/* Now call the function to signal the event. */
|
||||||
__linuxthreads_reap_event();
|
__linuxthreads_reap_event();
|
||||||
|
|
|
@ -1,5 +1,26 @@
|
||||||
1999-11-02 Ulrich Drepper <drepper@cygnus.com>
|
1999-11-02 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
|
* td_ta_thr_iter.c (td_ta_thr_iter): Optimize a bit. Read all
|
||||||
|
handles at once.
|
||||||
|
|
||||||
|
* thread_dbP.h (struct th_thragent): Add pthread_handle_num.
|
||||||
|
* td_ta_new.c: Initialize pthread_handle_num.
|
||||||
|
* td_ta_event_getmsg.c: If last event was already reported search
|
||||||
|
for another unreported event.
|
||||||
|
|
||||||
|
* td_thr_get_info.c (td_thr_get_info): Initialize ti_events.
|
||||||
|
|
||||||
|
* Makefile (libthread_db-routines): Add td_ta_set_event,
|
||||||
|
td_ta_event_getmsg, and td_ta_clear_event.
|
||||||
|
* td_ta_clear_event.c: New file.
|
||||||
|
* td_ta_event_getmsg.c: New file.
|
||||||
|
* td_ta_new.c: Get address of __pthread_last_event in target.
|
||||||
|
* td_ta_set_event.c: Don't overwrite old mask, set additional bits.
|
||||||
|
* td_thr_set_event.c: Likewise.
|
||||||
|
* td_thr_clear_event.c: Implement.
|
||||||
|
* thread_db.h: Declare td_ta_clear_event and td_ta_event_getmsg.
|
||||||
|
* thread_dbP.h (struct td_thragent): Add pthread_last_event.
|
||||||
|
|
||||||
* td_ta_new.c: Don't test for __pthread_threads_debug. Get address
|
* td_ta_new.c: Don't test for __pthread_threads_debug. Get address
|
||||||
of __pthread_threads_events and fail if this is not possible.
|
of __pthread_threads_events and fail if this is not possible.
|
||||||
* td_ta_event_addr.c: Implement.
|
* td_ta_event_addr.c: Implement.
|
||||||
|
|
|
@ -37,7 +37,9 @@ libthread_db-routines = td_init td_log td_ta_delete td_ta_get_nthreads \
|
||||||
td_ta_setconcurrency td_ta_enable_stats \
|
td_ta_setconcurrency td_ta_enable_stats \
|
||||||
td_ta_reset_stats td_ta_get_stats td_ta_event_addr \
|
td_ta_reset_stats td_ta_get_stats td_ta_event_addr \
|
||||||
td_thr_event_enable td_thr_set_event \
|
td_thr_event_enable td_thr_set_event \
|
||||||
td_thr_clear_event td_thr_event_getmsg
|
td_thr_clear_event td_thr_event_getmsg \
|
||||||
|
td_ta_set_event td_ta_event_getmsg \
|
||||||
|
td_ta_clear_event
|
||||||
|
|
||||||
libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
|
libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Globally disable events.
|
||||||
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "thread_dbP.h"
|
||||||
|
|
||||||
|
|
||||||
|
td_err_e
|
||||||
|
td_ta_clear_event (ta, event)
|
||||||
|
const td_thragent_t *ta;
|
||||||
|
td_thr_events_t *event;
|
||||||
|
{
|
||||||
|
td_thr_events_t old_event;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
LOG (__FUNCTION__);
|
||||||
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdread (ta->ph, ta->pthread_threads_eventsp,
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Remove the set bits in. */
|
||||||
|
for (i = 0; i < TD_EVENTSIZE; ++i)
|
||||||
|
old_event.event_bits[i] &= ~event->event_bits[i];
|
||||||
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp,
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
return TD_OK;
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/* Retrieve event.
|
||||||
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "thread_dbP.h"
|
||||||
|
|
||||||
|
|
||||||
|
td_err_e
|
||||||
|
td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg)
|
||||||
|
{
|
||||||
|
/* XXX I cannot think of another way but using a static variable. */
|
||||||
|
static td_thrhandle_t th;
|
||||||
|
td_eventbuf_t event;
|
||||||
|
psaddr_t addr;
|
||||||
|
|
||||||
|
LOG (__FUNCTION__);
|
||||||
|
|
||||||
|
/* Get the pointer to the thread descriptor with the last event. */
|
||||||
|
if (ps_pdread (ta->ph, ta->pthread_last_event,
|
||||||
|
&addr, sizeof (void *)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* If the pointer is NULL no event occurred. */
|
||||||
|
if (addr == 0)
|
||||||
|
return TD_NOMSG;
|
||||||
|
|
||||||
|
/* Read the even structure from the target. */
|
||||||
|
if (ps_pdread (ta->ph,
|
||||||
|
((char *) addr
|
||||||
|
+ offsetof (struct _pthread_descr_struct, p_eventbuf)),
|
||||||
|
&event, sizeof (td_eventbuf_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Check whether an event occurred. */
|
||||||
|
if (event.eventnum == TD_EVENT_NONE)
|
||||||
|
{
|
||||||
|
/* Oh well, this means the last event was already read. So
|
||||||
|
we have to look for any other event. */
|
||||||
|
struct pthread_handle_struct handles[ta->pthread_threads_max];
|
||||||
|
int num;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Read the number of currently active threads. */
|
||||||
|
if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
|
||||||
|
!= PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Now read the handles. */
|
||||||
|
if (ps_pdread (ta->ph, ta->handles, handles,
|
||||||
|
ta->pthread_threads_max * sizeof (handles[0])) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
for (i = 0; i < ta->pthread_threads_max && num > 0; ++i)
|
||||||
|
{
|
||||||
|
if (handles[i].h_descr == NULL)
|
||||||
|
/* No entry here. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* First count this active thread. */
|
||||||
|
--num;
|
||||||
|
|
||||||
|
if (handles[i].h_descr == addr)
|
||||||
|
/* We already handled this. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Read the event data for this thread. */
|
||||||
|
if (ps_pdread (ta->ph,
|
||||||
|
((char *) handles[i].h_descr
|
||||||
|
+ offsetof (struct _pthread_descr_struct,
|
||||||
|
p_eventbuf)),
|
||||||
|
&event, sizeof (td_eventbuf_t)) != PS_OK)
|
||||||
|
return TD_ERR;
|
||||||
|
|
||||||
|
if (event.eventnum != TD_EVENT_NONE)
|
||||||
|
{
|
||||||
|
/* We found a thread with an unreported event. */
|
||||||
|
addr = handles[i].h_descr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we haven't found any other event signal this to the user. */
|
||||||
|
if (event.eventnum == TD_EVENT_NONE)
|
||||||
|
return TD_NOMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate the thread descriptor. */
|
||||||
|
th.th_ta_p = (td_thragent_t *) ta;
|
||||||
|
th.th_unique = addr;
|
||||||
|
|
||||||
|
/* Fill the user's data structure. */
|
||||||
|
msg->event = event.eventnum;
|
||||||
|
msg->th_p = &th;
|
||||||
|
msg->msg.data = (uintptr_t) event.eventdata;
|
||||||
|
|
||||||
|
/* And clear the event message in the target. */
|
||||||
|
memset (&event, '\0', sizeof (td_eventbuf_t));
|
||||||
|
if (ps_pdwrite (ta->ph,
|
||||||
|
((char *) addr
|
||||||
|
+ offsetof (struct _pthread_descr_struct, p_eventbuf)),
|
||||||
|
&event, sizeof (td_eventbuf_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
return TD_OK;
|
||||||
|
}
|
|
@ -51,15 +51,29 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
|
||||||
/* Remember the address. */
|
/* Remember the address. */
|
||||||
(*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr;
|
(*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr;
|
||||||
|
|
||||||
/* See whether the library contains the necessary symbols. */
|
/* Get the pointer to the variable pointing to the thread descriptor
|
||||||
if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_handles",
|
with the last event. */
|
||||||
&addr) != PS_OK)
|
if (ps_pglobal_lookup (ps, LIBPTHREAD_SO,
|
||||||
|
"__pthread_last_event",
|
||||||
|
&(*ta)->pthread_last_event) != PS_OK)
|
||||||
{
|
{
|
||||||
free_return:
|
free_return:
|
||||||
free (*ta);
|
free (*ta);
|
||||||
return TD_ERR;
|
return TD_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the pointer to the variable containing the number of active
|
||||||
|
threads. */
|
||||||
|
if (ps_pglobal_lookup (ps, LIBPTHREAD_SO,
|
||||||
|
"__pthread_handles_num",
|
||||||
|
&(*ta)->pthread_handles_num) != PS_OK)
|
||||||
|
goto free_return;
|
||||||
|
|
||||||
|
/* See whether the library contains the necessary symbols. */
|
||||||
|
if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_handles",
|
||||||
|
&addr) != PS_OK)
|
||||||
|
goto free_return;
|
||||||
|
|
||||||
(*ta)->handles = (struct pthread_handle_struct *) addr;
|
(*ta)->handles = (struct pthread_handle_struct *) addr;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,23 @@ td_ta_set_event (ta, event)
|
||||||
const td_thragent_t *ta;
|
const td_thragent_t *ta;
|
||||||
td_thr_events_t *event;
|
td_thr_events_t *event;
|
||||||
{
|
{
|
||||||
|
td_thr_events_t old_event;
|
||||||
|
int i;
|
||||||
|
|
||||||
LOG (__FUNCTION__);
|
LOG (__FUNCTION__);
|
||||||
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdread (ta->ph, ta->pthread_threads_eventsp,
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Or the new bits in. */
|
||||||
|
for (i = 0; i < TD_EVENTSIZE; ++i)
|
||||||
|
old_event.event_bits[i] |= event->event_bits[i];
|
||||||
|
|
||||||
/* Write the new value into the thread data structure. */
|
/* Write the new value into the thread data structure. */
|
||||||
if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp,
|
if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp,
|
||||||
event, sizeof (td_thrhandle_t)) != PS_OK)
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
return TD_ERR; /* XXX Other error value? */
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
return TD_OK;
|
return TD_OK;
|
||||||
|
|
|
@ -26,64 +26,72 @@ td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback,
|
||||||
void *cbdata_p, td_thr_state_e state, int ti_pri,
|
void *cbdata_p, td_thr_state_e state, int ti_pri,
|
||||||
sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
|
sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
|
||||||
{
|
{
|
||||||
struct pthread_handle_struct *handles = ta->handles;
|
|
||||||
int pthread_threads_max = ta->pthread_threads_max;
|
int pthread_threads_max = ta->pthread_threads_max;
|
||||||
size_t sizeof_descr = ta->sizeof_descr;
|
size_t sizeof_descr = ta->sizeof_descr;
|
||||||
|
struct pthread_handle_struct phc[pthread_threads_max];
|
||||||
|
int num;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
LOG (__FUNCTION__);
|
LOG (__FUNCTION__);
|
||||||
|
|
||||||
|
/* Read all the descriptors. */
|
||||||
|
if (ps_pdread (ta->ph, ta->handles, phc,
|
||||||
|
sizeof (struct pthread_handle_struct) * pthread_threads_max)
|
||||||
|
!= PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Read the number of currently active threads. */
|
||||||
|
if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
|
||||||
|
!= PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
/* Now get all descriptors, one after the other. */
|
/* Now get all descriptors, one after the other. */
|
||||||
for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles)
|
for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt)
|
||||||
{
|
if (phc[cnt].h_descr != NULL)
|
||||||
struct pthread_handle_struct phc;
|
{
|
||||||
|
struct _pthread_descr_struct pds;
|
||||||
|
td_thrhandle_t th;
|
||||||
|
|
||||||
if (ps_pdread (ta->ph, handles, &phc,
|
/* First count this active thread. */
|
||||||
sizeof (struct pthread_handle_struct)) != PS_OK)
|
--num;
|
||||||
return TD_ERR; /* XXX Other error value? */
|
|
||||||
|
|
||||||
if (phc.h_descr != NULL)
|
if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr)
|
||||||
{
|
!= PS_OK)
|
||||||
struct _pthread_descr_struct pds;
|
return TD_ERR; /* XXX Other error value? */
|
||||||
td_thrhandle_t th;
|
|
||||||
|
|
||||||
if (ps_pdread (ta->ph, phc.h_descr, &pds, sizeof_descr) != PS_OK)
|
/* The manager thread must be handled special. The descriptor
|
||||||
return TD_ERR; /* XXX Other error value? */
|
exists but the thread only gets created when the first
|
||||||
|
`pthread_create' call is issued. A clear indication that
|
||||||
|
this happened is when the p_pid field is non-zero. */
|
||||||
|
if (cnt == 1 && pds.p_pid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* The manager thread must be handled special. The descriptor
|
/* Now test whether this thread matches the specified
|
||||||
exists but the thread only gets created when the first
|
conditions. */
|
||||||
`pthread_create' call is issued. A clear indication that
|
|
||||||
this happened is when the p_pid field is non-zero. */
|
|
||||||
if (cnt == 1 && pds.p_pid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Now test whether this thread matches the specified
|
/* Only if the priority level is as high or higher. */
|
||||||
conditions. */
|
if (pds.p_priority < ti_pri)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Only if the priority level is as high or higher. */
|
/* Test the state.
|
||||||
if (pds.p_priority < ti_pri)
|
XXX This is incomplete. */
|
||||||
continue;
|
if (state != TD_THR_ANY_STATE)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Test the state.
|
/* XXX For now we ignore threads which are not running anymore.
|
||||||
XXX This is incomplete. */
|
The reason is that gdb tries to get the registers and fails.
|
||||||
if (state != TD_THR_ANY_STATE)
|
In future we should have a special mode of the thread library
|
||||||
continue;
|
in which we keep the process around until the actual join
|
||||||
|
operation happened. */
|
||||||
|
if (pds.p_exited != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* XXX For now we ignore threads which are not running anymore.
|
/* Yep, it matches. Call the callback function. */
|
||||||
The reason is that gdb tries to get the registers and fails.
|
th.th_ta_p = (td_thragent_t *) ta;
|
||||||
In future we should have a special mode of the thread library
|
th.th_unique = phc[cnt].h_descr;
|
||||||
in which we keep the process around until the actual join
|
if (callback (&th, cbdata_p) != 0)
|
||||||
operation happened. */
|
return TD_DBERR;
|
||||||
if (pds.p_exited != 0)
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Yep, it matches. Call the callback function. */
|
|
||||||
th.th_ta_p = (td_thragent_t *) ta;
|
|
||||||
th.th_unique = phc.h_descr;
|
|
||||||
if (callback (&th, cbdata_p) != 0)
|
|
||||||
return TD_DBERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TD_OK;
|
return TD_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Disable specific event.
|
/* Disable specific event for thread.
|
||||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
|
||||||
|
@ -18,13 +18,40 @@
|
||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "thread_dbP.h"
|
#include "thread_dbP.h"
|
||||||
|
|
||||||
|
|
||||||
td_err_e
|
td_err_e
|
||||||
td_thr_clear_event (const td_thrhandle_t *th, td_thr_events_t *event)
|
td_thr_clear_event (th, event)
|
||||||
|
const td_thrhandle_t *th;
|
||||||
|
td_thr_events_t *event;
|
||||||
{
|
{
|
||||||
/* XXX We have to figure out what has to be done. */
|
td_thr_events_t old_event;
|
||||||
|
int i;
|
||||||
|
|
||||||
LOG (__FUNCTION__);
|
LOG (__FUNCTION__);
|
||||||
return TD_NOCAPAB;
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdread (th->th_ta_p->ph,
|
||||||
|
((char *) th->th_unique
|
||||||
|
+ offsetof (struct _pthread_descr_struct,
|
||||||
|
p_eventbuf.eventmask)),
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Remove the set bits in. */
|
||||||
|
for (i = 0; i < TD_EVENTSIZE; ++i)
|
||||||
|
old_event.event_bits[i] &= ~event->event_bits[i];
|
||||||
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdwrite (th->th_ta_p->ph,
|
||||||
|
((char *) th->th_unique
|
||||||
|
+ offsetof (struct _pthread_descr_struct,
|
||||||
|
p_eventbuf.eventmask)),
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
return TD_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "thread_dbP.h"
|
#include "thread_dbP.h"
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
|
||||||
infop->ti_lid = pds.p_pid;
|
infop->ti_lid = pds.p_pid;
|
||||||
infop->ti_ta_p = th->th_ta_p;
|
infop->ti_ta_p = th->th_ta_p;
|
||||||
infop->ti_startfunc = pds.p_start_args.start_routine;
|
infop->ti_startfunc = pds.p_start_args.start_routine;
|
||||||
|
memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask,
|
||||||
|
sizeof (td_thr_events_t));
|
||||||
|
|
||||||
return TD_OK;
|
return TD_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,29 @@ td_thr_set_event (th, event)
|
||||||
const td_thrhandle_t *th;
|
const td_thrhandle_t *th;
|
||||||
td_thr_events_t *event;
|
td_thr_events_t *event;
|
||||||
{
|
{
|
||||||
|
td_thr_events_t old_event;
|
||||||
|
int i;
|
||||||
|
|
||||||
LOG (__FUNCTION__);
|
LOG (__FUNCTION__);
|
||||||
|
|
||||||
|
/* Write the new value into the thread data structure. */
|
||||||
|
if (ps_pdread (th->th_ta_p->ph,
|
||||||
|
((char *) th->th_unique
|
||||||
|
+ offsetof (struct _pthread_descr_struct,
|
||||||
|
p_eventbuf.eventmask)),
|
||||||
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
|
/* Or the new bits in. */
|
||||||
|
for (i = 0; i < TD_EVENTSIZE; ++i)
|
||||||
|
old_event.event_bits[i] |= event->event_bits[i];
|
||||||
|
|
||||||
/* Write the new value into the thread data structure. */
|
/* Write the new value into the thread data structure. */
|
||||||
if (ps_pdwrite (th->th_ta_p->ph,
|
if (ps_pdwrite (th->th_ta_p->ph,
|
||||||
((char *) th->th_unique
|
((char *) th->th_unique
|
||||||
+ offsetof (struct _pthread_descr_struct,
|
+ offsetof (struct _pthread_descr_struct,
|
||||||
p_eventbuf.eventmask)),
|
p_eventbuf.eventmask)),
|
||||||
event, sizeof (td_thrhandle_t)) != PS_OK)
|
&old_event, sizeof (td_thrhandle_t)) != PS_OK)
|
||||||
return TD_ERR; /* XXX Other error value? */
|
return TD_ERR; /* XXX Other error value? */
|
||||||
|
|
||||||
return TD_OK;
|
return TD_OK;
|
||||||
|
|
|
@ -331,10 +331,18 @@ extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
|
||||||
extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
|
extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
|
||||||
td_event_e __event, td_notify_t *__ptr);
|
td_event_e __event, td_notify_t *__ptr);
|
||||||
|
|
||||||
/* Enable EVENT for all threads. */
|
/* Enable EVENT in global mask. */
|
||||||
extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
|
extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
|
||||||
td_thr_events_t *__event);
|
td_thr_events_t *__event);
|
||||||
|
|
||||||
|
/* Disable EVENT in global mask. */
|
||||||
|
extern td_err_e td_ta_clear_event (const td_thragent_t *__ta,
|
||||||
|
td_thr_events_t *__event);
|
||||||
|
|
||||||
|
/* Return information about last event. */
|
||||||
|
extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta,
|
||||||
|
td_event_msg_t *msg);
|
||||||
|
|
||||||
|
|
||||||
/* Set suggested concurrency level for process associated with TA. */
|
/* Set suggested concurrency level for process associated with TA. */
|
||||||
extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
|
extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
|
||||||
|
|
|
@ -41,6 +41,12 @@ struct td_thragent
|
||||||
|
|
||||||
/* Pointer to the `__pthread_threads_events' variable in the target. */
|
/* Pointer to the `__pthread_threads_events' variable in the target. */
|
||||||
psaddr_t pthread_threads_eventsp;
|
psaddr_t pthread_threads_eventsp;
|
||||||
|
|
||||||
|
/* Pointer to the `__pthread_last_event' variable in the target. */
|
||||||
|
psaddr_t pthread_last_event;
|
||||||
|
|
||||||
|
/* Pointer to the `__pthread_handles_num' variable. */
|
||||||
|
psaddr_t pthread_handles_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue