<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Oasis Feng &#187; Development</title>
	<atom:link href="http://blog.oasisfeng.com/tag/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.oasisfeng.com</link>
	<description>Challenge your imagination!</description>
	<lastBuildDate>Sun, 22 Aug 2010 18:15:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Timer in Symbian Development</title>
		<link>http://blog.oasisfeng.com/2006/10/07/timer-in-symbian-development/</link>
		<comments>http://blog.oasisfeng.com/2006/10/07/timer-in-symbian-development/#comments</comments>
		<pubDate>Sat, 07 Oct 2006 03:01:56 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Symbian]]></category>
		<category><![CDATA[Timer]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/2006/10/07/timer-in-symbian-development/</guid>
		<description><![CDATA[（1）TTime::HomeTime() / TTime::UniversalTime() 　　最常见的时间获取手段，精度不高；因涉及一定的运算过程，效率较低。适用于需要以常规“年月日时分秒”方式使用时间的场合。在EKA2平台下，其精度与低阶系统时钟（Nanokernel Timer）一致，通常为微妙级别。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获的具体精度。 　　注意：它们使用的是系统时间，这是可以被其它进程修改的。 （2）User::TickCount() 　　传统的Tick计数器，精度通常仅为1/64秒（可能随硬件有差异），适用于精度要求较低的场合。通过 HAL::Get(HAL::ESystemTickPeriod, result) 可以获得具体精度。 　　注意：在休眠（Standby）状态下，TickCount将停止计数，所以User::TickCount()在休眠状态下将“损失”计时！ （3）User::NTickCount() 　　低阶系统时钟（Nanokernel Timer），通常提供微妙级Tick。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获得具体精度。 　　注意：Symbian OS 6.x 没有此API。与TickCount不同的是，User::NTickCount()在休眠状态下不“损失”计时。 （4）User::FastCounter() 　　返回值类似于Tick，提供Symbian OS所能支持的最高精度，通常比TTime::HomeTime()更准确。（如果硬件不支持high resolution timer，则毫秒级时钟替代）而且，因为它采用快速的exec call读取一个硬件寄存器的数值，效率很高。通过 HAL::Get(HALData::EFastCounterFrequency, result) 可以获得其具体精度。 　　注意：在每次终端从休眠状态激活后，它将同步至正确的数值，也就是说User::FastCounter()在休眠状态下其实也是不“损失”计时的。 　　另外，User::After(), CPeriodic也会在休眠状态下“损失”计时，所以在手机这种特殊的应用环境中，需要特别注意不同定时器在“休眠”状态下计时的差异。]]></description>
			<content:encoded><![CDATA[<p><strong>（1）TTime::HomeTime() / TTime::UniversalTime()</strong></p>
<p>　　最常见的时间获取手段，精度不高；因涉及一定的运算过程，效率较低。适用于需要以常规“年月日时分秒”方式使用时间的场合。在EKA2平台下，其精度与低阶系统时钟（Nanokernel Timer）一致，通常为微妙级别。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获的具体精度。<br />
　　注意：它们使用的是系统时间，这是可以被其它进程修改的。</p>
<p><strong>（2）User::TickCount()</strong></p>
<p>　　传统的Tick计数器，精度通常仅为1/64秒（可能随硬件有差异），适用于精度要求较低的场合。通过 HAL::Get(HAL::ESystemTickPeriod, result) 可以获得具体精度。<br />
　　注意：在休眠（Standby）状态下，TickCount将停止计数，所以<strong>User::TickCount()在休眠状态下将“损失”计时！</strong></p>
<p><strong>（3）User::NTickCount()</strong></p>
<p>　　低阶系统时钟（Nanokernel Timer），通常提供微妙级Tick。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获得具体精度。<br />
　　注意：Symbian OS 6.x 没有此API。与TickCount不同的是，User::NTickCount()在休眠状态下不“损失”计时。</p>
<p><strong>（4）User::FastCounter()</strong></p>
<p>　　返回值类似于Tick，提供Symbian OS所能支持的最高精度，通常比TTime::HomeTime()更准确。（如果硬件不支持high resolution timer，则毫秒级时钟替代）而且，因为它采用快速的exec call读取一个硬件寄存器的数值，效率很高。通过 HAL::Get(HALData::EFastCounterFrequency, result) 可以获得其具体精度。<br />
　　注意：在每次终端从休眠状态激活后，它将同步至正确的数值，也就是说User::FastCounter()在休眠状态下其实也是不“损失”计时的。</p>
<p>　　另外，User::After(), CPeriodic也会在休眠状态下“损失”计时，所以在手机这种特殊的应用环境中，需要特别注意不同定时器在“休眠”状态下计时的差异。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2006/10/07/timer-in-symbian-development/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>变参在GCC(PowerPC)上的实现</title>
		<link>http://blog.oasisfeng.com/2006/09/08/gcc-va-ppc/</link>
		<comments>http://blog.oasisfeng.com/2006/09/08/gcc-va-ppc/#comments</comments>
		<pubDate>Thu, 07 Sep 2006 17:10:22 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[Variable-Arguments]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/2006/09/08/gcc-va-ppc/</guid>
		<description><![CDATA[Keywords: 变参，variable arguments, va_start, va_arg, va_end, GCC, PowerPC, ppc 　　花了两天时间定位的一个变参死机问题，结果查出来是传递变参的两个模块所用编译环境的Tornado版本不一致。虽然结果让我很无语，不过此间倒是第一次透彻的了解了变参在GCC(PowerPC)上的实现，一点心得暂记于此。 　　因为PowerPC在函数参数传递的机制上与ARM类似，都采用了一定数目的寄存器来传递参数，以提高执行效率。显然这是与va_list通常的定义和实现方式相矛盾的。所以，GCC采用了另一个途径来实现与原有的ANSI C变参机制的兼容：va_start首先将寄存器中的参数保存在栈区（实际上，为了避免寄存器被使用，这个操作会被提前到函数的入口处，而无视va_start的书写位置），当然，用于传递参数的寄存器数目是有限的，所以超出这个数目的参数仍是采用压栈的方式传递的。 　　注：va_start会将所有可能用于变参传递的寄存器均保存在栈中，因为它并不知道实际上传递来的参数个数。在PowerPC上，这些寄存器包括：r3 &#8211; r10, f1 &#8211; f8（下面会解释这两组寄存器），可以传递8个常规参数和8个浮点参数（如果CPU支持硬件浮点运算） 　　在ppc的变参定义头文件中，可以看到如下声明： typedef struct __va_list_tag { 　char gpr; 　char fpr; 　char *overflow_arg_area; 　char *reg_save_area; } __va_list[1], __gnuc_va_list[1]; 　　其中grp存储的是下一个“常规类型”变参在其暂存数组中的下标；fpr存储的是下一个“浮点类型”变参在其暂存数组中的下标；overflow_arg_area所指向的就是前面提到的超出数目的那些参数在堆栈中的首地址；而reg_save_area的指向正是va_start在栈区所分配的“寄存器暂存区”。 　　为什么要分为两种类型来存储变参呢？那是因为某些PowerPC芯片中有一组64位的浮点寄存器（fpr），它们可以用于存储浮点类型的参数；而其它类型的变参（即“常规类型”）均存储在通用寄存器（gpr）中。需要注意的是，对于聚合类型（结构体、联合等）的参数，实际保存在gpr中的是指向它的指针（传递引用）。 　　下面我们来看看va_arg的实现：（伪码书写，仅反映主要行为） if ( 需要获取的参数类型是“浮点类型” &#038;&#038; fpr < 8 ) { 　从reg_save_area的第二个数组中取下标为fpr的8字节量作为浮点数返回 　fpr++ } else if ( 需要获取的参数类型是“聚合类型” &#038;&#038; gpr [...]]]></description>
			<content:encoded><![CDATA[<p>Keywords: 变参，variable arguments, va_start, va_arg, va_end, GCC, PowerPC, ppc</p>
<p>　　花了两天时间定位的一个变参死机问题，结果查出来是传递变参的两个模块所用编译环境的Tornado版本不一致。虽然结果让我很无语，不过此间倒是第一次透彻的了解了变参在GCC(PowerPC)上的实现，一点心得暂记于此。</p>
<p><span id="more-91"></span>　　因为PowerPC在函数参数传递的机制上与ARM类似，都采用了一定数目的寄存器来传递参数，以提高执行效率。显然这是与va_list通常的定义和实现方式相矛盾的。所以，GCC采用了另一个途径来实现与原有的ANSI C变参机制的兼容：va_start首先将寄存器中的参数保存在栈区（实际上，为了避免寄存器被使用，这个操作会被提前到函数的入口处，而无视va_start的书写位置），当然，用于传递参数的寄存器数目是有限的，所以超出这个数目的参数仍是采用压栈的方式传递的。</p>
<p>　　注：va_start会将所有可能用于变参传递的寄存器均保存在栈中，因为它并不知道实际上传递来的参数个数。在PowerPC上，这些寄存器包括：r3 &#8211; r10, f1 &#8211; f8（下面会解释这两组寄存器），可以传递8个常规参数和8个浮点参数（如果CPU支持硬件浮点运算）</p>
<p>　　在ppc的变参定义头文件中，可以看到如下声明：</p>
<blockquote><p>
typedef struct __va_list_tag {<br />
　char gpr;<br />
　char fpr;<br />
　char *overflow_arg_area;<br />
　char *reg_save_area;<br />
} __va_list[1], __gnuc_va_list[1];
</p></blockquote>
<p>　　其中grp存储的是下一个“常规类型”变参在其暂存数组中的下标；fpr存储的是下一个“浮点类型”变参在其暂存数组中的下标；overflow_arg_area所指向的就是前面提到的超出数目的那些参数在堆栈中的首地址；而reg_save_area的指向正是va_start在栈区所分配的“寄存器暂存区”。</p>
<p>　　为什么要分为两种类型来存储变参呢？那是因为某些PowerPC芯片中有一组64位的浮点寄存器（fpr），它们可以用于存储浮点类型的参数；而其它类型的变参（即“常规类型”）均存储在通用寄存器（gpr）中。需要注意的是，对于聚合类型（结构体、联合等）的参数，实际保存在gpr中的是指向它的指针（传递引用）。</p>
<p>　　下面我们来看看va_arg的实现：（伪码书写，仅反映主要行为）</p>
<blockquote><p>
if ( 需要获取的参数类型是“浮点类型” &#038;&#038; fpr < 8 )<br />
{<br />
　从reg_save_area的第二个数组中取下标为fpr的8字节量作为浮点数返回<br />
　fpr++<br />
}</p>
<p>else if ( 需要获取的参数类型是“聚合类型” &#038;&#038; gpr < 8 )<br />
{<br />
　从reg_save_area的第一个数组中取下标为gpr的4字节量作为地址，并返回该所指向的聚合类型的内容<br />
　gpr++<br />
}</p>
<p>else if ( 既不是“浮点类型”，也不是“聚合类型” &#038;&#038; gpr < 8 )<br />
{<br />
　从reg_save_area的第一个数组中取下标为gpr的4字节量，转换为所需的类型并返回<br />
　gpr++<br />
}</p>
<p>else // 其它情况，也就是超出gpr和fpr所能存储的参数个数时<br />
{<br />
　从overflow_arg_area中读取所需的参数<br />
　overflow_arg_area += 参数长度<br />
}
</p></blockquote>
<p>　　注：上面省略了longlong类型参数的传递过程，其实longlong的参数在gpr剩余个数 >= 2时，仍然是通过寄存器传递的，只不过被分割在两个gpr寄存器中传递而已。</p>
<p>　　从如此复杂的一个流程来看，其实在PowerPC上使用变参的代价是比i386多出很多的。光是va_arg一个宏展开的代码长度就超过了1k字节。而实现的复杂性也必然导致问题的多样化，从GCC的更新记录来看，变参这一部分也是频繁出现bug的。在文章开头所提到的死机问题也是由于va_list结构在两个Tornado版本中对齐方式不一致而造成的。所以，PowerPC下使用变参真的是要尤其小心，千万别试图挑战GCC的智商哦。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2006/09/08/gcc-va-ppc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>终于让Source Insight也能识别Symbian的_LIT宏了</title>
		<link>http://blog.oasisfeng.com/2006/05/27/parse-lit-in-source-insight/</link>
		<comments>http://blog.oasisfeng.com/2006/05/27/parse-lit-in-source-insight/#comments</comments>
		<pubDate>Sat, 27 May 2006 09:56:02 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Symbian]]></category>
		<category><![CDATA[Source-Insight]]></category>

		<guid isPermaLink="false">http://www.oasisfeng.com/blog/2006/05/27/%e7%bb%88%e4%ba%8e%e8%ae%a9source-insight%e4%b9%9f%e8%83%bd%e8%af%86%e5%88%absymbian%e7%9a%84_lit%e5%ae%8f%e4%ba%86/</guid>
		<description><![CDATA[　　不得不承认，Source Insight 确实很强大，以至于太多的高级功能都未能在帮助文档中一一详述，只能依靠我们自己来发掘了…… 　　今天，碰巧发现了&#8221;Language &#8211; Custom Tag Type&#8221;这个功能，一举解决了困扰我已久的 Symbian &#8220;_LIT&#8221;宏解析问题。（也不知道是否因为我的 Conditions 定义的不足导致的……） 　　长话短说，&#8221;Options &#8211; Document Options&#8221;，新建一个&#8221;Document Type&#8221;，如&#8221;Symbian C++ Source Files&#8221;，继承原有&#8221;C++ Source Files&#8221;的属性。然后在左下角&#8221;Parsing&#8221;设置组中的&#8221;Custom Tag Type&#8221;下选择&#8221;Constant&#8221;，并将下面的正则表达式填入&#8221;Custom pattern&#8221;： 　　^\w*_LIT(\w*\([A-Za-z0-9]+\)\w*,.* 　　OK, resynchronize your project, you&#8217;ll see it! 　　注：记得将 Document Type 中原 c 和 cpp 的 File Filter 项里面的扩展名 .cpp 和 .h 屏蔽掉，否则 SI 不会调用我们新建的 Document Type 来解析的。]]></description>
			<content:encoded><![CDATA[<p>　　不得不承认，Source Insight 确实很强大，以至于太多的高级功能都未能在帮助文档中一一详述，只能依靠我们自己来发掘了……</p>
<p>　　今天，碰巧发现了&#8221;Language &#8211; Custom Tag Type&#8221;这个功能，一举解决了困扰我已久的 Symbian &#8220;_LIT&#8221;宏解析问题。（也不知道是否因为我的 Conditions 定义的不足导致的……）</p>
<p>　　长话短说，&#8221;Options &#8211; Document Options&#8221;，新建一个&#8221;Document Type&#8221;，如&#8221;Symbian C++ Source Files&#8221;，继承原有&#8221;C++ Source Files&#8221;的属性。然后在左下角&#8221;Parsing&#8221;设置组中的&#8221;Custom Tag Type&#8221;下选择&#8221;Constant&#8221;，并将下面的正则表达式填入&#8221;Custom pattern&#8221;：</p>
<p>　　<strong>^\w*_LIT(\w*\([A-Za-z0-9]+\)\w*,.*</strong></p>
<p>　　OK, resynchronize your project, you&#8217;ll see it!</p>
<p>　　注：记得将 Document Type 中原 c 和 cpp 的 File Filter 项里面的扩展名 .cpp 和 .h 屏蔽掉，否则 SI 不会调用我们新建的 Document Type 来解析的。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2006/05/27/parse-lit-in-source-insight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.281 seconds -->
