Daniel
Daniel

Reputation: 13

Is this implementation of a spinlock correct?

I am a novice studying Linux kernel, kernel modules and device drivers for operating systems. Can you please help me confirm if the following implementation of a spinlock is correct, If you assume that the multiprocessor system provides sequential consistency?

struct Lock{
        int locked;
    }

int exchange_value(int* ptr, int val){
    int was;
    wss=*ptr;
    *ptr=val;
    return was;
}
voidacquire(Lock *lock){
    local_irq_disable();
    while(1){
        if(exchange_value(&lock->locked, 1) == 0)
        break;
    }
}

void release(Lock *lock){
    exchange_value(&lock->locked, 0);
    local_irq_enable();
}

If it's not correct can you provide me with a better example so that i will understand it better? Sorry for not providing any commends or more explantions, it's because i don't fully understand this code that i was given. Thank you in advance for your assistance.

Upvotes: 0

Views: 784

Answers (1)

Achal
Achal

Reputation: 11921

Is this implementation of a spinlock correct? Not sure but I don't think so as you are asking about spinock but code you written is about interrupt handling in kernel. Well up to certain extent you can link them. Read this https://notes.shichao.io/lkd/ch8/#disabling-bottom-halves about interrupts in kernel.

Firstly why to use spinlock() mechanism ?

  • Simple answer would be to achieve the synchronization in interrupt handlers.
  • If the lock is available, process will acquire it and will continue in the critical section and unlock it, once its done. This is similar to mutex.
  • But, what if lock is not available ? Here, comes the interesting difference. With mutex, the process will sleep, until the lock is available. But, in case of spinlock, it goes into the tight loop, where it continuously checks for a lock, until it becomes available.
  • This is the spinning part of the spin lock. This was designed for multiprocessor systems.

API's for spinlock ?

  • First create the variable of struct spinlock_t as struct spinlock_t my_slock;

  • Initialize the my_slock as spinlock_init(&my_slock);.

  • while writing time, put the spin lock by calling spin_lock(&my_slock); when spin lock seen by reader application, it will wait.

  • unlock it once done by calling spin_unlock(&my_slock);

Here is the driver program for your reference about how to use spinlock.

#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
static int major;
static spinlock_t slock;
static unsigned int pwait = 10000;
module_param(pwait, int, 0);
/* Default delay is 10 seconds */
/* MilliSeconds */
static int spin_open(struct inode *inode, struct file *filp) {
        return 0;
}
static int spin_close(struct inode *inode, struct file *filp) {
        return 0;
}
static ssize_t spin_read(struct file *filp, char __user *buf,size_t sz, loff_t *fpos) {/* main is read function */
        printk("Read begins: Trying to aquire same spinlock\n");
        spin_lock( &slock ); /* applied the lock .. when reader apps seen it, it will wait */
        printk("Read : Acquired spinlock now !!\n");
        printk("Read done. Releasing the spinlock\n");
        spin_unlock( &slock );
        return 0;
}
static ssize_t spin_write( struct file *filp, const char __user *buf,size_t sz, loff_t *fpos )
{
        printk("Write begins\n");
        spin_lock( &slock );
        printk("Write : Acquired a spinlock...\n");
        mdelay( pwait );
        /* Pretending to do some work */
        printk("Write done. Releasing the spinlock\n");
        spin_unlock( &slock );
        return sz;
}
static struct file_operations spin_fops = {
        .open = spin_open,
        .release = spin_close,
        .read = spin_read,
        .write = spin_write,
        .owner = THIS_MODULE,
};
static int __init start(void) {
        major = register_chrdev(0, "spin", &spin_fops);
        if ( major < 0 ) {
                printk("Error obtaining major number\n");
                return -1;
        }
        else {
                printk("Successfully registered major number %d\n",major);
                printk("create device name = spin \n");
        }
        spin_lock_init( &slock );
        return 0;
}
void stop(void){
        pr_info("module unregistered successfully \n");
        unregister_chrdev(major, "spin");
}
module_init(start);
module_exit(stop);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("achal singh : [email protected]");
MODULE_DESCRIPTION("Syn Technique : Spin lock");

By assuming that you know how to create the Makefile for your driver, how to create device file using mknod or any other method & check dmesg. Finally write one user application & analyze.

I hope it gives you basic idea about spinlock.

Upvotes: 1

Related Questions