C program to use spinlock to block the process at a point and unblock it by sending SIGALRM which will unlock the spinlock

Mutex, Semaphore and Spinlock

Mutex provides one person to access a single resource at a time, others must wait in a queue. Once this person is done, the guy next in the queue acquire the resource.So access is serial, one guy after other. Too aggressive.Semaphore are useful if multiple instances (N) of a resource is to be shared among a set of users. As soon as all N resources are acquired, any new requester has to wait. Since there is no single lock to hold, there is as such no ownership of a semaphore.
Spinlock is an aggressive mutex.
 In mutex, if you find that resource is locked by someone else, you (the thread/process) switch the context and start to wait (non-blocking).
Whereas spinlocks do not switch context and keep spinning. As soon as resource is free, they go and grab it. In this process of spinning, they consume many CPU cycles. Also, on a uni-processor machine they are useless and perform very badly (do I need to explain that?).Whereas spinlocks do not switch context and keep spinning. As soon as resource is free, they go and grab it. In this process of spinning, they consume many CPU cycles. Also, on a uni-processor machine they are useless and perform very badly (do I need to explain that?).

C program

neelkanth_surekha#cat spinlock_example.c 
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

/*The call pthread_spin_init(). initializes a spin lock. A spin lock can be shared between processes or private to the process that created it. 
 * By passing the value PTHREAD_PROCESS_PRIVATE to the pthread_spin_init(), a spin lock is not shareable. 
 * To make it sharable, we need to pass the value PTHREAD_PROCESS_SHARED. The default is set to be private.*/

pthread_spinlock_t slock;

void splock()
{
    int i = 0;
    int ret = -1;

    while(1) {
         /* Apply spin lock for the first time */
         ret =  pthread_spin_lock(&slock);
         printf("first time spin lock applied: ret = %d\n", ret);
         printf("***************************************************\n");
         printf("******** GIVE SIGALRM TO THE PROCESS TO UNBLOCK THE SPINLOCK *****\n");
         printf("***************************************************\n");

         /* Apply spin lock for the 2nd time. since it's already locked, 
          * the process will spin here indefinitely till it's unlocked.
          * By calling spin lock again in the same process, we are making the 
          * process spin here till it gets SIGALARM and only then it will 
          * release the spin lock. 
          */
         if (pthread_spin_lock(&slock) == 0) {
             printf("\n Spin lock acquired again \n");
             /* Now unlock it */
             pthread_spin_unlock(&slock);
             printf("\n Spinlock unlocked immediately. At this point the process"
                     " is free of spin lock \n");
             break;
         }

         printf("the code shouldn't come here \n");
    }

    return;
}

static void hdl (int sig, siginfo_t *siginfo, void *context)
{
    printf("SIGALARM signal received.. unlock the spin lock");
    pthread_spin_unlock(&slock);
    return;

}

int main()
{
    /* REGISTER FOR SIGALARM SIGNAL */
    struct sigaction act;
    memset (&act, '\0', sizeof(act));
    /* Use the sa_sigaction field because the handles has two additional parameters */
    act.sa_sigaction = &hdl;
    /* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
    act.sa_flags = SA_SIGINFO;
    act.sa_flags = SA_INTERRUPT;
    if (sigaction(SIGALRM, &act, NULL) < 0) {
        perror ("sigaction");
        return 1;
    }

    pthread_spin_init(&slock, PTHREAD_PROCESS_PRIVATE);
    /* USING SPINLOCK, MAKE THE PROCESS SPIN INDEFINITELY HERE */
    splock();

    pthread_spin_destroy(&slock);
    return 0;
}


Output:

neelkanth_surekha#./a.out &
[1] 6459
neelkanth_surekha#

first time spin lock applied: ret = 0
***************************************************
******** GIVE SIGALRM TO THE PROCESS TO UNBLOCK THE SPINLOCK *****
***************************************************

neelkanth_surekha#ps -elf | grep a.out
0 R neelkan+  6459 14458 93  80   0 -  1630 -      01:29 pts/1    00:00:05 ./a.out
0 S neelkan+  6461 14458  0  80   0 -  3556 pipe_w 01:29 pts/1    00:00:00 grep --color=auto a.out

neelkanth_surekha#kill -14 6459          <------ Send SIGALRM to the process to unlock the spin lock
SIGALARM signal received.. unlock the spin lock
 Spin lock acquired again 

 Spinlock unlocked immediately. At this point the process is free of spin lock 
neelkanth_surekha#ps -elf | grep a.out
0 S neelkan+  6466 14458  0  80   0 -  3556 pipe_w 01:29 pts/1    00:00:00 grep --color=auto a.out
[1]+  Done                    ./a.out