6.6 linux內(nèi)核完成量

內(nèi)核完成量是一種輕量級(jí)的機(jī)制,它允許一個(gè)線程告訴另一個(gè)線程工作已經(jīng)完成。

完成量的定義

completion 結(jié)構(gòu)體的定義

/*
 * struct completion - structure used to maintain state for a "completion"
 *
 * This is the opaque structure used to maintain the state for a "completion".
 * Completions currently use a FIFO to queue threads that have to wait for
 * the "completion" event.
 *
 * See also:  complete(), wait_for_completion() (and friends _timeout,
 * _interruptible, _interruptible_timeout, and _killable), init_completion(),
 * reinit_completion(), and macros DECLARE_COMPLETION(),
 * DECLARE_COMPLETION_ONSTACK().
 */
struct completion {
    unsigned int done;
    struct swait_queue_head wait;
};
struct swait_queue_head {
    raw_spinlock_t      lock;
    struct list_head    task_list;
};

完成量的初始化

/**
 * init_completion - Initialize a dynamically allocated completion
 * @x:  pointer to completion structure that is to be initialized
 *
 * This inline function will initialize a dynamically created completion
 * structure.
 */
static inline void init_completion(struct completion *x)
{
    x->done = 0;
    init_swait_queue_head(&x->wait);
}

等待完成量

/**
 * wait_for_completion: - waits for completion of a task
 * @x:  holds the state of this particular completion
 *
 * This waits to be signaled for completion of a specific task. It is NOT
 * interruptible and there is no timeout.
 *
 * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
 * and interrupt capability. Also see complete().
 */
void __sched wait_for_completion(struct completion *x)
{
    wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(wait_for_completion);
static inline long __sched
do_wait_for_common(struct completion *x,
           long (*action)(long), long timeout, int state)
{
    if (!x->done) {
        DECLARE_SWAITQUEUE(wait);

        do {
            if (signal_pending_state(state, current)) {
                timeout = -ERESTARTSYS;
                break;
            }
            __prepare_to_swait(&x->wait, &wait);
            __set_current_state(state);
            raw_spin_unlock_irq(&x->wait.lock);
            timeout = action(timeout);
            raw_spin_lock_irq(&x->wait.lock);
        } while (!x->done && timeout);
        __finish_swait(&x->wait, &wait);
        if (!x->done)
            return timeout;
    }
    if (x->done != UINT_MAX)
        x->done--;
    return timeout ?: 1;
}

static inline long __sched
__wait_for_common(struct completion *x,
          long (*action)(long), long timeout, int state)
{
    might_sleep();

    complete_acquire(x);

    raw_spin_lock_irq(&x->wait.lock);
    timeout = do_wait_for_common(x, action, timeout, state);
    raw_spin_unlock_irq(&x->wait.lock);

    complete_release(x);

    return timeout;
}

static long __sched
wait_for_common(struct completion *x, long timeout, int state)
{
    return __wait_for_common(x, schedule_timeout, timeout, state);
}

通知完成量

/**
 * complete: - signals a single thread waiting on this completion
 * @x:  holds the state of this particular completion
 *
 * This will wake up a single thread waiting on this completion. Threads will be
 * awakened in the same order in which they were queued.
 *
 * See also complete_all(), wait_for_completion() and related routines.
 *
 * If this function wakes up a task, it executes a full memory barrier before
 * accessing the task state.
 */
void complete(struct completion *x)
{
    unsigned long flags;

    raw_spin_lock_irqsave(&x->wait.lock, flags);

    if (x->done != UINT_MAX)
        x->done++;
    swake_up_locked(&x->wait);
    raw_spin_unlock_irqrestore(&x->wait.lock, flags);
}
EXPORT_SYMBOL(complete);

完成量的使用

1、完成量的初始化
a)動(dòng)態(tài)初始化

struct completion my_comp;  
init_completion(&my_comp); 

b)靜態(tài)初始化

DECLARE_COMPLETION(my_comp);  

2、等待完成量

