(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl_db/td_ta_thr_iter.c

    1: /* Iterate over a process's threads.
    2:    Copyright (C) 1999,2000,2001,2002,2003,2004,2007
    3:         Free Software Foundation, Inc.
    4:    This file is part of the GNU C Library.
    5:    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
    6: 
    7:    The GNU C Library is free software; you can redistribute it and/or
    8:    modify it under the terms of the GNU Lesser General Public
    9:    License as published by the Free Software Foundation; either
   10:    version 2.1 of the License, or (at your option) any later version.
   11: 
   12:    The GNU C Library is distributed in the hope that it will be useful,
   13:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15:    Lesser General Public License for more details.
   16: 
   17:    You should have received a copy of the GNU Lesser General Public
   18:    License along with the GNU C Library; if not, write to the Free
   19:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   20:    02111-1307 USA.  */
   21: 
   22: #include "thread_dbP.h"
   23: 
   24: 
   25: static td_err_e
   26: iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
   27:                      void *cbdata_p, td_thr_state_e state, int ti_pri,
   28:                      psaddr_t head, bool fake_empty)
   29: {
   30:   td_err_e err;
   31:   psaddr_t next, ofs;
   32:   void *copy;
   33: 
   34:   /* Test the state.
   35:      XXX This is incomplete.  Normally this test should be in the loop.  */
   36:   if (state != TD_THR_ANY_STATE)
   37:     return TD_OK;
   38: 
   39:   err = DB_GET_FIELD (next, ta, head, list_t, next, 0);
   40:   if (err != TD_OK)
   41:     return err;
   42: 
   43:   if (next == 0 && fake_empty)
   44:     {
   45:       /* __pthread_initialize_minimal has not run.  There is just the main
   46:          thread to return.  We cannot rely on its thread register.  They
   47:          sometimes contain garbage that would confuse us, left by the
   48:          kernel at exec.  So if it looks like initialization is incomplete,
   49:          we only fake a special descriptor for the initial thread.  */
   50:       td_thrhandle_t th = { ta, 0 };
   51:       return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
   52:     }
   53: 
   54:   /* Cache the offset from struct pthread to its list_t member.  */
   55:   err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0);
   56:   if (err != TD_OK)
   57:     return err;
   58: 
   59:   if (ta->ta_sizeof_pthread == 0)
   60:     {
   61:       err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread);
   62:       if (err != TD_OK)
   63:         return err;
   64:     }
   65:   copy = __alloca (ta->ta_sizeof_pthread);
   66: 
   67:   while (next != head)
   68:     {
   69:       psaddr_t addr, schedpolicy, schedprio;
   70: 
   71:       addr = next - (ofs - (psaddr_t) 0);
   72:       if (next == 0 || addr == 0) /* Sanity check.  */
   73:         return TD_DBERR;
   74: 
   75:       /* Copy the whole descriptor in once so we can access the several
   76:          fields locally.  Excess copying in one go is much better than
   77:          multiple ps_pdread calls.  */
   78:       if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
   79:         return TD_ERR;
   80: 
   81:       err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
   82:                                 schedpolicy, 0);
   83:       if (err != TD_OK)
   84:         break;
   85:       err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
   86:                                 schedparam_sched_priority, 0);
   87:       if (err != TD_OK)
   88:         break;
   89: 
   90:       /* Now test whether this thread matches the specified conditions.  */
   91: 
   92:       /* Only if the priority level is as high or higher.  */
   93:       int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
   94:                        ? 0 : (uintptr_t) schedprio);
   95:       if (descr_pri >= ti_pri)
   96:         {
   97:           /* Yep, it matches.  Call the callback function.  */
   98:           td_thrhandle_t th;
   99:           th.th_ta_p = (td_thragent_t *) ta;
  100:           th.th_unique = addr;
  101:           if (callback (&th, cbdata_p) != 0)
  102:             return TD_DBERR;
  103:         }
  104: 
  105:       /* Get the pointer to the next element.  */
  106:       err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t,
  107:                                 next, 0);
  108:       if (err != TD_OK)
  109:         break;
  110:     }
  111: 
  112:   return err;
  113: }
  114: 
  115: 
  116: td_err_e
  117: td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
  118:                 void *cbdata_p, td_thr_state_e state, int ti_pri,
  119:                 sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
  120: {
  121:   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
  122:   td_err_e err;
  123:   psaddr_t list = 0;
  124: 
  125:   LOG ("td_ta_thr_iter");
  126: 
  127:   /* Test whether the TA parameter is ok.  */
  128:   if (! ta_ok (ta))
  129:     return TD_BADTA;
  130: 
  131:   /* The thread library keeps two lists for the running threads.  One
  132:      list contains the thread which are using user-provided stacks
  133:      (this includes the main thread) and the other includes the
  134:      threads for which the thread library allocated the stacks.  We
  135:      have to iterate over both lists separately.  We start with the
  136:      list of threads with user-defined stacks.  */
  137: 
  138:   err = DB_GET_SYMBOL (list, ta, __stack_user);
  139:   if (err == TD_OK)
  140:     err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
  141:                                list, true);
  142: 
  143:   /* And the threads with stacks allocated by the implementation.  */
  144:   if (err == TD_OK)
  145:     err = DB_GET_SYMBOL (list, ta, stack_used);
  146:   if (err == TD_OK)
  147:     err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
  148:                                list, false);
  149: 
  150:   return err;
  151: }
Syntax (Markdown)