📄 kernel.c
字号:
/*************************************
* Simulated Kernel Environment *
* Beta 2 (01-11-2001) *
* Copyright (c) 2001 Adrian O'Grady *
*************************************/
// configure the kernel source code
#include "settings.h"
// We don't need most of the win32 stuff (I hope)
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <windows.h>
#include "resource.h"
#include <stdio.h>
#include <stdlib.h>
// Defines all the functions of the kernel
#include "kernapi.h"
// Main event functions
BOOL CALLBACK DialogFunc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK SemDialogFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
// Kernel helper functions
void StartKernel(void);
int GetThreadIndex(HANDLE hand);
int GetSemaphoreIndex(HANDLE hand);
int GetTimerIndex(unsigned int ID);
long InitComPort(void);
void FireTimers(void);
// Event functions
void OnGarbageCollection(void);
void OnFrmMain_KillThread(void);
void OnFrmMain_PauseOutput(void);
void OnFrmMain_PauseThread(void);
void OnFrmMain_ResetThread(void);
void OnFrmMain_SelChange(void);
void OnFrmMain_StartKernel(void);
void OnFrmSem_Release(void);
void OnFrmSem_Wait(void);
void OnFrmSem_WindowInit(void);
// Global variables
char szWinName[] = "Win32AdiOS";
HINSTANCE g_hInst; // Instance of the application
HICON hIconLarge; // Large Icon for the app
HICON hIconSmall; // Small icon for the dialog window
HWND g_hwnd; // Handle to the Dialog window
HWND g_hwndSem; // Handle to the semaphore window
// Kernel control
BOOL g_KernelStarted; // Has the kernel started or not?
BOOL g_PauseOutput; // Is output paused or not?
BOOL g_SemWindowOpen;
// Threading bits
struct TL {
HANDLE handle; // The thread handle
BOOL Running; // Thread status
void * (*lpFunc)(__int32); // Entry function
__int32 param; // Parameter
};
HANDLE g_hThreadSem; // Semaphore for locking the thread list when making changes
int g_Threads; // How many threads have started?
struct TL ThreadList[ADIOS_THREADS_MAX]; // List of running threads
struct SL {
HANDLE handle; // The semaphore handle
int Value; // The current semaphore value
int MaxValue; // The maximum semaphore value
};
int g_Semaphores; // How many semaphores have been created
struct SL SemaphoreList[ADIOS_SEMAPHORES_MAX]; // List of semaphores
// Timer bits
struct TML {
unsigned int ID; // The timer ID
void (*lpFunc)(void); // The timer call function
int CurrentTime; // The current value of the timer
int Interval; // The interval between timer events
};
HANDLE g_hTimerSem; // Semaphore for locking the timer list
int g_Timers; // How many timers are there
unsigned int g_NextTimer; // The next timer ID to assign
struct TML TimerList[ADIOS_TIMERS_MAX]; // List of timers
// Com port globals
HANDLE g_com;
// This is where it all begins
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
// Load the icons
hIconLarge = LoadIcon(hThisInst, "IDI_ICON");
hIconSmall = LoadIcon(hThisInst, "IDI_ICONSM");
g_hInst = hThisInst; /* Save the current instance handle */
g_PauseOutput = FALSE;
g_KernelStarted = FALSE;
g_SemWindowOpen = FALSE;
g_NextTimer = 1;
// Create the thread semaphore
g_hThreadSem = CreateSemaphore(NULL, 1, 1, NULL);
//Create the timer semaphore
g_hTimerSem = CreateSemaphore(NULL, 1, 1, NULL);
// Display the dialog box
return DialogBox(g_hInst, "frmMain", NULL, DialogFunc);
}
// Our function to handle most of the events
BOOL CALLBACK DialogFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case WM_INITDIALOG:
// Set the icon and store the window handle
g_hwnd = hDlg;
SendMessage(hDlg, WM_SETICON, FALSE, (LPARAM)hIconSmall);
break;
case WM_TIMER:
#ifdef ADIOS_USE_GC
if(wParam == ADIOS_GC_TIMER) // Garbage collection
OnGarbageCollection();
#endif /* ADIOS_USE_GC */
if(wParam == ADIOS_TIMERS)
FireTimers();
break;
case WM_CLOSE:
// Exit the application
// I had problems before I added this kernel shutdown code
if (g_KernelStarted == TRUE) OnFrmMain_StartKernel();
EndDialog(hDlg, 0);
PostQuitMessage(0);
return 1;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_CMDSEM:
// If the semaphore window isn't open, open it
if(g_SemWindowOpen == FALSE) DialogBox(g_hInst, "FRMSEM", NULL, SemDialogFunc);
return 1;
case IDC_CMDSTART:
// Start/stop the kernel and sort the buttons out
OnFrmMain_StartKernel();
return 1;
case IDC_CMDPAUSE:
// Toggle the pause flag and button
OnFrmMain_PauseOutput();
return 1;
case IDC_CMDKILL:
// Kill a thread
OnFrmMain_KillThread();
return 1;
case IDC_CMDPAUSET:
// Pause a thread
OnFrmMain_PauseThread();
return 1;
case IDC_CMDRESET:
// Reset a thread
OnFrmMain_ResetThread();
return 1;
case IDC_LSTTHREADS:
// All the list box action
switch (HIWORD(wParam)) {
case LBN_DBLCLK:
// Pause a thread when it is double clicked
OnFrmMain_PauseThread();
break;
case LBN_SELCHANGE:
// Update the buttons when the selection is changed
OnFrmMain_SelChange();
break;
}
return 1;
case IDC_CMDCLEAR:
// Wipe the text from the window
SetDlgItemText(hDlg, IDC_TXTOUTPUT, "");
return 1;
}
break;
}
return 0;
}
BOOL CALLBACK SemDialogFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case WM_INITDIALOG:
// Set the icon and store the window handle
g_hwndSem = hDlg;
g_SemWindowOpen = TRUE; // Let the rest of the app know this window is open
OnFrmSem_WindowInit();
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDCANCEL:
// Close the window
g_SemWindowOpen = FALSE; // Tell every one we're now closed
EndDialog(hDlg, 0);
return 1;
case IDC_CMDWAIT:
// Call the WaitSem() function to decrement a semaphore
OnFrmSem_Wait();
break;
case IDC_CMDRELEASE:
// Call the ReleaseSem() function to increment a semaphore
OnFrmSem_Release();
break;
case IDC_CMDREFRESH:
// Refresh the semaphore list
OnFrmSem_WindowInit();
break;
case IDC_LSTSEM:
// All the list box action
switch (HIWORD(wParam)) {
case LBN_DBLCLK:
// refresh the list
OnFrmSem_Release();
break;
}
}
}
return 0;
}
//------ Window Event Functions ------//
#ifdef ADIOS_USE_GC
// Garbage Collection
void OnGarbageCollection(void)
{
// NOTE: This is a very slow way to do this!
int n, m, i, count;
char buf[1024];
DWORD Status;
// Scan through each thread
for(n = 0; n < ADIOS_THREADS_MAX; n++){
// Is there a thread here?
if(ThreadList[n].handle != 0){
// Get its current status
GetExitCodeThread(ThreadList[n].handle, &Status);
if (Status != STILL_ACTIVE){
// The thread is no longer active so close its handle
CloseHandle(ThreadList[n].handle);
// Find out how many items there are in the list box
count = SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETCOUNT, 0, 0);
// Loop through each item to find and remove the thread text
for(m = 0; m < count; m++){
// Get the text of the current item
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETTEXT, m, (LPARAM) (LPCTSTR) buf);
i = atoi(buf); // Turnit into an integer
if((HANDLE)i == ThreadList[n].handle){
// If the handles match, delete the string from the list box
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_DELETESTRING, m, 0);
// Now clear up our thread table
g_Threads--; // Decrement the thread counter
// Now copy the last thread launched's data over the top of the killed thread's
ThreadList[n].handle = ThreadList[g_Threads].handle;
ThreadList[n].Running = ThreadList[g_Threads].Running;
ThreadList[n].lpFunc = ThreadList[g_Threads].lpFunc;
ThreadList[n].param = ThreadList[g_Threads].param;
// Mark the last thread as truely dead
ThreadList[g_Threads].handle = 0;
ThreadList[g_Threads].Running = FALSE;
}
}
}
}
}
}
#endif /* ADIOS_USE_GC */
// Kill the selected thread
void OnFrmMain_KillThread(void)
{
int i;
char buf[1024];
// Lets get the list index of the selected item
i = SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETCURSEL, 0, 0);
if(i != -1) { // Make sure an item was selected
// Get the text of the item
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETTEXT, i, (LPARAM) (LPCTSTR) buf);
// Delete the item from the list
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_DELETESTRING, i, 0);
i = atoi(buf);
// Kill the thread
KillThread((unsigned int)i);
}
}
// Pause the output to the screen
void OnFrmMain_PauseOutput(void)
{
// Has the output been paused yet?
if (g_PauseOutput == FALSE){
// Pause the output (This free's up a lot of CPU time!)
g_PauseOutput = TRUE;
SetDlgItemText(g_hwnd, IDC_CMDPAUSE, "Start Output");
} else {
// Unpause the output
g_PauseOutput = FALSE;
SetDlgItemText(g_hwnd, IDC_CMDPAUSE, "Stop Output");
}
}
// Suspend or resume a thread
void OnFrmMain_PauseThread(void)
{
int i, n;
char buf[1024];
// Get the index of the selected thread from the list box
i = SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETCURSEL, 0, 0);
if(i != -1) { // Make sure there is an item selected
// Get the text of the item for the handle
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETTEXT, i, (LPARAM) (LPCTSTR) buf);
// Delete the item from the list box (because we'll be changing the text)
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_DELETESTRING, i, 0);
i = atoi(buf); // Turn the text from the list box into a usable form
n = GetThreadIndex((HANDLE)i);
// Time to toggle the thread running state
if(ThreadList[n].Running == TRUE){
// The thread was running, so we must stop it
SuspendThread(ThreadList[n].handle);
ThreadList[n].Running = FALSE; // Let the system know the thread has stopped
SetDlgItemText(g_hwnd, IDC_CMDPAUSET, "Unpause"); // Change the button text
sprintf(buf, "%d (Paused)", i); // Reform the list text
} else {
// The thread is currently suspended, so we must restart it
ResumeThread(ThreadList[n].handle);
ThreadList[n].Running = TRUE; // Let the system know it's running again
SetDlgItemText(g_hwnd, IDC_CMDPAUSET, "Pause"); // Change the button text
sprintf(buf, "%d", i); // Reform the list text
}
// Add the modified string back to the list (I'm glad it sorts automatically!)
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_ADDSTRING, 0, (LPARAM)buf);
}
}
// Relaunch the selected thread
// This works by killing it, then starting it off again
void OnFrmMain_ResetThread(void)
{
// Oooh, lots of nast bits!
int i, n;
char buf[1024];
void * (*lpFunc)(__int32);
__int32 param;
// Lets get the list index of the selected thread
i = SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETCURSEL, 0, 0);
if(i != -1) { // Make sure an item was selected
// Get the text for the thread handle
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETTEXT, i, (LPARAM) (LPCTSTR) buf);
// Remove the list item
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_DELETESTRING, i, 0);
i = atoi(buf);
// We need to store entry function and the parameter for the thread
n = GetThreadIndex((HANDLE)i);
lpFunc = ThreadList[n].lpFunc;
param = ThreadList[n].param;
// Time to kill off the thread
KillThread((unsigned int)ThreadList[n].handle);
// Now to restart the thread
StartThread(lpFunc, param);
}
}
// Update the pause thread button
void OnFrmMain_SelChange(void)
{
int i;
char buf[1024];
// Get the current list box index
i = SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETCURSEL, 0, 0);
// Get the text for the item
SendDlgItemMessage(g_hwnd, IDC_LSTTHREADS, LB_GETTEXT, i, (LPARAM) (LPCTSTR) buf);
// Turn it into an integer
i = atoi(buf);
// Set the pause thread button to either Pause or Unpause
if(ThreadList[GetThreadIndex((HANDLE)i)].Running == TRUE){
SetDlgItemText(g_hwnd, IDC_CMDPAUSET, "Pause");
} else {
SetDlgItemText(g_hwnd, IDC_CMDPAUSET, "Unpause");
}
}
// Start/Stop the kernel
void OnFrmMain_StartKernel(void)
{
// Has the kernel been started yet?
if (g_KernelStarted == FALSE){
// Start the kernel
g_KernelStarted = TRUE;
StartKernel();
SetDlgItemText(g_hwnd, IDC_CMDSTART, "Stop Kernel");
} else {
// Stop the kernel
g_KernelStarted = FALSE;
ExitKernel();
SetDlgItemText(g_hwnd, IDC_CMDSTART, "Start Kernel");
}
}
// Release a semaphore
void OnFrmSem_Release(void)
{
int i;
char buf[1024];
// Lets get the list index of the selected item
i = SendDlgItemMessage(g_hwndSem, IDC_LSTSEM, LB_GETCURSEL, 0, 0);
if(i != -1) { // Make sure an item was selected
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -