Saturday, January 17, 2015

IPC: SIGNAL

IPC: signal example:

IPC:Interrupts and Signals: 

  In this section will look at ways in which two processes can communicate. When a process terminates abnormally it usually tries to send a signal indicating what went wrong. C programs (and UNIX) can trap these for diagnostics. Also user specified communication can take place in this way.
Signals are software generated interrupts that are sent to a process when a event happens. Signals can be synchronously generated by an error in an application, such as SIGFPE and SIGSEGV, but most signals are asynchronous. Signals can be posted to a process when the system detects a software event, such as a user entering an interrupt or stop or a kill request from another process. Signals can also be come directly from the OS kernel when a hardware event such as a bus error or an illegal instruction is encountered. The system defines a set of signals that can be posted to a process. Signal delivery is analogous to hardware interrupts in that a signal can be blocked from being delivered in the future. Most signals cause termination of the receiving process if no action is taken by the process in response to the signal. Some signals stop the receiving process and other signals can be ignored. Each signal has a default action which is one of the following:
  • The signal is discarded after being received
  • The process is terminated after the signal is received
  • A core file is written, then the process is terminated
  • Stop the process after the signal is received
Each signal defined by the system falls into one of five classes:
  • Hardware conditions
  • Software conditions
  • Input/output notification
  • Process control
  • Resource control

why we need to handle the singal:

This program is a simple demonstration of signals. Signals are like sofware interrupts, that are used to inform a process of the occurence of an event. Programs can be designed to catch a a signal, by providing a function to handle it.
For example, when shutting down a Linux box, the SIGTERM signal is sent to all processes. Processes that catch this signal, can properly terminate (e.g. de-allocate resources, close all open files). sighandler_t signal(int signum, sighandler_t handler);

 pgm example1:


/* Includes */
#include <stdio.h>      /* Input/Output */
#include <stdlib.h>     /* General Utilities */
#include <signal.h>     /* Signal handling */

/* This will be our new SIGINT handler.
   SIGINT is generated when user presses Ctrl-C.
   Normally, program will exit with Ctrl-C.
   With our new handler, it won't exit. */
void mysigint()
{
    printf("I caught the SIGINT signal!\n");
    return;    
} 

/* Our own SIGKILL handler */
void mysigkill()
{
    printf("I caught the SIGKILL signal!\n");
    return;    
} 

/* Our own SIGHUP handler */
void mysighup()
{
    printf("I caught the SIGHUP signal!\n");
    return;    
} 

/* Our own SIGTERM handler */
void mysigterm()
{
    printf("I caught the SIGTERM signal!\n");
    return;    
} 

int main()
{
    /* Use the signal() call to associate our own functions with
       the SIGINT, SIGHUP, and SIGTERM signals */
    if (signal(SIGINT, mysigint) == SIG_ERR)
       printf("Cannot handle SIGINT!\n");        
    if (signal(SIGHUP, mysighup) == SIG_ERR)
       printf("Cannot handle SIGHUP!\n");        
    if (signal(SIGTERM, mysigterm) == SIG_ERR)
       printf("Cannot handle SIGTERM!\n");        
           
    /* can SIGKILL be handled by our own function? */
    if (signal(SIGKILL, mysigkill) == SIG_ERR) 
       printf("Cannot handle SIGKILL!\n");        

    while(1);  /* infinite loop */

    /* exit */  
    exit(0);
} /* main() */
 
 
 
pgm2:
 

#include <stdio.h>
#include <signal.h>
 
void sigproc(void);
 
void quitproc(void); 
 
main()
{   signal(SIGINT, sigproc);
   signal(SIGQUIT, quitproc);
   printf("ctrl-c disabled use ctrl-\\ to quit\n");
   for(;;); /* infinite loop */}
 
void sigproc()
{    signal(SIGINT, sigproc); /*  */
   /* NOTE some versions of UNIX will reset signal to default
   after each call. So for portability reset signal each time */
 
   printf("you have pressed ctrl-c \n");
}
 
void quitproc()
{    printf("ctrl-\\ pressed to quit\n");
   exit(0); /* normal exit status */
}

 
PGM3:  

 sig_talk.c -- complete example program (fork ex)

Let us now write a program that communicates between child and parent processes using kill() and signal().

fork() creates the child process from the parent. The pid can be checked to decide whether it is the child (== 0) or the parent (pid = child process id).

The parent can then send messages to child using the pid and kill().

The child picks up these signals with signal() and calls appropriate functions.

An example of communicating process using signals is sig_talk.c:
/* sig_talk.c --- Example of how 2 processes can talk */
/* to each other using kill() and signal() */
/* We will fork() 2 process and let the parent send a few */
/* signals to it`s child  */

