2011年5月7日 星期六

Linux Kernel(14)- Kernel Synchronization


這裡簡單介紹的介紹一下Kernel Synchronization的幾個觀念的幾個觀念。
  1. Race Condition
  2. 當多個process同時對同一個資料進行存取,且執行結果和其存取順序的不同而有所不同,稱為race condition。
  3. Critical Regions(或稱critical sections)
  4. 指的是一個存取共用資源的程式片斷。
  5. Kernel Synchronization
  6. 簡單說防止kernel發生race condition。保護的重點是shared data,而且保護的範圍和負擔越小越好。

Kernel Synchronization常見的作法就是locking,每次只允許一個process可以存取share data,就可以避免race condition了。

    在kernel中有幾種引發concurrency的可能
  1. Interrupt
  2. 當CPU收到interrupt會立刻中斷目前工作去執行interrupt handler。
  3. Softirq
  4. 當softirq被raise起來就會中斷目前工作去執行softirq。
  5. kernel preemption
  6. 如果kernel preemption被開啟,那麼task就可能被中斷。
  7. Sleeping
  8. 如果kernel執行到blocking code,就可能被schedule出去。
  9. SMP
  10. 同時間兩個以上的CPU存取相同的資料就會發生race condition。


在linunx kernel中,執行的context主要分成兩種interrupt context和process context,凡是只要in_interrupt()都是interrupt context,所以引起的原因包含Hardware interrupt和softirq兩種。以下就擷取片段程式碼說明。
// thread_info存放在task的stack裡面
# define task_thread_info(task)  ((struct thread_info *)(task)->stack)

// thread_info中的preempt_count分成幾個部份
// bits 0-7 are the preemption count (max preemption depth: 256)
// bits 8-15 are the softirq count (max # of softirqs: 256)
// bits 16-25 are the hardirq count (max # of nested hardirqs: 1024)
// bit 26 is the NMI_MASK
// bit 28 is the PREEMPT_ACTIVE flag
struct thread_info {
    struct task_struct *task;   /* main task structure */
    int    preempt_count;       /* 0 => preemptable */
};

# define preempt_count()        (current_thread_info()->preempt_count)
# define add_preempt_count(val) do { preempt_count() += (val); } while (0)
# define sub_preempt_count(val) do { preempt_count() -= (val); } while (0)

// 當每次呼叫irq_enter()就會將preempt_count屬於HARDIRQ的部份遞增
#define __irq_enter()                       \
    do {                                    \
        account_system_vtime(current);      \
        add_preempt_count(HARDIRQ_OFFSET);  \
        trace_hardirq_enter();              \
    } while (0)

# define invoke_softirq()   do_softirq()
# define IRQ_EXIT_OFFSET    HARDIRQ_OFFSET
/*
 * Exit an interrupt context. Process softirqs if needed and possible:
 */
void irq_exit(void)
{
    // 離開hard interrupt所以要減回去HARDIRQ_OFFSET
    sub_preempt_count(IRQ_EXIT_OFFSET);
    // 如果不在interrupt context(如softirq裡面),
    // 而且softirq有被raise就執行softirq
    if (!in_interrupt() && local_softirq_pending())
        invoke_softirq();
}

此圖出於http://blog.csdn.net/hero7935/archive/2011/05/07/6401522.aspx

    參考資料:
  • Linux Kernel Development 2nd, Novell Press



2011年4月16日 星期六

Adobe Flash “Square” on 64bit Linux for Firefox


安裝Adobe Flash到firefox事件小事,不過記一下免得以後還要再找一次,可以省事,
  1. http://labs.adobe.com/downloads/flashplayer10_square.html下載
  2. 解壓縮到/usr/lib64/mozilla/plugins
簡單結束。

現在可以看大盤的技術分析啦。


2011年3月19日 星期六

寫作小技巧in C


有些code寫的有些trick,不過常常因為太久沒用就忘記了,所以我決定特別留一篇,專門收集這種短小精幹的code。

判斷是不是2的n次方
if_power_of_2(n) (n != 0 && ((n & (n -1)) == 0))


XOR swap
void swap(int *x, int *y) {
    if (x != y) {
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}


Memory Alignment
作embedded常常會需要作一些Memory alignment的動作的動作,Linux的Netlink就有一小段macro可以拿來用。
#define NLMSG_ALIGNTO       4U // 作4byte alignment
#define NLMSG_ALIGN(len)    (((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1))
比如要讓NLMSG_HDRLEN能符合4byte-alignment就是定義如下的macro
#define NLMSG_HDRLEN        ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
陸續收集中...


熱門文章