1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2023-2024 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Test can create at most this number of extra threads. */
24 /* For convenience. */
28 /* Controls a thread created by this test. */
29 struct thread_descriptor
31 /* The pthread handle. Not valid unless STARTED is true. */
34 /* This field is set to TRUE when a thread has been created, otherwise,
38 /* A condition variable and mutex, used for synchronising between the
39 worker thread and the main thread. */
41 pthread_mutex_t mutex
;
44 /* Keep track of worker threads. */
45 struct thread_descriptor threads
[MAX_THREADS
];
47 /* Worker thread function. Doesn't do much. Synchronise with the main
48 thread, mark the thread as started, and then block waiting for the main
49 thread. Once the main thread wakes us, this thread exits.
51 ARG is a thread_descriptor shared with the main thread. */
54 thread_function (void *arg
)
57 struct thread_descriptor
*thread
= (struct thread_descriptor
*) arg
;
59 /* Acquire the thread's lock. Initially the main thread holds this lock,
60 but releases it when the main thread enters a pthread_cond_wait. */
61 res
= pthread_mutex_lock (&thread
->mutex
);
64 /* Mark the thread as started. */
65 thread
->started
= TRUE
;
67 /* Signal the main thread to tell it we are started. The main thread
68 will still be blocked though as we hold the thread's lock. */
69 res
= pthread_cond_signal (&thread
->cond
);
72 /* Now wait until the main thread tells us to exit. By entering this
73 pthread_cond_wait we release the lock, which allows the main thread to
75 res
= pthread_cond_wait (&thread
->cond
, &thread
->mutex
);
78 /* The main thread woke us up. We reacquired the thread lock as we left
79 the pthread_cond_wait, so release the lock now. */
80 res
= pthread_mutex_unlock (&thread
->mutex
);
86 /* Start a new thread within the global THREADS array. Return true if a
87 new thread was started, otherwise return false. */
94 for (idx
= 0; idx
< MAX_THREADS
; ++idx
)
95 if (!threads
[idx
].started
)
98 if (idx
== MAX_THREADS
)
101 /* Acquire the thread lock before starting the new thread. */
102 res
= pthread_mutex_lock (&threads
[idx
].mutex
);
105 /* Start the new thread. */
106 res
= pthread_create (&threads
[idx
].thr
, NULL
,
107 thread_function
, &threads
[idx
]);
110 /* Unlock and wait. The thread signals us once it is ready. */
111 res
= pthread_cond_wait (&threads
[idx
].cond
, &threads
[idx
].mutex
);
114 /* The worker thread is now blocked in a pthread_cond_wait and we
115 reacquired the lock as we left our own pthread_cond_wait above. */
116 res
= pthread_mutex_unlock (&threads
[idx
].mutex
);
122 /* Stop a thread from within the global THREADS array. Return true if a
123 thread was stopped, otherwise return false. */
127 /* Look for a thread that is started. */
128 for (int idx
= 0; idx
< MAX_THREADS
; ++idx
)
129 if (threads
[idx
].started
)
133 /* Grab the thread lock. */
134 res
= pthread_mutex_lock (&threads
[idx
].mutex
);
137 /* Signal the worker thread, this wakes it up, but it can't exit
138 until it acquires the thread lock, which we currently hold. */
139 res
= pthread_cond_signal (&threads
[idx
].cond
);
142 /* Release the thread lock, this allows the worker thread to exit. */
143 res
= pthread_mutex_unlock (&threads
[idx
].mutex
);
146 /* Now wait for the thread to exit. */
148 res
= pthread_join (threads
[idx
].thr
, &retval
);
150 assert (retval
== NULL
);
152 /* Now the thread has exited, mark it as no longer started. */
153 assert (threads
[idx
].started
);
154 threads
[idx
].started
= FALSE
;
163 init_descriptor_array ()
165 for (int i
= 0; i
< MAX_THREADS
; ++i
)
169 threads
[i
].started
= FALSE
;
170 res
= pthread_cond_init (&threads
[i
].cond
, NULL
);
172 res
= pthread_mutex_init (&threads
[i
].mutex
, NULL
);
186 init_descriptor_array ();