//等待完成量喚醒且不會(huì)被外部信號(hào)打斷
void wait_for_completion(struct completion *comp); 
//等待一個(gè)完成量被喚醒;但是它可以被外部信號(hào)打斷;
int wait_for_completion_interruptible(struct completion* comp):
//該函數(shù)等待一個(gè)完成量被喚醒,如果沒(méi)有喚醒也會(huì)超時(shí)返回
unsigned long wait_for_completion_timeout(struct completion* comp, unsigned long timeout):

3、喚醒等待的線程

//只喚醒一個(gè)正在等待完成量comp的執(zhí)行單元;
void complete(struct completion* comp):
//喚醒所有正在等待同一個(gè)完成量comp的執(zhí)行單元;
void complete_all(struct completion* comp):

實(shí)例

struct cyttsp {
        ......
    struct completion bl_ready;
        ......
}

init_completion(&ts->bl_ready);

static int cyttsp_soft_reset(struct cyttsp *ts)
{
    int retval;

    /* wait for interrupt to set ready completion */
    reinit_completion(&ts->bl_ready);
    ts->state = CY_BL_STATE;

    enable_irq(ts->irq);

    retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
    if (retval) {
        dev_err(ts->dev, "failed to send soft reset\n");
        goto out;
    }

    if (!wait_for_completion_timeout(&ts->bl_ready,
            msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX))) {
        dev_err(ts->dev, "timeout waiting for soft reset\n");
        retval = -EIO;
    }

out:
    ts->state = CY_IDLE_STATE;
    disable_irq(ts->irq);
    return retval;
}

static irqreturn_t cyttsp_irq(int irq, void *handle)
{
    struct cyttsp *ts = handle;
    int error;

    if (unlikely(ts->state == CY_BL_STATE)) {
        complete(&ts->bl_ready);
        goto out;
    }

    /* Get touch data from CYTTSP device */
    error = ttsp_read_block_data(ts, CY_REG_BASE,
                 sizeof(struct cyttsp_xydata), &ts->xy_data);
    if (error)
        goto out;

    /* provide flow control handshake */
    error = cyttsp_handshake(ts);
    if (error)
        goto out;

    if (unlikely(ts->state == CY_IDLE_STATE))
        goto out;

    if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
        /*
         * TTSP device has reset back to bootloader mode.
         * Restore to operational mode.
         */
        error = cyttsp_exit_bl_mode(ts);
        if (error) {
            dev_err(ts->dev,
                "Could not return to operational mode, err: %d\n",
                error);
            ts->state = CY_IDLE_STATE;
        }
    } else {
        cyttsp_report_tchdata(ts);
    }

out:
    return IRQ_HANDLED;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一章 設(shè)備驅(qū)動(dòng)程序的簡(jiǎn)介 處于上層應(yīng)用與底層硬件設(shè)備的軟件層 區(qū)分機(jī)制和策略是Linux最好的思想之一,機(jī)制指的...
    xiaozi63閱讀 900評(píng)論 0 0
  • 綜述 并發(fā)問(wèn)題是編程中經(jīng)常遇到的難題,我們需要學(xué)會(huì)針對(duì)并發(fā)產(chǎn)生的競(jìng)態(tài)進(jìn)行編程 一、信號(hào)量和互斥體 Linux上信號(hào)...
    擼碼的日子閱讀 567評(píng)論 0 1
  • 在驅(qū)動(dòng)程序中,當(dāng)多個(gè)線程同時(shí)訪問(wèn)相同的資源時(shí)(驅(qū)動(dòng)程序中的全局變量是一種典型的共享資源),可能會(huì)引發(fā)"競(jìng)態(tài)",因此...
    sinlinx123閱讀 581評(píng)論 0 0
  • 個(gè)人筆記,方便自己查閱使用 Contents Java LangAssignment, ReferenceData...
    freenik閱讀 1,536評(píng)論 0 6
  • 進(jìn)程與線程 典型的UNIX/Linux進(jìn)程可以看成只有一個(gè)控制線程:一個(gè)進(jìn)程在同一時(shí)刻只做一件事情。有了多個(gè)控制線...
    北支浪閱讀 357評(píng)論 0 0

友情鏈接更多精彩內(nèi)容