现在的位置: 首页 > 综合 > 正文

trace-clock-32-to-64.c 分析

2013年02月08日 ⁄ 综合 ⁄ 共 11628字 ⁄ 字号 评论关闭

AUTHOR: Joseph Yang (杨红刚) <ganggexiongqi@gmail.com>
CONTENT: trace-clock-32-to-64.c 分析 
NOTE: linux2.6.38.6
LAST MODIFIED:10-09-2011
-----------------------------------------------------------------------------------------------------------
Distributed and Embedded System Lab (分布式嵌入式系统实验室,兰州大学)
===============================================================

 /*
 * Extends a 32 bits clock source to a full 64 bits count, readable atomically
 * from any execution context.
 */

-  trace-clock-32-to-64.c (/usr/src/linux2.6.38.6-lttng-0.249/kernel/trace)
|-   macro
||     HW_BITMASK
||     HW_LS32
||     SW_MS32                
|  
|-   struct
||     synthetic_tsc_struct   
|  
|-   variable
||     synthetic_tsc_refcount
||     synthetic_tsc_enabled  
||     precalc_expire
||     trace_clock_read_synthetic_tsc
||     get_synthetic_tsc      
||     put_synthetic_tsc
||     init_synthetic_tsc     
|  
|-   function
||     update_synthetic_tsc +
||     _trace_clock_write_synthetic_tsc
||     trace_clock_read_synthetic_tsc  
||     synthetic_tsc_ipi  +     
||     tsc_timer_fct +
||     precalc_stsc_interval   +
||     prepare_synthetic_tsc  +
||     enable_synthetic_tsc +
||     disable_synthetic_tsc +
||     hotcpu_callback +
||     get_synthetic_tsc +
||     put_synthetic_tsc +
||     init_synthetic_tsc     +
=============================================

---------------- 相关变量和结构
#define HW_BITMASK          ((1ULL << TC_HW_BITS) - 1)
#define HW_LS32(hw)         ((hw) & HW_BITMASK)
#define SW_MS32(sw)         ((sw) & ~HW_BITMASK)

static DEFINE_SPINLOCK(synthetic_tsc_lock); // 用来保护synthetic_tsc_refcount, synthetic_tsc_enabled
         //tsc_timer, synthetic_tsc
static int synthetic_tsc_refcount;  /* Number of readers */
static int synthetic_tsc_enabled;   /* synth. TSC enabled on all online CPUs */

static DEFINE_PER_CPU(struct timer_list, tsc_timer); //在该内核定时器的回调函数
                                          //用于在硬件时钟源溢出前,做出溢出处理,更新“伪时钟“的值。
static unsigned int precalc_expire; // 该值用来设置内核定时器tsc_timer的定时间隔。

struct synthetic_tsc_struct {
    union {
        u64 val;
        struct {
#ifdef __BIG_ENDIAN
            u32 ms32;
            u32 ls32;
#else
            u32 ls32;
            u32 ms32;
#endif
        } sel;
    } tsc[2];
    unsigned int index; /* Index of the current synth. tsc. */
};

static DEFINE_PER_CPU(struct synthetic_tsc_struct, synthetic_tsc);//每个CPU一个“伪tsc时钟”

外部接口:
EXPORT_SYMBOL_GPL(trace_clock_read_synthetic_tsc);
EXPORT_SYMBOL_GPL(get_synthetic_tsc);
EXPORT_SYMBOL_GPL(put_synthetic_tsc);
----------------- 函数
1.
函数:
/* Called from CPU 0, before any tracing starts, to init each structure */
static int __init init_synthetic_tsc(void)
参数:
功能:/* Called from CPU 0, before any tracing starts, to init each structure */
流程:
             Precalculates the interval between the clock wraparound //precalc_stsc_interval()
             注册hotcpu_callback用以在CPU的不同状态下,管理  synthetic tsc 和 tsc_timer //hotcpu_notifier
