momo zone

调核人的blog

Monthly Archives: 六月 2013

另外一个线速发包架构

除了之前的intel发布的DPDK这里又发现了一个,貌似比DPDK还猛
http://info.iet.unipi.it/~luigi/netmap/#31bf

[转]vim的自动补全

Vim 一共提供了 15 种自动补全的模式(:help ins-completion)。其中有两种的补全列表内容与另外两种相同,只是排序不同,这 15 种模式:

1 文字编辑用的 3 种:

—- 文字编辑显然是不用 Vim 的,所以这三种模式比较悲催,我从没用过:

K 模式    (Vim 默认: CTRL-X CTRL-K) — 字典补全,查找字典文件中的匹配单词,组成补全列表
H 模式    (Vim 默认: CTRL-X CTRL-T) — 分类补全,查找分类文件(thesaurus 文件)中的匹配单词,组成补全列表
S 模式    (Vim 默认: CTRL-X s)        — 拼写建议

2 Vim 牛人用的两种:

—- 自定义的,我也没用过:

O 模式    (Vim 默认: CTRL-X CTRL-O) — 全能补全,由一个自定义函数生成补全列表
U 模式    (Vim 默认: CTRL-X CTRL-U) — 自定义补全,也是由自定义函数生成补全列表

3 所有人都喜欢的四种:

—- 我用来应付 99% 的情况:

n 模式    (Vim 默认: CTRL-N)        — 关键字补全,查找 ‘complete’ 选项指定文件中的匹配单词,组成补全列表
N 模式    (Vim 默认: CTRL-X CTRL-N) — 关键字补全,查找当前 buffer 里的匹配单词,组成补全列表

另外两种: p 模式与 P 模式,分别与 n 模式和 N 模式相同,只是补全列表中候选词的排序相反。

4 程序员用的三种:

    T 模式    (Vim 默认: CTRL-X CTRL-]) — tag 补全,查找 tag 中的匹配单词,组成补全列表
    I 模式    (Vim 默认: CTRL-X CTRL-I) — 头文件补全,查找当前 buffer 和 include file 中的匹配单词,组成补全列表
D 模式    (Vim 默认: CTRL-X CTRL-D) — 定义补全,查找当前 buffer 与 include file 中匹配的名称定义,组成补全列表

5 特殊语境下专用的三种:

—- 还好,偶尔用一用 …

V 模式    (Vim 默认: CTRL-X CTRL-V) — Vim 补全,查找 Vim 的命令名, 函数名等等,组成补全列表
F 模式    (Vim 默认: CTRL-X CTRL-F) — 文件名补全,查找匹配的路径或文件名,组成补全列表

L 模式    (Vim 默认: CTRL-X CTRL-L) — 整行补全,查找 ‘complete’ 选项指定文件中匹配的整行内容,组成补全列表

问题1 用O模式需要在.vimrc中设置:

set omnifunc=ccomplete#Complete

问题2 T模式需要tags文件已经排序,奇怪的是内核的make tags竟然没有排序,改scripts/tags.sh:

xtags()
{
	if $1 --version 2>&1 | grep -iq exuberant; then
		exuberant $1
	elif $1 --version 2>&1 | grep -iq emacs; then
		emacs $1
	else
		all_sources | xargs $1 $2 -a
        fi
}

........................

case "$1" in
	"cscope")
		docscope
		;;

	"gtags")
		dogtags
		;;

	"tags")
		rm -f tags
		xtags ctags --sort=yes
		;;

	"TAGS")
		rm -f TAGS
		xtags etags
		;;
esac

问题3 补全菜单需要修改一下才好用:

“让Vim的补全菜单随着用户输入自动调整匹配内容,否则一旦输入的没有匹配的,就退出了匹配模式
set completeopt+=longest

“离开插入模式后自动关闭菜单
autocmd InsertLeave * if pumvisible() == 0|pclose|endif

“回车选中当前项
inoremap pumvisible() ? “\” : “\”

gcc 4.5 以后strict-aliasing的问题

我之前总喜欢拿这个去面试其他人,结果后来重构os镜像后gcc升级到4.5发现原来该报 warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing],现在不报了。

看了一下gcc的log发现4.5中-Wstrict-aliasing分为几个级别,等级1检查的项目最多,-Wall 只是包含-Wstrict-aliasing=3。

