Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301309
  • 博文数量: 94
  • 博客积分: 2163
  • 博客等级: 大尉
  • 技术积分: 932
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-20 09:23
文章存档

2012年(2)

2011年(92)

分类: LINUX

2011-09-27 19:33:09

  由于写到这里才想起写博客:
[code]
typedef struct raw_spinlock{
arch_spinlock_t raw_lock; /* asm/spinlock_types/

#ifdef CONFIG_GENERIC_LOCKBREAK
    unsigned int break_lock;  /*进程正在忙等待自旋(在smp和内核抢占的情况下使用*/
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
  unsigned int magic , owner_cpu;
  void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
   struct lock_map dep_map;
#endif
}raw_spinlock_t; /*一般在某种结构体名称都有_t。*/
typedef struct arch_spinlock{
unsigned int lock;
}arch_spinlock_t;/*是吧,又一个_t*/ 
typedef struct arch_spinlock{

/*Next ticket number to hand out 下一个要取出的锁号*/
int next_ticket;
/*The ticket number that currently owns this lock :当前拥有锁号*/
int current_ticket;
}arch_spinlock_t; /*I guess it will be here :)*/
整个锁最后就是调用的辙个。看看其中的一种加锁
#define raw_spin_lock_irqsave(lock, flags )  \
do {                          \
               typecheck(unsigned long ,flags);   /*check the type* linux/typecheck.h /
               flags = _raw_spin_lock_irqsave(lock); \   /*linux/spinlock.c*/
}while (0)      

#define typecheck(type, x) \
({    type __dummy; \
      typeof(x) __dummy2; \
     (void) (&__dummy == &__dummy2); \  /* gcc warning if the type is not same*/
              1; \  /*Always evaluates to 1 so you may use it easily in comarions.这个 1 是用做比较等*/
})

[/code]
为了看void的作用,我写了程序。
[code]
#include
int main()
{
   int a = 1;
   int b = 2;
  void (a > b);
 return 1; /*这句没有写*/
}
objdump -d
 08048374
:
 8048374:       8d 4c 24 04             lea    0x4(%esp),%ecx  /*将堆栈的原栈顶保存*/
 8048378:       83 e4 f0                and    $0xfffffff0,%esp /*将现在的堆栈以4字节对齐*/
 804837b:       ff 71 fc                pushl  0xfffffffc(%ecx) /*0xfffffffc是-4,将原堆栈入栈*/
 804837e:       55                      push   %ebp  /*原堆栈基地址入栈*/
 804837f:       89 e5                   mov    %esp,%ebp /*换入新堆栈基地址(就是当前的栈顶)*/
 8048381:       51                      push   %ecx  /*远来的堆栈栈顶入栈*/
 8048382:       83 ec 10                sub    $0x10,%esp /*现在的堆栈栈顶下移 0x10就是4个字节*/
 8048385:       c7 45 f4 01 00 00 00    movl   $0x1,0xfffffff4(%ebp) /*移入数据 1*/
 804838c:       c7 45 f8 02 00 00 00    movl   $0x2,0xfffffff8(%ebp) /*移入数据 2*/
 8048393:       83 c4 10                add    $0x10,%esp  /*栈顶返回到原来的存放 %ecx的地址*/
 8048396:       59                      pop    %ecx   /*出栈*/
 8048397:       5d                      pop    %ebp  /*%ebp出栈*/
 8048398:       8d 61 fc                lea    0xfffffffc(%ecx),%esp /*同上,这是返回远来堆栈栈顶*/
 804839b:       c3                      ret    /*返回*/
 804839c:       90                      nop   
 804839d:       90                      nop   
 804839e:       90                      nop   
 804839f:       90                      nop 

没有见到void 的那一行操作,看样子只是gcc检查出现错误才会出现。
[/code]

unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
    return __raw_spin_lock_irqsave(lock); /* include/linux/spinlock_api_smp.h*/
}
EXPORT_SYMBLE(_raw_spin_lock_irqsave); /*这是输出到内核符号表*/
static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
    unsigned long flags;
  
    lock_irq_save(flags);/*
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

#ifdef CONFIG_LOCKDEP
   LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);/*检测是否死锁的宏定义 linux-2.6.39.1 ..../lockdep.h/*/
#else
   do_raw_spin_lock_flags(lock, flags);
#endif
    return flags;
}

