Originally Published: Wednesday, 15 August 2001 Author: Subhasish Ghosh
Published to: develop_articles/Development Articles Page: 3/4 - [Printable]

Understanding Re-entrant Kernels

Undertanding the details of the Linux kernel may seem beyond the reach of many people, but at Linux.com we don't believe in "beyond the reach". In this article Ghosh begins his exploration down into the depths of the machine with a look at how a multi-threaded program can help illustrate re-entrancy, and vica versa.

Code, Code, Code  << Page 3 of 4  >>

Threads in action

There is a whole set of library calls associated with threads. Most of those names start with pthread_. To use these library calls, we must define the macro _REENTRANT, include the file pthread.h and then link with the threads library using -lpthread. We utilize the functionality of routines called "re-entrant routines". Re-entrant code can be called more than once, either by different threads running together, or maybe be called by thread invocations in some other way. But the significant point to note is that: The re-entrant section of code must only use local variables, and in such a way that every call to the code gets its own unique copy of the data. This is very important to note.

All the re-entrancy issues that we have discussed so far are implemented in multithreaded programs using the macro _REENTRANT. We define this macro before any #include lines in our program. Including the macro _REENTRANT in the command line when we are compiling the program does three significant things for us:

  1. Some chosen functions get re-entrant safe equivalents. They have a _r appended to their initial name. For example, a function gethostbyname becomes gethostbyname_r.

  2. Some stdio.h functions that are normally implemented as macros become proper re-entrant safe functions.

      The variable errno from the file errno.h is changed to call a function, whose real value can be read in a multithread safe way.

    Get a Multithreaded Program Running

    Okay, now perform the following steps to get a multithreaded program running:
    • Step 1: Boot your system into Linux, and then create a file named thread1.c

    • Step 2: Type this down neat and smooth.

      /* A Simple Threaded Program: By: Subhasish Ghosh Date: August 14th 2001 Place: Calcutta, West Bengal, India */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> void *thread_function(void *arg); char message[ ] = "Hello World"; int main( ) { int res; pthread_t a_thread; void *thread_result; res = pthread_create(&a_thread, NULL, thread_function, (void *)message); if (res != 0) { perror("Thread creation failed."); exit(EXIT_FAILURE); } printf("Waiting for thread to finish....\n"); res = pthread_join(a_thread, &thread_result); if (res != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); } printf("Thread joined, it returned %s\n", (char *)thread_result); printf("Message is now %s\n", message); exit(EXIT_SUCCESS); } void *thread_function(void *arg) { printf("thread_function is running. Argument was %s\n", (char *)arg); sleep(3); strcpy(message, "Bye!"); pthread_exit("Thank you for the CPU time"); }

    • Step 3: To compile this, we need to define _REENTRANT macro on the command line. So, do this now:

      cc -D_REENTRANT -o thread1 thread1.c -lpthread

    • Step 4: It should compile without any errors and you will get an object file thread1. Then execute thread1 from the command line: ./thread1 and press enter. You should see an output similar to this:
      Waiting for thread to finish...
      thread_function is running. Argument was Hello World
      Thread joined, it returned Thank you for the CPU time
      Message is now Bye!

Code, Code, Code  << Page 3 of 4  >>