/* cc sig_talk.c -o sig_talk  */

#include <stdio.h>
#include <signal.h>

void sighup(); /* routines child will call upon sigtrap */
void sigint();
void sigquit();

main()
{ int pid;

  /* get child process */
  
   if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
    }
    
   if (pid == 0)
     { /* child */
       signal(SIGHUP,sighup); /* set function calls */
       signal(SIGINT,sigint);
       signal(SIGQUIT, sigquit);
       for(;;); /* loop for ever */
     }
  else /* parent */
     {  /* pid hold id of child */
       printf("\nPARENT: sending SIGHUP\n\n");
       kill(pid,SIGHUP);
       sleep(3); /* pause for 3 secs */
       printf("\nPARENT: sending SIGINT\n\n");
       kill(pid,SIGINT);
       sleep(3); /* pause for 3 secs */
       printf("\nPARENT: sending SIGQUIT\n\n");
       kill(pid,SIGQUIT);
       sleep(3);
     }
}

void sighup()

{  signal(SIGHUP,sighup); /* reset signal */
   printf("CHILD: I have received a SIGHUP\n");
}

void sigint()

{  signal(SIGINT,sigint); /* reset signal */
   printf("CHILD: I have received a SIGINT\n");
}

void sigquit()

{ printf("My DADDY has Killed me!!!\n");
  exit(0);
}

http://www.cs.cf.ac.uk/Dave/C/node24.html
http://www.amparo.net/ce155/signals-ex.html
www.amparo.net/ce155/signals-ex.html

IPC: conditional variable vs semaphore

IPC: message passing through pipe

simple pipe ipc:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

int main(void)
{
    int pfds[2];
    char buf[30];

    if (pipe(pfds) == -1) {
        perror("pipe");
        exit(1);
    }

    printf("writing to file descriptor #%d\n", pfds[1]);
    write(pfds[1], "test", 5);
    printf("reading from file descriptor #%d\n", pfds[0]);
    read(pfds[0], buf, 5);
    printf("read \"%s\"\n", buf);

    return 0;
}

example 2:

#include<stdio.h>
#include<stdlib.h>
#include<wait.h>
#include<unistd.h>
main()
{
    int pfd[2],retval=1,status;
    char buf1[]="hi selvakumar";
    char buf2[30]={0};
    pid_t pid;
    pipe(pfd);
    pid=fork();
    switch(pid)
    {
        case -1:
            printf("\n failing in the process creation");
            break;
        case 0:
            printf("\n in child process \n");
            write(pfd[1],buf1,sizeof(buf1));
            exit(retval);
            break;
        default:
            printf("\n in parent process \n");
            printf("\n waiting for the child process to complete \n");
            read(pfd[0],buf2,sizeof(buf2));
            printf("\n information from the child process:\t%s\n",buf2);
            wait(&status);

    }
}

Message passing through pipe

/*
Name        :   Message passing through pipe
Author      :   jishnu7
Web         :   http://thecodecracker.com
Date        :   25-Sep-2010
Description :   C Program to implement message
                passing between processes using pipe
License     :   GNU GPL License
*/

#include<stdio.h>
#include<unistd.h>


int main()
{
    int f[2],count,i;
    char a[20];
        
    pipe(f);
    i = fork();
    if(i==0)
    {  
        read(f[0],a,sizeof(a));
        printf("-------------\nChild process\n-------------\n");
        printf("Message from parent : \"%s\"\n",a);
        printf("Message to patent process : ");
        scanf("%s",a);
        write(f[1],a,sizeof(a));
    }  
    else
    {  
        printf("--------------\nParent Process\n--------------\n");
        printf("Enter the message to child process : ");
        scanf("%s",a);
        write(f[1],a,sizeof(a));
        sleep(1);
        read(f[0],a,sizeof(a));
        printf("--------------\nParent Process\n--------------\n");
        printf("Message from child : \"%s\"\n",a);
    }
}


OUTPUT
--------------
Parent Process
--------------
Enter the message to child process : hello
-------------
Child process
-------------
Message from parent : "hello"
Message to patent process : hai
--------------
Parent Process
--------------
Message from child : "hai" 
 
 
reference:
http://beej.us/guide/bgipc/output/html/multipage/pipes.html
https://linuxprograms.wordpress.com/2008/01/23/using-pipes-in-linux-programming/ 
 

IPC: mutex vs conditional variable or semaphore

