Thread Creation and Thread related API

Thread Creation and Thread related API

POSIX- Portable Operating System Interface is a set of standard specified by the IEEE computer society which defines Application Programming Interface(API), header file,command line shells for software compatibility with variants of Unix and other operating system.

POSIX defines set of API, function, header file for threaded programming known as POSIX threads or Pthreads.

API related to Thread:

  • pthread_create(pthread_t *th_id, pthread_attr_t *attr, void *(*fun), void *arg)
  • pthread_join(pthread_t th_id, void **exit_status);
  • pthread_exit(void *ret_value);
  • pthread_cancel(pthread_t th_id);
  • pthread_detach(pthread_t th_id);

API for creation of Thread:

int res = pthread_create(pthread_t *th_id, pthread_attr_t *attr, void *(*fun), void *arg)

Explanation for each parameter:

  • pthread_t *th_id:

Each thread is identified by id known as thread identifier, so this variable(pointer) points to address which hold identifier for the created thread.

  • pthread_attr_t *attr:

This is used for thread attributes, usually we pass NULL.

  • void *(*fun):

This is the function which the thread need to execute.

  • void *arg:

This is the argument passed to function which the thread would execute.

Return Value: It return 0 on

success or an error number on failure.

Note:

  • Only one argument can be passed to thread function, if required to pass multiple arguments pointer to structure can be used.
  • Always the return type and passed argument should be void*
  • In the thread function, it can be typecasted accordingly.

Sample program(Passing string to the thread function)

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
void *fun ( void *arg)
{
  printf("\n %s This is the thread function\n", (char *)arg);
}
  
int main()
{
  pthread_t th_id;
  int res = pthread_create(&th_id, NULL, fun, "Hello");
  if (res!=0)
  {
     printf("\n Thread creation failed with error num %s\n", strerror(res));
     exit(0);
  }
  printf("\n Waiting for the thread to finish\n");
  res = pthread_join(th_id, NULL);
  if (res!=0)
  {
    printf("\n Thread join failed with error no %s\n", strerror(res));
    exit(0);
  }
  printf("\n Thread joined\n");  
  return 0;
}  
  
Output:
[aprakash@wtl-lview-6 thread]$ gcc thread.c -lpthread
[aprakash@wtl-lview-6 thread]$ ./a.out 

Waiting for the thread to finish
Hello This is the thread function
Thread Joined

pthread_join():

  • The pthread_join() function provides a simple mechanism allowing an application to wait for a thread to terminate. After the thread terminates, the application may then choose to clean up resources that were used by the thread.
  • This is similar to wait() and waitpid() in the case of process.
  • This is again a blocking call and is used to get the exit status of the thread.

Syntax:

pthread_join(pthread_t th_id, void **exit_status)

  • First parameter is the thread to be waited for that is the thread identifier filled while creating pthread_create()
  • Second parameter is a pointer to pointer that point to return value(exit status) of the thread. Can be passed NULL.

Return Value: It return 0 in success and error number in case of failure.

pthread_join()

Sample program(Passing pointer to structure to the thread function)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

struct student
{
  char *name;
  int roll;
};

void *fun(void *input)
{
   printf("\n This is thread function\n");
   ((struct student*)input)->roll =10;
   pthread_exit((void*)10);
}  

int main()
{
  pthread_t th_id;
  void *exit_status;
  struct student *st = (struct student *)malloc(sizeof(struct student));
  
  char name[] = "Hello";
  st->name= name; 
  int res = pthread_create(&th_id, NULL, fun, (void *)st);
  if (res !=0)
  {
    printf("\n Thread creation failed with error num: %s\n", strerror(res));
    exit(0);
  } 
  
  printf("\n Waiting for the thread to finish\n");
  res= pthread_join(th_id, &exit_status);
  if (res !=0)
  {
    printf("\n Thread join failed with error num: %d\n", strerror(res));
    exit(0);
  } 
  printf("\n Thread Joined successfully\n"); 
  printf("\n The exit status of thread is %d\n",(int*)exit_status);
  printf("\n student roll number is %d\n", st->roll);
  printf("\n student name is %s\n", st->name);
  return 0;
} 

Output:
[aprakash@wtl-lview-6 thread]$ gcc thread_creation_strcuture.c -lpthread
[aprakash@wtl-lview-6 thread]$ ./a.out 

 Waiting for the thread to finish

 This is thread function

 Thread Joined successfully

 The exit status of thread is 10

 student roll number is 10

 student name is Hello

