rtt若干疑问
我一直都在WINCE上做开发,最近有时间就想找个开源的OS研究一下,觉得rtt不错,因此下了0.3的版本,最近花了一点时间看了内部部分代码。当然是结合那本编程指南,同时也是参照AT91SAM7S工程进行的,不过目前碰到几个疑问,请版主答疑。1:结构体对齐问题:我一些内核结构体定义,不知道版主是否考虑到结构体对齐问题。我不知道MDK3.8的结构体对齐采用几字节对齐,我猜可能是4.所以某些结构体定义的地方,浪费了一些内存空间。比如: struct rt_thread 中的
char name; /* the name of thread */
rt_uint8_ttype; /* type of object */
rt_uint8_tflags; /* thread's flags */
rt_list_t list;
如果RT_NAME_MAX定义为4(默认也为4),则list和flgs当中会有两字节填充,我把type和flags都改为rt_uint16_t不影响结构体大小。如果非要说,type和flags用8位表示足够,我建议应该显示定义那保留的两字节,也方便以后扩展。其实刚才那个定义也是rt_object的定义,因此这影响到所以内核对象。还有其他地方成员定义也没对齐,我就不举例子了。另外,我还有个疑问:为什么线程控制块,没有定义struct rt_object parent呢?
2:内核对象名:如上面所述,内核对象名长度是宏控制,因此上面的问题可通过将宏定义为4xN-2。但始终觉得此举不妥,为保证对齐建议:
#define ALLIG_LEN (4)
char name;
内核对象名的设置的源码为:
/* copy name */
for (temp = 0; temp < RT_NAME_MAX; temp ++)
{
object->name = name;
}
如果是把object->name做为固定长度的数据,在使用过程中应该不会出错。但是如果把它做为字符串使用就会导致溢出,因为name长度可能大于RT_NAME_MAX.而恰恰在代码中有的地方把object->name当做字符串操作。
3:小内存管理中的void *rt_realloc(void *rmem, rt_size_t newsize)函数。这个函数中在重新分配完新内存后,没有检测是否成功而直接操作,可能会导致异常。/* expand memory */
nmem = rt_malloc(newsize);
rt_memcpy(nmem, rmem, size < newsize ? size : newsize);
rt_free(rmem);
这个函数,在我参看的工程中没出现,不知其他工程是否引用。
4:关于timer,这只是我个人想法,不知道是否正确,想和版主交流下。timer在每个tick的是否都会检测,里面的超时函数也是在里面调用,因此每个超时函数相当于被中断调用,因此不能阻塞或者执行时间过长。因此建议像这种硬timer只对内核与驱动开放,应用的定时器可以通过新建一个服务来满足,既:软定时器。虽然里面有这样的设计,希望能更明确。
5:函数rt_tick_t rt_tick_from_millisecond(rt_uint32_t ms)
{
/* return the calculated tick */
return RT_TICK_PER_SECOND * (ms / 1000); //? (RT_TICK_PER_SECOND *ms) / 1000 + (RT_TICK_PER_SECOND *ms) % 1000 ? 1:0;
}
6:函数void rt_tick_increase()
{
struct rt_thread* thread;
/* increase the global tick */
++ rt_tick;
/* check timer*/
rt_timer_check();
/* check time slice */
thread = rt_thread_self();
-- thread->remaining_tick;
if (thread->remaining_tick == 0)
{
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;
/* yield */
rt_thread_yield();
}
}
可能导致线程少执行一个tick同时上个线程多执行一个tick,假如rt_timer_check();中发生调度则rt_current_thread改变,变成将调度的线程,这个问题解决应该不难。
7:/**
* This function will lock the thread scheduler.
*/
void rt_enter_critical()
{
register rt_base_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
if (rt_scheduler_lock_nest < 255u) //?为什么知道255,而rt_scheduler_lock_nest 定位为16位整形, 只允许255层嵌套?
rt_scheduler_lock_nest++;
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
/**
* This function will unlock the thread scheduler.
*/
void rt_exit_critical()
{
register rt_base_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
rt_scheduler_lock_nest --;
if (rt_scheduler_lock_nest <= 0)
{
rt_scheduler_lock_nest = 0;
/* enable interrupt */
rt_hw_interrupt_enable(level);
rt_schedule();
}
else
{
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
}
8:其他若干细节问题,主要是针对考虑到的编写C代码,一些比较好的习惯,举个例子:
/* set ptr */
mb->msg_pool = value;
/* increase input offset */
++ mb->in_offset;
mb->in_offset %= mb->size; //if( mb->in_offset >= mb->size)mb->in_offset -= mb->size
/* increase message entry */
mb->entry ++;
还有一些其他细节就不举例了。如果我有什么理解不对,希望版主对以上几个问题给我答疑。
最后,我是关心RTT并希望她发展更好,加上自己技术功底不够,所以提出以上问题,同时也能提升自己。 谢谢你提出的这么多的建议。
1. 确实存在浪费的可能,所以在0.4.x中对这些进行了部分调整,但还没达到最优的目的。线程块这样定义仅方便代码编写,实质是一样的。0.4.x还有一个需要解决的问题是,各个控制块针对pipeline对齐的问题,因为这个会影响到ARM9这类带cache的系统性能。
这个问题,似乎在name定义为6的长度时比较合理些。
2. name本身就应该采用非字符串或规定长度的字符串来使用的,这块我再检查下代码是否有遗漏的地方。
3. 0.4.x中已有修正,这个是0.3.0正式版的一个bug,0.3.1版本就没有了。
4. 这个确实需要在编程指南中再行强调指出。软定时器也已经有了,只是默认没开启。0.3.0还有上次的tick溢出的问题,定时器可能会被错误的执行的问题,这些也已经在0.4.x中修正了。
5. rt_tick_from_millisecond 实现得果真有问题,谢谢指出。
6. 上次shellstudio已经讨论过,确实存在这个问题,解决这个问题比较难,还未好的办法。
7. 谢谢指出。
8. 等会我看看汇编代码,看看哪种方式好一些。 ffxz你们有QQ群之类的,那样交流起来比较方便快捷。刚才又看了点代码,发现几个细节问题,想继续和你确认。关于结构体定义,如果上到有MMU的CPU,确实需要考虑了。注意cache 今天有些忙,ld不在家,负责带孩子:-P
QQ群:90978992,这个是原来的HMI群。稍后再仔细交流下,BTW,请看0.4.x的代码,因为有可能有些东西已经在0.4.x分支中已经有修正了。 最新的代码已经修正了rt_tick_from_millisecond()函数,我看代码可以这样写:
rt_tick_t rt_tick_from_millisecond(rt_uint32_t ms)
{
/* return the calculated tick */
ms = ms * RT_TICK_PER_SECOND + 999;
return ms / 1000;
}
这样,用EWARM编译,打开全部优化,结果如下:
SECTION `.text`:CODE:NOROOT(2)
ARM
rt_tick_from_millisecond:
MOV R2,#+231
MOV R1,#+500
ORR R2,R2,#0x300
MLA R0,R1,R0,R2
LDR R2,??DataTable1_4;; 0x83126e98
UMULL R2,R1,R0,R2
LSR R0,R1,#+9
BX LR ;; return
比原来的结果运行效率要高:
SECTION `.text`:CODE:NOROOT(2)
ARM
rt_tick_from_millisecond:
LDR R2,??DataTable1_4;; 0x83126e98
MOV R1,#+500
MUL R0,R1,R0
UMULL R2,R1,R0,R2
LDR R2,??DataTable1_5;; 0x10624dd3
UMULL R3,R12,R2,R0
LSR R12,R12,#+6
MOV R3,#+1000
MUL R12,R3,R12
SUB R12,R0,R12
ADDS R0,R12,R1, LSR #+9
MOVNE R0,#+1
BX LR ;; return
可见,上面两次乘法指令,两次存储器访问。 高 楼主QQ号怎么联系啊?有些问题想请教一下。。。。。 请教不用,可以一起讨论:29265903 加的时候注明RTT
页:
[1]