Friday, July 23, 2010

cpufreq stuck in lowest gear

我的M1330不知道从哪个kernel版本开始, 会时不时被锁定在最低频率上运行, ondemand 和performance都一样,并且/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq始终为800000.

找了一圈google后, 有人使用acpi_osi="!Windows 2006" gets workaround, 尝试后无效.

打开cpufreq.debug=7后发现以下日志:

Jul 22 16:18:05 laptop kernel: cpufreq-core: setting new policy for CPU 0: 800000 - 2401000 kHz
Jul 22 16:18:05 laptop kernel: acpi-cpufreq: acpi_cpufreq_verify
Jul 22 16:18:05 laptop kernel: freq-table: request for verification of policy (800000 - 2401000 kHz) for cpu 0
Jul 22 16:18:05 laptop kernel: freq-table: verification lead to (800000 - 2401000 kHz) for cpu 0
Jul 22 16:18:05 laptop kernel: acpi-cpufreq: acpi_cpufreq_verify
Jul 22 16:18:05 laptop kernel: freq-table: request for verification of policy (800000 - 800000 kHz) for cpu 0
Jul 22 16:18:05 laptop kernel: freq-table: verification lead to (800000 - 800000 kHz) for cpu 0
Jul 22 16:18:05 laptop kernel: cpufreq-core: new min and max freqs are 800000 - 800000 kHz

追踪代码至: /usr/src/linux/drivers/cpufreq/cpufreq.c 有 static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) 函数
得知它会检查CPU温度来获得一个加权过的值和ACPI P-State的容忍值.
定位在此,写上
dprintk("after CPUFREQ_ADJUST, %u - %u kHz", policy->min, policy->max);
dprintk("after CPUFREQ_INCOMPATIBLE, %u - %u kHz", policy->min, policy->max);
出现
Jul 23 23:39:31 laptop kernel: cpufreq-core: after CPUFREQ_ADJUST, 800000 - 2401000 kHz
Jul 23 23:39:31 laptop kernel: cpufreq-core: after CPUFREQ_INCOMPATIBLE, 800000 - 800000 kHz
comment之,结束

Friday, May 15, 2009

secondlife 修改拍照目录

每次拍照,secondlife都会弹出个对话框,然后默认目录在/usr/share/games/secondlife下,很气人。今天搞了一下,很dirty不过it works。

找到linden/indra/newview/llviewerwindow.cpp文件,大概在3911行左右有一个void LLViewerWindow::resetSnapshotLoc()方法。
删除 sSnapshotDir.clear();加上如下几行:
sSnapshotDir = gDirUtilp->getOSUserAppDir();
sSnapshotDir += gDirUtilp->getDirDelimiter();
sSnapshotDir += "/screenshot";

搞定,然后把目标目录软链接到$SECONDLIFE_USER_DIR/.就可以了(这个是我在llvfs_linux.cpp里发现的,有一个环境变量$SECONDLIFE_USER_DIR,默认是$HOME/.secondlife)

Wednesday, May 13, 2009

omvviewer-light - GTK# application


我一直对mono没什么兴趣,这次因为要装一个omvviewer-light,所以安上了
感觉好像还可以

Tuesday, May 12, 2009

函数指针 (*(void (*)( ) )0)( ) 解析[转]

概述

在很多情况下,尤其是读别人所写代码的时候,对 C语言声明的理解能力变得非常重要,而C语言本身的凝练简约也使得C语言的声明常常会令人感到非常困惑,因此,在这里我用一篇的内容来集中阐述一下这个问题。

问题:声明与函数

有一段程序存储在起始地址为 0的一段内存上,如果我们想要调用这段程序,请问该如何去做?

答案

答案是 (*(void (*)( ) )0)( )。看起来确实令人头大,那好,让我们知难而上,从两个不同的途径来详细分析这个问题。

答案分析:从尾到头

首先,最基本的函数声明: void function (paramList);

最基本的函数调用: function(paramList);

鉴于问题中的函数没有参数,函数调用可简化为 function();

其次,根据问题描述,可以知道 0是这个函数的入口地址,也就是说,0是一个函数的指针。使用函数指针的函数声明形式是:void (*pFunction)(),相应的调用形式是: (*pFunction)(),则问题中的函数调用可以写作:(*0)( )。

第三,大家知道,函数指针变量不能是一个常数,因此上式中的 0必须要被转化为函数指针。

我们先来研究一下,对于使用函数指针的函数:比如 void (*pFunction)( ),函数指针变量的原型是什么?这个问题很简单,pFunction函数指针原型是( void (*)( ) ),即去掉变量名,清晰起见,整个加上()号。

所以将 0强制转换为一个返回值为void,参数为空的函数指针如下:( void (*)( ) )。

OK,结合2)和3)的分析,结果出来了,那就是:(*(void (*)( ) )0)( ) 。

答案分析:从头到尾理解答案

(void (*)( )) ,是一个返回值为void,参数为空的函数指针原型。
(void (*)( ))0,把0转变成一个返回值为void,参数为空的函数指针,指针指向的地址为0.
*(void (*)( ))0,前面加上*表示整个是一个返回值为void的函数的名字
(*(void (*)( ))0)( ),这当然就是一个函数了。

我们可以使用 typedef清晰声明如下:

typedef void (*pFun)( );

这样定义之后,pFun就是一个返回类型为void无参数的函数指针变量了。

这样函数变为 (*(pFun)0 )( );

问题:三个声明的分析