--------------------
 

2.
函数: 没有看懂计算公式
/*
 * precalc_stsc_interval: - Precalculates the interval between the clock
 * wraparounds.
 */
static int __init precalc_stsc_interval(void)
参数:
返回值: static unsigned int precalc_expire;
功能:Precalculates the interval between the clock wraparounds. (jiffies)
流程:
                                                                              

                                                    2^TC_HW_BITS - 1
precalc_expire = --------------------------------------------------------------------------------------------------------
                               2^ TRACE_CLOCK_SHIFT - 1 - TC_EXPECTED_INTERRUPT_LATENCY*HZ/1000
               
                                                                                                2^TC_HW_BITS - 1              
            = ------------------------------------------------------------------------------------------------------------------ ------------------------------
               {trace_clock_frequency() / [ HZ * trace_clock_freq_scale()]}*2 - 1 - TC_EXPECTED_INTERRUPT_LATENCY*HZ/1000 

     
     
     
 时间*HZ : 从时间转化为对应的jiffies数(tickes)。
 jiffies / HZ :从jiffies(tickes)转化为时间。
           
----------------
trace_clock_frequency(): HZ << TRACE_CLOCK_SHIFT,  TRACE_CLOCK_SHIFT = 13
 __iter_div_u64_rem(a,b,&c):  返回值是32位无符号的商,
                                               a是64位被除数,b是32位除数,c是余数
trace_clock_freq_scale():  返回1
#define TC_EXPECTED_INTERRUPT_LATENCY 30
#define HW_BITMASK          ((1ULL << TC_HW_BITS) - 1) // 32个1
/*
* Number of hardware clock bits. The higher order bits are expected to be 0.
* If the hardware clock source has more than 32 bits, the bits higher than the
* 32nd will be truncated by a cast to a 32 bits unsigned. Range : 1 - 32.
* (too few bits would be unrealistic though, since we depend on the timer to
* detect the overflows).
*/
#define TC_HW_BITS          32

3.
函数: // kernel/trace/trace-clock-32-to-64.c
 *  @action: hotplug action to take
 *  @hcpu: CPU number
 *
 *  Sets the new CPU's current synthetic TSC to the same value as the
 *  currently running CPU.
 *
 *  Returns the success/failure of the operation. (NOTIFY_OK, NOTIFY_BAD)
 */
static int __cpuinit hotcpu_callback(struct notifier_block *nb,
                unsigned long action,
                void *hcpu);
参数:
返回值:
功能:在CPU的不同状态下,管理  synthetic tsc 和 tsc_timer
流程:

     CPU_UP_PREPARE  或者 CPU_UP_PREPARE_FROZEN:
             初始化设置 per cpu 变量 synthetic tsc 和 tsc_timer //prepare_synthetic_tsc
     CPU_ONLINE 或者 CPU_ONLINE_FROZEN:
           更新synthetic_tsc的值并在cpu号CPU上开始运行 tsc_time  //enable_synthetic_tsc
     CPU_DOWN_PREPARE 或者 CPU_DOWN_PREPARE_FROZEN:
            在CPU cpu 上,删除内核定时器 tsc_timer //disable_synthetic_tsc
      
          -------------
#define hotcpu_notifier(fn, pri)    cpu_notifier(fn, pri)
#define cpu_notifier(fn, pri) {                 \
    static struct notifier_block fn##_nb __cpuinitdata =    \
        { .notifier_call = fn, .priority = pri };   \
    register_cpu_notifier(&fn##_nb);            \
}

#define CPU_UP_PREPARE      0x0003 /* CPU (unsigned)v coming up */
#define CPU_ONLINE      0x0002 /* CPU (unsigned)v is up */
#define CPU_DOWN_PREPARE    0x0005 /* CPU (unsigned)v going down */

/* Used for CPU hotplug events occuring while tasks are frozen due to a suspend
 * operation in progress
 */  
