手动进行线程切换的问题

jjiaming 2014-01-10 10:34:45
各位大虾,最近我在把一个多线程单核的嵌入式实时操作系统移植到WINDOWS XP上来(准确的说是用XP来模拟这么一个操作系统), 在进行线程调度的时候遇到了问题:因为WINDOWS的线程调度某种程度上都是自动的,所提供的API没办法去进行内核层面的调度,还请大家提供一种可靠的办法。现把代码贴出:

BOOL ThreadSwap(HANDLE oldTaskHandle, UINT32 newTaskHandle)
{
ResumeThread(newTaskHandle);
SuspendThread(oldTaskHandle);
}

问题来了,在运行到了ResumeThread时,newTask可能立即就得到了执行,导致SuspendThread还没法执行到。oldTask没法立即Suspend住,系统再运行一段时间后,各个Thread的状态就乱掉了。如果能保证ResumeThread和SuspendThread这两个操作的原子性,那么也是可以的。请教各位有什么好办法没?

当然,还有另外一种办法,把所有的虚拟线程都放在一个线程中跑,在Swap时,备份当前线程的上下文,再恢复新线程的上下文,之后再修改PC指针,这个办法也是可以的,但这样就没法查看各个虚拟线程的调用栈,不到万不得已不想用这种办法。
...全文
233 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
jjiaming 2014-04-25
  • 打赏
  • 举报
回复
自己搞定了,多谢两位
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
schlafenhamster,能否把下载链接发给一下,谢谢
schlafenhamster 2014-01-10
  • 打赏
  • 举报
回复
ucos 有 PC 上的实现 可以参考
wangk 2014-01-10
  • 打赏
  • 举报
回复
不能,至少我不知道如何直接在VS2008查看。
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
wangK兄,刚才想了想,这个缺陷可以自己解决,使用FSAVE FRSTOR指令来备份和恢复浮点寄存器。我想问的是可以用VS 2008查看每个Fiber的状态和调用栈吗?如果不能,那也比较麻烦。我现在给公司做这么一个嵌入式操作系统的模拟器,方便同事用VS 2008调试,使用起来自然是越方便越好
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
感谢wangk!!   默认情况下,x86系统的CPU的浮点数状态信息在纤程看来不属于CPU寄存器,因此会导致在纤程中执行一些相关的浮点运算会破坏数据。为了克服这个缺点,你需要呼叫ConvertThreadToFiberEx函数(Windows Vista及其以上版本中才有),并且传递FIBER_FLAG_FLOAT_SWITCH给它的第2个参数dwFlags ------------------------------------------------------------------------------------------- 唉,公司的电脑都是XP的,看来此路不通啊
wangk 2014-01-10
  • 打赏
  • 举报
回复
Windows提供了一个模拟调度线程的方式叫做Fiber 你可以参考下面的文章: 《Windows via C/C++》学习笔记 —— 纤程(Fiber) Using Fibers
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
自己顶一下,各位高手速速进来,高分请教啊
schlafenhamster 2014-01-10
  • 打赏
  • 举报
回复
我有个“使用Fiber复制文件”0分。 http://download.csdn.net/detail/schlafenhamster/5584061 “this directry contains 4 projects: 1. Counter.dsw One Cell like excel. 2. fibers.dsw Use fibers copy a file. copy "REDIST.TXT" to "REDIST_1.TXT" 3. Under “FiberCopy” Use fibers copy the same file. FiberCopy.dsw vc6 version copy "..\\REDIST.TXT" to "..\\REDIST_” 供参考。 另外 BOOL ThreadSwap 是管理 线程的 , 所以 他不能在任何一个被管理的线程内
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
刚才我想了另外一个办法:把各个线程调用ConvertThreadToFiber进行纤程化,然后调用SwitchToFiber进行调度,但是发现运行到SwitchToFiber时发生了ASSERT,信息如下:“test.exe 中的 0x7c81074e 处未处理的异常: 0xC0000005: 写入位置 0x00001eb8 时发生访问冲突”,难道Fiber无法进行跨线程的调度?也就说一个thread无法调度另一个thread的Fiber?但是MSDN中说得很明白,是可以调度的: The SwitchToFiber function saves the state information of the current fiber and restores the state of the specified fiber. You can call SwitchToFiber with the address of a fiber created by a different thread. 所以还请两位大虾帮忙解决一下,谢谢
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
SuspendThread完了之后ResumeThread就没法执行了啊
schlafenhamster 2014-01-10
  • 打赏
  • 举报
回复
BOOL ThreadSwap(HANDLE oldTaskHandle, UINT32 newTaskHandle) { while( SuspendThread(oldTaskHandle) != 1); while ( ResumeThread(newTaskHandle) != 0); }
jjiaming 2014-01-10
  • 打赏
  • 举报
回复
这已经看过了,也就是我说的第二种办法,但是不太想使用
schlafenhamster 2014-01-10
  • 打赏
  • 举报
回复
搜搜 “ucos2在PC上的实现”

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