Reentrant and thread safe functions

December 31st, 2009 by Kevin | Posted under programming.

Threads

Process with two concurrent threads

©en:User:Cburnett

A thread is a sequence of execution in a process. Multiple threads can run concurrently in a process as shown in the figure above. The feature of concurrently executing threads of a process is that they share resources such as memory.

An example of a project using threads that I have worked on is playing an MPEG4 stream. The stream contains both audio and video tracks. We should be able to play them concurrently with the timing information provided inside the tracks. So we create a thread to play the audio, another thread to play the video and a third thread to maintain synchronization between the two.

Since the threads share the same address space, we can share the synchronization information between them. The only issue is when the address space is accessed concurrently and the threads are writing on it at the same time or with one read and the other write. To solve this problem we have to make the functions thread safe.

The way to make functions thread safe is to use one of the following mechanisms:

1) Using local variables: By ensuring that we just use local variables we can make the function thread safe. This is because even though the global address space is shared between the threads, each thread is assigned it’s own stack with separate memory for it’s local variables.

2) Using mutual exclusion: Mutex as they are popularly know are another way of making a function thread safe. This is done by ensuring that the shared resources of the function are accessed by only one thread at a time i.e the access to these critical shared resources are mutually exclusive among the threads.

pthread_mutex_t VideoStatusMutex = PTHREAD_MUTEX_INITIALIZER;

static int GetVideoStatus()
{
  int tmp = 0;
  pthread_mutex_lock(&VideoStatusMutex);
  tmp = g_VideoStatus;
  pthread_mutex_unlock(&VideoStatusMutex);
  return tmp;
}

static int SetVideoStatus(int VideoStatus)
{
  pthread_mutex_lock(&VideoStatusMutex);
  g_VideoStatus = VideoStatus;
  pthread_mutex_unlock(&VideoStatusMutex);
  return 0;
}

Whenever we need to use a share resource like g_VideoStatus, we use the mutex functions SetVideoStatus() and GetVideoStatus() instead.

3) Reentrant functions: To make a function a list of requirements is below (from Wikipedia):

  • Must hold no static (or global) non-constant data.
  • Must not return the address to static (or global) non-constant data.
  • Must work only on the data provided to it by the caller.
  • Must not rely on locks to singleton resources.
  • Must not modify its own code. (unless executing in its own unique thread storage)
  • Must not call non-reentrant computer programs or routines.

All reentrant functions are thread safe but not all thread safe functions are reentrant. An example of a reentrant function is our recursive factorial example which satisfies all the above conditions.

int fact(int n)
{
   if(n == 0 || n == 1)
   {
      return 1;
   }else{
      return n * fact(n-1);
   }
}
 

Related Posts:

Tags: ,

Comments

One Response to “Reentrant and thread safe functions”

Do you have any comments on Reentrant and thread safe functions ?

Spam protection by WP Captcha-Free