what is lock and conditional variable:


  • Condition variables provide yet another way for threads to synchronize. While mutexes implement synchronization by controlling thread access to data, condition variables allow threads to synchronize based upon the actual value of data.
  • Without condition variables, the programmer would need to have threads continually polling (possibly in a critical section), to check if the condition is met. This can be very resource consuming since the thread would be continuously busy in this activity. A condition variable is a way to achieve the same goal without polling.
  • A condition variable is always used in conjunction with a mutex lock. 
why we need conditional variable or semaphore instead of mutex lock:

  • Locks are used for mutual exclusion. When you want to ensure that a piece of code is atomic, put a lock around it. You could theoretically use a binary semaphore to do this, but that's a special case.
  • Semaphores and condition variables build on top of the mutual exclusion provide by locks and are used for providing synchronized access to shared resources. They can be used for similar purposes.
  • A condition variable is generally used to avoid busy waiting (looping repeatedly while checking a condition) while waiting for a resource to become available. For instance, if you have a thread (or multiple threads) that can't continue onward until a queue is empty, the busy waiting approach would be to just doing something like:
  • //pseudocode
    while(!queue.empty())
    {
       sleep(1);
    }
    
  • The problem with this is that you're wasting processor time by having this thread repeatedly check the condition. Why not instead have a synchronization variable that can be signaled to tell the thread that the resource is available?
  • //pseudocode
    syncVar.lock.acquire();
    
    while(!queue.empty())
    {
       syncVar.wait();
    }
    
    //do stuff with queue
    
    syncVar.lock.release();
    
  • Presumably, you'll have a thread somewhere else that is pulling things out of the queue. When the queue is empty, it can call syncVar.signal() to wake up a random thread that is sitting asleep on syncVar.wait() (or there's usually also a signalAll() or broadcast() method to wake up all the threads that are waiting).
  • I generally use synchronization variables like this when I have one or more threads waiting on a single particular condition (e.g. for the queue to be empty).
  • Semaphores can be used similarly, but I think they're better used when you have a shared resource that can be available and unavailable based on some integer number of available things. Semaphores are good for producer/consumer situations where producers are allocating resources and consumers are consuming them.
  • Think about if you had a soda vending machine. There's only one soda machine and it's a shared resource. You have one thread that's a vendor (producer) who is responsible for keeping the machine stocked and N threads that are buyers (consumers) who want to get sodas out of the machine. The number of sodas in the machine is the integer value that will drive our semaphore.
  • Every buyer (consumer) thread that comes to the soda machine calls the semaphore down() method to take a soda. This will grab a soda from the machine and decrement the count of available sodas by 1. If there are sodas available, the code will just keep running past the down() statement without a problem. If no sodas are available, the thread will sleep here waiting to be notified of when soda is made available again (when there are more sodas in the machine).
  • The vendor (producer) thread would essentially be waiting for the soda machine to be empty. The vendor gets notified when the last soda is taken from the machine (and one or more consumers are potentially waiting to get sodas out). The vendor would restock the soda machine with the semaphore up() method, the available number of sodas would be incremented each time and thereby the waiting consumer threads would get notified that more soda is available.
  • The wait() and signal() methods of a synchronization variable tend to be hidden within the down() and up() operations of the semaphore.
  • Certainly there's overlap between the two choices. There are many scenarios where a semaphore or a condition variable (or set of condition variables) could both serve your purposes. Both semaphores and condition variables are associated with a lock object that they use to maintain mutual exclusion, but then they provide extra functionality on top of the lock for synchronizing thread execution. It's mostly up to you to figure out which one makes the most sense for your situation.
  • That's not necessarily the most technical description, but that's how it makes sense in my head.
  • reference: 
http://stackoverflow.com/questions/3513045/conditional-variable-vs-semaphore 



Difference between mutex and semaphore:
https://techdifferences.com/difference-between-semaphore-and-mutex.html



Example for mutex:

