/* Test case for hand function calls in multi-threaded program.

   Copyright 2008-2021 Free Software Foundation, Inc.

   This file is part of GDB.

   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 <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#ifndef NR_THREADS
#define NR_THREADS 4
#endif

int thread_count;

pthread_mutex_t thread_count_mutex;

pthread_cond_t thread_count_condvar;

void
incr_thread_count (void)
{
  pthread_mutex_lock (&thread_count_mutex);
  ++thread_count;
  if (thread_count == NR_THREADS)
    pthread_cond_signal (&thread_count_condvar);
  pthread_mutex_unlock (&thread_count_mutex);
}

void
cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut)
{
  pthread_mutex_lock (mut);
  pthread_cond_wait (cond, mut);
  pthread_mutex_unlock (mut);
}

void
noreturn (void)
{
  pthread_mutex_t mut;
  pthread_cond_t cond;

  pthread_mutex_init (&mut, NULL);
  pthread_cond_init (&cond, NULL);

  /* Wait for a condition that will never be signaled, so we effectively
     block the thread here.  */
  cond_wait (&cond, &mut);
}

void *
forever_pthread (void *unused)
{
  incr_thread_count ();
  noreturn ();
}

void
hand_call (void)
{
}

/* Wait until all threads are running.  */

void
wait_all_threads_running (void)
{
  pthread_mutex_lock (&thread_count_mutex);
  if (thread_count == NR_THREADS)
    {
      pthread_mutex_unlock (&thread_count_mutex);
      return;
    }
  pthread_cond_wait (&thread_count_condvar, &thread_count_mutex);
  if (thread_count == NR_THREADS)
    {
      pthread_mutex_unlock (&thread_count_mutex);
      return;
    }
  pthread_mutex_unlock (&thread_count_mutex);
  printf ("failed waiting for all threads to start\n");
  abort ();
}

/* Called when all threads are running.
   Easy place for a breakpoint.  */

void
all_threads_running (void)
{
}

int
main (void)
{
  pthread_t forever[NR_THREADS];
  int i;

  pthread_mutex_init (&thread_count_mutex, NULL);
  pthread_cond_init (&thread_count_condvar, NULL);

  for (i = 0; i < NR_THREADS; ++i)
    pthread_create (&forever[i], NULL, forever_pthread, NULL);

  wait_all_threads_running ();
  all_threads_running ();

  return 0;
}