#define LOCK_CONTENDED(_lock, try, lock)
\
do {
\   
if  (!try (_lock)) { /*Here is the do_raw_spin_trylock(lock) */
 \
    lock_contended ( &(_lock)->dep_map, _RET_IP_); /* `uname -r`/....lockdep.c*/
\
    lock(_lock);
\
}
\
   lock_acquired( &(_lock)->dep_map, _RET_IP_);
}while(0)
void lock_contended(struct lockdep_map *lock, unsigned long ip) /*检验*/
{
     unsigned long flags;

    if (unlikely(! lock_stat)) /*linux-2...../compiler.h, it is used here, it will be have return value 0 or 1  0.0 */
        return ;
    if(unlikely(current->lock_recursion))
       return ;
   raw_local_irq_save(flags);
   check_flags(flags);
   current->lockdep_recursion = 1;
   trace_lock_contended(lock, ip);
  __lock_contended(lock, ip);
  current->lockdep_recursion = 0;
  raw_local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(lock_contended);

#ifndef unlikely
# define unlikely(x)  (__builtin_constant_p(x) ? ! !(x) : __branch_check__(x, 0)) /*__builtin_constant_p()是gcc 专用函数 如果x在编译的时候就能获得常值,则为TRUE;如果是变量则为FALSE ||||||||||||||||||__branch_check__(x, expect) 同一个文件*/
#endif
#define __branch_check__(x, expect) ({  \ /*记录当前的trace点,并用后面的函数ftrace_likely_update记录likely的正确性,结果保存在ring buffer中。*/
 int ______r;
\
       static int ftrace_branch_data  /*定义在本文件中*/
 \
    __attribute__((__aligned__(4)))
\
    __attribute__((section("_ftrace_annotated_brach"))) \
    ________f = {
    \
   .func = __func___, /*这是宏定义见下面*/
\
   .file = __FILE__, /*这些元素都是标志trace节点*/
\
   .line = __LINE__,
\
};
\
______r = likely_notrace(x);  /*likely_notrace和unlilely_notrace宏使用__builtin_expect函数,告诉编译器程序设计者期望的比较结果,以便编译器对代码进行优化,改变汇编中的跳转语句*/
\
  ftrace_likely_update(&______f, ______r, expect); \
_____r;
\
})
#define likely_notrace(x)   __builtin_expect(! !(x), 1) /*期望运行可以说这里对应到 jne ,如果命中了,那么就返回1。*/
#define unlikely_notrace(x) __builtin_expect(! !(x), 0) /*这里对应到je,如果期望不继续追逐*/

struct ftrace_branch_data { /*结构体用于记录ftrace branch的trace记录*/
 const char *func;       
 const char *file;
 unsigned line;
 union {
  struct {
   unsigned long correct;
   unsigned long incorrect;
  };
  struct {
   unsigned long miss;
   unsigned long hit;
  };
  unsigned long miss_hit[2];
 };
};

0000000 :
      0: 55                       push      %ebp
      1: 89 e5                    mov       %esp,%ebp
      3: 8b 45 08                 mov       0x8(%ebp),%eax  /*这应该是取那个测试参数*/
      6: 83 05 38 00 00 00 01  addl      $0x1,0x38
    d: 83 15 3c 00 00 00 00  adcl      $0x0,0x3c

  14: 85 c0                    test      %eax,%eax   
  16: 74 15                    je        2d   /*如果是 %eax是0的时候,zf边成1,就跳转.这就是test_likely的好处,为以后最可能的跳转准备好了一切。*/
  18: 83 05 40 00 00 00 01  addl      $0x1,0x40
  1f: b8 05 00 00 00           mov       $0x5,%eax
  24: 83 15 44 00 00 00 00  adcl      $0x0,0x44
  2b: 5d                       pop       %ebp
    2c: c3                       ret /*注意这里如果没有跳转,就已经返回了*/
---------------------------
以下就是修改地址部分*/
 
   

  2d: 83 05 48 00 00 00 01  addl      $0x1,0x48/*48 00 00 00 是32位地址,储存地址是大端模式。*/
  34: b8 06 00 00 00           mov       $0x6,%eax /*修改地址,以变成不同的分支*/
  39: 83 15 4c 00 00 00 00  adcl      $0x0,0x4c
  40: 5d                       pop       %ebp
  41: c3                       ret      
  42: 8d b4 26 00 00 00 00  lea       0x0(%esi,%eiz,1),%esi
  49: 8d bc 27 00 00 00 00  lea       0x0(%edi,%eiz,1),%edi  /*这里是nop指令的汇编写法,占用可以看到是7个字节,而运行长字节指令快于多个短字节指令,0*0所以就用快的!*/

对于__FILE__,__LINE__,__func__这样的宏,在调试程序时是很有用的,因为你可以很容易的知道程序运行到了哪个文件的那一行,是哪个函数。
   下面一个例子是打印上面这些预定义的宏的。
  #include
  #include
  void why_me();
  int main()
  {
   printf( "The file is %s.\n", __FILE__ );
   printf( "The date is %s.\n", __DATE__ );
   printf( "The time is %s.\n", __TIME__ );
   printf( "This is line %d.\n", __LINE__ );
   printf( "This function is %s.\n", __func__ );
  
   why_me();
  
   return 0;
  }
  void why_me()
  {
   printf( "This function is %s\n", __func__ );
   printf( "The file is %s.\n", __FILE__ );
   printf( "This is line %d.\n", __LINE__ );
  }  ./funcline
The file is funcline.c
The date is Sep 28 2011
The time is 10:21:54.
This is line 15
This function is main.
This function is why_me
The file is funcline.c
This is line 25

阅读(1455) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~