#define CPU_UP_PREPARE_FROZEN   (CPU_UP_PREPARE | CPU_TASKS_FROZEN)

4.
函数:static void prepare_synthetic_tsc(int cpu)
参数:
返回值:
功能: 初始化设置 per cpu 变量 synthetic tsc 和 tsc_timer
流程:
               获得跟cpu相关的synthetic_tsc // &per_cpu
               读取 synthetic tsc 的值 //trace_clock_read_synthetic_tsc
               把读到的 synthetic tsc 的值存入 cpu_synth->tsc[0].val,并把指示当前synth. tsc.
                         的索引 cpu_synth->index 置为0
             // init_timer_deferrable(&per_cpu(tsc_timer, cpu));                                                                             // ??????????
             设置tsc_timer的function 为 tsc_timer_fct
             设置tsc_timer的 expires 为 jiffies + precalc_expire              
               
5.
函数:
/* Called from buffer switch : in _any_ context (even NMI) */
u64 notrace trace_clock_read_synthetic_tsc(void);
参数:
返回值: 64位的 synthetic tsc 的值
功能:读取 synthetic tsc 的值
流程:
             preempt_disable_notrace()   // 当前进程的preempt_count增一
            读取synthetic tsc的索引(Index of the current synth. tsc. ) // ACCESS_ONCE  
            读取 TSC的值(只读取了32位)
                                           /* Hardware clocksource read */ //trace_clock_read32        (arch/x86/include/asm/trace-clock.h)
             溢出检测与处理://这个处理假设了溢出只发生了一次的情况
                     如果有溢出,则  返回 (高32位 | 低32位 + 低32向高32的一个进位)//假设TC_HW_BITS 为32
                     如果没有溢出,则 返回(高32位 | 低32位)  
               
            当前进程的preempt_count减一,如果需要调度,则调度//  preempt_enable_notrace()      
            
6.
函数:static void enable_synthetic_tsc(int cpu)
参数:
返回值:
功能:更新synthetic_tsc的值并在cpu号CPU上开始运行 tsc_timer
流程:
             在cpu号CPU上执行synthetic_tsc_ipi以便更新synthetic_tsc的值,
                            并等待它在其他CPU上执行完毕                     //smp_call_function_single
             在cpu号CPU上开始运行 tsc_timer //add_timer_on
                        // tsc_timer_fct:更新synthetic_tsc的值,修改tsc_timer的超时值 为 precalc_expire   
                      
7.
函数:static void synthetic_tsc_ipi(void *info)
参数:
返回值:
功能:更新synthetic_tsc的值
流程:
              更新synthetic_tsc的值 //update_synthetic_tsc()

             
8.     ///重点分析:synthetic_tsc_struct结构的设计和操作原理                                                           ????
函数:
/* Called from IPI or timer interrupt */
static void update_synthetic_tsc(void)
参数:
返回值:
功能:更新synthetic_tsc的值
流程:
            /* Hardware clocksource read */ // trace_clock_read32()
            
            检查本cpu上 synthetic_tsc是否有溢出:
                          如果有溢出,则  
                                        计算新的synthetic tsc 索引 ( Index of the current synth. tsc.)         //  index 0 <-> 1
                                       用(高32位 | 低32位 + 低32向高32的一个进位)更新
                                                cpu_synth->tsc[new_index].val                            //假设TC_HW_BITS 为32
                                       更新 cpu_synth->index
                          如果没有溢出,则
                                    更新 cpu_synth->tsc[cpu_synth->index].sel.ls32
                                    
9.
函数: //没有看懂为什么要这么做????//为了在硬件计数器溢出前异步的更新
                                                                                        //伪时钟的计数值
/*
 * tsc_timer_fct : - Timer function synchronizing synthetic TSC.
 * @data: unused
 * Guarantees at least 1 execution before low word of TSC wraps.
 */