对声明进行分析,最根本的方法还是类比替换法,从那些最基本的声明上进行类比,简化,从而进行理解,下面通过分析三个例子,来具体阐述如何使用这种方法。

# 1:int* (*a[5])(int, char*);

首先看到标识符名 a,"[]"优先级大于"*",a与"[5]"先结合。所以a是一个数组,这个数组有5个元素,每一个元素都是一个指针,指针指向"(int, char*)",很明显,指向的是一个函数,这个函数参数是"int, char*",返回值是"int*"。OK,结束了一个。:)

# 2:void (*b[10]) (void (*)());

b是一个数组,这个数组有10个元素,每一个元素都是一个指针,指针指向一个函数,函数参数是"void (*)()"【注10】,返回值是"void"。完毕!

注意:这个参数又是一个指针,指向一个函数,函数参数为空,返回值是 "void"。

# 3. doube(*)() (*pa)[9];

pa是一个指针,指针指向一个数组,这个数组有9个元素,每一个元素都是"doube(*)()"(也即一个函数指针,指向一个函数,这个函数的参数为空,返回值是"double")。

C语言中的函数指针

函 数在内存中有一个物理位置,而这个位置是可以赋给一个指针的。一零点函数的地址就是该函数的入口点。因此,函数指针可被用来调用一个函数。函数的地址是用 不带任何括号或参数的函数名来得到的。(这很类似于数组地址的得到方法,即,在只有数组名而无下标是就得到数组地址。)

怎样说明一个函数指针变量呢 ?
为了说明一个变量 fn_pointer 的类型是"返回值为 int 的函数指针", 你可以使用下面的说明语句:
int (*fn_pointer) ();
为了让编译器能正确地解释这句语句, *fn_pointer 必须用括号围起来。若漏了这对括号, 则:
int *fn_pointer ();
的意思完全不同了。fn_pointer 将是一个函数名, 其返回值为 int 类型的指针。

函数指针变量

在C语言中规定,一个函数总是占用一段连续的内存区, 而函数名就是该函数所占内存区的首地址。 我们可以把函数的这个首地址 ( 或称入口地址 ) 赋予一个指针变量, 使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。 我们把这种指向函数的指针变量称为 " 函数指针变量 " 。
函数指针变量定义的一般形式为:
类型说明符 (* 指针变量名 )();
其中 " 类型说明符 " 表示被指函数的返回值的类型。 "(* 指针变量名 )" 表示 "*" 后面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。
例如: int (*pf)();
表示 pf 是一个指向函数入口的指针变量,该函数的返回值 ( 函数值 ) 是整型。
下面通过例子来说明用指针形式实现对函数调用的方法。
int max(int a,int b){
if(a>b)return a;
else return b;
}
main(){
int max(int a,int b);
int(*pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:\n");
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
printf("maxmum=%d",z);
}
从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:

1. 先定义函数指针变量,如后一程序中第 9 行 int (*pmax)(); 定义 pmax 为函数指针变量。

2. 把被调函数的入口地址 ( 函数名 ) 赋予该函数指针变量,如程序中第 11 行 pmax=max;

3. 用函数指针变量形式调用函数,如程序第 14 行 z=(*pmax)(x,y);  调用函数的一般形式为: (* 指针变量名 ) ( 实参表 ) 使用函数指针变量还应注意以下两点:

a. 函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。

b. 函数调用中 "(* 指针变量名 )" 的两边的括号不可少,其中的 * 不应该理解为求值运算,在此处它只是一种表示符号。
原文地址 http://blog.csdn.net/norbe/archive/2006/03/14/624257.aspx

Monday, May 11, 2009

很萌的clannad paino

video

就是发现视频和音频不是很同步,随便看看拉
现在很佩服用脚键盘的,高手啊

Monday, May 4, 2009

Secondlife on Gentoo AMD64

一直想玩Secondlife,但他就是不出64位版本,搞得我非常不舒服。这次用了2个星期好好整了一下。

首先用techwolf的overlay: http://overlay.techwolf.net/
然后编译secondlife。注意,我编译的时候出现'-Wl,--as-needed'链接问题,在configure之后立马在编译目录中寻找这个关键词,删除之(记得有2处)。

然后准备让openal支持pulseaudio,发现有个ebuild在http://www.lastlog.de/wiki/index.php/Pulseaudio 装上!!
openal现在版本的配置文件从.openalrc迁移到.alsoftrc,格式也完全不一样。填上drivers=pulseaudio

关键是SLVoice没有64bit版本,只好使用emul-linux-x86-*模拟。这边吃尽了苦头,SLVoice死活不工作!!把SLVoice move 成SLVoice.bin,再加入-ll 5 使loglevel=5 发现dns无法工作,查了google很久都没有发现,后来想到好像以前googleearth也出现这个状况,推测并非SLVoice的问题。把nsswtich.conf的mdns删掉后成功了。原来是SLVoice没有找到mdns的32位lib,结果dns无法工作。这个问题真的很tricky!

好了,开始研究如何建模了,在学校上了堂blender的课,稍微了解了一下如何建模。哎……小时候没有好好学画画,现在后悔了。我要找个画画好的女朋友!!~~


这是我在Help Desk看到的一位非常好看的MM

Wednesday, April 29, 2009

NU的教授让我们做这个……

哎……什么都不说了,这个是第一个星期的作业,搞个计算长方体和圆柱体的体积计算器……这……

加个opengl的实时作图,否则这个作业实在不像硕士生的作业……