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