1 | /* Iterate over a process's threads. |
---|
2 | Copyright (C) 1999, 2000 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 <alloca.h> |
---|
23 | |
---|
24 | static int |
---|
25 | handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback, |
---|
26 | void *cbdata_p, td_thr_state_e state, int ti_pri, |
---|
27 | size_t cnt, pthread_descr descr) |
---|
28 | { |
---|
29 | struct _pthread_descr_struct pds; |
---|
30 | size_t sizeof_descr = ta->sizeof_descr; |
---|
31 | td_thrhandle_t th; |
---|
32 | |
---|
33 | if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK) |
---|
34 | return TD_ERR; /* XXX Other error value? */ |
---|
35 | |
---|
36 | /* The manager thread must be handled special. The descriptor |
---|
37 | exists but the thread only gets created when the first |
---|
38 | `pthread_create' call is issued. A clear indication that this |
---|
39 | happened is when the p_pid field is non-zero. */ |
---|
40 | if (cnt == 1 && pds.p_pid == 0) |
---|
41 | return TD_OK; |
---|
42 | |
---|
43 | /* Now test whether this thread matches the specified |
---|
44 | conditions. */ |
---|
45 | |
---|
46 | /* Only if the priority level is as high or higher. */ |
---|
47 | if (pds.p_priority < ti_pri) |
---|
48 | return TD_OK; |
---|
49 | |
---|
50 | /* Test the state. |
---|
51 | XXX This is incomplete. */ |
---|
52 | if (state != TD_THR_ANY_STATE) |
---|
53 | return TD_OK; |
---|
54 | |
---|
55 | /* XXX For now we ignore threads which are not running anymore. |
---|
56 | The reason is that gdb tries to get the registers and fails. |
---|
57 | In future we should have a special mode of the thread library |
---|
58 | in which we keep the process around until the actual join |
---|
59 | operation happened. */ |
---|
60 | if (pds.p_exited != 0) |
---|
61 | return TD_OK; |
---|
62 | |
---|
63 | /* Yep, it matches. Call the callback function. */ |
---|
64 | th.th_ta_p = (td_thragent_t *) ta; |
---|
65 | th.th_unique = descr; |
---|
66 | if (callback (&th, cbdata_p) != 0) |
---|
67 | return TD_DBERR; |
---|
68 | |
---|
69 | /* All done successfully. */ |
---|
70 | return TD_OK; |
---|
71 | } |
---|
72 | |
---|
73 | |
---|
74 | td_err_e |
---|
75 | td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, |
---|
76 | void *cbdata_p, td_thr_state_e state, int ti_pri, |
---|
77 | sigset_t *ti_sigmask_p, unsigned int ti_user_flags) |
---|
78 | { |
---|
79 | int pthread_threads_max; |
---|
80 | struct pthread_handle_struct *phc; |
---|
81 | td_err_e result = TD_OK; |
---|
82 | int cnt; |
---|
83 | #ifdef ALL_THREADS_STOPPED |
---|
84 | int num; |
---|
85 | #else |
---|
86 | # define num 1 |
---|
87 | #endif |
---|
88 | |
---|
89 | LOG ("td_ta_thr_iter"); |
---|
90 | |
---|
91 | /* Test whether the TA parameter is ok. */ |
---|
92 | if (! ta_ok (ta)) |
---|
93 | return TD_BADTA; |
---|
94 | |
---|
95 | pthread_threads_max = ta->pthread_threads_max; |
---|
96 | phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) |
---|
97 | * pthread_threads_max); |
---|
98 | |
---|
99 | /* First read only the main thread and manager thread information. */ |
---|
100 | if (ps_pdread (ta->ph, ta->handles, phc, |
---|
101 | sizeof (struct pthread_handle_struct) * 2) != PS_OK) |
---|
102 | return TD_ERR; /* XXX Other error value? */ |
---|
103 | |
---|
104 | /* Now handle these descriptors. */ |
---|
105 | result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0, |
---|
106 | phc[0].h_descr); |
---|
107 | if (result != TD_OK) |
---|
108 | return result; |
---|
109 | result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1, |
---|
110 | phc[1].h_descr); |
---|
111 | if (result != TD_OK) |
---|
112 | return result; |
---|
113 | |
---|
114 | /* Read all the descriptors. */ |
---|
115 | if (ps_pdread (ta->ph, ta->handles + 2, &phc[2], |
---|
116 | (sizeof (struct pthread_handle_struct) |
---|
117 | * (pthread_threads_max - 2))) != PS_OK) |
---|
118 | return TD_ERR; /* XXX Other error value? */ |
---|
119 | |
---|
120 | #ifdef ALL_THREADS_STOPPED |
---|
121 | /* Read the number of currently active threads. */ |
---|
122 | if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) |
---|
123 | return TD_ERR; /* XXX Other error value? */ |
---|
124 | #endif |
---|
125 | |
---|
126 | /* Now get all descriptors, one after the other. */ |
---|
127 | for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt) |
---|
128 | if (phc[cnt].h_descr != NULL) |
---|
129 | { |
---|
130 | #ifdef ALL_THREADS_STOPPED |
---|
131 | /* First count this active thread. */ |
---|
132 | --num; |
---|
133 | #endif |
---|
134 | |
---|
135 | result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt, |
---|
136 | phc[cnt].h_descr); |
---|
137 | if (result != TD_OK) |
---|
138 | break; |
---|
139 | } |
---|
140 | |
---|
141 | return result; |
---|
142 | } |
---|