为什么要在同一个数据结构中使用多个锁?

时间:2019-06-26 01:47:23

标签: concurrency locking linux-device-driver device-driver

我一直在学习一些我想写的existing C code for a device driver。这是我第一次处理并发和锁定,也是我第一次处理任何与硬件相关的问题,例如设备驱动程序。我发现了一段代码,似乎对同一数据结构使用了多个锁。我想知道为什么有人会在 same 数据结构中包括两个不同的锁定结构(自旋锁和互斥锁),而不是仅一个锁来锁定整个数据结构?

struct wiimote_state {
    spinlock_t lock;
    __u32 flags;
    __u8 accel_split[2];
    __u8 drm;
    __u8 devtype;
    __u8 exttype;
    __u8 mp;

    /* synchronous cmd requests */
    struct mutex sync;
    struct completion ready;
    int cmd;
    __u32 opt;

    /* results of synchronous requests */
    __u8 cmd_battery;
    __u8 cmd_err;
    __u8 *cmd_read_buf;
    __u8 cmd_read_size;

    /* calibration/cache data */
    __u16 calib_bboard[4][3];
    __s16 calib_pro_sticks[4];
    __u8 pressure_drums[7];
    __u8 cache_rumble;
};

使用这些多重锁定的代码段示例:

static void wiimote_init_detect(struct wiimote_data *wdata)
{
    __u8 exttype = WIIMOTE_EXT_NONE, extdata[6];
    bool ext;
    int ret;

    wiimote_cmd_acquire_noint(wdata);

    spin_lock_irq(&wdata->state.lock);
    wdata->state.devtype = WIIMOTE_DEV_UNKNOWN;
    wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
    wiiproto_req_status(wdata);
    spin_unlock_irq(&wdata->state.lock);

    ret = wiimote_cmd_wait_noint(wdata);
    if (ret)
        goto out_release;

    spin_lock_irq(&wdata->state.lock);
    ext = wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED;
    spin_unlock_irq(&wdata->state.lock);

    if (!ext)
        goto out_release;

    wiimote_cmd_init_ext(wdata);
    exttype = wiimote_cmd_read_ext(wdata, extdata);

out_release:
    wiimote_cmd_release(wdata);
    wiimote_init_set_type(wdata, exttype);

    /* schedule MP timer */
    spin_lock_irq(&wdata->state.lock);
    if (!(wdata->state.flags & WIIPROTO_FLAG_BUILTIN_MP) &&
        !(wdata->state.flags & WIIPROTO_FLAG_NO_MP))
        mod_timer(&wdata->timer, jiffies + HZ * 4);
    spin_unlock_irq(&wdata->state.lock);
}

static inline void wiimote_cmd_acquire_noint(struct wiimote_data *wdata)
{
    mutex_lock(&wdata->state.sync);
}

static inline void wiimote_cmd_release(struct wiimote_data *wdata)
{
    mutex_unlock(&wdata->state.sync);
}

1 个答案:

答案 0 :(得分:0)

这里发生了几件事。

首先,不要认为自旋锁和互斥锁必然是“用于”数据结构的,仅仅是因为它们位于数据结构中。在这种情况下,自旋锁似乎就是您所描述的,它是用于访问数据结构的锁。互斥锁似乎是命令wiimote动作的锁。

接下来,自旋锁和互斥锁完全不同,关键是互斥锁被阻塞,自旋锁会轮询直到资源可用。

最后,虽然这不是我在这里看到的,但是如果模块是由不同的开发人员在不同的时间实现的,则该模块可以同时包含自旋锁和互斥锁,它们具有相似的功能。