summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/specs/SPECFICATION_MACROS.md (renamed from src/kernel/MACROS_MAP.md)10
-rw-r--r--public/frameworks/KernelTest.fwrk/headers/Foundation.h6
-rw-r--r--public/frameworks/KernelTest.fwrk/headers/TestCase.h3
-rw-r--r--src/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc48
-rw-r--r--src/libSystem/src/SystemCalls.cc54
-rw-r--r--src/modules/CoreGfx/CoreGfx.h2
-rw-r--r--test/.keep0
-rw-r--r--test/kernel_test/Makefile22
-rw-r--r--test/kernel_test/error.test.cc2
-rw-r--r--test/kernel_test/event.test.cc103
-rw-r--r--test/kernel_test/process.test.cc13
-rw-r--r--test/kernel_test/scheduler.test.cc108
-rw-r--r--test/libsystem_test/Makefile22
-rw-r--r--test/libsystem_test/memory.test.cc2
-rw-r--r--test/libsystem_test/thread.test.cc2
15 files changed, 144 insertions, 253 deletions
diff --git a/src/kernel/MACROS_MAP.md b/doc/specs/SPECFICATION_MACROS.md
index bae5aef1..e3456e50 100644
--- a/src/kernel/MACROS_MAP.md
+++ b/doc/specs/SPECFICATION_MACROS.md
@@ -1,5 +1,11 @@
-# __nekernel: Configuration Macros of NeKernel.
+# Configuration Macros of NeKernel.
+
+## NeKernel
- `__nekernel_max_cores` -> Max SMP cores usable by NeKernel's scheduler.
-- `__nekernel_boot_core_index` -> Index of the boot core (0, 1, or 3)
+- `__nekernel_boot_core_index` -> Index of the boot core (0, 1, or 3).
+
+## KernelTest:
+
+- `__KT_TEST_MAIN` -> KernelTest entrypoint symbol.
diff --git a/public/frameworks/KernelTest.fwrk/headers/Foundation.h b/public/frameworks/KernelTest.fwrk/headers/Foundation.h
index e1ebb936..97f82e59 100644
--- a/public/frameworks/KernelTest.fwrk/headers/Foundation.h
+++ b/public/frameworks/KernelTest.fwrk/headers/Foundation.h
@@ -17,4 +17,10 @@
#define KT_TEST_SUCCESS (kErrorSuccess)
#define KT_TEST_FAILURE (kErrorSuccess + 1)
+#ifndef __KT_TEST_MAIN
+#define __KT_TEST_MAIN WinMain
+#endif
+
+#define KT_TEST_MAIN __KT_TEST_MAIN
+
#endif
diff --git a/public/frameworks/KernelTest.fwrk/headers/TestCase.h b/public/frameworks/KernelTest.fwrk/headers/TestCase.h
index 46568233..79ebab8d 100644
--- a/public/frameworks/KernelTest.fwrk/headers/TestCase.h
+++ b/public/frameworks/KernelTest.fwrk/headers/TestCase.h
@@ -14,7 +14,8 @@
#define KT_RUN_TEST(OBJECT) \
{ \
- KTTestCase##OBJECT{}.Run(); \
+ KTTestCase##OBJECT obj{}; \
+ obj.Run(); \
}
#define KT_MUST_PASS(MSG, LEFT_COND, RIGHT_COND) \
diff --git a/src/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc b/src/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc
index bb735ffb..7ee4a69c 100644
--- a/src/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc
+++ b/src/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc
@@ -26,26 +26,26 @@ STATIC void hal_int_send_eoi(UInt8 vector) {
/// @param rsp
EXTERN_C Kernel::Void int_handle_gpf(Kernel::UIntPtr rsp) {
auto process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
- process.Leak().Crash();
+ process.Crash();
hal_int_send_eoi(13);
- process.Leak().Signal.SignalArg = rsp;
- process.Leak().Signal.SignalID = SIGKILL;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.SignalArg = rsp;
+ process.Signal.SignalID = SIGKILL;
+ process.Signal.Status = process.Status;
}
/// @brief Handle page fault.
/// @param rsp
EXTERN_C void int_handle_pf(Kernel::UIntPtr rsp) {
auto process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
- process.Leak().Crash();
+ process.Crash();
hal_int_send_eoi(14);
- process.Leak().Signal.SignalArg = rsp;
- process.Leak().Signal.SignalID = SIGKILL;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.SignalArg = rsp;
+ process.Signal.SignalID = SIGKILL;
+ process.Signal.Status = process.Status;
}
/// @brief Handle scheduler interrupt.
@@ -67,28 +67,28 @@ EXTERN_C void int_handle_scheduler(Kernel::UIntPtr rsp) {
/// @param rsp
EXTERN_C void int_handle_math(Kernel::UIntPtr rsp) {
auto process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
- process.Leak().Crash();
+ process.Crash();
hal_int_send_eoi(8);
- process.Leak().Signal.SignalArg = rsp;
- process.Leak().Signal.SignalID = SIGKILL;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.SignalArg = rsp;
+ process.Signal.SignalID = SIGKILL;
+ process.Signal.Status = process.Status;
}
/// @brief Handle any generic fault.
/// @param rsp
EXTERN_C void int_handle_generic(Kernel::UIntPtr rsp) {
auto process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
- process.Leak().Crash();
+ process.Crash();
hal_int_send_eoi(30);
Kernel::kout << "Kernel: Generic Process Fault.\r";
- process.Leak().Signal.SignalArg = rsp;
- process.Leak().Signal.SignalID = SIGKILL;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.SignalArg = rsp;
+ process.Signal.SignalID = SIGKILL;
+ process.Signal.Status = process.Status;
Kernel::kout << "Kernel: SIGKILL status.\r";
}
@@ -98,25 +98,25 @@ EXTERN_C Kernel::Void int_handle_breakpoint(Kernel::UIntPtr rip) {
hal_int_send_eoi(3);
- process.Leak().Signal.SignalArg = rip;
- process.Leak().Signal.SignalID = SIGTRAP;
+ process.Signal.SignalArg = rip;
+ process.Signal.SignalID = SIGTRAP;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.Status = process.Status;
- process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+ process.Status = Kernel::ProcessStatusKind::kFrozen;
}
/// @brief Handle #UD fault.
/// @param rsp
EXTERN_C void int_handle_ud(Kernel::UIntPtr rsp) {
auto process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
- process.Leak().Crash();
+ process.Crash();
hal_int_send_eoi(6);
- process.Leak().Signal.SignalArg = rsp;
- process.Leak().Signal.SignalID = SIGKILL;
- process.Leak().Signal.Status = process.Leak().Status;
+ process.Signal.SignalArg = rsp;
+ process.Signal.SignalID = SIGKILL;
+ process.Signal.Status = process.Status;
}
/// @brief Enter syscall from assembly (libSystem only)
diff --git a/src/libSystem/src/SystemCalls.cc b/src/libSystem/src/SystemCalls.cc
index 0574d7ba..2651fb28 100644
--- a/src/libSystem/src/SystemCalls.cc
+++ b/src/libSystem/src/SystemCalls.cc
@@ -6,6 +6,8 @@
#include <libSystem/SystemKit/Syscall.h>
#include <libSystem/SystemKit/System.h>
#include <libSystem/SystemKit/Verify.h>
+#include "hint/CompilerHint.h"
+#include "libSystem/SystemKit/Macros.h"
using namespace LibSystem;
@@ -148,6 +150,58 @@ IMPORT_C UInt64 IoTellFile(_Input Ref desc) {
return *ret;
}
+IMPORT_C SInt32 PrintRelease(_Input IORef buf) {
+ SInt32* ret = static_cast<SInt32*>(libsys_syscall_arg_2(SYSCALL_HASH("PrintRelease"), static_cast<VoidPtr>(buf)));
+ if (!ret) return -kErrorInvalidData;
+
+ return static_cast<SInt32>(*ret);
+}
+
+IMPORT_C IORef PrintCreate(Void) {
+ return static_cast<IORef>(libsys_syscall_arg_1(SYSCALL_HASH("PrintCreate")));
+}
+
+
+IMPORT_C VoidPtr MmCreateHeap(UInt64 initial_size, UInt32 max_size) {
+ return static_cast<VoidPtr>(libsys_syscall_arg_3(SYSCALL_HASH("MmCreateHeap"),
+ reinterpret_cast<VoidPtr>(&initial_size),
+ reinterpret_cast<VoidPtr>(&max_size)));
+}
+
+IMPORT_C SInt32 MmDestroyHeap(VoidPtr heap)
+{
+ auto ret = libsys_syscall_arg_2(SYSCALL_HASH("MmDestroyHeap"), static_cast<VoidPtr>(heap));
+ return *static_cast<SInt32*>(ret);
+}
+
+IMPORT_C SInt32 PrintIn(_Input IORef desc, const Char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ auto buf = StrFmt(fmt, args);
+
+ va_end(args);
+
+ // if truncated, `needed` >= kBufferSz; we still send truncated buffer
+ auto ret_ptr = libsys_syscall_arg_3(SYSCALL_HASH("PrintIn"), static_cast<VoidPtr>(desc),
+ Verify::sys_safe_cast<Char, Void>(buf));
+
+ if (!ret_ptr) return -kErrorInvalidData;
+
+ auto ret = static_cast<const volatile SInt32*>(ret_ptr);
+
+ return *ret;
+}
+
+IMPORT_C IORef PrintGet(const Char* path) {
+ return static_cast<IORef>(libsys_syscall_arg_2(SYSCALL_HASH("PrintGet"),
+ Verify::sys_safe_cast<Char, Void>(path)));
+}
+
+IMPORT_C ErrRef ErrGetLastError(Void) {
+ return *static_cast<ErrRef*>(libsys_syscall_arg_1(SYSCALL_HASH("ErrGetLastError")));
+}
+
IMPORT_C SInt32 PrintOut(_Input IORef desc, const Char* fmt, ...) {
va_list args;
va_start(args, fmt);
diff --git a/src/modules/CoreGfx/CoreGfx.h b/src/modules/CoreGfx/CoreGfx.h
index 470dd510..c22aee38 100644
--- a/src/modules/CoreGfx/CoreGfx.h
+++ b/src/modules/CoreGfx/CoreGfx.h
@@ -11,7 +11,7 @@
#define cg_color(R, G, B) RGB(R, G, B)
-#define cg_get_clear_clr() RGB(0, 0, 0x80)
+#define cg_get_clear_clr() RGB(0, 0, 0)
#define cg_clear() kCGCursor = 0UL
diff --git a/test/.keep b/test/.keep
deleted file mode 100644
index e69de29b..00000000
--- a/test/.keep
+++ /dev/null
diff --git a/test/kernel_test/Makefile b/test/kernel_test/Makefile
new file mode 100644
index 00000000..823ac0d2
--- /dev/null
+++ b/test/kernel_test/Makefile
@@ -0,0 +1,22 @@
+##################################################
+# (c) Amlal El Mahrouss and NeKernel Authors, licensed under the Apache 2.0 license.
+# This file is for libSystem.dll's testing stubs.
+##################################################
+
+GCC=x86_64-w64-mingw32-g++ -Wl,-subsystem=17
+LIB=-L../../src/libSystem -lSystem
+STD=-std=c++20 -DKT_TESTING_ENABLED
+INCLUDE=-I../../src -I../../public -I../../public/frameworks/ -I../../
+
+OBJ_FILES = \
+ error.test.exe \
+ print.test.exe \
+ process.test.exe
+
+.PHONY: all
+all: $(OBJ_FILES)
+
+%.exe: %.cc
+ @echo "==> Building test: $@"
+ $(GCC) $(LIB) $< \
+ $(STD) $(INCLUDE) -o $(basename $<).exe \ No newline at end of file
diff --git a/test/kernel_test/error.test.cc b/test/kernel_test/error.test.cc
index 084566b2..ece8f71d 100644
--- a/test/kernel_test/error.test.cc
+++ b/test/kernel_test/error.test.cc
@@ -55,7 +55,7 @@ KT_DECL_TEST(ErrGetLastErrorMultipleCalls, []() -> bool {
});
/// \brief Run error tests.
-SInt32 KT_TEST_MAIN() {
+IMPORT_C SInt32 KT_TEST_MAIN() {
KT_RUN_TEST(ErrGetLastErrorInitial);
KT_RUN_TEST(ErrGetLastErrorAfterSuccess);
KT_RUN_TEST(ErrGetLastErrorAfterFailure);
diff --git a/test/kernel_test/event.test.cc b/test/kernel_test/event.test.cc
deleted file mode 100644
index 6e342c6b..00000000
--- a/test/kernel_test/event.test.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-/// \file event.test.cc
-/// \brief Event handling API tests.
-/// \author Amlal El Mahrouss (amlal at nekernel dot org)
-
-#include <libSystem/SystemKit/System.h>
-#include <public/frameworks/KernelTest.fwrk/headers/TestCase.h>
-
-/// \note Mock event listener
-static Bool event_listener_called = NO;
-
-static Void mock_event_listener(VoidPtr data) {
- event_listener_called = YES;
-}
-
-/// \note EvtAddListener tests
-KT_DECL_TEST(EvtAddListenerValid, []() -> bool {
- REF_TYPE listener_ref;
- listener_ref.__hash = 0x1234;
- listener_ref.__self = (VoidPtr) mock_event_listener;
-
- EvtAddListener("test_event", (Ref) &listener_ref);
- return YES;
-});
-
-KT_DECL_TEST(EvtAddListenerNull, []() -> bool {
- EvtAddListener(nullptr, nullptr);
- return YES;
-});
-
-/// \note EvtRemoveListener tests
-KT_DECL_TEST(EvtRemoveListenerValid, []() -> bool {
- REF_TYPE listener_ref;
- listener_ref.__hash = 0x1234;
- listener_ref.__self = (VoidPtr) mock_event_listener;
-
- EvtAddListener("remove_test", (Ref) &listener_ref);
- EvtRemoveListener("remove_test", (Ref) &listener_ref);
- return YES;
-});
-
-KT_DECL_TEST(EvtRemoveListenerNull, []() -> bool {
- EvtRemoveListener(nullptr, nullptr);
- return YES;
-});
-
-/// \note EvtDispatchEvent tests
-KT_DECL_TEST(EvtDispatchEventValid, []() -> bool {
- REF_TYPE listener_ref;
- listener_ref.__hash = 0x5678;
- listener_ref.__self = (VoidPtr) mock_event_listener;
-
- event_listener_called = NO;
-
- EvtAddListener("dispatch_test", (Ref) &listener_ref);
-
- char data[] = "event_data";
- EvtDispatchEvent("dispatch_test", (VoidPtr) data);
-
- return YES;
-});
-
-KT_DECL_TEST(EvtDispatchEventNull, []() -> bool {
- VoidPtr result = EvtDispatchEvent(nullptr, nullptr);
- return result == nullptr;
-});
-
-KT_DECL_TEST(EvtDispatchEventNotExist, []() -> bool {
- VoidPtr result = EvtDispatchEvent("nonexistent_event", nullptr);
- return YES;
-});
-
-/// \note Event lifecycle test
-KT_DECL_TEST(EvtLifecycleTest, []() -> bool {
- REF_TYPE listener_ref;
- listener_ref.__hash = 0xABCD;
- listener_ref.__self = (VoidPtr) mock_event_listener;
-
- EvtAddListener("lifecycle_event", (Ref) &listener_ref);
-
- char data[] = "test";
- EvtDispatchEvent("lifecycle_event", (VoidPtr) data);
-
- EvtRemoveListener("lifecycle_event", (Ref) &listener_ref);
-
- return YES;
-});
-
-/// \brief Run event tests.
-SInt32 KT_TEST_MAIN() {
- KT_RUN_TEST(EvtAddListenerValid);
- KT_RUN_TEST(EvtAddListenerNull);
-
- KT_RUN_TEST(EvtRemoveListenerValid);
- KT_RUN_TEST(EvtRemoveListenerNull);
-
- KT_RUN_TEST(EvtDispatchEventValid);
- KT_RUN_TEST(EvtDispatchEventNull);
- KT_RUN_TEST(EvtDispatchEventNotExist);
-
- KT_RUN_TEST(EvtLifecycleTest);
-
- return KT_TEST_SUCCESS;
-}
diff --git a/test/kernel_test/process.test.cc b/test/kernel_test/process.test.cc
index 451cacfe..b742b5c1 100644
--- a/test/kernel_test/process.test.cc
+++ b/test/kernel_test/process.test.cc
@@ -3,7 +3,7 @@
/// \author Amlal El Mahrouss (amlal at nekernel dot org)
#include <libSystem/SystemKit/System.h>
-#include <public/frameworks/KernelTest.fwrk/headers/TestCase.h>
+#include <KernelTest.fwrk/headers/TestCase.h>
/// \note RtlSpawnProcess tests
KT_DECL_TEST(ProcessHasFailed, []() -> bool {
@@ -17,14 +17,6 @@ KT_DECL_TEST(ProcessHasSucceeded, []() -> bool {
return RtlSpawnProcess("/system/list", 0, nullptr, nullptr, 0) > 0;
});
-KT_DECL_TEST(ProcessSpawnWithArgs, []() -> bool {
- Char* argv[] = {(Char*) "arg1", (Char*) "arg2"};
- Char* envp[] = {(Char*) "VAR=value"};
-
- UIntPtr pid = RtlSpawnProcess("/system/list", 2, argv, envp, 1);
- return pid > 0;
-});
-
KT_DECL_TEST(ProcessSpawnNullPath,
[]() -> bool { return RtlSpawnProcess(nullptr, 0, nullptr, nullptr, 0) == -1; });
@@ -69,10 +61,9 @@ KT_DECL_TEST(ProcessExitInvalid, []() -> bool {
});
/// \brief Run 'process' test.
-SInt32 KT_TEST_MAIN() {
+IMPORT_C SInt32 KT_TEST_MAIN() {
KT_RUN_TEST(ProcessHasFailed);
KT_RUN_TEST(ProcessHasSucceeded);
- KT_RUN_TEST(ProcessSpawnWithArgs);
KT_RUN_TEST(ProcessSpawnNullPath);
KT_RUN_TEST(ProcessSpawnInvalidPath);
diff --git a/test/kernel_test/scheduler.test.cc b/test/kernel_test/scheduler.test.cc
deleted file mode 100644
index 58cf6017..00000000
--- a/test/kernel_test/scheduler.test.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/// \file scheduler.test.cc
-/// \brief Scheduler and debugging API tests.
-/// \author Amlal El Mahrouss (amlal at nekernel dot org)
-
-#include <libSystem/SystemKit/System.h>
-#include <public/frameworks/KernelTest.fwrk/headers/TestCase.h>
-
-/// \note SchedGetCurrentProcessID tests
-KT_DECL_TEST(SchedGetCurrentPIDValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- return pid > 0;
-});
-
-/// \note SchedSetAffinity/SchedGetAffinity tests
-KT_DECL_TEST(SchedSetAffinityValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- AffinityRef affinity;
-
- SInt32 result = SchedSetAffinity(pid, 1, &affinity);
- return result >= 0;
-});
-
-KT_DECL_TEST(SchedGetAffinityValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- AffinityRef affinity;
-
- SInt32 result = SchedGetAffinity(pid, &affinity);
- return result >= 0;
-});
-
-KT_DECL_TEST(SchedSetAffinityInvalid, []() -> bool {
- AffinityRef affinity;
- SInt32 result = SchedSetAffinity(0, 1, &affinity);
- return result < 0;
-});
-
-KT_DECL_TEST(SchedGetAffinityInvalid, []() -> bool {
- AffinityRef affinity;
- SInt32 result = SchedGetAffinity(0, &affinity);
- return result < 0;
-});
-
-KT_DECL_TEST(SchedAffinityRoundTrip, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- AffinityRef affinity_set;
- AffinityRef affinity_get;
-
- SchedSetAffinity(pid, 2, &affinity_set);
- SInt32 result = SchedGetAffinity(pid, &affinity_get);
-
- return result >= 0;
-});
-
-/// \note SchedFireSignal tests
-KT_DECL_TEST(SchedFireSignalValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- SInt32 result = SchedFireSignal(pid, 1);
- return result >= 0;
-});
-
-KT_DECL_TEST(SchedFireSignalInvalid, []() -> bool {
- SInt32 result = SchedFireSignal(0, 1);
- return result < 0;
-});
-
-/// \note SchedReadMemory/SchedWriteMemory tests
-KT_DECL_TEST(SchedReadMemoryValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- SInt32 result = SchedReadMemory(pid, 0x1000, 64);
- return result >= 0;
-});
-
-KT_DECL_TEST(SchedWriteMemoryValid, []() -> bool {
- UIntPtr pid = SchedGetCurrentProcessID();
- SInt32 result = SchedWriteMemory(pid, 0x1000, 0x42);
- return result >= 0;
-});
-
-KT_DECL_TEST(SchedReadMemoryInvalid, []() -> bool {
- SInt32 result = SchedReadMemory(0, 0x1000, 64);
- return result < 0;
-});
-
-KT_DECL_TEST(SchedWriteMemoryInvalid, []() -> bool {
- SInt32 result = SchedWriteMemory(0, 0x1000, 0x42);
- return result < 0;
-});
-
-/// \brief Run scheduler tests.
-SInt32 KT_TEST_MAIN() {
- KT_RUN_TEST(SchedGetCurrentPIDValid);
-
- KT_RUN_TEST(SchedSetAffinityValid);
- KT_RUN_TEST(SchedGetAffinityValid);
- KT_RUN_TEST(SchedSetAffinityInvalid);
- KT_RUN_TEST(SchedGetAffinityInvalid);
- KT_RUN_TEST(SchedAffinityRoundTrip);
-
- KT_RUN_TEST(SchedFireSignalValid);
- KT_RUN_TEST(SchedFireSignalInvalid);
-
- KT_RUN_TEST(SchedReadMemoryValid);
- KT_RUN_TEST(SchedWriteMemoryValid);
- KT_RUN_TEST(SchedReadMemoryInvalid);
- KT_RUN_TEST(SchedWriteMemoryInvalid);
-
- return KT_TEST_SUCCESS;
-}
diff --git a/test/libsystem_test/Makefile b/test/libsystem_test/Makefile
new file mode 100644
index 00000000..0e38e134
--- /dev/null
+++ b/test/libsystem_test/Makefile
@@ -0,0 +1,22 @@
+##################################################
+# (c) Amlal El Mahrouss and NeKernel Authors, licensed under the Apache 2.0 license.
+# This file is for libSystem.dll's testing stubs.
+##################################################
+
+GCC=x86_64-w64-mingw32-g++ -Wl,-subsystem=17
+LIB=-L../../src/libSystem -lSystem
+STD=-std=c++20 -DKT_TESTING_ENABLED
+INCLUDE=-I../../src -I../../public -I../../public/frameworks/ -I../../
+
+OBJ_FILES = \
+ thread.test.exe \
+ memory.test.exe \
+ io.test.exe
+
+.PHONY: all
+all: $(OBJ_FILES)
+
+%.exe: %.cc
+ @echo "==> Building test: $@"
+ $(GCC) $(LIB) $< \
+ $(STD) $(INCLUDE) -o $(basename $<).exe \ No newline at end of file
diff --git a/test/libsystem_test/memory.test.cc b/test/libsystem_test/memory.test.cc
index 5083570c..28d758cc 100644
--- a/test/libsystem_test/memory.test.cc
+++ b/test/libsystem_test/memory.test.cc
@@ -110,7 +110,7 @@ KT_DECL_TEST(MmFillCRC32HeapValid, []() -> bool {
});
/// \brief Run memory tests.
-SInt32 KT_TEST_MAIN() {
+IMPORT_C SInt32 KT_TEST_MAIN() {
KT_RUN_TEST(MmCreateHeapSuccess);
KT_RUN_TEST(MmCreateHeapZeroSize);
KT_RUN_TEST(MmDestroyHeapValid);
diff --git a/test/libsystem_test/thread.test.cc b/test/libsystem_test/thread.test.cc
index ec8ccbad..db248e26 100644
--- a/test/libsystem_test/thread.test.cc
+++ b/test/libsystem_test/thread.test.cc
@@ -120,7 +120,7 @@ KT_DECL_TEST(ThrExitMainThreadValid, []() -> bool {
});
/// \brief Run threading tests.
-SInt32 KT_TEST_MAIN() {
+IMPORT_C SInt32 KT_TEST_MAIN() {
KT_RUN_TEST(ThrCreateThreadValid);
KT_RUN_TEST(ThrCreateThreadNull);
KT_RUN_TEST(ThrCreateThreadWithName);