`-Wstrict-aliasing=n'
     This option is only active when `-fstrict-aliasing' is active.  It
     warns about code that might break the strict aliasing rules that
     the compiler is using for optimization.  Higher levels correspond
     to higher accuracy (fewer false positives).  Higher levels also
     correspond to more effort, similar to the way -O works.
     `-Wstrict-aliasing' is equivalent to `-Wstrict-aliasing=n', with
     n=3.

     Level 1: Most aggressive, quick, least accurate.  Possibly useful
     when higher levels do not warn but -fstrict-aliasing still breaks
     the code, as it has very few false negatives.  However, it has
     many false positives.  Warns for all pointer conversions between
     possibly incompatible types, even if never dereferenced.  Runs in
     the front end only.

     Level 2: Aggressive, quick, not too precise.  May still have many
     false positives (not as many as level 1 though), and few false
     negatives (but possibly more than level 1).  Unlike level 1, it
     only warns when an address is taken.  Warns about incomplete
     types.  Runs in the front end only.

     Level 3 (default for `-Wstrict-aliasing'): Should have very few
     false positives and few false negatives.  Slightly slower than
     levels 1 or 2 when optimization is enabled.  Takes care of the
     common pun+dereference pattern in the front end:
     `*(int*)&some_float'.  If optimization is enabled, it also runs in
     the back end, where it deals with multiple statement cases using
     flow-sensitive points-to information.  Only warns when the
     converted pointer is dereferenced.  Does not warn about incomplete
     types.

再介绍一下C的aliasing概念:

aliasing指的是当有多个指针指向同一内存区域时,第二个及其后的指针都是第一个指针的aliasing。写C代码的人都知道这种情况是十分复杂的,容易引起内存重复释放,引用类型错误等等。所谓的strict-aliasing就是针对后者做的一项检查,即不同类型的指针不能指向同一个内存区域。举例:

int foo()
{
	long a = 4;
	int * p = (int *)&a;
	return *p+1;
}
gcc -Wstrict-aliasing=1 -Wall -O3 foo.c -o foo

编译器就会报错,说明违反strict-aliasing约定
如果不进行strict-aliasing检查,那么有可能会有个非常隐蔽的优化问题出现:

long _g;
int foo(int *b)
{
    _g = 1;
    *b = 3333333;
    return _g;
}

int main()
{
    printf("%d\n", foo((int *)(&_g)));
    return 0;
}

上面的代码用-O3编译结果是1,用-O0 编译是3333333。当然是后者正确,原因就是进行编译器优化的话,编译器认为foo函数中的b 指向的数据和_g没有关系,根据是b的指针类型和_g不同,所以优化编译时*b=3333333被认为为无效语句,结果也就是错的了。

IRQ N: nobody cared 问题

前两天在IRQ handle中加了一段代码结果加载后oops报如下内容:

irq 18: nobody cared (try booting with the "irqpoll" option) 
Pid: 0, comm: swapper Tainted: P 3.4.42 #1 
[ 4684.693296] Call Trace: 
printk+0x18/0x1a 
__report_bad_irq.clone.2+0x27/0x90 
note_interrupt+0x14f/0x190 
...................................................
handlers: 
 (e100_intr+0x0/0xd0 [e100]) 
 Disabling IRQ #18

看下代码

static void
__report_bad_irq(unsigned int irq, struct irq_desc *desc,
		 irqreturn_t action_ret)
{
	struct irqaction *action;
	unsigned long flags;

	if (bad_action_ret(action_ret)) {
		printk(KERN_ERR "irq event %d: bogus return value %x\n",
				irq, action_ret);
	} else {
		printk(KERN_ERR "irq %d: nobody cared (try booting with "
				"the \"irqpoll\" option)\n", irq);
	}
	dump_stack();
	printk(KERN_ERR "handlers:\n");

	/*
	 * We need to take desc->lock here. note_interrupt() is called
	 * w/o desc->lock held, but IRQ_PROGRESS set. We might race
	 * with something else removing an action. It's ok to take
	 * desc->lock here. See synchronize_irq().
	 */
	raw_spin_lock_irqsave(&desc->lock, flags);
	action = desc->action;
	while (action) {
		printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
		if (action->thread_fn)
			printk(KERN_CONT " threaded [<%p>] %pf",
					action->thread_fn, action->thread_fn);
		printk(KERN_CONT "\n");
		action = action->next;
	}
	raw_spin_unlock_irqrestore(&desc->lock, flags);
}

我改返回值为其他类型,但内核只认这几种,所以就报错了

static inline int bad_action_ret(irqreturn_t action_ret)
{
	if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
		return 0;
	return 1;
}

不过这错误很容易误导人,之前遇到的第三方驱动报这个错也许不是因为中断挂起无人处理的问题,而是因为返回值内核看不懂而已。