1/* This testcase is part of GDB, the GNU debugger. 2 3 Copyright 2018-2023 Free Software Foundation, Inc. 4 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. 9 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. 14 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/>. */ 17 18#include <stdio.h> 19#include <stdlib.h> 20#include <pthread.h> 21 22/* This defines the number of threads to spawn. */ 23#define THREADCOUNT 4 24 25/* Global barrier type to control synchronization between threads. */ 26static pthread_barrier_t print_barrier; 27 28/* Define global thread identifiers. */ 29static pthread_t threads[THREADCOUNT]; 30 31/* Hold values for each thread at the index supplied to the thread 32 on creation. */ 33static int thread_ids[THREADCOUNT]; 34 35/* Find the value associated with the calling thread. */ 36static int 37get_value () 38{ 39 for (int tid = 0; tid < THREADCOUNT; ++tid) 40 { 41 if (pthread_equal (threads[tid], pthread_self ())) 42 return thread_ids[tid]; 43 } 44 /* Value for the main thread. */ 45 return 1; 46} 47 48/* Return the nth Fibonacci number. */ 49static unsigned long 50fast_fib (unsigned int n) 51{ 52 int a = 0; 53 int b = 1; 54 int t; 55 for (unsigned int i = 0; i < n; ++i) 56 { 57 t = b; 58 b = a + b; 59 a = t; 60 } 61 return a; 62} 63 64/* Encapsulate the synchronization of the threads. Perform a barrier before 65 and after the computation. */ 66static void * 67thread_function (void *args) 68{ 69 int tid = *((int *) args); 70 int status = pthread_barrier_wait (&print_barrier); 71 if (status == PTHREAD_BARRIER_SERIAL_THREAD) 72 printf ("All threads entering compute region\n"); 73 74 unsigned long result = fast_fib (100); /* testmarker01 */ 75 status = pthread_barrier_wait (&print_barrier); 76 if (status == PTHREAD_BARRIER_SERIAL_THREAD) 77 printf ("All threads outputting results\n"); 78 79 pthread_barrier_wait (&print_barrier); 80 printf ("Thread %d Result: %lu\n", tid, result); 81} 82 83int 84main (void) 85{ 86 int err = pthread_barrier_init (&print_barrier, NULL, THREADCOUNT); 87 if (err != 0) 88 { 89 fprintf (stderr, "Barrier creation failed\n"); 90 return EXIT_FAILURE; 91 } 92 /* Create the worker threads (main). */ 93 printf ("Spawning worker threads\n"); 94 for (int tid = 0; tid < THREADCOUNT; ++tid) 95 { 96 /* Add 2 so the value maps to the debugger's thread identifiers. */ 97 thread_ids[tid] = tid + 2; /* prethreadcreationmarker */ 98 err = pthread_create (&threads[tid], NULL, thread_function, 99 (void *) &thread_ids[tid]); 100 if (err != 0) 101 { 102 fprintf (stderr, "Thread creation failed\n"); 103 return EXIT_FAILURE; 104 } 105 } 106 /* Wait for the threads to complete then exit. */ 107 for (int tid = 0; tid < THREADCOUNT; ++tid) 108 pthread_join (threads[tid], NULL); 109 110 return EXIT_SUCCESS; 111} 112