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