Blame tests/t-thread.c

Packit 5e354d
/* t-thread.c
Packit 5e354d
 * Copyright 2012 g10 Code GmbH
Packit 5e354d
 *
Packit 5e354d
 * This file is free software; as a special exception the author gives
Packit 5e354d
 * unlimited permission to copy and/or distribute it, with or without
Packit 5e354d
 * modifications, as long as this notice is preserved.
Packit 5e354d
 *
Packit 5e354d
 * This file is distributed in the hope that it will be useful, but
Packit 5e354d
 * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
Packit 5e354d
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit 5e354d
 */
Packit 5e354d
Packit 5e354d
#include "t-support.h"
Packit 5e354d
Packit 5e354d
Packit 5e354d
static int counter;
Packit 5e354d
static npth_mutex_t counter_mutex;
Packit 5e354d
static int thread_twoone_ready;
Packit 5e354d
Packit 5e354d
static void *
Packit 5e354d
thread_one (void *arg)
Packit 5e354d
{
Packit 5e354d
  int rc, i;
Packit 5e354d
Packit 5e354d
  info_msg ("thread-one started");
Packit 5e354d
  npth_usleep (10);  /* Give the other thread some time to start.  */
Packit 5e354d
  for (i=0; i < 10; i++)
Packit 5e354d
    {
Packit 5e354d
      /* We would not need the mutex here, but we use it to allow the
Packit 5e354d
         system to switch to another thread.  */
Packit 5e354d
      rc = npth_mutex_lock (&counter_mutex);
Packit 5e354d
      fail_if_err (rc);
Packit 5e354d
Packit 5e354d
      counter++;
Packit 5e354d
Packit 5e354d
      rc = npth_mutex_unlock (&counter_mutex);
Packit 5e354d
      fail_if_err (rc);
Packit 5e354d
    }
Packit 5e354d
  info_msg ("thread-one terminated");
Packit 5e354d
Packit 5e354d
  return (void*)4711;
Packit 5e354d
}
Packit 5e354d
Packit 5e354d
Packit 5e354d
static void *
Packit 5e354d
thread_twoone (void *arg)
Packit 5e354d
{
Packit 5e354d
  int rc, i;
Packit 5e354d
Packit 5e354d
  npth_setname_np (npth_self (), "thread-twoone");
Packit 5e354d
  info_msg ("thread-twoone started");
Packit 5e354d
Packit 5e354d
  rc = npth_detach (npth_self ());
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
Packit 5e354d
  while (counter < 100)
Packit 5e354d
    {
Packit 5e354d
      npth_usleep (1000);
Packit 5e354d
      counter++;
Packit 5e354d
    }
Packit 5e354d
  info_msg ("thread-twoone terminated");
Packit 5e354d
  thread_twoone_ready = 1;
Packit 5e354d
Packit 5e354d
  return NULL;
Packit 5e354d
}
Packit 5e354d
Packit 5e354d
Packit 5e354d
static void *
Packit 5e354d
thread_two (void *arg)
Packit 5e354d
{
Packit 5e354d
  int rc, i;
Packit 5e354d
Packit 5e354d
  info_msg ("thread-two started");
Packit 5e354d
Packit 5e354d
  for (i=0; i < 10; i++)
Packit 5e354d
    {
Packit 5e354d
      rc = npth_mutex_lock (&counter_mutex);
Packit 5e354d
      fail_if_err (rc);
Packit 5e354d
Packit 5e354d
      counter--;
Packit 5e354d
Packit 5e354d
      if (i == 5)
Packit 5e354d
        {
Packit 5e354d
          npth_t tid;
Packit 5e354d
Packit 5e354d
          info_msg ("creating thread-twoone");
Packit 5e354d
          rc = npth_create (&tid, NULL, thread_twoone, NULL);
Packit 5e354d
          fail_if_err (rc);
Packit 5e354d
          npth_usleep (10);  /* Give new thread some time to start.  */
Packit 5e354d
        }
Packit 5e354d
Packit 5e354d
      rc = npth_mutex_unlock (&counter_mutex);
Packit 5e354d
      fail_if_err (rc);
Packit 5e354d
    }
Packit 5e354d
Packit 5e354d
  info_msg ("busy waiting for thread twoone");
Packit 5e354d
  while (!thread_twoone_ready)
Packit 5e354d
    npth_sleep (0);
Packit 5e354d
Packit 5e354d
  info_msg ("thread-two terminated");
Packit 5e354d
Packit 5e354d
  return (void*)4722;
Packit 5e354d
}
Packit 5e354d
Packit 5e354d
Packit 5e354d
Packit 5e354d
Packit 5e354d
Packit 5e354d
int
Packit 5e354d
main (int argc, char *argv[])
Packit 5e354d
{
Packit 5e354d
  int rc;
Packit 5e354d
  npth_attr_t tattr;
Packit 5e354d
  int state;
Packit 5e354d
  npth_t tid1, tid2;
Packit 5e354d
  void *retval;
Packit 5e354d
Packit 5e354d
  if (argc >= 2 && !strcmp (argv[1], "--verbose"))
Packit 5e354d
    opt_verbose = 1;
Packit 5e354d
Packit 5e354d
  rc = npth_init ();
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
Packit 5e354d
  rc = npth_mutex_init (&counter_mutex, NULL);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
Packit 5e354d
  rc = npth_attr_init (&tattr);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  rc = npth_attr_getdetachstate (&tattr, &state);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  if ( state != NPTH_CREATE_JOINABLE )
Packit 5e354d
    fail_msg ("new tattr is not joinable");
Packit 5e354d
Packit 5e354d
  info_msg ("creating thread-one");
Packit 5e354d
  rc = npth_create (&tid1, &tattr, thread_one, NULL);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  npth_setname_np (tid1, "thread-one");
Packit 5e354d
Packit 5e354d
  info_msg ("creating thread-two");
Packit 5e354d
  rc = npth_create (&tid2, &tattr, thread_two, NULL);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  npth_setname_np (tid2, "thread-two");
Packit 5e354d
Packit 5e354d
  rc = npth_attr_destroy (&tattr);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
Packit 5e354d
  info_msg ("waiting for thread-one to terminate");
Packit 5e354d
  rc = npth_join (tid1, &retval);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  if (retval != (void*)4711)
Packit 5e354d
    fail_msg ("thread-one returned an unexpected value");
Packit 5e354d
Packit 5e354d
  info_msg ("waiting for thread-two to terminate");
Packit 5e354d
  rc = npth_join (tid2, &retval);
Packit 5e354d
  fail_if_err (rc);
Packit 5e354d
  if (retval != (void*)4722)
Packit 5e354d
    fail_msg ("thread-two returned an unexpected value");
Packit 5e354d
Packit 5e354d
  if (counter != 100)
Packit 5e354d
    fail_msg ("counter value not as expected");
Packit 5e354d
Packit 5e354d
  return 0;
Packit 5e354d
}