Example: Using Mutexes

    Example Code - Using Mutexes
        This example program illustrates the use of mutex variables in a threads program that performs a dot product. The main data is made available to all threads through a globally accessible structure. Each thread works on a different part of the data. The main thread waits for all the threads to complete their computations, and then it prints the resulting sum.

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

    /*  
    The following structure contains the necessary information 
    to allow the function "dotprod" to access its input data and
    place its output into the structure. 
    */

    typedef struct
     {
       double      *a;
       double      *b;
       double     sum;
       int     veclen;
     } DOTDATA;

    /* Define globally accessible variables and a mutex */

    #define NUMTHRDS 4
    #define VECLEN 100
       DOTDATA dotstr;
       pthread_t callThd[NUMTHRDS];
       pthread_mutex_t mutexsum;

    /*
    The function dotprod is activated when the thread is created.
    All input to this routine is obtained from a structure
    of type DOTDATA and all output from this function is written into
    this structure. The benefit of this approach is apparent for the
    multi-threaded program: when a thread is created we pass a single
    argument to the activated function - typically this argument
    is a thread number. All  the other information required by the
    function is accessed from the globally accessible structure.
    */

    void *dotprod(void *arg)
    {

       /* Define and use local variables for convenience */

       int i, start, end, len ;
       long offset;
       double mysum, *x, *y;
       offset = (long)arg;
        
       len = dotstr.veclen;
       start = offset*len;
       end   = start + len;
       x = dotstr.a;
       y = dotstr.b;

       /*
       Perform the dot product and assign result
       to the appropriate variable in the structure.
       */

       mysum = 0;
       for (i=start; i<end ; i++)
        {
          mysum += (x[i] * y[i]);
        }

       /*
       Lock a mutex prior to updating the value in the shared
       structure, and unlock it upon updating.
       */
       pthread_mutex_lock (&mutexsum);
       dotstr.sum += mysum;
       pthread_mutex_unlock (&mutexsum);

       pthread_exit((void*) 0);
    }

    /*
    The main program creates threads which do all the work and then
    print out result upon completion. Before creating the threads,
    the input data is created. Since all threads update a shared structure,
    we need a mutex for mutual exclusion. The main thread needs to wait for
    all threads to complete, it waits for each one of the threads. We specify
    a thread attribute value that allow the main thread to join with the
    threads it creates. Note also that we free up handles when they are
    no longer needed.
    */

    int main (int argc, char *argv[])
    {
       long i;
       double *a, *b;
       void *status;
       pthread_attr_t attr;

       /* Assign storage and initialize values */
       a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
       b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
     
       for (i=0; i<VECLEN*NUMTHRDS; i++)
        {
         a[i]=1.0;
         b[i]=a[i];
        }

       dotstr.veclen = VECLEN;
       dotstr.a = a;
       dotstr.b = b;
       dotstr.sum=0;

       pthread_mutex_init(&mutexsum, NULL);
            
       /* Create threads to perform the dotproduct  */
       pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

        for(i=0; i<NUMTHRDS; i++)
            {
        /*
        Each thread works on a different set of data.
        The offset is specified by 'i'. The size of
        the data for each thread is indicated by VECLEN.
        */
        pthread_create(&callThd[i], &attr, dotprod, (void *)i);
        }

         pthread_attr_destroy(&attr);

            /* Wait on the other threads */
        for(i=0; i<NUMTHRDS; i++)
            {
          pthread_join(callThd[i], &status);
        }

       /* After joining, print out the results and cleanup */
       printf ("Sum =  %f \n", dotstr.sum);
       free (a);
       free (b);
       pthread_mutex_destroy(&mutexsum);
       pthread_exit(NULL);
    }  



Example 1: Using Condition Variables

    Example Code - Using Condition Variables
        This simple example code demonstrates the use of several Pthread condition variable routines. The main routine creates three threads. Two of the threads perform work and update a "count" variable. The third thread waits until the count variable reaches a specified value.

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

    #define NUM_THREADS  3
    #define TCOUNT 10
    #define COUNT_LIMIT 12

    int     count = 0;
    int     thread_ids[3] = {0,1,2};
    pthread_mutex_t count_mutex;
    pthread_cond_t count_threshold_cv;

    void *inc_count(void *t)
    {
      int i;
      long my_id = (long)t;

      for (i=0; i<TCOUNT; i++) {
        pthread_mutex_lock(&count_mutex);
        count++;

        /*
        Check the value of count and signal waiting thread when condition is
        reached.  Note that this occurs while mutex is locked.
        */
        if (count == COUNT_LIMIT) {
          pthread_cond_signal(&count_threshold_cv);
          printf("inc_count(): thread %ld, count = %d  Threshold reached.\n",
                 my_id, count);
          }
        printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
           my_id, count);
        pthread_mutex_unlock(&count_mutex);

        /* Do some "work" so threads can alternate on mutex lock */
        sleep(1);
        }
      pthread_exit(NULL);
    }

    void *watch_count(void *t)
    {
      long my_id = (long)t;

      printf("Starting watch_count(): thread %ld\n", my_id);

      /*
      Lock mutex and wait for signal.  Note that the pthread_cond_wait
      routine will automatically and atomically unlock mutex while it waits.
      Also, note that if COUNT_LIMIT is reached before this routine is run by
      the waiting thread, the loop will be skipped to prevent pthread_cond_wait
      from never returning.
      */
      pthread_mutex_lock(&count_mutex);
      while (count<COUNT_LIMIT) {
        pthread_cond_wait(&count_threshold_cv, &count_mutex);
        printf("watch_count(): thread %ld Condition signal received.\n", my_id);
        count += 125;
        printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
        }
      pthread_mutex_unlock(&count_mutex);
      pthread_exit(NULL);
    }

    int main (int argc, char *argv[])
    {
      int i, rc;
      long t1=1, t2=2, t3=3;
      pthread_t threads[3];
      pthread_attr_t attr;

      /* Initialize mutex and condition variable objects */
      pthread_mutex_init(&count_mutex, NULL);
      pthread_cond_init (&count_threshold_cv, NULL);

      /* For portability, explicitly create threads in a joinable state */
      pthread_attr_init(&attr);
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
      pthread_create(&threads[0], &attr, watch_count, (void *)t1);
      pthread_create(&threads[1], &attr, inc_count, (void *)t2);
      pthread_create(&threads[2], &attr, inc_count, (void *)t3);

      /* Wait for all threads to complete */
      for (i=0; i<NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
      }
      printf ("Main(): Waited on %d  threads. Done.\n", NUM_THREADS);

      /* Clean up and exit */
      pthread_attr_destroy(&attr);
      pthread_mutex_destroy(&count_mutex);
      pthread_cond_destroy(&count_threshold_cv);
      pthread_exit(NULL);

    }

