Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7b32308
Eliminate unnecessary setters for Thread
bSchnepp Dec 21, 2022
ce6cd5a
Allow TLA to be read/write from userspace
bSchnepp Dec 21, 2022
09c47a4
Initial implementation of a skiplist
bSchnepp Dec 22, 2022
4611de4
Add MinKey and MaxKey
bSchnepp Dec 22, 2022
d115149
Convert GlobalScheduler to a namespace
bSchnepp Dec 22, 2022
d3d37fb
Move unnecessary public functions into private scope
bSchnepp Dec 22, 2022
f40c88a
Initial TryAcquire implementation
bSchnepp Dec 22, 2022
25998be
Initial rewrite of scheduler code
bSchnepp Dec 22, 2022
10c7a98
Implement TryLock for Lockable
bSchnepp Dec 23, 2022
7f2e06e
Associate LocalScheduler with CoreInfo
bSchnepp Dec 23, 2022
a3e7343
Initial implementation of CreateProcess under new scheduler
bSchnepp Dec 23, 2022
8de0c8e
Implement CreateThread for new scheduler
bSchnepp Dec 23, 2022
7498af0
Add SetThreadState to Scheduler, re-add MapPages
bSchnepp Dec 23, 2022
a23022d
Re-add CPU context switch
bSchnepp Dec 23, 2022
b218aa7
Re-do SkipList to avoid weird linked lists for levels
bSchnepp Dec 23, 2022
f5b0992
Use jiffies in Rand() to help avoid prediction
bSchnepp Dec 24, 2022
2c9edbd
Cleanup unnecessary scheduling routines
bSchnepp Dec 25, 2022
3fa52c9
Allow entry back into userland programs again
bSchnepp Dec 25, 2022
f6ee852
Enforce consistency of state view
bSchnepp Dec 26, 2022
727d8dd
Allow programs to switch again
bSchnepp Dec 27, 2022
f6a89d6
Correct TLS setup
bSchnepp Dec 28, 2022
fbd22ad
Define constant for RR_INTERVAL
bSchnepp Dec 29, 2022
2f1ec28
Move thread switch code to a static method
bSchnepp Dec 30, 2022
8256435
Make spinlock errors more descriptive
bSchnepp Dec 30, 2022
049c3e1
Enforce consistency of TIDs and PIDs
bSchnepp Dec 31, 2022
b4fabe9
Cleanup unnecessary methods in Thread class
bSchnepp Dec 31, 2022
55fd3be
Strengthen lock invariants
bSchnepp Dec 31, 2022
0b6319c
Add 2SMP debug launch script
bSchnepp Jan 1, 2023
bbd0e40
Cleanup Doxygen comments
bSchnepp Jan 1, 2023
fcecb01
Move ThreadID creation to kern_sched.cpp
bSchnepp Jan 1, 2023
8bfddad
Improve logging for errors under traps
bSchnepp Jan 1, 2023
4944886
Cleanup thread-related initialization and tracing
bSchnepp Jan 1, 2023
b40e66d
Finish documentation for the Scheduler namespace
bSchnepp Jan 1, 2023
dc8ccdb
Enforce additional consistency with the scheduler
bSchnepp Jan 2, 2023
0210481
Enforce additiona locked requirement checks
bSchnepp Jan 2, 2023
ecc5b18
Stop crashing with SMP
bSchnepp Jan 2, 2023
b7f9478
Implement O(k) task lookup algorithm
bSchnepp Jan 3, 2023
1e19989
Don't drop ticks when issuing SVCYield()
bSchnepp Jan 3, 2023
eafa44f
Increase scope of scheduler locks to cover more possible races
bSchnepp Jan 4, 2023
1e8dece
Enforce memory poisoning for slab allocators
bSchnepp Jan 4, 2023
32463ed
Implement and use SkipList Pop() function
bSchnepp Jan 4, 2023
71167c0
Blend slab allocation in with BasicMalloc to avoid the explicit free …
bSchnepp Jan 4, 2023
dba5eaa
Implement PANIC_ON macro
bSchnepp Jan 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ SET(PANTHEON_VERSION_MINOR 0)
SET(PANTHEON_VERSION_PATCH 1)

SET(POISON_MEMORY TRUE)
SET(FSANITIZE TRUE)
SET(FSANITIZE FALSE)

