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