output:
Starting watch_count(): thread 1
inc_count(): thread 2, count = 1, unlocking mutex
inc_count(): thread 3, count = 2, unlocking mutex
watch_count(): thread 1 going into wait...
inc_count(): thread 3, count = 3, unlocking mutex
inc_count(): thread 2, count = 4, unlocking mutex
inc_count(): thread 3, count = 5, unlocking mutex
inc_count(): thread 2, count = 6, unlocking mutex
inc_count(): thread 3, count = 7, unlocking mutex
inc_count(): thread 2, count = 8, unlocking mutex
inc_count(): thread 3, count = 9, unlocking mutex
inc_count(): thread 2, count = 10, unlocking mutex
inc_count(): thread 3, count = 11, unlocking mutex
inc_count(): thread 2, count = 12  Threshold reached. Just sent signal.
inc_count(): thread 2, count = 12, unlocking mutex
watch_count(): thread 1 Condition signal received.
watch_count(): thread 1 count now = 137.
inc_count(): thread 3, count = 138, unlocking mutex
inc_count(): thread 2, count = 139, unlocking mutex
inc_count(): thread 3, count = 140, unlocking mutex
inc_count(): thread 2, count = 141, unlocking mutex
inc_count(): thread 3, count = 142, unlocking mutex
inc_count(): thread 2, count = 143, unlocking mutex
inc_count(): thread 3, count = 144, unlocking mutex
inc_count(): thread 2, count = 145, unlocking mutex
Main(): Waited on 3 threads. Final value of count = 145. Done.

Example2:

here critical and global data is event variable





in ethernet world, pkt may come at any time. so to a pkt one thread was waiting(pktrcv thread). and if pkt received (TA,TB,TC) threads will do some actions. so untill pkt received TA,TB,TC went to conditional wait state. if pkt received those pktrcv thread wakes up the TA,TB,TC thread and then it process that common pkt buffer global data structures using mutex lock(may be TA,TB,TC are waken up parallely). so before global pkt buffer data strucutre we need a mutex lock.

say thread1 and thread 2 and thread 3 is waiting for an event,
so those thread will unlock the mutex anevend go for the cond wiat. say thread 4 taking mutex lock and sending the signal to waiting thread2 . Among that thread2 taking lock and checking whether event is recived. if yes it note that event and unset that event and return success. so thread 2 do action based on the rx event and again waiting for any new event.


Reference:
https://computing.llnl.gov/tutorials/pthreads/#Exercise1



What is lock and what is semaphore?

As per operating system terminology, the mutex and semaphore are kernel resources that provide synchronization services (also called as synchronization primitives). Why do we need such synchronization primitives? Won’t be only one sufficient?

A semaphore is a generalized mutex. In lieu of single buffer, we can split the 4 KB buffer into four 1 KB buffers (identical resources). A semaphore can be associated with these four buffers. The consumer and producer can work on different buffers at the same time.


Differnce between lock and semaphore:

a mutex is locking mechanism used to synchronize access to a resource. Only one task (can be a thread or process based on OS abstraction) can acquire the mutex. It means there will be ownership associated with mutex, and only the owner can release the lock (mutex)

 A semaphore is a generalized mutex. In lieu of single buffer, we can split the 4 KB buffer into four 1 KB buffers (identical resources). A semaphore can be associated with these four buffers. The consumer and producer can work on different buffers at the same time.


Reference:

https://computing.llnl.gov/tutorials/pthreads/#Exercise1