CONFIGURE_FILE(
"${CMAKE_SOURCE_DIR}/kern.h.in"
Expand Down
3 changes: 3 additions & 0 deletions Common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ LIST(APPEND COMMON_HEADERS kern_datatypes.hpp)
LIST(APPEND COMMON_HEADERS kern_runtime.hpp)
LIST(APPEND COMMON_HEADERS kern_string.hpp)
LIST(APPEND COMMON_HEADERS kern_object.hpp)
LIST(APPEND COMMON_HEADERS kern_rand.hpp)
LIST(APPEND COMMON_HEADERS Sync/kern_spinlock.hpp)
LIST(APPEND COMMON_HEADERS Sync/kern_atomic.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_optional.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_bitmap.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_rawbitmap.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_slab.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_linkedlist.hpp)
LIST(APPEND COMMON_HEADERS Structures/kern_skiplist.hpp)


LIST(APPEND COMMON_SOURCES kern_rand.cpp)
LIST(APPEND COMMON_SOURCES kern_runtime.cpp)
LIST(APPEND COMMON_SOURCES kern_basic_malloc.cpp)
LIST(APPEND COMMON_SOURCES kern_status.cpp)
Expand Down
1 change: 0 additions & 1 deletion Common/Structures/kern_allocatable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class Allocatable
static void Init()
{
AllocSpinlock = pantheon::Spinlock("Allocatable Lock");
ClearBuffer((CHAR*)Items, sizeof(T) * Count);
Allocator = pantheon::mm::SlabCache<T>(Items, Count);
}

Expand Down
350 changes: 350 additions & 0 deletions Common/Structures/kern_skiplist.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
#include <kern_rand.hpp>
#include <kern_datatypes.hpp>

#include <Common/Structures/kern_optional.hpp>
#include <Common/Structures/kern_allocatable.hpp>

#ifndef _KERN_SKIPLIST_HPP_
#define _KERN_SKIPLIST_HPP_

namespace pantheon
{

template <typename K, typename V, UINT8 MaxLvl = 8>
class SkipList
{
public:
SkipList()
{
this->Head = nullptr;
this->Level = 0;
this->Sz = 0;
}

~SkipList()
{
/* NYI */
}

[[nodiscard]] UINT64 Size() const
{
return this->Sz;
}

[[nodiscard]] BOOL Contains(K Key) const
{
return this->Get(Key).GetOkay();
}

[[nodiscard]] Optional<V> Get(K Key) const
{
if (this->Head == nullptr)
{
return Optional<V>();
}

INT16 Lvl = this->Level;
KVPair *Current = this->Head;
KVPair *Next = Current;
while (Lvl >= 0)
{
Next = Current->Next[Lvl];
while (Next && (Next->Key <= Key))
{
Current = Next;
Next = Current->Next[Lvl];
}
Lvl--;
}

if (Current->Key == Key)
{
return Optional<V>(Current->Value);
}
return Optional<V>();

}

[[nodiscard]] Optional<K> MinKey() const
{
if (this->Head == nullptr)
{
return Optional<K>();
}

KVPair *Current = this->Head->Next[0];
if (Current && Current->Key != (K() - 1))
{
return Optional<K>(Current->Key);
}
return Optional<K>();
}

[[nodiscard]] Optional<K> MaxKey() const
{
if (this->Head == nullptr)
{
return Optional<K>();
}

KVPair *Current = this->Head->Prev[0];
if (Current && Current->Key != (K() - 1))
{
return Optional<K>(Current->Key);
}
return Optional<K>();
}

VOID Insert(K Key, V Value)
{
this->Setup();

KVPair *Update[MaxLvl];
INT16 Lvl = this->Level;

KVPair *Current = this->Head;
KVPair *Next = Current;
while (Lvl >= 0)
{
Next = Current->Next[Lvl];
while (Next && (Next->Key <= Key))
{
Current = Next;
Next = Current->Next[Lvl];
}
Update[Lvl] = Current;
Lvl--;
}

/* This is where we'll need to be: this needs to match the current key. */
if (Current->Key == Key)
{
Current->Value = Value;
return;
}

/* Actually make the new entry */
INT16 NewLvl = this->RandLevel();
if (NewLvl > this->Level)
{
NewLvl = ++(this->Level);
Update[NewLvl] = this->Head;
}

KVPair *NewNode = new KVPair();
NewNode->Key = Key;
NewNode->Value = Value;
NewNode->Level = NewLvl;
for (UINT8 Index = 0; Index < MaxLvl; Index++)
{
NewNode->Next[Index] = nullptr;
NewNode->Prev[Index] = nullptr;
}

while (NewLvl >= 0)
{
Current = Update[NewLvl];

NewNode->Next[NewLvl] = Current->Next[NewLvl];
Current->Next[NewLvl] = NewNode;

NewNode->Prev[NewLvl] = Current;
NewNode->Next[NewLvl]->Prev[NewLvl] = NewNode;
NewLvl--;
}

this->Sz++;

}

BOOL Delete(K Key)
{
this->Setup();

KVPair *Update[MaxLvl];
INT16 Lvl = this->Level;

KVPair *Current = this->Head;
KVPair *Next = Current;
while (Lvl >= 0)
{
Next = Current->Next[Lvl];
while (Next && (Next->Key <= Key))
{
Current = Next;
Next = Current->Next[Lvl];
}
Update[Lvl] = Current;
Lvl--;
}

/* This is where we'll need to be: this needs to match the current key. */
if (Current->Key == Key)
{
UINT8 CurLvl = Current->Level;
for (UINT8 Lvl = 0; Lvl <= CurLvl; Lvl++)
{
Current->Prev[Lvl]->Next[Lvl] = Current->Next[Lvl];
Current->Next[Lvl]->Prev[Lvl] = Current->Prev[Lvl];
}

/* If this was top, we might have to fix levels. */
if (CurLvl == this->Level)
{
while (this->Head->Next[CurLvl] == this->Head && this->Head->Prev[CurLvl] == this->Head)
{
if (CurLvl > 0)
{
CurLvl--;
} else
{
break;
}

}
this->Level = CurLvl;
}

this->Sz--;
delete Current;
return TRUE;
}
return FALSE;
}

Optional<V> Pop(K Key)
{
this->Setup();

KVPair *Update[MaxLvl];
INT16 Lvl = this->Level;

KVPair *Current = this->Head;
KVPair *Next = Current;
while (Lvl >= 0)
{
Next = Current->Next[Lvl];
while (Next && (Next->Key <= Key))
{
Current = Next;
Next = Current->Next[Lvl];
}
Update[Lvl] = Current;
Lvl--;
}

/* This is where we'll need to be: this needs to match the current key. */
if (Current->Key == Key)
{
UINT8 CurLvl = Current->Level;
for (UINT8 Lvl = 0; Lvl <= CurLvl; Lvl++)
{
Current->Prev[Lvl]->Next[Lvl] = Current->Next[Lvl];
Current->Next[Lvl]->Prev[Lvl] = Current->Prev[Lvl];
}

/* If this was top, we might have to fix levels. */
if (CurLvl == this->Level)
{
while (this->Head->Next[CurLvl] == this->Head && this->Head->Prev[CurLvl] == this->Head)
{
if (CurLvl > 0)
{
CurLvl--;
} else
{
break;
}

}
this->Level = CurLvl;
}

this->Sz--;
if (Current->Key == Key)
{
return Optional<V>(Current->Value);
}
return Optional<V>();
}
return Optional<V>();
}


V& operator[](K Key)
{
this->Setup();

INT16 Lvl = this->Level;
KVPair *Current = this->Head;
KVPair *Next = Current;
while (Lvl >= 0)
{
Next = Current->Next[Lvl];
while (Next && (Next->Key <= Key))
{
Current = Next;
Next = Current->Next[Lvl];
}
Lvl--;
}

if (Current->Key == Key)
{
return Current->Value;
}
static V DefaultItem;
return DefaultItem;
}

private:
struct KVPair
{
K Key;
V Value;
UINT64 Level;
KVPair *Next[MaxLvl];
KVPair *Prev[MaxLvl];
};

static_assert(sizeof(KVPair) > 32);

KVPair *Head;
INT16 Level;
UINT64 Sz;

UINT8 RandLevel()
{
UINT8 Level = 1;

/* Rand() generates a 64-bit number.
* The probability of any one bit in particular being 0 or 1
* is 25% for either case. We only care about two bits,
* so let's use the bottom 2 bits for this.
*/
while ((pantheon::Rand() & 0x3) && Level < MaxLvl)
{
Level++;
}
return Level % MaxLvl;
}

void Setup()
{
if (this->Head == nullptr)
{
this->Head = new KVPair();
this->Level = 0;
this->Head->Key = K() - 1; /* HACK: Sets this at a huge value for integers only */
this->Head->Value = V();
for (UINT8 Lvl = 0; Lvl < MaxLvl; Lvl++)
{
this->Head->Next[Lvl] = this->Head;
this->Head->Prev[Lvl] = this->Head;
}
}
}
};

}
#endif
Loading