/* This testcase is part of GDB, the GNU debugger. Copyright 2018-2023 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include /* This defines the number of threads to spawn. */ #define THREADCOUNT 4 /* Global barrier type to control synchronization between threads. */ static pthread_barrier_t print_barrier; /* Define global thread identifiers. */ static pthread_t threads[THREADCOUNT]; /* Hold values for each thread at the index supplied to the thread on creation. */ static int thread_ids[THREADCOUNT]; /* Find the value associated with the calling thread. */ static int get_value () { for (int tid = 0; tid < THREADCOUNT; ++tid) { if (pthread_equal (threads[tid], pthread_self ())) return thread_ids[tid]; } /* Value for the main thread. */ return 1; } /* Return the nth Fibonacci number. */ static unsigned long fast_fib (unsigned int n) { int a = 0; int b = 1; int t; for (unsigned int i = 0; i < n; ++i) { t = b; b = a + b; a = t; } return a; } /* Encapsulate the synchronization of the threads. Perform a barrier before and after the computation. */ static void * thread_function (void *args) { int tid = *((int *) args); int status = pthread_barrier_wait (&print_barrier); if (status == PTHREAD_BARRIER_SERIAL_THREAD) printf ("All threads entering compute region\n"); unsigned long result = fast_fib (100); /* testmarker01 */ status = pthread_barrier_wait (&print_barrier); if (status == PTHREAD_BARRIER_SERIAL_THREAD) printf ("All threads outputting results\n"); pthread_barrier_wait (&print_barrier); printf ("Thread %d Result: %lu\n", tid, result); } int main (void) { int err = pthread_barrier_init (&print_barrier, NULL, THREADCOUNT); if (err != 0) { fprintf (stderr, "Barrier creation failed\n"); return EXIT_FAILURE; } /* Create the worker threads (main). */ printf ("Spawning worker threads\n"); for (int tid = 0; tid < THREADCOUNT; ++tid) { /* Add 2 so the value maps to the debugger's thread identifiers. */ thread_ids[tid] = tid + 2; /* prethreadcreationmarker */ err = pthread_create (&threads[tid], NULL, thread_function, (void *) &thread_ids[tid]); if (err != 0) { fprintf (stderr, "Thread creation failed\n"); return EXIT_FAILURE; } } /* Wait for the threads to complete then exit. */ for (int tid = 0; tid < THREADCOUNT; ++tid) pthread_join (threads[tid], NULL); return EXIT_SUCCESS; }