http://www.geeksforgeeks.org/mutex-vs-semaphore/
see.stanford.edu/materials/icsppcs107/23-Concurrency-Examples.pdf
http://koti.mbnet.fi/niclasw/MutexSemaphore.html
http://www.scs.stanford.edu/15wi-cs140/notes/
https://jlmedina123.wordpress.com/2013/05/03/pthreads-with-mutex-and-semaphores/

print even and odd:

https://freethreads.wordpress.com/2012/05/05/two-indepedent-threads-to-print-even-and-odd-numbers-in-c/

reader and writer problem(using binary semaphore)

 pgm1:

/*
Name        :   Readers writers problem
Author      :   jishnu7
Web         :   http://thecodecracker.com
Date        :   26-Sep-2010
Description :   C Program to solve Dining philosophers problem
License     :   GNU GPL License
*/
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#define NUM_READ 2
#define NUM_WRIT 2
sem_t mutex;
sem_t db;
int reader_count=0;
int reader_name[]={1,2};
int writer_name[]={1,2};
void *reader(void *i);
void *writer(void *i);
int main()
{
  int i,j;
  pthread_t readers[NUM_READ];
  pthread_t writers[NUM_WRIT];
  if((sem_init(&mutex,0,1))<0)
    perror("ERROR");
  if((sem_init(&db,0,1))<0)
    perror("ERROR");
  for(i=0;i<NUM_READ;i++)
    if((pthread_create(&readers[i],NULL,reader,&reader_name[i]))!=0)
      perror("ERROR");
  for(j=0;j<NUM_WRIT;j++)
    if((pthread_create(&writers[j],NULL,writer,&writer_name[j]))!=0)
      perror("ERROR");
  for(i=0;i<NUM_READ;i++)
    if((pthread_join(readers[i],NULL))!=0)
      perror("ERROR");
  for(j=0;j<NUM_WRIT;j++)
    if((pthread_join(writers[j],NULL))!=0)
      perror("ERROR");
  sem_destroy(&mutex);
  sem_destroy(&db);
}
void *reader(void *n)
{
  int i=*(int *)n;
  if((sem_wait(&mutex))<0)
    perror("ERROR");
  reader_count++;
  if(reader_count==1)
    if((sem_wait(&db))<0)
      perror("ERROR");
  if((sem_post(&mutex))<0)
    perror("ERROR");
  printf("reader %d is reading\n",i);
  sleep(1);
  if((sem_wait(&mutex))<0)
    perror("ERROR");
  reader_count=reader_count-1;
  if((sem_post(&mutex))<0)
    perror("ERROR");
  if(reader_count==0)
  {
    if((sem_post(&db))<0)
      perror("ERROR");
  }
}
void *writer(void *n)
{
  int j=*((int *)n);
  printf("writer %d is waiting\n",j);
  if((sem_wait(&db))<0)
    perror("ERROR");
  printf("writer %d is writing\n",j);
  if((sem_post(&db))<0)
    perror("ERROR");
}


pgm2:

#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>

sem_t readCountAccess;
sem_t databaseAccess;
int readCount=0;

void *Reader(void *arg);
void *Writer(void *arg);

int main()
{
 int i=0,NumberofReaderThread=0,NumberofWriterThread;
 sem_init(&readCountAccess,0,1);
 sem_init(&databaseAccess,0,1);

 pthread_t Readers_thr[100],Writer_thr[100];
 printf("\nEnter number of Readers thread(MAX 10)");
 scanf("%d",&NumberofReaderThread);
 printf("\nEnter number of Writers thread(MAX 10)");
 scanf("%d",&NumberofWriterThread);

 for(i=0;i<NumberofReaderThread;i++)
 {
  pthread_create(&Readers_thr[i],NULL,Reader,(void *)i);
 }
 for(i=0;i<NumberofWriterThread;i++)
 {
  pthread_create(&Writer_thr[i],NULL,Writer,(void *)i);
 }
 for(i=0;i<NumberofWriterThread;i++)
 {
  pthread_join(Writer_thr[i],NULL);
 }

 for(i=0;i<NumberofReaderThread;i++)
 {
  pthread_join(Readers_thr[i],NULL);
 }
 sem_destroy(&databaseAccess);
 sem_destroy(&readCountAccess);
 return 0;
}

void * Writer(void *arg)
{

 sleep(1);
 int temp=(int)arg;
 printf("\nWriter %d is trying to enter into database for modifying the data",temp);
 sem_wait(&databaseAccess);
 printf("\nWriter %d is writting into the database",temp);
 printf("\nWriter %d is leaving the database");
 sem_post(&databaseAccess);
}