pthread_exit():

  • This is similar to exit() in the case of process.
  • When a thread terminates this function is called to terminate the threads, returning a pointer to an object.
  • When thread needed to continue execution but no longer need the main thread. In that case, pthread_exit(NULL); can be used from main thread which will let other threads to continue even after main thread exits.

Syntax:

void pthread_exit(void * ret_value);

Example:

void *fun(void *input)
{
   printf("\n This is thread function\n");
   ((struct student*)input)->roll =10;
   pthread_exit((void*)10);
}
/*catching it with the help of pthread_join */
void *exit_status;
res= pthread_join(th_id, &exit_status);
printf("\n The exit status of thread is %d\n",(int*)exit_status);

Second Example:

void *fun(void *input)
{
   printf("\n This is thread function\n");
   ((struct student*)input)->roll =10;
   pthread_exit("Thank you!);
}
/* catching it with the help of pthread_join */
void *exit_status;
res= pthread_join(th_id, &exit_status);
printf("\n The exit status of thread is %d\n",(char*)exit_status);

pthread_detach(pthread_t th_id):

  • This function allows the pthread library to release all the resources when the thread terminates.
  • It just lets the pthread library to know whether the resources can be released or can be kept to call pthread_join() later.
  • The thread once detached cannot be joined later.
  • If the thread has not terminated, pthread_detached() does not causes it to terminates.
  • By default all the threads are joinable, hence this must be called explicitly

Syntax:

pthread_detach(pthread_t th_id);

Return:

It returns 0 on success and other value on failure.

Sample Program

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

void *fun( void *arg)
{
  printf("\n %s\n", (char*)arg);
}
  
int main()
{
  pthread_t th_id;
  int res = pthread_create(&th_id, NULL, fun, "Thread executing");
  if (res !=0)
  {
    printf("\n Thread creation failed with error num %d\n", errno);
    exit(0);
  }
  /* Sleep is given so that thread finishes its work */
  sleep(5);
  res = pthread_detach(th_id);
  if (res)
    printf("\n Failed to detach thread");
  else
    printf("\n Thread detached successfully\n");
  return 0;
}    

Output:

[aprakash@wtl-lview-6 packetlogic2]$ gcc thread/detach.c -lpthread
[aprakash@wtl-lview-6 packetlogic2]$ ./a.out 

 Thread executing

 Thread detached successfully

pthread_cancel(thread_t id):

This API is used to cancel the thread using thread id. This function sends a cancellation request to the thread.

Syntax: pthread_cancel(thread_t id);

Return: It return 0 on success and non zero(positive) for error.

Sample Program(cancellation of self thread)

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>

void *fun(void *arg)
{
    printf("\n Thread function is executing\n");
    pthread_cancel(pthread_self());
}

int main()
{
    pthread_t th_id;
    int res = pthread_create(&th_id, NULL, fun, NULL);
    if(res)
    {
        printf("\n Thread creation failed %s\n", strerror(res));
        exit(0);
    }
    pthread_join(th_id, NULL);
    return 0;
}

output:
[aprakash@wtl-lview-6 packetlogic2]$ gcc thread_slef_cancel.c -lpthread
[aprakash@wtl-lview-6 packetlogic2]$ ./a.out 

 Thread function is executing


Sample Program(cancellation of another thread)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

pthread_t th_id1, th_id2;
void *fun1(void *arg)
{
    printf("\n Thread function  1 is executing\n");
}

void *fun2(void *arg)
{
    printf("\n Thread function 2 is executing\n");
    sleep(5);
    printf("\n Cancelling thread 1\n");
    pthread_cancel(th_id1);
    
    pthread_exit(NULL);
}

int main()
{
    
    int res = pthread_create(&th_id1, NULL, fun1, NULL);
    if(res)
    {
        printf("\n Thread creation failed %s\n", strerror(res));
        exit(0);
    }
    res = pthread_create(&th_id2, NULL, fun2, NULL);
    if(res)
    {
        printf("\n Thread creation failed %s\n", strerror(res));
        exit(0);
    }
    pthread_join(th_id1, NULL);
    pthread_join(th_id2, NULL);
    return 0;
}

Output:

[aprakash@wtl-lview-6 packetlogic2]$ gcc thread_other_cancel.c -lpthread
[aprakash@wtl-lview-6 packetlogic2]$ ./a.out 

 Thread function  1 is executing

 Thread function 2 is executing

 Cancelling thread 1


Categories: Operating system (OS)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: