OSDN Git Service

Add the linuxthreads Makefiles too
[uclinux-h8/uClibc.git] / libpthread / linuxthreads_db / td_ta_thr_iter.c
1 /* Iterate over a process's threads.
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include "thread_dbP.h"
22 #include "../linuxthreads/internals.h"
23 #include <alloca.h>
24
25 static int
26 handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback,
27               void *cbdata_p, td_thr_state_e state, int ti_pri,
28               size_t cnt, pthread_descr descr)
29 {
30   struct _pthread_descr_struct pds;
31   size_t sizeof_descr = ta->sizeof_descr;
32   td_thrhandle_t th;
33
34   if (descr == NULL)
35     {
36       /* No descriptor (yet).  */
37       if (cnt == 0)
38         {
39           /* This is the main thread.  Create a fake descriptor.  */
40           memset (&pds, '\0', sizeof (pds));
41
42           /* Empty thread descriptor the thread library would create.  */
43           pds.p_self = &pds;
44           pds.p_nextlive = pds.p_prevlive = &pds;
45           pds.p_tid = PTHREAD_THREADS_MAX;
46           /* The init code also sets up p_lock, p_errnop, p_herrnop, and
47              p_userstack but this should not be necessary here.  */
48
49           th.th_ta_p = (td_thragent_t *) ta;
50           th.th_unique = NULL;
51           if (callback (&th, cbdata_p) != 0)
52             return TD_DBERR;
53
54           /* All done successfully.  */
55           return TD_OK;
56         }
57       else if (cnt == 1)
58         /* The manager is not yet started.  No big deal.  */
59         return TD_OK;
60       else
61         /* For every other thread this should not happen.  */
62         return TD_ERR;
63     }
64
65   if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK)
66     return TD_ERR;      /* XXX Other error value?  */
67
68   /* The manager thread must be handled special.  The descriptor
69      exists but the thread only gets created when the first
70      `pthread_create' call is issued.  A clear indication that this
71      happened is when the p_pid field is non-zero.  */
72   if (cnt == 1 && pds.p_pid == 0)
73     return TD_OK;
74
75   /* Now test whether this thread matches the specified
76      conditions.  */
77
78   /* Only if the priority level is as high or higher.  */
79   if (pds.p_priority < ti_pri)
80     return TD_OK;
81
82   /* Test the state.
83      XXX This is incomplete.  */
84   if (state != TD_THR_ANY_STATE)
85     return TD_OK;
86
87   /* XXX For now we ignore threads which are not running anymore.
88      The reason is that gdb tries to get the registers and fails.
89      In future we should have a special mode of the thread library
90      in which we keep the process around until the actual join
91      operation happened.  */
92   if (pds.p_exited != 0)
93     return TD_OK;
94
95   /* Yep, it matches.  Call the callback function.  */
96   th.th_ta_p = (td_thragent_t *) ta;
97   th.th_unique = descr;
98   if (callback (&th, cbdata_p) != 0)
99     return TD_DBERR;
100
101   /* All done successfully.  */
102   return TD_OK;
103 }
104
105
106 td_err_e
107 td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback,
108                 void *cbdata_p, td_thr_state_e state, int ti_pri,
109                 sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
110 {
111   int pthread_threads_max;
112   struct pthread_handle_struct *phc;
113   td_err_e result = TD_OK;
114   int cnt;
115 #ifdef ALL_THREADS_STOPPED
116   int num;
117 #else
118 # define num 1
119 #endif
120
121   LOG ("td_ta_thr_iter");
122
123   /* Test whether the TA parameter is ok.  */
124   if (! ta_ok (ta))
125     return TD_BADTA;
126
127   pthread_threads_max = ta->pthread_threads_max;
128   phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0])
129                                                  * pthread_threads_max);
130
131   /* First read only the main thread and manager thread information.  */
132   if (ps_pdread (ta->ph, ta->handles, phc,
133                  sizeof (struct pthread_handle_struct) * 2) != PS_OK)
134     return TD_ERR;      /* XXX Other error value?  */
135
136   /* Now handle these descriptors.  */
137   result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0,
138                          phc[0].h_descr);
139   if (result != TD_OK)
140     return result;
141   result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1,
142                          phc[1].h_descr);
143   if (result != TD_OK)
144     return result;
145
146   /* Read all the descriptors.  */
147   if (ps_pdread (ta->ph, ta->handles + 2, &phc[2],
148                  (sizeof (struct pthread_handle_struct)
149                   * (pthread_threads_max - 2))) != PS_OK)
150     return TD_ERR;      /* XXX Other error value?  */
151
152 #ifdef ALL_THREADS_STOPPED
153   /* Read the number of currently active threads.  */
154   if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK)
155     return TD_ERR;      /* XXX Other error value?  */
156 #endif
157
158   /* Now get all descriptors, one after the other.  */
159   for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt)
160     if (phc[cnt].h_descr != NULL)
161       {
162 #ifdef ALL_THREADS_STOPPED
163         /* First count this active thread.  */
164         --num;
165 #endif
166
167         result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt,
168                                phc[cnt].h_descr);
169         if (result != TD_OK)
170           break;
171       }
172
173   return result;
174 }