void *Reader(void *arg)
{
 sleep(1);
 int temp=(int)arg;
 printf("\nReader %d is trying to enter into the Database for reading the data",temp);
 sem_wait(&readCountAccess);
 readCount++;
 if(readCount==1)
 {
  sem_wait(&databaseAccess);
  printf("\nReader %d is reading the database",temp);
 }
 sem_post(&readCountAccess);
 sem_wait(&readCountAccess);
 readCount--;
 if(readCount==0)
 {
  printf("\nReader %d is leaving the database",temp); 
  sem_post(&databaseAccess);
 }
 sem_post(&readCountAccess);
}
 




reference:
http://www.codingdevil.com/2014/04/c-program-for-reader-writer-problem.html
http://thecodecracker.com/c-programming/readers-writers-problem/

Friday, January 16, 2015

process vs thread difference

very great difference:

The major differences between threads and processes are:
  1. Threads share the address space of the process that created it; processes have their own address space.
  2. Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
  3. Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
  4. Threads have almost no overhead; processes have considerable overhead.
  5. New threads are easily created; new processes require duplication of the parent process.
  6. Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
  7. Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process do not affect child processes.
From:https://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread

First, let's look at the theoretical aspect. You need to understand what a process is conceptually to understand the difference between a process and a thread and what's shared between them.
We have the following from section 2.2.2 The Classical Thread Model in Modern Operating Systems 3e by Tanenbaum:
The process model is based on two independent concepts: resource grouping and execution. Sometimes it is use­ful to separate them; this is where threads come in....
He continues:
One way of looking at a process is that it is a way to group related resources together. A process has an address space containing program text and data, as well as other resources. These resource may include open files, child processes, pending alarms, signal handlers, accounting information, and more. By putting them together in the form of a process, they can be managed more easily. The other concept a process has is a thread of execution, usually shortened to just thread. The thread has a program counter that keeps track of which instruc­tion to execute next. It has registers, which hold its current working variables. It has a stack, which contains the execution history, with one frame for each proce­dure called but not yet returned from. Although a thread must execute in some process, the thread and its process are different concepts and can be treated sepa­rately. Processes are used to group resources together; threads are the entities scheduled for execution on the CPU.
Further down he provides the following table:
Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |
Let's deal with the hardware multithreading issue. Classically, a CPU would support a single thread of execution, maintaining the thread's state via a single program counter, and set of registers. But what happens if there's a cache miss? It takes a long time to fetch data from main memory, and while that's happening the CPU is just sitting there idle. So someone had the idea to basically have two sets of thread state ( PC + registers ) so that another thread ( maybe in the same process, maybe in a different process ) can get work done while the other thread is waiting on main memory. There are multiple names and implementations of this concept, such as HyperThreading and Simultaneous Multithreading ( SMT for short ).
Now let's look at the software side. There are basically three ways that threads can be implemented on the software side.
  1. Userspace Threads
  2. Kernel Threads
  3. A combination of the two
All you need to implement threads is the ability to save the CPU state and maintain multiple stacks, which can in many cases be done in user space. The advantage of user space threads is super fast thread switching since you don't have to trap into the kernel and the ability to schedule your threads the way you like. The biggest drawback is the inability to do blocking I/O ( which would block the entire process and all it's user threads ), which is one of the big reasons we use threads in the first place. Blocking I/O using threads greatly simplifies program design in many cases.
Kernel threads have the advantage of being able to use blocking I/O, in addition to leaving all the scheduling issues to the OS. But each thread switch requires trapping into the kernel which is potentially relatively slow. However, if you're switching threads because of blocked I/O this isn't really an issue since the I/O operation probably trapped you into the kernel already anyway.
Another approach is to combine the two, with multiple kernel threads each having multiple user threads.
So getting back to your question of terminology, you can see that a process and a thread of execution are two different concepts and your choice of which term to use depends on what you're talking about. Regarding the term "light weight process", I don't personally see the point in it since it doesn't really convey what's going on as well as the term "thread of execution".


reference:

thanks to robert.s.barnes

http://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread

why mempool and calloc better than malloc


memory allocation cost:

Every memory allocation has a performance cost. That cost includes the time it takes to allocate the memory in your program’s logical address space and the time it takes to assign that address space to physical memory.


best point:

1. to avoid memory internal fragmentation  by malloc
2. its better than heap based algorithm from system dynamically

http://www.embeddedlinux.org.cn/RTConforEmbSys/5107final/LiB0081.html
http://www.embeddedlinux.org.cn/RTConforEmbSys/5107final/LiB0082.html

internal vs external fragmentation:

https://techdifferences.com/difference-between-internal-and-external-fragmentation.html


point :

Initialize Memory Blocks Efficiently

