#include <iostream>
#include <Windows.h>
using
namespace
std;
#pragma once
#define MAXGMTHREAD 100
typedef
struct
{
char
* name;
int
Flags;
int
SleepMillsecondDot;
void
* initialStack;
void
* StackLimit;
void
* KernelStack;
void
* lpParameter;
void
(*func)(
void
* lpParameter);
}GMThread_t;
void
GMSleep(
int
MilliSeconds);
int
RegisterGMThread(
char
* name,
void
(*func)(
void
*lpParameter),
void
* lpParameter);
void
Scheduling(
void
);
#include "ThreadSwitch.h"
#define GMTHREADSTACKSIZE 0x80000
int
CurrentThreadIndex = 0;
GMThread_t GMThreadList[MAXGMTHREAD] = { NULL, 0 };
enum
FLAGS
{
GMTHREAD_CREATE = 0x1,
GMTHREAD_READY = 0x2,
GMTHREAD_SLEEP = 0x4,
GMTHREAD_EXIT = 0x8,
};
void
GMThreadStartup(GMThread_t* GMThreadp)
{
GMThreadp->func(GMThreadp->lpParameter);
GMThreadp->Flags = GMTHREAD_EXIT;
Scheduling();
return
;
}
void
IdleGMThread(
void
* lpParameter)
{
printf
(
"IdleGMThread---------------\n"
);
Scheduling();
return
;
}
void
PushStack(unsigned
int
** Stackpp, unsigned
int
v)
{
*Stackpp -= 1;
**Stackpp = v;
return
;
}
void
initGMThread(GMThread_t* GMThreadp,
char
* name,
void
(*func)(
void
* lpParameter),
void
* lpParameter)
{
unsigned
char
* StackPages;
unsigned
int
* StackDWordParam;
GMThreadp->Flags = GMTHREAD_CREATE;
GMThreadp->name = name;
GMThreadp->func = func;
GMThreadp->lpParameter = lpParameter;
StackPages = (unsigned
char
*)VirtualAlloc(NULL, GMTHREADSTACKSIZE, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(StackPages, GMTHREADSTACKSIZE);
GMThreadp->initialStack = StackPages + GMTHREADSTACKSIZE;
StackDWordParam = (unsigned
int
*)GMThreadp->initialStack;
PushStack(&StackDWordParam, (unsigned
int
)GMThreadp);
PushStack(&StackDWordParam, (unsigned
int
)0);
PushStack(&StackDWordParam, (unsigned
int
)GMThreadStartup);
PushStack(&StackDWordParam, (unsigned
int
)5);
PushStack(&StackDWordParam, (unsigned
int
)7);
PushStack(&StackDWordParam, (unsigned
int
)6);
PushStack(&StackDWordParam, (unsigned
int
)3);
PushStack(&StackDWordParam, (unsigned
int
)2);
PushStack(&StackDWordParam, (unsigned
int
)1);
PushStack(&StackDWordParam, (unsigned
int
)0);
GMThreadp->KernelStack = StackDWordParam;
GMThreadp->Flags = GMTHREAD_READY;
return
;
}
int
RegisterGMThread(
char
* name,
void
(*func)(
void
*lpParameter),
void
* lpParameter)
{
int
i = 0;
for
(i = 1; GMThreadList[i].name; i++) {
if
(0 == _stricmp(GMThreadList[i].name, name)) {
break
;
}
}
initGMThread(&GMThreadList[i], name, func, lpParameter);
return
(i & 0x55AA0000);
}
__declspec
(
naked
)
void
SwitchContext(GMThread_t* SrcGMThreadp, GMThread_t* DstGMThreadp)
{
__asm {
push ebp
mov ebp, esp
push edi
push esi
push ebx
push ecx
push edx
push eax
mov esi, SrcGMThreadp
mov edi, DstGMThreadp
mov[esi + GMThread_t.KernelStack], esp
mov esp, [edi + GMThread_t.KernelStack]
pop eax
pop edx
pop ecx
pop ebx
pop esi
pop edi
pop ebp
ret
}
}
void
Scheduling(
void
)
{
int
i;
int
TickCount;
GMThread_t* SrcGMThreadp;
GMThread_t* DstGMThreadp;
TickCount = GetTickCount();
SrcGMThreadp = &GMThreadList[CurrentThreadIndex];
DstGMThreadp = &GMThreadList[0];
for
(i = 1; GMThreadList[i].name; i++) {
if
(GMThreadList[i].Flags & GMTHREAD_SLEEP) {
if
(TickCount > GMThreadList[i].SleepMillsecondDot) {
GMThreadList[i].Flags = GMTHREAD_READY;
}
}
if
(GMThreadList[i].Flags & GMTHREAD_READY) {
DstGMThreadp = &GMThreadList[i];
break
;
}
}
CurrentThreadIndex = DstGMThreadp - GMThreadList;
SwitchContext(SrcGMThreadp, DstGMThreadp);
return
;
}
void
GMSleep(
int
MilliSeconds)
{
GMThread_t* GMThreadp;
GMThreadp = &GMThreadList[CurrentThreadIndex];
if
(GMThreadp->Flags != 0) {
GMThreadp->Flags = GMTHREAD_SLEEP;
GMThreadp->SleepMillsecondDot = GetTickCount() + MilliSeconds;
}
Scheduling();
return
;
}
#include "ThreadSwitch.h"
extern
int
CurrentThreadIndex;
extern
GMThread_t GMThreadList[MAXGMTHREAD];
void
Thread1(
void
*) {
while
(1) {
printf
(
"Thread1\n"
);
GMSleep(100);
}
}
void
Thread2(
void
*) {
while
(1) {
printf
(
"Thread2\n"
);
GMSleep(200);
}
}
void
Thread3(
void
*) {
while
(1) {
printf
(
"Thread3\n"
);
GMSleep(300);
}
}
void
Thread4(
void
*) {
while
(1) {
printf
(
"Thread4\n"
);
GMSleep(200);
}
}
int
main()
{
char
name1[20] =
"Thread1"
;
char
name2[20] =
"Thread2"
;
char
name3[20] =
"Thread3"
;
char
name4[20] =
"Thread4"
;
RegisterGMThread(name1, Thread1, NULL);
RegisterGMThread(name2, Thread2, NULL);
RegisterGMThread(name3, Thread3, NULL);
RegisterGMThread(name4, Thread4, NULL);
while
(TRUE) {
Sleep(20);
Scheduling();
}
return
0;
}