| /* Get thread information. |
| Copyright (C) 1999-2003,2007,2009 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 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 |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; 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_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) |
| { |
| td_err_e err; |
| void *copy; |
| psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events; |
| |
| LOG ("td_thr_get_info"); |
| |
| if (th->th_unique == 0) |
| { |
| /* Special case for the main thread before initialization. */ |
| copy = NULL; |
| tls = 0; |
| cancelhandling = 0; |
| schedpolicy = SCHED_OTHER; |
| schedprio = 0; |
| tid = 0; |
| err = DB_GET_VALUE (report_events, th->th_ta_p, |
| __nptl_initial_report_events, 0); |
| } |
| else |
| { |
| /* Copy the whole descriptor in once so we can access the several |
| fields locally. Excess copying in one go is much better than |
| multiple ps_pdread calls. */ |
| err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread); |
| if (err != TD_OK) |
| return err; |
| |
| err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique, |
| pthread, specific, 0); |
| if (err != TD_OK) |
| return err; |
| |
| err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread, |
| schedpolicy, 0); |
| if (err != TD_OK) |
| return err; |
| err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread, |
| schedparam_sched_priority, 0); |
| if (err != TD_OK) |
| return err; |
| err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0); |
| if (err != TD_OK) |
| return err; |
| err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread, |
| cancelhandling, 0); |
| if (err != TD_OK) |
| return err; |
| err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread, |
| report_events, 0); |
| } |
| if (err != TD_OK) |
| return err; |
| |
| /* Fill in information. Clear first to provide reproducable |
| results for the fields we do not fill in. */ |
| memset (infop, '\0', sizeof (td_thrinfo_t)); |
| |
| infop->ti_tid = (thread_t) th->th_unique; |
| infop->ti_tls = (char *) tls; |
| infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER |
| ? 0 : (uintptr_t) schedprio); |
| infop->ti_type = TD_THR_USER; |
| |
| if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0) |
| /* XXX For now there is no way to get more information. */ |
| infop->ti_state = TD_THR_ACTIVE; |
| else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) |
| infop->ti_state = TD_THR_ZOMBIE; |
| else |
| infop->ti_state = TD_THR_UNKNOWN; |
| |
| /* Initialization which are the same in both cases. */ |
| infop->ti_ta_p = th->th_ta_p; |
| infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid; |
| infop->ti_traceme = report_events != 0; |
| |
| if (copy != NULL) |
| err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread, |
| start_routine, 0); |
| if (copy != NULL && err == TD_OK) |
| { |
| uint32_t idx; |
| for (idx = 0; idx < TD_EVENTSIZE; ++idx) |
| { |
| psaddr_t word; |
| err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread, |
| eventbuf_eventmask_event_bits, idx); |
| if (err != TD_OK) |
| break; |
| infop->ti_events.event_bits[idx] = (uintptr_t) word; |
| } |
| if (err == TD_NOAPLIC) |
| memset (&infop->ti_events.event_bits[idx], 0, |
| (TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]); |
| } |
| |
| return err; |
| } |