Small blocks of memory, allocated using the malloc function, are not guaranteed to be initialized with zeroes. Although you could use the memset function to initialize the memory, a better choice is to use the calloc routine to allocate the memory in the first place. The calloc function reserves the required virtual address space for the memory but waits until the memory is actually used before initializing it. This approach is much more efficient than using memset, which forces the virtual memory system to map the corresponding pages into physical memory in order to zero-initialize them. Another advantage of using the calloc function is that it lets the system initialize pages as they’re used, as opposed to all at once.


link:
https://developer.apple.com/library/mac/documentation/Performance/Conceptual/ManagingMemory/Articles/MemoryAlloc.html


why custom allocator best:

  • Speed: return &pool[last++] is faster than malloc. (A real pool would usually be slower than that, but still faster than malloc; especially since your "free", ready-to-be-allocated objects in the pool could have a lot of state initialized already since the last time they were used, unlike a malloc'd buffer – in OO terms, you don't need to call the constructor after allocating).
  • Predictability: people usually refer to "the pool advantage" as "lower fragmentation" and hence less chances of running out of memory due to "sudden" fragmentation in unexpected circumstances. Actually, fragmentation is higher with pools: a pool of 100 objects of type A can not be used to allocate objects of type B, even if you're using just one (or zero) A objects right now – so your memory is very much fragmented. However, it's fragmented predictably, leading to predictable allocation times.
  • Stability: Another things which higher fragmentation buys. Pools let you allocate B objects after running out of A objects from the predictably available "B fragment" (pool). This means you can actually handle out-of-memory conditions if you can live without another A object. A malloc-based program "runs out of everything" when it runs out of memory, so it's very unlikely to survive.


 Ref:
http://yosefk.com/blog/why-custom-allocatorspools-are-hard.html






 point:
http://voices.canonical.com/jussi.pakkanen/2011/09/27/is-malloc-slow/



lazy memory  allocation:

Every memory allocation has a performance cost. That cost includes the time it takes to allocate the memory in your program’s logical address space and the time it takes to assign that address space to physical memory. If you do not plan to use a particular block of memory right away, deferring the allocation until the time when you actually need it is the best course of action. For example, to avoid the appearance of your app launching slowly, minimize the amount of memory you allocate at launch time. Instead, focus your initial memory allocations on the objects needed to display your user interface and respond to input from the user. Defer other allocations until the user issues starts interacting with your application and issuing commands. This lazy allocation of memory saves time right away and ensures that any memory that is allocated is actually used.


Tuesday, January 13, 2015

end to end communcation -> browser to web server communcation using HTTP TCP/UDP IP ETHERNET

TTL and traceroute and ICMP

what is TTL:
en.wikipedia.org/wiki/Time_to_live

how traceroute works:

http://www.cs.cf.ac.uk/Dave/Internet/node77.html


icmp error message and its reason:

pages 56 and 57:
If a router cannot forward a packet because it has no routes at all (including no default route) to the destination specified in the packet, then the router MUST generate a Destination Unreachable, Code 0 (Network Unreachable) ICMP message. If the router does have routes to the destination network specified in the packet but the (Type of Service) TOS specified for the routes is neither the default TOS (0000) nor the TOS of the packet that the router is attempting to route, then the router MUST generate a Destination Unreachable, Code 11 (Network Unreachable for TOS) ICMP message.
If a packet is to be forwarded to a host on a network that is directly connected to the router (i.e., the router is the last-hop router) and the router has ascertained that there is no path to the destination host then the router MUST generate a Destination Unreachable, Code 1 (Host Unreachable) ICMP message. If a packet is to be forwarded to a host that is on a network that is directly connected to the router and the router cannot forward the packet because no route to the destination has a TOS that is either equal to the TOS requested in the packet or is the default TOS (0000) then the router MUST generate a Destination Unreachable, Code 12 (Host Unreachable for TOS) ICMP message.

 URL:

http://www.networksorcery.com/enp/protocol/icmp/msg3.htm


other reason for time exceeded icmp msg:

http://www.tcpipguide.com/free/t_ICMPv4TimeExceededMessages.htm


perfect example for how tra ceroute sends and gets the path:

http://www.cisco.com/c/en/us/support/docs/ios-nx-os-software/ios-software-releases-121-mainline/12778-ping-traceroute.html
https://learningnetwork.cisco.com/thread/31415


ICMP positve way and negative hacking way:

http://www.techrepublic.com/article/prevent-hacker-probing-block-bad-icmp-messages/


path mtu and vpn:
http://www.enterprisenetworkingplanet.com/netsp/article.php/3584166/Networking-101-Understanding-and-Using-ICMP.htm