/* example of thread creation and termination This is a modification of example1a, to further illustrate how execution times are affected by true parallelism versus interleaved execution. To see the effects, the program must be executed on an SMP system, with several processors. As with example1a, the behavior depends on the first argument. See function usage() for details. In order to make the example shorter and to allow the main point to be more easily grasped, this example takes some short cuts. In particular, it abuses the "void *" argument and return-values of the thread body to hold an "int" value. This is usually safe, since the size of a pointer is usually longer than or equal to the size of an integer. However, a person concerned with portability would create an integer variable to hold the value and pass a pointer to the variable. */ #define _XOPEN_SOURCE 500 #define _REENTRANT #include #include #include #include #include #include #include #include #define NTHREADS 5 int index[NTHREADS]; #define NITERATIONS 1000000 void * thread_body (void *arg) { int *index = (int *) arg; long int k; time_t now, dummy; fprintf(stderr, "thread %d starts\n", *index); /* the following is to keep the CPU busy for a fixed amount of work, so we can compare how long it takes with several threads versus a single thread */ for (k = 0; k < NITERATIONS; k++) now = time(&dummy); fprintf(stderr, "thread %d exits\n", *index); *index = *index * 10; return (void *) index; } void usage () { fprintf (stderr, "usage: example1 [ n | x | j | d ]\n" "n : use PTHREAD_CREATE_JOINABLE but don't wait\n" "j : use PTHREAD_CREATE_JOINABLE, with pthread_join\n" "d : use PTHREAD_CREATE_DETACHED, and don't wait\n" "x : use PTHREAD_CREATE_DETACHED, and wait 3 seconds\n"); } int main(int argc, char **argv) { int i, result; pthread_attr_t attrs; pthread_t thread[NTHREADS]; void * value_ptr; long int k; time_t now, start, dummy; if (argc != 2) { usage(); exit (-1); } start = time (&dummy); for (k = 0; k < NITERATIONS; k++) now = time (&dummy); fprintf (stderr, "elapsed time for one loop = %ld\n", (int) now - start); start = time (&dummy); pthread_setconcurrency (4); pthread_attr_init (&attrs); /* use the command-line argument to decide whether to create the threads detached or joinable */ if ((strcmp (argv[1], "d") == 0) || (strcmp (argv[1], "x") == 0)) pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED); /* create threads */ for (i = 0; i < NTHREADS; i++) { index [i] = i; if ((result = pthread_create ( &thread[i], /* place to store the id of new thread */ &attrs, /* thread creation attributes */ thread_body, /* function for thread to execute */ (void *) &index[i]))) /* pass index as parameter */ { fprintf (stderr, "pthread_create: %d\n", result); exit (-1); } } fprintf (stderr, "threads created\n"); /* wait for the threads to complete */ if (strcmp (argv[1], "j") == 0) { for (i = 0; i < NTHREADS; i++) { pthread_join (thread[i], &value_ptr); fprintf(stderr, "thread %d returned value %d\n", i, (int) value_ptr); } } /* find out how long the computation took */ now = time (&dummy); fprintf (stderr, "elapsed time for all %d threads = %ld\n", NTHREADS, (int) now - start); if (strcmp (argv[1], "x") == 0) { fprintf (stderr, "initial thread waiting 3 seconds\n"); sleep (3); } fprintf (stderr, "initial thread exiting\n"); exit (0); }