//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/7999585e-fdab-4e7b-b86c-67d55e862138/nks/ThrJmp.c

//Warning: This code has been marked up for HTML

/***************************************************************************
$name: ThrJmp.c 
$version: 1.0 
$date_modified: 041903 
$description: Demonstrates the use of setjmp and longjmp to jump back
              in your code if a special situation like an error occurs.
$owner: Ulrich Neumann, Germany
Copyright (c) 2003 Novell, Inc. All Rights Reserved.

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
CUSTOMERS WITH RESPECT TO THIS CODE.

BSD License
****************************************************************************/
#include <stdio.h>
#include <screen.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <nksapi.h>


int   gThreadCount;               // counter of actual number of running threads

int   gMainPid;                  // thread id of main thread


void   my_thread( int my_number );

/*
** To start the application type ThrJmp X where X is the number of threads
** you want to create.
*/
int main
(
   int   argc,
   char   *argv[]
)
{
   int    thr, thr_count;
   pid_t   thr_id;

   setscreenmode(0);               // keeps the screen open after program finish


   if (argc < 2)                  // if no parameter, print out usage

   {
      fprintf(stderr, "%s <num_threads>\n", argv[0]);
      return 1;
   }

   thr_count    = atoi(argv[1]);
   gMainPid     = pthread_self();
   gThreadCount = 0;

   // loop to create the threads...

   for (thr = 0; thr <= thr_count; thr++)
   {
      int   inc;

      inc = thr + 1;

      /* create the new thread (exit on failuree) */
      if (pthread_create(&thr_id, NULL, (void *(*)(void *)) my_thread,
                                                            (void *) inc) > 0)
      {
         fprintf(stderr, "pthread_create failure\n");
         return 2;
      }

      sleep(1);                   // wait 1 second until next thread starts

   }

/*
** Wait until all threads are finished. In real applications you should use a
** semaphore instead of a simple counter to be MP safe.
*/
   while (gThreadCount)
      sleep(1);

   return 0;
}

/*
** thread routine - passed a not used value
*/
void my_thread
(
   int   my_number
)
{
   int      thr, gogo = FALSE;
   jmp_buf   restart;

   // increase the thread counter by one--not MP-safe...

   gThreadCount++;

   for (thr = 0; thr < 7; ++thr)
   {
      printf ("Thread number: %X counter is: %d\n", pthread_self(), thr);

      /*
      ** After 4 rounds in the loop we set a the marker here. This will set
      ** the stack back as well if longjmp is called.
      */
      if (thr == 4)
      {
         if (setjmp(restart) != 0)// (set the marker here)

         {
            printf("In restart section of thread number: %d\n", pthread_self());
            gogo = TRUE;
         }
      }

      sleep(1);                  // wait 1 second before looping again...

   }

   if (!gogo)
      longjmp(restart, 1);         // jump to marker if gogo is FALSE


   gThreadCount--;
}