summaryrefslogtreecommitdiffstats
path: root/src/lib/kStuff/kHlp/Bare
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kStuff/kHlp/Bare')
-rw-r--r--src/lib/kStuff/kHlp/Bare/Makefile.kup0
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c223
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c138
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c102
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c763
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c85
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpBareThread.c93
-rw-r--r--src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c345
8 files changed, 1749 insertions, 0 deletions
diff --git a/src/lib/kStuff/kHlp/Bare/Makefile.kup b/src/lib/kStuff/kHlp/Bare/Makefile.kup
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/Makefile.kup
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c b/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c
new file mode 100644
index 0000000..889e48f
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBare-gcc.c
@@ -0,0 +1,223 @@
+/* $Id: kHlpBare-gcc.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - The Dynamic Loader, Helper Functions for GCC.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <k/kLdr.h>
+#include "kHlp.h"
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+
+
+void *memchr(const void *pv, int ch, KSIZE cb)
+{
+ const char *pb = pv;
+ while (cb-- > 0)
+ {
+ if (*pb == ch)
+ return (void *)pb;
+ pb++;
+ }
+ return 0;
+}
+
+
+int memcmp(const void *pv1, const void *pv2, KSIZE cb)
+{
+ /*
+ * Pointer size pointer size.
+ */
+ if ( cb > 16
+ && !((KUPTR)pv1 & (sizeof(void *) - 1))
+ && !((KUPTR)pv2 & (sizeof(void *) - 1)) )
+ {
+ const KUPTR *pu1 = pv1;
+ const KUPTR *pu2 = pv2;
+ while (cb >= sizeof(KUPTR))
+ {
+ const KUPTR u1 = *pu1++;
+ const KUPTR u2 = *pu2++;
+ if (u1 != u2)
+ return u1 > u2 ? 1 : -1;
+ cb -= sizeof(KUPTR);
+ }
+ if (!cb)
+ return 0;
+ pv1 = (const void *)pu1;
+ pv2 = (const void *)pu2;
+ }
+
+ /*
+ * Byte by byte.
+ */
+ if (cb)
+ {
+ const unsigned char *pb1 = pv1;
+ const unsigned char *pb2 = pv2;
+ while (cb-- > 0)
+ {
+ const unsigned char b1 = *pb1++;
+ const unsigned char b2 = *pb2++;
+ if (b1 != b2)
+ return b1 > b2 ? 1 : -1;
+ }
+ }
+ return 0;
+}
+
+
+void *memcpy(void *pv1, const void *pv2, KSIZE cb)
+{
+ void *pv1Start = pv1;
+
+ /*
+ * Pointer size pointer size.
+ */
+ if ( cb > 16
+ && !((KUPTR)pv1 & (sizeof(void *) - 1))
+ && !((KUPTR)pv2 & (sizeof(void *) - 1)) )
+ {
+ KUPTR *pu1 = pv1;
+ const KUPTR *pu2 = pv2;
+ while (cb >= sizeof(KUPTR))
+ {
+ cb -= sizeof(KUPTR);
+ *pu1++ = *pu2++;
+ }
+ if (!cb)
+ return 0;
+ pv1 = (void *)pu1;
+ pv2 = (const void *)pu2;
+ }
+
+ /*
+ * byte by byte
+ */
+ if (cb)
+ {
+ unsigned char *pb1 = pv1;
+ const unsigned char *pb2 = pv2;
+ while (cb-- > 0)
+ *pb1++ = *pb2++;
+ }
+
+ return pv1Start;
+}
+
+void *memset(void *pv, int ch, KSIZE cb)
+{
+ void *pvStart = pv;
+
+ /*
+ * Pointer size pointer size.
+ */
+ if ( cb > 16
+ && !((KUPTR)pv & (sizeof(void *) - 1)))
+ {
+ KUPTR *pu = pv;
+ KUPTR u = ch | (ch << 8);
+ u |= u << 16;
+#if K_ARCH_BITS >= 64
+ u |= u << 32;
+#endif
+#if K_ARCH_BITS >= 128
+ u |= u << 64;
+#endif
+
+ while (cb >= sizeof(KUPTR))
+ {
+ cb -= sizeof(KUPTR);
+ *pu++ = u;
+ }
+ }
+
+ /*
+ * Byte by byte
+ */
+ if (cb)
+ {
+ unsigned char *pb = pv;
+ while (cb-- > 0)
+ *pb++ = ch;
+ }
+ return pvStart;
+}
+
+
+int strcmp(const char *psz1, const char *psz2)
+{
+ for (;;)
+ {
+ const char ch1 = *psz1++;
+ const char ch2 = *psz2++;
+ if (ch1 != ch2)
+ return (int)ch1 - (int)ch2;
+ if (!ch1)
+ return 0;
+ }
+}
+
+
+int strncmp(const char *psz1, const char *psz2, KSIZE cch)
+{
+ while (cch-- > 0)
+ {
+ const char ch1 = *psz1++;
+ const char ch2 = *psz2++;
+ if (ch1 != ch2)
+ return (int)ch1 - (int)ch2;
+ if (!ch1)
+ break;
+ }
+ return 0;
+}
+
+char *strchr(const char *psz, int ch)
+{
+ for (;;)
+ {
+ const char chCur = *psz;
+ if (chCur == ch)
+ return (char *)psz;
+ if (!chCur)
+ return 0;
+ psz++;
+ }
+}
+
+KSIZE strlen(const char *psz)
+{
+ const char *pszStart = psz;
+ while (*psz)
+ psz++;
+ return psz - pszStart;
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c b/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c
new file mode 100644
index 0000000..138e73e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareAssert.c
@@ -0,0 +1,138 @@
+/* $Id: kHlpBareAssert.c 82 2016-08-22 21:01:51Z bird $ */
+/** @file
+ * kHlpBare - Assert Backend.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <k/kHlpAssert.h>
+#include <k/kHlpString.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Writes a assert string with unix lineendings.
+ *
+ * @param pszMsg The string.
+ */
+static void kHlpAssertWrite(const char *pszMsg)
+{
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+ KSIZE cchMsg = kHlpStrLen(pszMsg);
+ kHlpSys_write(2 /* stderr */, pszMsg, cchMsg);
+
+#elif K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS
+ /*
+ * Line by line.
+ */
+ ULONG cbWritten;
+ const char *pszNl = kHlpStrChr(pszMsg, '\n');
+ while (pszNl)
+ {
+ cbWritten = pszNl - pszMsg;
+
+# if K_OS == K_OS_OS2
+ if (cbWritten)
+ DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+ DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
+# else /* K_OS == K_OS_WINDOWS */
+ if (cbWritten)
+ WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+ WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
+# endif
+
+ /* next */
+ pszMsg = pszNl + 1;
+ pszNl = kHlpStrChr(pszMsg, '\n');
+ }
+
+ /*
+ * Remaining incomplete line.
+ */
+ if (*pszMsg)
+ {
+ cbWritten = kHlpStrLen(pszMsg);
+# if K_OS == K_OS_OS2
+ DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+# else /* K_OS == K_OS_WINDOWS */
+ WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+# endif
+ }
+
+#else
+# error "port me"
+#endif
+}
+
+
+KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+ char szLine[16];
+
+ kHlpAssertWrite("\n!!!kLdr Assertion Failed!!!\nExpression: ");
+ kHlpAssertWrite(pszExpr);
+ kHlpAssertWrite("\nAt: ");
+ kHlpAssertWrite(pszFile);
+ kHlpAssertWrite("(");
+ kHlpAssertWrite(kHlpInt2Ascii(szLine, sizeof(szLine), iLine, 10));
+ kHlpAssertWrite(") ");
+ kHlpAssertWrite(pszFunction);
+ kHlpAssertWrite("\n");
+}
+
+
+KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...)
+{
+ kHlpAssertWrite(pszFormat);
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c b/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c
new file mode 100644
index 0000000..353c19e
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareEnv.c
@@ -0,0 +1,102 @@
+/* $Id: kHlpBareEnv.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Environment Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <k/kHlpEnv.h>
+#include <k/kHlpString.h>
+#include <k/kErrors.h>
+
+#if K_OS == K_OS_DARWIN
+
+#elif K_OS == K_OS_LINUX
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# error "port me"
+#endif
+
+
+KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal)
+{
+#if K_OS == K_OS_DARWIN
+ /** @todo need to figure out where the stuff is or how it's inherited on darwin ... */
+ return KERR_ENVVAR_NOT_FOUND;
+
+#elif K_OS == K_OS_LINUX
+ /** @todo either read /proc/self/environ or figure out where in the memory the initial environment is... */
+ return KERR_ENVVAR_NOT_FOUND;
+
+#elif K_OS == K_OS_OS2
+ PSZ pszValue = NULL;
+ int rc;
+
+ *pszVal = '\0';
+ rc = DosScanEnv((PCSZ)pszVar, &pszValue);
+ if (!rc)
+ {
+ KSIZE cch = kHlpStrLen((const char *)pszValue);
+ if (cchVal > cch)
+ kHlpMemCopy(pszVal, pszValue, cch + 1);
+ else
+ rc = KERR_BUFFER_OVERFLOW;
+ }
+ else
+ rc = KERR_ENVVAR_NOT_FOUND;
+ return rc;
+
+#elif K_OS == K_OS_WINDOWS
+ DWORD cch;
+
+ SetLastError(0);
+ cch = GetEnvironmentVariable(pszVar, pszVal, cchVal);
+ if (cch > 0 && cch < cchVal)
+ return 0;
+
+ *pszVal = '\0';
+ if (cch >= cchVal)
+ return KERR_BUFFER_OVERFLOW;
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ return KERR_ENVVAR_NOT_FOUND;
+ return GetLastError();
+
+#else
+# error "Port me"
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c b/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c
new file mode 100644
index 0000000..d5e44b4
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareHeap.c
@@ -0,0 +1,763 @@
+/* $Id: kHlpBareHeap.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Heap.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define KHLPHEAP_STRICT
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <k/kHlpAlloc.h>
+#include <k/kHlpString.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+
+#elif K_OS == K_OS_WINDOWS
+# include <Windows.h>
+
+#else
+# include <k/kHlpAlloc.h>
+#endif
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+/**
+ * A heap block.
+ */
+typedef struct KHLPHEAPBLOCK
+{
+ /** Next block in the global list. */
+ struct KHLPHEAPBLOCK *pNext;
+ /** Previous block in the global list. */
+ struct KHLPHEAPBLOCK *pPrev;
+ /** The size of this block including this header. */
+ KSIZE cb;
+ /** The flags. */
+ KSIZE fFlags;
+} KHLPHEAPBLOCK, *PKHLPHEAPBLOCK;
+
+/** Indicates whether the block is free (set) or allocated (clear). */
+#define KHLPHEAPBLOCK_FLAG_FREE ((KSIZE)1)
+/** Valid flag mask. */
+#define KHLPHEAPBLOCK_FLAG_MASK ((KSIZE)1)
+
+/** Checks if the block is freed. */
+#define KHLPHEAPBLOCK_IS_FREE(pB) ( (pB)->fFlags & KHLPHEAPBLOCK_FLAG_FREE )
+/** Check if the block is allocated. */
+#define KHLPHEAPBLOCK_IS_ALLOCATED(pB) !KHLPHEAPBLOCK_IS_FREE(pB)
+/** Checks if the two blocks are adjacent.
+ * Assumes pB1 < pB2. */
+#define KHLPHEAPBLOCK_IS_ADJACENT(pB1, pB2) \
+ ( ((KUPTR)(pB1) + (pB1)->cb) == (KUPTR)(pB2) )
+
+/** The block alignment. */
+#define KHLPHEAPBLOCK_ALIGNMENT sizeof(KHLPHEAPBLOCK)
+
+/** @def KHLPHEAP_ASSERT
+ * Heap assertion. */
+/** @def KHLPHEAP_ASSERT_BLOCK
+ * Assert that a heap block is valid. */
+/** @def KHLPHEAP_ASSERT_FREE
+ * Assert that a heap free block is valid. */
+#ifdef KHLPHEAP_STRICT
+# define KHLPHEAP_ASSERT(expr) kHlpAssert(expr)
+
+# define KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock) \
+ do { \
+ KHLPHEAP_ASSERT(!((pBlock)->fFlags & ~KHLPHEAPBLOCK_FLAG_MASK)); \
+ KHLPHEAP_ASSERT(!((pBlock)->cb & (KHLPHEAPBLOCK_ALIGNMENT - 1))); \
+ KHLPHEAP_ASSERT((KUPTR)(pBlock)->pPrev < (KUPTR)(pBlock)); \
+ KHLPHEAP_ASSERT((KUPTR)(pBlock)->pNext > (KUPTR)(pBlock) || !(pBlock)->pNext); \
+ } while (0)
+
+# define KHLPHEAP_ASSERT_FREE(pHeap, pFree) \
+ do { \
+ KHLPHEAP_ASSERT_BLOCK(pHeap, &(pFree)->Core); \
+ KHLPHEAP_ASSERT((KUPTR)(pFree)->pPrev < (KUPTR)(pFree)); \
+ KHLPHEAP_ASSERT((KUPTR)(pFree)->pNext > (KUPTR)(pFree) || !(pFree)->pNext); \
+ } while (0)
+
+#else
+# define KHLPHEAP_ASSERT(expr) do { } while (0)
+# define KHLPHEAP_ASSERT_BLOCK(pH, pB) do { } while (0)
+# define KHLPHEAP_ASSERT_FREE(pH, pF) do { } while (0)
+#endif
+
+
+/**
+ * A free heap block.
+ */
+typedef struct KHLPHEAPFREE
+{
+ /** The core bit which we have in common with used blocks. */
+ KHLPHEAPBLOCK Core;
+ /** The next free block. */
+ struct KHLPHEAPFREE *pNext;
+ /** The previous free block. */
+ struct KHLPHEAPFREE *pPrev;
+} KHLPHEAPFREE, *PKHLPHEAPFREE;
+
+
+/**
+ * A heap segment.
+ */
+typedef struct KHLPHEAPSEG
+{
+ /** The base address of the segment. */
+ void *pvBase;
+ /** The length of the segment (in bytes). */
+ KSIZE cb;
+} KHLPHEAPSEG, *PKHLPHEAPSEG;
+
+/**
+ * Bundle of heap segments.
+ */
+typedef struct KHLPHEAPSEGS
+{
+ /** Pointer to the next segment bundle. */
+ struct KHLPHEAPSEGS *pNext;
+ /** The number of segments used. */
+ KU32 cSegs;
+ /** Array of chunks. */
+ KHLPHEAPSEG aSegs[64];
+} KHLPHEAPSEGS, *PKHLPHEAPSEGS;
+
+
+/**
+ * Heap anchor block.
+ */
+typedef struct KHLPHEAPANCHOR
+{
+ /** Head of the block list. */
+ PKHLPHEAPBLOCK pHead;
+ /** Tail of the block list. */
+ PKHLPHEAPBLOCK pTail;
+ /** Head of the free list. */
+ PKHLPHEAPFREE pFreeHead;
+ /** Head segment bundle.
+ * The order of this list is important, but a bit peculiar.
+ * Logically, SegsHead::pNext is the tail pointer. */
+ KHLPHEAPSEGS SegsHead;
+} KHLPHEAPANCHOR, *PKHLPHEAPANCHOR;
+
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/** The heap anchor block. */
+static KHLPHEAPANCHOR g_Heap;
+
+
+/*******************************************************************************
+* Internal Functions *
+*******************************************************************************/
+static int khlpHeapInit(PKHLPHEAPANCHOR pHeap);
+static void khlpHeapDelete(PKHLPHEAPANCHOR pHeap);
+static void * khlpHeapAlloc(PKHLPHEAPANCHOR pHeap, KSIZE cb);
+static void khlpHeapFree(PKHLPHEAPANCHOR pHeap, void *pv);
+static KSIZE khlpHeapBlockSize(PKHLPHEAPANCHOR pHeap, void *pv);
+static void khlpHeapDonate(PKHLPHEAPANCHOR pHeap, void *pv, KSIZE cb);
+static int khlpHeapSegAlloc(PKHLPHEAPSEG pSeg, KSIZE cb);
+static void khlpHeapSegFree(PKHLPHEAPSEG pSeg);
+
+
+/**
+ * Initializes the kLdr heap.
+ *
+ * @returns 0 on success, non-zero OS specific status code on failure.
+ */
+KHLP_DECL(int) kHlpHeapInit(void)
+{
+ return khlpHeapInit(&g_Heap);
+}
+
+
+/**
+ * Terminates the kLdr heap.
+ */
+KHLP_DECL(void) kHlpHeapTerm(void)
+{
+ khlpHeapDelete(&g_Heap);
+}
+
+
+KHLP_DECL(void *) kHlpAlloc(KSIZE cb)
+{
+ return khlpHeapAlloc(&g_Heap, cb);
+}
+
+
+KHLP_DECL(void *) kHlpAllocZ(KSIZE cb)
+{
+ void *pv = khlpHeapAlloc(&g_Heap, cb);
+ if (pv)
+ kHlpMemSet(pv, 0, cb);
+ return pv;
+}
+
+
+KHLP_DECL(void *) kHlpDup(const void *pv, KSIZE cb)
+{
+ void *pvNew = khlpHeapAlloc(&g_Heap, cb);
+ if (pvNew)
+ kHlpMemCopy(pvNew, pv, cb);
+ return pvNew;
+}
+
+
+KHLP_DECL(char *) kHlpStrDup(const char *psz)
+{
+ return (char *)kHlpDup(psz, kHlpStrLen(psz) + 1);
+}
+
+
+KHLP_DECL(void *) kHlpRealloc(void *pv, KSIZE cb)
+{
+ void *pvNew;
+ if (!cb)
+ {
+ kHlpFree(pv);
+ pvNew = NULL;
+ }
+ else if (!pv)
+ pvNew = khlpHeapAlloc(&g_Heap, cb);
+ else
+ {
+ KSIZE cbToCopy = khlpHeapBlockSize(&g_Heap, pv);
+ pvNew = khlpHeapAlloc(&g_Heap, cb);
+ if (pvNew)
+ {
+ kHlpMemCopy(pvNew, pv, cb);
+ kHlpFree(pv);
+ }
+ }
+ return pvNew;
+}
+
+
+KHLP_DECL(void) kHlpFree(void *pv)
+{
+ khlpHeapFree(&g_Heap, pv);
+}
+
+
+/**
+ * Donates memory to the heap.
+ *
+ * @param pv The address of the memory.
+ * @param cb The amount of memory.
+ */
+KHLP_DECL(void) kHlpHeapDonate(void *pv, KSIZE cb)
+{
+ khlpHeapDonate(&g_Heap, pv, cb);
+}
+
+
+
+/**
+ * Initializes the heap anchor.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param pHeap The heap anchor to be initialized.
+ */
+static int khlpHeapInit(PKHLPHEAPANCHOR pHeap)
+{
+ pHeap->pHead = NULL;
+ pHeap->pTail = NULL;
+ pHeap->pFreeHead = NULL;
+ pHeap->SegsHead.pNext = NULL;
+ pHeap->SegsHead.cSegs = 0;
+ return 0;
+}
+
+
+/**
+ * Deletes a heap.
+ * This will free all resources (memory) associated with the heap.
+ *
+ * @param pHeap The heap to be deleted.
+ */
+static void khlpHeapDelete(PKHLPHEAPANCHOR pHeap)
+{
+ /*
+ * Free the segments, LIFO order.
+ * The head element is the last to be free, while the
+ * head.pNext is really the tail pointer - neat or what?
+ */
+ while ( pHeap->SegsHead.cSegs
+ || pHeap->SegsHead.pNext)
+ {
+ /* find the tail. */
+ KU32 iSeg;
+ PKHLPHEAPSEGS pSegs = pHeap->SegsHead.pNext;
+ if (!pSegs)
+ pSegs = &pHeap->SegsHead;
+ else
+ {
+ pHeap->SegsHead.pNext = pSegs->pNext;
+ pSegs->pNext = NULL;
+ }
+
+ /* free the segments */
+ iSeg = pSegs->cSegs;
+ while (iSeg-- > 0)
+ khlpHeapSegFree(&pSegs->aSegs[iSeg]);
+ pSegs->cSegs = 0;
+ }
+
+ /* Zap the anchor. */
+ pHeap->pHead = NULL;
+ pHeap->pTail = NULL;
+ pHeap->pFreeHead = NULL;
+ pHeap->SegsHead.pNext = NULL;
+ pHeap->SegsHead.cSegs = 0;
+}
+
+
+/**
+ * Internal heap block allocator.
+ */
+static void * kldrHeapAllocSub(PKHLPHEAPANCHOR pHeap, KSIZE cb)
+{
+ /*
+ * Find a fitting free block.
+ */
+ const KSIZE cbReq = K_ALIGN_Z(cb + sizeof(KHLPHEAPBLOCK), KHLPHEAPBLOCK_ALIGNMENT);
+ PKHLPHEAPFREE pCur = pHeap->pFreeHead;
+ while (pCur)
+ {
+ if (pCur->Core.cb >= cbReq)
+ {
+ if (pCur->Core.cb != cbReq)
+ {
+ /* check and see if there is a better match close by. */
+ PKHLPHEAPFREE pCur2 = pCur->pNext;
+ unsigned i = 16;
+ while (i-- > 0 && pCur2)
+ {
+ if (pCur2->Core.cb >= cbReq)
+ {
+ if (pCur2->Core.cb == cbReq)
+ {
+ pCur = pCur2;
+ break;
+ }
+ if (pCur2->Core.cb < pCur->Core.cb)
+ pCur = pCur2;
+ }
+
+ /* next */
+ KHLPHEAP_ASSERT_FREE(pHeap, pCur2);
+ pCur2 = pCur2->pNext;
+ }
+ }
+ break;
+ }
+
+ /* next */
+ KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+ pCur = pCur->pNext;
+ }
+ if (!pCur)
+ return NULL;
+ KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+
+ /*
+ * Do we need to split out a block?
+ */
+ if (pCur->Core.cb - cbReq >= KHLPHEAPBLOCK_ALIGNMENT * 2)
+ {
+ PKHLPHEAPBLOCK pNew;
+
+ pCur->Core.cb -= cbReq;
+
+ pNew = (PKHLPHEAPBLOCK)((KUPTR)pCur + pCur->Core.cb);
+ pNew->fFlags = 0;
+ pNew->cb = cbReq;
+ pNew->pNext = pCur->Core.pNext;
+ if (pNew->pNext)
+ pNew->pNext->pPrev = pNew;
+ else
+ pHeap->pTail = pNew;
+ pNew->pPrev = &pCur->Core;
+ pCur->Core.pNext = pNew;
+
+ KHLPHEAP_ASSERT_FREE(pHeap, pCur);
+ KHLPHEAP_ASSERT_BLOCK(pHeap, pNew);
+ return pNew + 1;
+ }
+
+ /*
+ * No, just unlink it from the free list and return.
+ */
+ if (pCur->pNext)
+ pCur->pNext->pPrev = pCur->pPrev;
+ if (pCur->pPrev)
+ pCur->pPrev->pNext = pCur->pNext;
+ else
+ pHeap->pFreeHead = pCur->pNext;
+ pCur->Core.fFlags &= ~KHLPHEAPBLOCK_FLAG_FREE;
+
+ KHLPHEAP_ASSERT_BLOCK(pHeap, &pCur->Core);
+ return &pCur->Core + 1;
+}
+
+
+/**
+ * Allocate a heap block.
+ *
+ * @returns Pointer to the allocated heap block on success. On failure NULL is returned.
+ * @param pHeap The heap.
+ * @param cb The requested heap block size.
+ */
+static void * khlpHeapAlloc(PKHLPHEAPANCHOR pHeap, KSIZE cb)
+{
+ void *pv;
+
+ /* adjust the requested block size. */
+ cb = K_ALIGN_Z(cb, KHLPHEAPBLOCK_ALIGNMENT);
+ if (!cb)
+ cb = KHLPHEAPBLOCK_ALIGNMENT;
+
+ /* try allocate the block. */
+ pv = kldrHeapAllocSub(pHeap, cb);
+ if (!pv)
+ {
+ /*
+ * Failed, add another segment and try again.
+ */
+ KHLPHEAPSEG Seg;
+ if (khlpHeapSegAlloc(&Seg, cb + sizeof(KHLPHEAPSEGS) + sizeof(KHLPHEAPBLOCK) * 16))
+ return NULL;
+
+ /* donate before insterting the segment, this makes sure we got heap to expand the segment list. */
+ khlpHeapDonate(pHeap, Seg.pvBase, Seg.cb);
+
+ /* insert the segment. */
+ if (pHeap->SegsHead.cSegs < sizeof(pHeap->SegsHead.aSegs) / sizeof(pHeap->SegsHead.aSegs[0]))
+ pHeap->SegsHead.aSegs[pHeap->SegsHead.cSegs++] = Seg;
+ else if ( pHeap->SegsHead.pNext
+ && pHeap->SegsHead.pNext->cSegs < sizeof(pHeap->SegsHead.aSegs) / sizeof(pHeap->SegsHead.aSegs[0]))
+ pHeap->SegsHead.pNext->aSegs[pHeap->SegsHead.pNext->cSegs++] = Seg;
+ else
+ {
+ PKHLPHEAPSEGS pSegs = (PKHLPHEAPSEGS)kldrHeapAllocSub(pHeap, sizeof(*pSegs));
+ KHLPHEAP_ASSERT(pSegs);
+ pSegs->pNext = pHeap->SegsHead.pNext;
+ pHeap->SegsHead.pNext = pSegs;
+ pSegs->aSegs[0] = Seg;
+ pSegs->cSegs = 1;
+ }
+
+ /* retry (should succeed) */
+ pv = kldrHeapAllocSub(pHeap, cb);
+ KHLPHEAP_ASSERT(pv);
+ }
+
+ return pv;
+}
+
+
+/**
+ * Frees a heap block.
+ *
+ * @param pHeap The heap.
+ * @param pv The pointer returned by khlpHeapAlloc().
+ */
+static void khlpHeapFree(PKHLPHEAPANCHOR pHeap, void *pv)
+{
+ PKHLPHEAPFREE pFree, pLeft, pRight;
+
+ /* ignore NULL pointers. */
+ if (!pv)
+ return;
+
+ pFree = (PKHLPHEAPFREE)((PKHLPHEAPBLOCK)pv - 1);
+ KHLPHEAP_ASSERT_BLOCK(pHeap, &pFree->Core);
+ KHLPHEAP_ASSERT(KHLPHEAPBLOCK_IS_ALLOCATED(&pFree->Core));
+
+ /*
+ * Merge or link with left node?
+ */
+ pLeft = (PKHLPHEAPFREE)pFree->Core.pPrev;
+ if ( pLeft
+ && KHLPHEAPBLOCK_IS_FREE(&pLeft->Core)
+ && KHLPHEAPBLOCK_IS_ADJACENT(&pLeft->Core, &pFree->Core)
+ )
+ {
+ /* merge left */
+ pLeft->Core.pNext = pFree->Core.pNext;
+ if (pFree->Core.pNext)
+ pFree->Core.pNext->pPrev = &pLeft->Core;
+ else
+ pHeap->pTail = &pLeft->Core;
+
+ pLeft->Core.cb += pFree->Core.cb;
+ pFree->Core.fFlags = ~0;
+ pFree = pLeft;
+ }
+ else
+ {
+ /* link left */
+ while (pLeft && !KHLPHEAPBLOCK_IS_FREE(&pLeft->Core))
+ pLeft = (PKHLPHEAPFREE)pLeft->Core.pPrev;
+ if (pLeft)
+ {
+ pFree->pPrev = pLeft;
+ pFree->pNext = pLeft->pNext;
+ if (pLeft->pNext)
+ pLeft->pNext->pPrev = pFree;
+ pLeft->pNext = pFree;
+ }
+ else
+ {
+ pFree->pPrev = NULL;
+ pFree->pNext = pHeap->pFreeHead;
+ if (pHeap->pFreeHead)
+ pHeap->pFreeHead->pPrev = pFree;
+ pHeap->pFreeHead = pFree;
+ }
+ pFree->Core.fFlags |= KHLPHEAPBLOCK_FLAG_FREE;
+ }
+ KHLPHEAP_ASSERT_FREE(pHeap, pFree);
+
+ /*
+ * Merge right?
+ */
+ pRight = (PKHLPHEAPFREE)pFree->Core.pNext;
+ if ( pRight
+ && KHLPHEAPBLOCK_IS_FREE(&pRight->Core)
+ && KHLPHEAPBLOCK_IS_ADJACENT(&pFree->Core, pRight)
+ )
+ {
+ /* unlink pRight from the global list. */
+ pFree->Core.pNext = pRight->Core.pNext;
+ if (pRight->Core.pNext)
+ pRight->Core.pNext->pPrev = &pFree->Core;
+ else
+ pHeap->pTail = &pFree->Core;
+
+ /* unlink pRight from the free list. */
+ pFree->pNext = pRight->pNext;
+ if (pRight->pNext)
+ pRight->pNext->pPrev = pFree;
+
+ /* update size and invalidate pRight. */
+ pFree->Core.cb += pRight->Core.cb;
+ pRight->Core.fFlags = ~0;
+ }
+}
+
+
+/**
+ * Calcs the size of a heap block.
+ *
+ * @returns The block size (in bytes).
+ * @param pHeap The heap.
+ * @param pv Pointer to an in-use heap block.
+ */
+static KSIZE khlpHeapBlockSize(PKHLPHEAPANCHOR pHeap, void *pv)
+{
+ PKHLPHEAPBLOCK pBlock = (PKHLPHEAPBLOCK)pv - 1;
+ KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock);
+ KHLPHEAP_ASSERT(KHLPHEAPBLOCK_IS_ALLOCATED(pBlock));
+ return (KU8 *)pBlock->pNext - (KU8 *)pv;
+}
+
+
+/**
+ * Donates memory to the heap.
+ *
+ * The donated memory is returned to the donator when the heap is deleted.
+ *
+ * @param pHeap The heap
+ * @param pv The pointer to the donated memory.
+ * @param cb Size of the donated memory.
+ */
+static void khlpHeapDonate(PKHLPHEAPANCHOR pHeap, void *pv, KSIZE cb)
+{
+ PKHLPHEAPBLOCK pBlock;
+
+ /*
+ * Don't bother with small donations.
+ */
+ if (cb < KHLPHEAPBLOCK_ALIGNMENT * 4)
+ return;
+
+ /*
+ * Align the donation on a heap block boundrary.
+ */
+ if ((KUPTR)pv & (KHLPHEAPBLOCK_ALIGNMENT - 1))
+ {
+ cb -= (KUPTR)pv & 31;
+ pv = K_ALIGN_P(pv, KHLPHEAPBLOCK_ALIGNMENT);
+ }
+ cb &= ~(KSIZE)(KHLPHEAPBLOCK_ALIGNMENT - 1);
+
+ /*
+ * Create an allocated block, link it and free it.
+ */
+ pBlock = (PKHLPHEAPBLOCK)pv;
+ pBlock->pNext = NULL;
+ pBlock->pPrev = NULL;
+ pBlock->cb = cb;
+ pBlock->fFlags = 0;
+
+ /* insert */
+ if ((KUPTR)pBlock < (KUPTR)pHeap->pHead)
+ {
+ /* head */
+ pBlock->pNext = pHeap->pHead;
+ pHeap->pHead->pPrev = pBlock;
+ pHeap->pHead = pBlock;
+ }
+ else if ((KUPTR)pBlock > (KUPTR)pHeap->pTail)
+ {
+ if (pHeap->pTail)
+ {
+ /* tail */
+ pBlock->pPrev = pHeap->pTail;
+ pHeap->pTail->pNext = pBlock;
+ pHeap->pTail = pBlock;
+ }
+ else
+ {
+ /* first */
+ pHeap->pHead = pBlock;
+ pHeap->pTail = pBlock;
+ }
+ }
+ else
+ {
+ /* in list (unlikely) */
+ PKHLPHEAPBLOCK pPrev = pHeap->pHead;
+ PKHLPHEAPBLOCK pCur = pPrev->pNext;
+ for (;;)
+ {
+ KHLPHEAP_ASSERT_BLOCK(pHeap, pCur);
+ if ((KUPTR)pCur > (KUPTR)pBlock)
+ break;
+ pPrev = pCur;
+ pCur = pCur->pNext;
+ }
+
+ pBlock->pNext = pCur;
+ pBlock->pPrev = pPrev;
+ pPrev->pNext = pBlock;
+ pCur->pPrev = pBlock;
+ }
+ KHLPHEAP_ASSERT_BLOCK(pHeap, pBlock);
+
+ /* free it */
+ khlpHeapFree(pHeap, pBlock + 1);
+}
+
+
+
+/**
+ * Allocates a new segment.
+ *
+ * @returns 0 on success, non-zero OS status code on failure.
+ * @param pSeg Where to put the info about the allocated segment.
+ * @param cbMin The minimum segment size.
+ */
+static int khlpHeapSegAlloc(PKHLPHEAPSEG pSeg, KSIZE cbMin)
+{
+#if K_OS == K_OS_OS2
+ APIRET rc;
+
+ pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+ pSeg->pvBase = NULL;
+ rc = DosAllocMem(&pSeg->pvBase, pSeg->cb, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
+ if (rc == ERROR_INVALID_PARAMETER)
+ rc = DosAllocMem(&pSeg->pvBase, pSeg->cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
+ if (rc)
+ {
+ pSeg->pvBase = NULL;
+ pSeg->cb = 0;
+ return rc;
+ }
+
+#elif K_OS == K_OS_WINDOWS
+ pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+ pSeg->pvBase = VirtualAlloc(NULL, pSeg->cb, MEM_COMMIT, PAGE_READWRITE);
+ if (!pSeg->pvBase)
+ {
+ pSeg->cb = 0;
+ return GetLastError();
+ }
+
+#else
+ int rc;
+
+ pSeg->cb = (cbMin + 0xffff) & ~(KSIZE)0xffff;
+ pSeg->pvBase = NULL;
+ rc = kHlpPageAlloc(&pSeg->pvBase, pSeg->cb, KPROT_READWRITE, K_FALSE);
+ if (rc)
+ {
+ pSeg->pvBase = NULL;
+ pSeg->cb = 0;
+ return rc;
+ }
+
+#endif
+
+ return 0;
+}
+
+
+/**
+ * Frees a segment.
+ *
+ * @param pSeg The segment to be freed.
+ */
+static void khlpHeapSegFree(PKHLPHEAPSEG pSeg)
+{
+#if K_OS == K_OS_OS2
+ APIRET rc = DosFreeMem(pSeg->pvBase);
+ KHLPHEAP_ASSERT(!rc); (void)rc;
+
+#elif K_OS == K_OS_WINDOWS
+ BOOL fRc = VirtualFree(pSeg->pvBase, 0 /*pSeg->cb*/, MEM_RELEASE);
+ KHLPHEAP_ASSERT(fRc); (void)fRc;
+
+#else
+ int rc = kHlpPageFree(pSeg->pvBase, pSeg->cb);
+ KHLPHEAP_ASSERT(!rc); (void)rc;
+
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c b/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c
new file mode 100644
index 0000000..f7db3ff
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareProcess.c
@@ -0,0 +1,85 @@
+/* $Id: kHlpBareProcess.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Process Management
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <k/kHlpProcess.h>
+#include <k/kHlpAssert.h>
+
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+#elif K_OS == K_OS_WINDOWS
+# include <Windows.h>
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Terminate the process.
+ *
+ * @param rc The exit status.
+ */
+void kHlpExit(int rc)
+{
+ for (;;)
+ {
+#if K_OS == K_OS_DARWIN \
+ || K_OS == K_OS_FREEBSD \
+ || K_OS == K_OS_LINUX \
+ || K_OS == K_OS_NETBSD \
+ || K_OS == K_OS_OPENBSD \
+ || K_OS == K_OS_SOLARIS
+ kHlpSys_exit(rc);
+
+#elif K_OS == K_OS_OS2
+ DosExit(EXIT_PROCESS, rc);
+
+#elif K_OS == K_OS_WINDOWS
+ TerminateProcess(GetCurrentProcess(), rc);
+
+#else
+# error "Port me"
+#endif
+ kHlpAssert(!"Impossible");
+ }
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c b/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c
new file mode 100644
index 0000000..b484676
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpBareThread.c
@@ -0,0 +1,93 @@
+/* $Id: kHlpBareThread.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare - Thread Manipulation.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <k/kHlpThread.h>
+
+#if K_OS == K_OS_DARWIN
+# include <mach/mach_time.h>
+
+#elif K_OS == K_OS_LINUX
+# include <k/kHlpSys.h>
+
+#elif K_OS == K_OS_OS2
+# define INCL_BASE
+# define INCL_ERRORS
+# include <os2.h>
+#elif K_OS == K_OS_WINDOWS
+# include <Windows.h>
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Sleep for a number of milliseconds.
+ * @param cMillies Number of milliseconds to sleep.
+ */
+void kHlpSleep(unsigned cMillies)
+{
+#if K_OS == K_OS_DARWIN
+ static struct mach_timebase_info s_Info;
+ static KBOOL s_fNanoseconds = K_UNKNOWN;
+ KU64 uNow = mach_absolute_time();
+ KU64 uDeadline;
+ KU64 uPeriod;
+
+ if (s_fNanoseconds == K_UNKNOWN)
+ {
+ if (mach_timebase_info(&s_Info))
+ s_fNanoseconds = K_TRUE; /* the easy way out */
+ else if (s_Info.denom == s_Info.numer)
+ s_fNanoseconds = K_TRUE;
+ else
+ s_fNanoseconds = K_FALSE;
+ }
+
+ uPeriod = (KU64)cMillies * 1000 * 1000;
+ if (!s_fNanoseconds)
+ uPeriod = (double)uPeriod * s_Info.denom / s_Info.numer; /* Use double to avoid 32-bit trouble. */
+ uDeadline = uNow + uPeriod;
+ mach_wait_until(uDeadline);
+
+#elif K_OS == K_OS_LINUX
+ /** @todo find the right syscall... */
+
+#elif K_OS == K_OS_OS2
+ DosSleep(cMillies);
+#elif K_OS == K_OS_WINDOWS
+ Sleep(cMillies);
+#else
+ usleep(cMillies * 1000);
+#endif
+}
+
diff --git a/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c b/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c
new file mode 100644
index 0000000..b4153f2
--- /dev/null
+++ b/src/lib/kStuff/kHlp/Bare/kHlpSys-darwin.c
@@ -0,0 +1,345 @@
+/* $Id: kHlpSys-darwin.c 29 2009-07-01 20:30:29Z bird $ */
+/** @file
+ * kHlpBare -
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <k/kHlpSys.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <sys/mman.h>
+#include <mach/mach_time.h>
+
+
+#define USE_DARWIN_SYSCALLS
+
+#if K_ARCH == K_ARCH_X86_32
+# define DARWIN_SYSCALL(name, code) \
+ asm("\
+ .text \n\
+ .globl _" #name " \n\
+ _" #name ": \n\
+ mov $ " #code ", %eax \n\
+ call 1f \n\
+ 1: \n\
+ pop %edx \n\
+ mov %esp, %ecx \n\
+ sysenter \n\
+ jnae 2f \n\
+ ret \n\
+ 2: \n\
+ neg %eax \n\
+ ret \n\
+ ")
+
+# define DARWIN_SYSCALL_RET64(name, code) \
+ asm("\
+ .text \n\
+ .globl _" #name " \n\
+ _" #name ": \n\
+ mov $ " #code ", %eax \n\
+ int $0x80 \n\
+ jnae 2f \n\
+ ret \n\
+ 2: \n\
+ neg %eax \n\
+ mov $0xffffffff, %edx \n\
+ ret \n\
+ ")
+
+# define DARWIN_SYSCALL_NOERR(name, code) \
+ asm("\
+ .text \n\
+ .globl _" #name " \n\
+ _" #name ": \n\
+ mov $ " #code ", %eax \n\
+ call 1f \n\
+ 1: \n\
+ pop %edx \n\
+ mov %esp, %ecx \n\
+ sysenter \n\
+ ret \n\
+ ")
+
+#elif K_ARCH == K_ARCH_AMD64
+# define DARWIN_SYSCALL(name, code) \
+ asm("\
+ .text \n\
+ .globl _" #name " \n\
+ _" #name ": \n\
+ mov $ " #code ", %eax \n\
+ mov %rcx, %r10 \n\
+ sysenter \n\
+ jnae 2f \n\
+ ret \n\
+ 2: \n\
+ neg %eax \n\
+ movsx %eax, %rax \n\
+ ret \n\
+ ")
+
+# define DARWIN_SYSCALL_RET64(name, code) DARWIN_SYSCALL_RET(name, code)
+
+# define DARWIN_SYSCALL_NOERR(name, code) \
+ asm("\
+ .text \n\
+ .globl _" #name " \n\
+ _" #name ": \n\
+ mov $ " #code ", %eax \n\
+ mov %rcx, %r10 \n\
+ sysenter \n\
+ ret \n\
+ ")
+
+
+#else
+# error later...
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_readlink, 0x000c003a);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_readlink, 0x0200003a);
+#else
+KSSIZE kHlpSys_readlink(const char *pszPath, char *pszBuf, KSIZE cbBuf)
+{
+ KSSIZE cbRet = readlink(pszPath, pszBuf, cbBuf);
+ return cbRet >= 0 ? cbRet : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_open, 0x000c0005);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_open, 0x02000005);
+#else
+int kHlpSys_open(const char *filename, int flags, int mode)
+{
+ int fd = open(filename, flags, mode);
+ return fd >= 0 ? fd : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_close, 0x000c0006);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_close, 0x02000006);
+#else
+int kHlpSys_close(int fd)
+{
+ if (!close(fd))
+ return 0;
+ return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_RET64(kHlpSys_lseek, 0x000000c7);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_RET64(kHlpSys_lseek, 0x020000c7);
+#else
+KFOFF kHlpSys_lseek(int fd, int whench, KFOFF off)
+{
+ KFOFF offRet = lseek(fd, whench, off);
+ return offRet >= 0 ? offRet : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_read, 0x000c0003);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_read, 0x02000003);
+#else
+KSSIZE kHlpSys_read(int fd, void *pvBuf, KSIZE cbBuf)
+{
+ KSSIZE cbRead = read(fd, pvBuf, cbBuf);
+ return cbRead >= 0 ? cbRead : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_write, 0x000c0004);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_write, 0x02000004);
+#else
+KSSIZE kHlpSys_write(int fd, const void *pvBuf, KSIZE cbBuf)
+{
+ KSSIZE cbWritten = write(fd, pvBuf, cbBuf);
+ return cbWritten >= 0 ? cbWritten : -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mmap, 0x020000c5);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mmap, 0x020000c5);
+#else
+void *kHlpSys_mmap(void *addr, KSIZE len, int prot, int flags, int fd, KI64 off)
+{
+ void *pv = mmap(addr, len, prot, flags, fd, off);
+ return pv != (void *)-1
+ ? pv
+ : errno < 256 ? (void *)(long)errno : (void *)(long)ENOMEM;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mprotect, 0x000c004a);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_mprotect, 0x0200004a);
+#else
+int kHlpSys_mprotect(void *addr, KSIZE len, int prot)
+{
+ if (!mprotect(addr, len, prot))
+ return 0;
+ return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_munmap, 0x00080049);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_munmap, 0x02000049);
+#else
+int kHlpSys_munmap(void *addr, KSIZE len)
+{
+ if (!munmap(addr, len))
+ return 0;
+ return -errno;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_exit, 0x00040001);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(kHlpSys_exit, 0x02000001);
+#else
+void kHlpSys_exit(int rc)
+{
+ _Exit(rc);
+}
+#endif
+
+
+/*
+ * Some other stuff we'll be needing - Move to an appropriate place?
+ */
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_NOERR(mach_task_self, 0xffffffe4);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL_NOERR(mach_task_self, 0xffffffe4);
+#endif
+
+//#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_create, 0x00040001);
+//#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_create, 0x02000001);
+//#endif
+#ifdef USE_DARWIN_SYSCALLS
+kern_return_t semaphore_create(task_t t, semaphore_t *ps, int p, int v)
+{
+ return 0;
+}
+#endif
+
+//#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_destroy, 0x00040001);
+//#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+//DARWIN_SYSCALL(semaphore_destroy, 0x02000001);
+//#endif
+#ifdef USE_DARWIN_SYSCALLS
+kern_return_t semaphore_destroy(task_t t, semaphore_t s)
+{
+ return 0;
+}
+#endif
+
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_wait, 0xffffffdc);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_wait, 0xffffffdc);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_signal, 0xffffffdf);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(semaphore_signal, 0xffffffdf);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_wait_until, 0xffffffa6);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_wait_until, 0xffffffa6);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_timebase_info, 0xffffffa7);
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+DARWIN_SYSCALL(mach_timebase_info, 0xffffffa7);
+#endif
+
+#if K_ARCH == K_ARCH_X86_32 && defined(USE_DARWIN_SYSCALLS)
+asm("\n\
+.text \n\
+.globl _mach_absolute_time \n\
+_mach_absolute_time: \n\
+ mov $0xffff1700, %edx \n\
+ jmp *%edx\n"); /* common page stuff. */
+#elif K_ARCH == K_ARCH_AMD64 && defined(USE_DARWIN_SYSCALLS)
+#endif
+
+
+void *dlopen(const char *pszModule, int fFlags)
+{
+ return NULL;
+}
+
+
+int dlclose(void *pvMod)
+{
+
+}
+
+
+void *dlsym(void *pvMod, const char *pszSymbol)
+{
+ return NULL;
+}
+