Sandy
Sandy

Reputation: 65

Difference between mutual exclusion and blocked-IO in kernel programming?

I am unable to understand the difference between the follwing two codes. Can any body explain the difference between the following codes & also explain the differnece between semaphore and mutex with example....

Mutual exclusion:

DEFINE_SEMAPHORE(mysem);
static ssize_t dev_read(struct file *file,char *buf, size_t lbuf, loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_to_user(buf,dev_buf+*ppos,bytes_to_do);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}
static ssize_t dev_write(struct file *file,const char *buf, size_t lbuf, 
                            loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_from_user(dev_buf+*ppos,buf,bytes_to_do);
    ssleep(10);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}

Blocked IO

init_MUTEX_LOCKED(&mysem);
static ssize_t dev_read(struct file *file,char *buf, size_t lbuf, loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    if(down_interruptible(&mysem))
        return -ERESTARTSYS;
    nbytes = bytes_to_do - copy_to_user(buf,dev_buf+*ppos,bytes_to_do);
    *ppos += nbytes;
    return nbytes;
}
static ssize_t dev_write(struct file *file,const char *buf, size_t lbuf, 
                            loff_t *ppos)
{
    int maxbytes, bytes_to_do, nbytes;
    maxbytes = SIZE - *ppos;
    if(maxbytes < lbuf) bytes_to_do = maxbytes;
    else bytes_to_do = lbuf;
    if(bytes_to_do == 0){
        printk("reached end of device\n");
        return -ENOSPC;
    }
    nbytes = bytes_to_do - copy_from_user(dev_buf+*ppos,buf,bytes_to_do);
    ssleep(10);
    up(&mysem);
    *ppos += nbytes;
    return nbytes;
}

Upvotes: 0

Views: 358

Answers (1)

pratik
pratik

Reputation: 434

Mutex is nothing but a binary semaphore. It means that mutex can have only two states : locked and unlocked. But semaphore can have more than two counts. So number of processes which can acquire the semaphore lock is equal to the count with which semaphore is initialized.

In your example, in first code snippet, whether it is read or write, whichever is acquiring the lock is itself releasing the lock also after it completes its respective read or write. Both can not work simultaneously due to mutex.

While in second code snippet, the code exhibits blocking I/O concept which is designed to solve a problem explained in a book Linux Device Drivers(LDD) : "what to do when there's no data yet to read, but we're not at end-of-file. The default answer is go to sleep waiting for data". As you can see in the code, lock is declared as Mutex and that also in locked state. So, if any read comes when there is no data, it can not acquire a lock as mutex is already in locked state, so it will go to sleep (In short read is blocked). Whenever any write come, it first writes to device and then it releases the mutex. So, now blocked read can acquire that lock and can complete its read process. Here also, both can not work simultaneously, but lock acquiring and releasing mechanism is synchronized in such a manner that read can not progress until write does not write anything to device.

Upvotes: 2

Related Questions