static void tsc_timer_fct(unsigned long data)
参数:
返回值:
功能:更新synthetic_tsc的值,修改tsc_timer的超时值 为 precalc_expire                                     
流程:
             更新synthetic_tsc的值 //update_synthetic_tsc
             修改tsc_timer的超时值 为 precalc_expire //mod_timer_pinned
             
10.
函数:static void disable_synthetic_tsc(int cpu)
参数:
返回值:
功能:在CPU cpu 上,删除内核定时器 tsc_timer
流程:
              在CPU cpu 上,删除内核定时器 tsc_timer //del_timer_sync
              
11.
函数:void get_synthetic_tsc(void)
参数:
返回值:
功能:对synthetic_tsc读者计数器 synthetic_tsc_refcount 加一,
               第一次执行时: synthetic_tsc_enabled 置1(synth. TSC enabled on all online CPUs)
                                                  开始synthetic tsc 的运行
流程:
           获得synthetic_tsc_lock锁 //spin_lock
           
           synthetic_tsc_refcount++
           如果是第一次执行,则
                            synthetic_tsc_enabled 置1,synth. TSC enabled on all online CPUs
                           对于所有在线的CPUs:
                                 初始化设置 per cpu 变量 synthetic tsc 和 tsc_timer //prepare_synthetic_tsc
                                 更新synthetic_tsc的值并在cpu号CPU上开始运行 tsc_timer //enable_synthetic_tsc
                
           释放synthetic_tsc_lock 锁//spin_unlock
           
12.
函数:void put_synthetic_tsc(void)
参数:
返回值:
功能:对synthetic_tsc读者计数器 synthetic_tsc_refcount 减一,
                最后一个读者时:synthetic_tsc_enabled关闭停止synthetic_tsc
                                          
流程:
             获得synthetic_tsc_lock锁 //spin_lock
             当最后一个读者时,
                     在所有在线的CPU执行:
                              在CPU cpu 上,删除内核定时器 tsc_timer  // disable_synthetic_tsc
              
              synthetic_tsc_refcount--     
             释放synthetic_tsc_lock 锁//spin_unlock
             
13.
函数: // ???被谁调用
 /*
 * Should only be called when interrupts are off. Affects only current CPU.
 */
void _trace_clock_write_synthetic_tsc(u64 value)
参数:
返回值:
功能: 更新 cpu_synth->tsc[].val 的值,和索引
流程:
             获得本CPU的synthetic_tsc的指针 //&per_cpu
             计算新的索引new_index//   0 <--> 1
             cpu_synth->tsc[new_index].val = value
             /* atomic change of index */
           
              
---------------------------
 
typedef struct {
    int counter;
} atomic_t;

/*
 * bits 0..12 : counter, atomically incremented
 * bits 13..{32,64} : time counter, incremented each jiffy.
 */
atomic_long_t trace_clock_var;                                                                                                                           //作用????
EXPORT_SYMBOL(trace_clock_var);

-------------
#define preempt_disable_notrace() \ // 当前进程的preempt_count增一
do { \
    inc_preempt_count_notrace(); \
    barrier(); \
} while (0)

#define inc_preempt_count_notrace() add_preempt_count_notrace(1)

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

#define preempt_enable_notrace() \ // 当前进程的preempt_count减一,如果需要调度,则调度
do { \
    preempt_enable_no_resched_notrace(); \   // 当前进程的preempt_count减一
    barrier(); \
    preempt_check_resched(); \ //如果需要调度,则调度
} while (0)

#define preempt_check_resched() \
do { \
    if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ //如果需要调度
        preempt_schedule(); \  // 调度
} while (0)

#define test_thread_flag(flag) \  // 测试 进程的 flag是否值位
    test_ti_thread_flag(current_thread_info(), flag)
    
static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
{
    return test_bit(flag, (unsigned long *)&ti->flags);
}

抱歉!评论已关闭.