/* example comparing threads to processes This illustrates that memory is shared between threads but not (normally) shared between processes. The behaviour depends on the first argument. See function usage() for details. Note that in order to keep the example short, so as to be more quickly grasped by a reader, we have taken several short cuts that would be bad style in a real application and would result in a reduction in grade if they were done in a program turning for an assignment in this course. 1) We abuse the "void *" argument and return-value 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 purist would create an integer variable to hold the value and pass the pointer. 2) We do not check the return values of system calls, including pthread_create, pthread_join, pthread_attr_init, and waitpid. 3) We assume after the call to waitpid() that the child exited normally. 4) We are taking no trouble here to prevent interleaving of output from the various threads/processes. */ #define _XOPEN_SOURCE 500 #define _REENTRANT #include #include #include #include #include #include #include int global = 0; void * thread_body (void *arg) { fprintf(stderr, "thread found global = %d\n", global); global++; fprintf(stderr, "thread incremented global: %d\n", global); return (void *) global; } void usage () { fprintf (stderr, "usage: example0 [ p | t]\n" "t : use threads\n" "p : use processes\n"); } int main(int argc, char **argv) { pthread_attr_t attrs; pthread_t thread; void * value_ptr; pid_t child; int status; if (argc != 2) { usage(); exit (-1); } fprintf(stderr, "initially global = %d\n", global); if (strcmp (argv[1], "t") == 0) { pthread_attr_init (&attrs); /* use the default attributes */ /* create thread */ pthread_create ( &thread, /* place to store the id of new thread */ &attrs, /* thread creation attributes */ thread_body, /* function for thread to execute */ NULL); /* pass no parameter */ fprintf(stderr, "thread created\n"); fprintf(stderr, "main found global = %d\n", global); global++; fprintf(stderr, "main incremented global\n"); pthread_join(thread, &value_ptr); fprintf(stderr, "thread returned value %d\n", (int) value_ptr); } else { if ((child = fork())) { /* we are the parent */ global++; fprintf(stderr, "parent incremented global\n"); waitpid (child, &status, 0); fprintf(stderr, "child returned value %d\n", WEXITSTATUS(status)); } else { /* we are the child */ global++; fprintf(stderr, "child incremented global\n"); exit (global); } } fprintf(stderr, "finally global = %d\n", global); fprintf(stderr, "main exiting\n"); exit (0); }