📄 tk_386.c
字号:
/* tk_386.c
Copyright 2000 by InterNiche Technologies Inc. All rights reserved.
Machine dependant portions of tasking package.
This code does Microsoft C++ v6.0, Intel 386 "protected" mode, small model.
*/
#include "ipport.h"
#ifndef SUPERLOOP
#include "task.h"
static int task_sem = 0; /* semaphore to keep task switch single-threaded */
/* void tk_frame(task * newtk, int (*proc)(int), int parm);
Prepare a new task to run (low level). newtk->tk_stack and
newtk->tk_size should be set before this is called. This fills in the
task frame as though the task had called tk_block(). When the round
robin scheduler gets to it, it should look like any other task ready
to resume.
Stack on C++ v6.0 compiled tk_switch() at instant of
wake is:
sp -> EBP (done by our inline asm)
sp+4 -> pushed EDI (C frame )
sp+8 -> pushed ESI
sp+12 -> pushed EBX
sp+16 -> pushed ECX
sp+20 -> pushed EBP (done by C frame ) <- EBP points here
sp+24 -> ret value (tk_entry)
sp+28 -> parameter
Returns a pointer for insertion as the stack pointer (SP)
in the new task.
*/
stack_t *
tk_frame(task * newtk, int (*proc)(int), unsigned parm)
{
stack_t * fp;
int stacksize = newtk->tk_size;
stack_t* stackbase = newtk->tk_stack;
_asm { mov ecx, parm }; /* get initial parameter for task */
_asm { mov ebx, stackbase };
_asm { add ebx, stacksize }; /* ebx -> top of task stack */
_asm { sub ebx, 32 }; /* adjust frame pointer */
_asm { mov [ebx]+28, ecx }; /* load param into stack so as to "pass" it */
_asm { mov eax, proc }; /* get pointer to initial task routine */
_asm { mov [ebx]+24, eax }; /* load it on stack as "ret" address */
_asm { mov eax, ebx }; /* copy stack frame ptr */
_asm { add eax, 20 }; /* make into EBP value */
_asm { mov [ebx]+20, eax }; /* load tasks EBP value */
_asm { mov [ebx], eax }; /* ...in two places */
_asm { mov fp, ebx }; /* load frame pointer for return */
return fp;
}
/* tk_switch() - yield CPU, swap in next runnable task */
void
tk_switch(struct task * newtk)
{
stack_t * tmp_fp;
if (task_sem != 0) /* Keep tasks out of this */
return;
task_sem++;
/* _asm { cli }; Keep tasks out of this */
_asm { push ebp }; /* Intel weirdness */
_asm { mov tmp_fp, esp }; /* get current stack pointer */
tk_cur->tk_fp = tmp_fp; /* save current SP in task */
tk_cur = newtk; /* swap in the new task */
tmp_fp = newtk->tk_fp; /* get new tasks SP */
_asm { mov esp, tmp_fp }; /* Install new tasks stack */
_asm { pop ebp };
task_sem--; /* Reset semaphore */
/* _asm { sti }; */
}
stack_t *
tk_getsp() /* for small model 32 bit just return ESP reg. */
{
stack_t * retval;
_asm { mov retval, esp }
return retval;
}
#endif /* ifndef SUPERLOOP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -