/* This testcase is part of GDB, the GNU debugger.

   Copyright 2018-2021 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 <http://www.gnu.org/licenses/>.  */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

/* 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;
}
