Add JKRHeap.cpp

This commit is contained in:
SwareJonge
2023-02-19 23:26:52 +01:00
parent a0393eb164
commit 0311f06aa3
15 changed files with 1255 additions and 3 deletions
+14
View File
@@ -332,7 +332,21 @@ SDK_CFLAG = [
ALIGN16_CFLAG = [
"-func_align 16",
]
JSYSTEM_BASE = [
"-lang=c++",
"-inline on",
"-fp fmadd",
"-fp_contract on",
"-pool off",
"-Cpp_exceptions off",
"-RTTI on",
"-char signed",
"-enum int",
"-sym on", # might also be on for base flags?
"-O4,s" # in mkdd some libraries use O4,p, might be the case here too
]
JSYSTEM_CFLAGS = ' '.join(JSYSTEM_BASE + LOCAL_CFLAGS)
DOL_CFLAGS = ' '.join(BASE_DOL_CFLAGS + LOCAL_CFLAGS)
SDK_FLAGS = ' '.join(SDK_CFLAG + LOCAL_CFLAGS)
ALIGN16 = ' '.join(BASE_DOL_CFLAGS + LOCAL_CFLAGS + ALIGN16_CFLAG)
+5
View File
@@ -4,6 +4,11 @@ libultra/gfxprint/gfxprint_locate8x8.c:
.text: [0x8005B210, 0x8005B238]
libforest/ReconfigBATs.c:
.text: [0x8005adac, 0x8005aed4]
JSystem/JKernel/JKRHeap.cpp:
.text: [0x80063748, 0x80064028]
.data: [0x800ddf20, 0x800ddf98]
.sdata: [0x80217e58, 0x80217e80]
.sbss: [0x802186d8, 0x80218700]
dolphin/BASE/ppcarch.c:
.text: [0x8007867c, 0x80078718]
dolphin/OS/OSArena.c:
+17 -1
View File
@@ -2624,7 +2624,23 @@ global:
0x8009ae00: __save_fpr
0x8009ae4c: __restore_fpr
0x8009ae98: __save_gpr
0x8009aee4: __restore_gpr
0x8009aeb8: _savegpr_22
0x8009aebc: _savegpr_23
0x8009aec0: _savegpr_24
0x8009aec4: _savegpr_25
0x8009aec8: _savegpr_26
0x8009aecc: _savegpr_27
0x8009aed0: _savegpr_28
0x8009aed4: _savegpr_29
0x8009aee4: __restore_gpr
0x8009af04: _restgpr_22
0x8009af08: _restgpr_23
0x8009af0c: _restgpr_24
0x8009af10: _restgpr_25
0x8009af14: _restgpr_26
0x8009af18: _restgpr_27
0x8009af1c: _restgpr_28
0x8009af20: _restgpr_29
0x8009af30: __div2u
0x8009b01c: __div2i
0x8009b154: __mod2u
+3
View File
@@ -577,6 +577,9 @@ class CSource(Source):
if path.startswith("src/dolphin/"):
self.cflags = c.SDK_FLAGS
self.cc = c.OCC
elif path.startswith("src/JSystem/JKernel/"):
self.cflags = c.JSYSTEM_CFLAGS
self.cc = c.CC
elif path.startswith("src/jaudio_NES"):
self.cc = c.CC
self.cflags = c.DOL_CPPFLAGS
+21
View File
@@ -0,0 +1,21 @@
#ifndef JKRDISPOSER_H
#define JKRDISPOSER_H
#include "types.h"
#include "JSystem/JSupport/JSUList.h"
class JKRHeap;
class JKRDisposer
{
public:
JKRDisposer();
virtual ~JKRDisposer();
public:
JKRHeap *mRootHeap; // _4
JSULink<JKRDisposer> mPointerLinks; // _8
};
#endif
+288
View File
@@ -0,0 +1,288 @@
#ifndef JKRHEAP_H
#define JKRHEAP_H
#include "dolphin/OS/OSMutex.h"
#include "JSystem/JKernel/JKRDisposer.h"
#include "types.h"
typedef void JKRHeapErrorHandler(void *, u32, int);
class JKRHeap : public JKRDisposer
{
public:
enum EAllocMode
{
HEAPALLOC_Unk1 = 1,
};
struct TState
{ // NB: this struct doesn't agree with TP's struct
struct TLocation
{
TLocation() : _00(nullptr), _04(-1)
{
}
void *_00; // _00
int _04; // _04
};
struct TArgument
{
TArgument(const JKRHeap *heap, u32 p2, bool p3)
: mHeap((heap) ? heap : JKRHeap::sCurrentHeap), mId(p2), mIsCompareOnDestructed(p3)
{
}
const JKRHeap *mHeap; // _00
u32 mId; // _04
bool mIsCompareOnDestructed; // _08
};
TState(const JKRHeap *heap, u32 id, bool isCompareOnDestructed)
: mUsedSize(0), mCheckCode(0), mArgument(heap, id, isCompareOnDestructed)
{
mArgument.mHeap->state_register(this, mArgument.mId);
}
TState(JKRHeap *heap)
: mUsedSize(0), mCheckCode(0), mArgument(heap, 0xFFFFFFFF, true)
{
}
~TState();
void dump() const { mArgument.mHeap->state_dump(*this); }
bool isVerbose() { return bVerbose_; };
bool isCompareOnDestructed() const { return mArgument.mIsCompareOnDestructed; };
u32 getUsedSize() const { return mUsedSize; }
u32 getCheckCode() const { return mCheckCode; }
const JKRHeap *getHeap() const { return mArgument.mHeap; }
u32 getId() const { return mArgument.mId; }
// unused/inlined:
TState(const JKRHeap::TState::TArgument &arg, const JKRHeap::TState::TLocation &location);
TState(const JKRHeap::TState &other, bool p2);
TState(const JKRHeap::TState &other, const JKRHeap::TState::TLocation &location, bool p3);
static bool bVerbose_;
u32 mUsedSize; // _00
u32 mCheckCode; // _04, plausibly TLocation when combined with _00
u32 mBuf; // _08
u8 _0C[0x4]; // _0C
TArgument mArgument; // _10
TLocation mLocation; // _1C
};
public:
JKRHeap(void *, u32, JKRHeap *, bool);
bool setErrorFlag(bool errorFlag);
bool isSubHeap(JKRHeap *heap) const;
virtual ~JKRHeap();
virtual void callAllDisposer();
virtual void *do_alloc(u32, int) = 0;
virtual void do_free(void *) = 0;
virtual void do_freeAll() = 0;
virtual void do_freeTail() = 0;
virtual s32 do_resize(void *, u32) = 0;
virtual s32 do_getSize(void *) = 0;
virtual s32 do_getFreeSize() = 0;
virtual s32 do_getTotalFreeSize() = 0;
virtual u32 getHeapType() = 0;
virtual bool check() = 0;
virtual bool dump_sort() { return true; }
virtual bool dump() = 0;
virtual s32 do_changeGroupID(u8 newGroupID) { return 0; }
virtual u8 do_getCurrentGroupId() { return 0; }
virtual void state_register(JKRHeap::TState *, u32) const;
virtual bool state_compare(JKRHeap::TState const &, JKRHeap::TState const &) const;
virtual void state_dump(JKRHeap::TState const &) const;
JKRHeap *becomeSystemHeap();
JKRHeap *becomeCurrentHeap();
void destroy();
void *alloc(u32, int);
void free(void *);
void freeAll();
void freeTail();
void fillFreeArea();
void resize(void *, u32);
static s32 getSize(void *, JKRHeap*);
// ... more functions
s32 getSize(void *ptr);
s32 getFreeSize();
void *getMaxFreeBlock();
s32 getTotalFreeSize();
u8 getCurrentGroupId();
s32 changeGroupID(u8 newGroupId);
u32 getMaxAllocatableSize(int alignment);
JKRHeap *find(void *) const; // 0x80084640
JKRHeap *findAllHeap(void *) const; // 0x8008492c
void dispose_subroutine(u32 begin, u32 end);
bool dispose(void *, u32); // 0x80084b9c
void dispose(void *, void *); // 0x80084c2c
void dispose(); // 0x80084cb8
void appendDisposer(JKRDisposer *disposer)
{
mDisposerList.append(&disposer->mPointerLinks);
}
void removeDisposer(JKRDisposer *disposer)
{
mDisposerList.remove(&disposer->mPointerLinks);
}
void setDebugFill(bool debugFill) { mDebugFill = debugFill; }
bool getDebugFill() const { return mDebugFill; }
void *getStartAddr() const { return (void *)mStart; }
void *getEndAddr() const { return (void *)mEnd; }
u32 getHeapSize() const { return mSize; }
bool getErrorFlag() const { return mErrorFlag; }
void callErrorHandler(JKRHeap *heap, u32 size, int alignment)
{
if (mErrorHandler)
{
(*mErrorHandler)(heap, size, alignment);
}
}
// Unused
void checkMemoryFilled(u8 *, u32 size, u8);
static void destroy(JKRHeap *heap); // fabricated
static bool initArena(char **, u32 *, int);
static void *alloc(u32, int, JKRHeap *);
static void copyMemory(void *, void *, u32);
static void free(void *, JKRHeap *);
static void state_dumpDifference(const TState &, const TState &);
static JKRHeap *findFromRoot(void *);
static JKRHeapErrorHandler *setErrorHandler(JKRHeapErrorHandler *);
static void *getCodeStart()
{
return mCodeStart;
}
static void *getCodeEnd()
{
return mCodeEnd;
}
static void *getUserRamStart()
{
return mUserRamStart;
}
static void *getUserRamEnd()
{
return mUserRamEnd;
}
static u32 getMemorySize()
{
return mMemorySize;
}
static JKRHeap *getCurrentHeap()
{
return sCurrentHeap;
}
static JKRHeap *getRootHeap()
{
return sRootHeap;
}
static JKRHeap *getSystemHeap()
{
return sSystemHeap;
}
static void *mCodeStart;
static void *mCodeEnd;
static void *mUserRamStart;
static void *mUserRamEnd;
static u32 mMemorySize;
static JKRHeap *sSystemHeap;
static JKRHeap *sCurrentHeap;
static JKRHeap *sRootHeap;
static bool sDefaultFillFlag;
static bool sDefaultFillCheckFlag;
static JKRHeapErrorHandler *mErrorHandler;
protected:
/* 0x00 */ // vtable
/* 0x04 */ // JKRDisposer
/* 0x18 */ OSMutex mMutex;
/* 0x30 */ void *mStart;
/* 0x34 */ void *mEnd;
/* 0x38 */ u32 mSize;
/* 0x3C */ bool mDebugFill;
/* 0x3D */ bool mCheckMemoryFilled;
/* 0x3E */ u8 mAllocationMode; // EAllocMode?
/* 0x3F */ u8 mGroupId;
/* 0x40 */ JSUTree<JKRHeap> mChildTree;
/* 0x5C */ JSUList<JKRDisposer> mDisposerList;
/* 0x68 */ bool mErrorFlag;
/* 0x69 */ bool mInitFlag;
/* 0x6A */ u8 padding_0x6a[2];
};
inline JKRHeap *JKRGetCurrentHeap()
{
return JKRHeap::getCurrentHeap();
}
inline JKRHeap *JKRGetSystemHeap()
{
return JKRHeap::getSystemHeap();
}
inline JKRHeap *JKRGetRootHeap()
{
return JKRHeap::getRootHeap();
}
inline void *JKRAllocFromSysHeap(u32 size, int alignment)
{
return JKRHeap::getSystemHeap()->alloc(size, alignment);
}
inline void *JKRAllocFromHeap(JKRHeap *heap, u32 size, int alignment)
{
return JKRHeap::alloc(size, alignment, heap);
}
inline void JKRFree(void *pBuf)
{
JKRHeap::free(pBuf, nullptr);
}
inline void JKRFreeToSysHeap(void *buf)
{
JKRHeap::getSystemHeap()->free(buf);
}
void JKRDefaultMemoryErrorRoutine(void *, u32, int);
void *operator new(size_t);
void *operator new(size_t, s32);
void *operator new(size_t, JKRHeap *, int);
void *operator new[](size_t);
void *operator new[](size_t, s32);
void *operator new[](size_t, JKRHeap *, int);
void operator delete(void *);
void operator delete[](void *);
#endif // !JKRHEAP_H
+223
View File
@@ -0,0 +1,223 @@
#ifndef JSULIST_H
#define JSULIST_H
#include "types.h"
class JSUPtrLink;
class JSUPtrList
{
public:
JSUPtrList()
{
initiate();
}
JSUPtrList(bool);
~JSUPtrList();
void initiate();
void setFirst(JSUPtrLink *);
bool append(JSUPtrLink *);
bool prepend(JSUPtrLink *);
bool insert(JSUPtrLink *, JSUPtrLink *);
bool remove(JSUPtrLink *);
JSUPtrLink *getNthLink(u32 idx) const;
JSUPtrLink *getFirstLink() const { return mHead; }
JSUPtrLink *getLastLink() const { return mTail; }
u32 getNumLinks() const { return mLinkCount; }
JSUPtrLink *mHead; // _0
JSUPtrLink *mTail; // _4
u32 mLinkCount; // _8
};
class JSUPtrLink
{
public:
JSUPtrLink(void *);
~JSUPtrLink();
void *getObjectPtr() const { return mData; }
JSUPtrList *getList() const { return mPtrList; }
JSUPtrLink *getNext() const { return mNext; }
JSUPtrLink *getPrev() const { return mPrev; }
void *mData; // _0
JSUPtrList *mPtrList; // _4
JSUPtrLink *mPrev; // _8
JSUPtrLink *mNext; // _C
};
template <class T>
class JSULink; // friend class? i'm C++ noob
template <class T>
class JSUList : public JSUPtrList
{
public:
JSUList(bool thing) : JSUPtrList(thing)
{
}
JSUList() : JSUPtrList()
{
}
bool append(JSULink<T> *link) { return JSUPtrList::append((JSUPtrLink *)link); }
bool prepend(JSULink<T> *link) { return JSUPtrList::prepend((JSUPtrLink *)link); }
bool insert(JSULink<T> *before, JSULink<T> *link) { return JSUPtrList::insert((JSUPtrLink *)before, (JSUPtrLink *)link); }
bool remove(JSULink<T> *link) { return JSUPtrList::remove((JSUPtrLink *)link); }
JSULink<T> *getFirst() const { return (JSULink<T> *)getFirstLink(); }
JSULink<T> *getLast() const { return (JSULink<T> *)getLastLink(); }
JSULink<T> *getEnd() const { return nullptr; }
u32 getNumLinks() const { return mLinkCount; }
};
template <typename T>
class JSUListIterator
{
public:
JSUListIterator()
: mLink(nullptr)
{
}
JSUListIterator(JSULink<T> *link)
: mLink(link)
{
}
JSUListIterator(JSUList<T> *list)
: mLink(list->getFirst())
{
}
JSUListIterator<T> &operator=(JSULink<T> *link)
{
this->mLink = link;
return *this;
}
T *getObject() { return this->mLink->getObject(); }
bool operator==(JSULink<T> const *other) const { return this->mLink == other; }
bool operator!=(JSULink<T> const *other) const { return this->mLink != other; }
bool operator==(JSUListIterator<T> const &other) const { return this->mLink == other.mLink; }
bool operator!=(JSUListIterator<T> const &other) const { return this->mLink != other.mLink; }
JSUListIterator<T> operator++(int)
{
JSUListIterator<T> prev = *this;
this->mLink = this->mLink->getNext();
return prev;
}
JSUListIterator<T> &operator++()
{
this->mLink = this->mLink->getNext();
return *this;
}
JSUListIterator<T> operator--(int)
{
JSUListIterator<T> prev = *this;
this->mLink = this->mLink->getPrev();
return prev;
}
JSUListIterator<T> &operator--()
{
this->mLink = this->mLink->getPrev();
return *this;
}
T &operator*() { return *this->getObject(); }
T *operator->() { return this->getObject(); }
// private:
JSULink<T> *mLink;
};
template <class T>
class JSULink : public JSUPtrLink
{
public:
JSULink(void *pData) : JSUPtrLink(pData)
{
}
T *getObject() const { return (T *)mData; }
JSUList<T> *getList() const { return (JSUList<T> *)JSUPtrLink::getList(); } // fabricated, offcial name: getSupervisor
JSULink<T> *getNext() const { return (JSULink<T> *)JSUPtrLink::getNext(); }
JSULink<T> *getPrev() const { return (JSULink<T> *)JSUPtrLink::getPrev(); }
~JSULink()
{
}
};
template <typename T> // TODO: most of these inlines are probably wrong: rework
class JSUTree : public JSUList<T>, public JSULink<T>
{
public:
JSUTree(T *owner) : JSUList<T>(), JSULink<T>(owner) {}
~JSUTree() {}
bool appendChild(JSUTree<T> *child) { return this->append(child); }
bool prependChild(JSUTree<T> *child) { return this->prepend(child); }
bool removeChild(JSUTree<T> *child) { return this->remove(child); }
bool insertChild(JSUTree<T> *before, JSUTree<T> *child) { return this->insert(before, child); }
JSUTree<T> *getEndChild() const { return nullptr; }
JSUTree<T> *getFirstChild() const { return (JSUTree<T> *)getFirstLink(); }
JSUTree<T> *getLastChild() const { return (JSUTree<T> *)this->getLast(); }
JSUTree<T> *getNextChild() const { return (JSUTree<T> *)mNext; }
JSUTree<T> *getPrevChild() const { return (JSUTree<T> *)this->getPrev(); }
u32 getNumChildren() const { return mLinkCount; }
T *getObject() const { return (T *)this->mData; }
JSUTree<T> *getParent() const { return (JSUTree<T> *)this->mPtrList; }
};
template <typename T>
class JSUTreeIterator
{
public:
JSUTreeIterator() : mTree(nullptr) {}
JSUTreeIterator(JSUTree<T> *tree) : mTree(tree) {}
JSUTreeIterator<T> &operator=(JSUTree<T> *tree)
{
this->mTree = tree;
return *this;
}
T *getObject() const { return mTree->getObject(); }
bool operator==(JSUTree<T> *other) { return this->mTree == other; }
bool operator!=(const JSUTree<T> *other) const { return this->mTree != other; }
JSUTreeIterator<T> operator++(int)
{
JSUTreeIterator<T> prev = *this;
this->mTree = this->mTree->getNextChild();
return prev;
}
JSUTreeIterator<T> &operator++()
{
this->mTree = this->mTree->getNextChild();
return *this;
}
T &operator*() { return *this->getObject(); }
T *operator->() const { return mTree->getObject(); }
private:
JSUTree<T> *mTree;
};
#endif /* JSULIST_H */
+24 -1
View File
@@ -1,6 +1,29 @@
#ifndef _JSYSTEM_JUT_JUTASSERTION_H
#define _JSYSTEM_JUT_JUTASSERTION_H
void JC_JUTAssertion_changeDevice(u32);
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
void JC_JUTAssertion_changeDevice(u32);
#define JUT_PANIC(...)
#define JUT_PANIC_F(...)
#define JUT_CONFIRM_MESSAGE(...)
#define JUT_WARNING(...)
#define JUT_WARNING_F(...)
#define JUT_ASSERT(...)
#define JUT_ASSERT_F(...)
#define JUT_ASSERT_MSG(...)
#define JUT_MINMAX_ASSERT(...)
#define JUT_MAX_ASSERT(...)
#define JUT_LOG_F(...)
#ifdef __cplusplus
}
#endif
#endif
+32
View File
@@ -0,0 +1,32 @@
#ifndef OS_ADDRESS_H
#define OS_ADDRESS_H
// maybe put this in OSUtil instead
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
// Defines for cached and uncached memory.
#define OS_BASE_CACHED (0x80000000)
#define OS_BASE_UNCACHED (0xC0000000)
// Address conversions.
#define OSPhysicalToCached(paddr) ((void *)((u32)(paddr) + OS_BASE_CACHED))
#define OSPhysicalToUncached(paddr) ((void *)((u32)(paddr) + OS_BASE_UNCACHED))
#define OSCachedToPhysical(caddr) ((u32)((u8 *)(caddr)-OS_BASE_CACHED))
#define OSUncachedToPhysical(ucaddr) ((u32)((u8 *)(ucaddr)-OS_BASE_UNCACHED))
#define OSCachedToUncached(caddr) ((void *)((u8 *)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED)))
#define OSUncachedToCached(ucaddr) ((void *)((u8 *)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED)))
#define OS_CACHED_REGION_PREFIX 0x8000
#define OS_UNCACHED_REGION_PREFIX 0xC000
#define OS_PHYSICAL_MASK 0x3FFF
#ifdef __cplusplus
};
#endif
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef OS_ALLOC_H
#define OS_ALLOC_H
#ifdef __cplusplus
extern "C"
{
#endif
void *OSInitAlloc(void *, void *, int);
#ifdef __cplusplus
}
#endif
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef OS_MUTEX_H
#define OS_MUTEX_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "dolphin/OS/OSThread.h"
struct OSMutex
{
OSThreadQueue queue;
OSThread *thread; // the current owner
s32 count; // lock count
OSMutexLink link; // for OSThread.queueMutex
};
struct OSCond
{
OSThreadQueue queue;
};
void OSInitMutex(OSMutex *mutex);
void OSLockMutex(OSMutex *mutex);
void OSUnlockMutex(OSMutex *mutex);
BOOL OSTryLockMutex(OSMutex *mutex);
void OSInitCond(OSCond *cond);
void OSWaitCond(OSCond *cond, OSMutex *mutex);
void OSSignalCond(OSCond *cond);
#ifdef __cplusplus
}
#endif
#endif // DOLPHIN_OSMUTEX_H
+129
View File
@@ -0,0 +1,129 @@
#ifndef OS_THREAD_H
#define OS_THREAD_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "dolphin/os/OSContext.h"
typedef struct OSThread OSThread;
typedef struct OSThreadQueue OSThreadQueue;
typedef struct OSThreadLink OSThreadLink;
typedef s32 OSPriority; // 0 highest, 31 lowest
typedef struct OSMutex OSMutex;
typedef struct OSMutexQueue OSMutexQueue;
typedef struct OSMutexLink OSMutexLink;
typedef struct OSCond OSCond;
typedef void (*OSIdleFunction)(void *param);
struct OSThreadQueue
{
OSThread *head;
OSThread *tail;
};
struct OSThreadLink
{
OSThread *next;
OSThread *prev;
};
struct OSMutexQueue
{
OSMutex *head;
OSMutex *tail;
};
struct OSMutexLink
{
OSMutex *next;
OSMutex *prev;
};
struct OSThread
{
OSContext context; // register context
u16 state; // OS_THREAD_STATE_*
u16 attr; // OS_THREAD_ATTR_*
s32 suspend; // suspended if the count is greater than zero
OSPriority priority; // effective scheduling priority
OSPriority base; // base scheduling priority
void *val; // exit value
OSThreadQueue *queue; // queue thread is on
OSThreadLink link; // queue link
OSThreadQueue queueJoin; // list of threads waiting for termination (join)
OSMutex *mutex; // mutex trying to lock
OSMutexQueue queueMutex; // list of mutexes owned
OSThreadLink linkActive; // link of all threads for debugging
u8 *stackBase; // the thread's designated stack (high address)
u32 *stackEnd; // last word of stack (low address)
};
// Thread states
enum OS_THREAD_STATE
{
OS_THREAD_STATE_READY = 1,
OS_THREAD_STATE_RUNNING = 2,
OS_THREAD_STATE_WAITING = 4,
OS_THREAD_STATE_MORIBUND = 8
};
// Thread priorities
#define OS_PRIORITY_MIN 0 // highest
#define OS_PRIORITY_MAX 31 // lowest
#define OS_PRIORITY_IDLE OS_PRIORITY_MAX
// Thread attributes
#define OS_THREAD_ATTR_DETACH 0x0001u // detached
// Stack magic value
#define OS_THREAD_STACK_MAGIC 0xDEADBABE
void OSInitThreadQueue(OSThreadQueue *queue);
OSThread *OSGetCurrentThread(void);
BOOL OSIsThreadSuspended(OSThread *thread);
BOOL OSIsThreadTerminated(OSThread *thread);
s32 OSDisableScheduler(void);
s32 OSEnableScheduler(void);
void OSYieldThread(void);
BOOL OSCreateThread(OSThread *thread,
void *(*func)(void *),
void *param,
void *stack,
u32 stackSize,
OSPriority priority,
u16 attr);
void OSExitThread(void *val);
void OSCancelThread(OSThread *thread);
BOOL OSJoinThread(OSThread *thread, void **val);
void OSDetachThread(OSThread *thread);
s32 OSResumeThread(OSThread *thread);
s32 OSSuspendThread(OSThread *thread);
BOOL OSSetThreadPriority(OSThread *thread, OSPriority priority);
OSPriority OSGetThreadPriority(OSThread *thread);
void OSSleepThread(OSThreadQueue *queue);
void OSWakeupThread(OSThreadQueue *queue);
OSThread *OSSetIdleFunction(OSIdleFunction idleFunction,
void *param,
void *stack,
u32 stackSize);
OSThread *OSGetIdleFunction(void);
long OSCheckActiveThreads(void);
#ifdef __cplusplus
}
#endif
#endif // DOLPHIN_OSTHREAD_H
+18
View File
@@ -0,0 +1,18 @@
#ifndef OS_UTIL_H
#define OS_UTIL_H
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define OSRoundUp32B(x) (((u32)(x) + 0x1F) & ~(0x1F))
#define OSRoundDown32B(x) (((u32)(x)) & ~(0x1F))
#ifdef __cplusplus
};
#endif
#endif
+4 -1
View File
@@ -8,14 +8,17 @@
extern "C" {
#endif
void OSPanic(const char *file, int line, const char *message, ...);
void OSReport(const char*, ...);
void OSVReport(const char* format, va_list list);
#define OSErrorLine(line, ...) \
OSPanic(__FILE__, line, __VA_ARGS__)
asm BOOL OSDisableInterrupts(void);
asm BOOL OSEnableInterrupts(void);
asm BOOL OSRestoreInterrupts(BOOL level);
void __RAS_OSDisableInterrupts_begin(void);
void __RAS_OSDisableInterrupts_end(void);
+426
View File
@@ -0,0 +1,426 @@
#include "JSystem/JUT/JUTAssertion.h"
#include "JSystem/JKernel/JKRHeap.h"
#include "dolphin/OS/os.h"
#include "dolphin/OS/OSArena.h"
#include "dolphin/OS/OSAlloc.h"
#include "dolphin/OS/OSMemory.h"
#include "dolphin/OS/OSUtil.h"
#include "dolphin/OS/OSAddress.h"
JKRHeap *JKRHeap::sSystemHeap;
JKRHeap *JKRHeap::sCurrentHeap;
JKRHeap *JKRHeap::sRootHeap;
JKRHeapErrorHandler *JKRHeap::mErrorHandler;
void *JKRHeap::mCodeStart;
void *JKRHeap::mCodeEnd;
void *JKRHeap::mUserRamStart;
void *JKRHeap::mUserRamEnd;
u32 JKRHeap::mMemorySize;
bool JKRHeap::sDefaultFillFlag = true;
JKRHeap::JKRHeap(void *data, u32 size, JKRHeap *heap, bool errorFlag) : JKRDisposer(),
mChildTree(this),
mDisposerList()
{
OSInitMutex(&mMutex);
mSize = size;
mStart = (u8 *)data;
mEnd = ((u8 *)data + size);
if (heap == nullptr)
{
becomeSystemHeap();
becomeCurrentHeap();
}
else
{
heap->mChildTree.appendChild(&mChildTree);
if (sSystemHeap == sRootHeap)
becomeSystemHeap();
if (sCurrentHeap == sRootHeap)
becomeCurrentHeap();
}
mErrorFlag = errorFlag;
if (mErrorFlag == true && mErrorHandler == nullptr)
mErrorHandler = JKRDefaultMemoryErrorRoutine;
mDebugFill = sDefaultFillFlag;
mInitFlag = false;
}
JKRHeap::~JKRHeap()
{
mChildTree.getParent()->removeChild(&mChildTree);
JSUTree<JKRHeap> *nextRootHeap = sRootHeap->mChildTree.getFirstChild();
if (sCurrentHeap == this)
sCurrentHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject();
if (sSystemHeap == this)
sSystemHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject();
}
bool JKRHeap::initArena(char **outUserRamStart, u32 *outUserRamSize, int numHeaps)
{
void *arenaLo = OSGetArenaLo();
void *arenaHi = OSGetArenaHi();
if (arenaLo == arenaHi)
{
return false;
}
void *arenaStart = OSInitAlloc(arenaLo, arenaHi, numHeaps);
arenaHi = (u8 *)OSRoundDown32B(arenaHi);
arenaLo = (u8 *)OSRoundUp32B(arenaStart);
u8 *start = (u8 *)OSPhysicalToCached(0);
mCodeStart = (u8 *)start;
mCodeEnd = (u8 *)arenaLo;
mUserRamStart = (u8 *)arenaLo;
mUserRamEnd = (u8 *)arenaHi;
mMemorySize = *(u32 *)((start + 0x28));
OSSetArenaLo(arenaHi);
OSSetArenaHi(arenaHi);
*outUserRamStart = (char *)arenaLo;
*outUserRamSize = (u32)arenaHi - (u32)arenaLo;
return true;
}
JKRHeap *JKRHeap::becomeSystemHeap()
{
JKRHeap *old = sSystemHeap;
sSystemHeap = this;
return old;
}
JKRHeap *JKRHeap::becomeCurrentHeap()
{
JKRHeap *old = sCurrentHeap;
sCurrentHeap = this;
return old;
}
void JKRHeap::destroy(JKRHeap *heap)
{
JUT_ASSERT(200, heap != 0);
heap->destroy();
}
void *JKRHeap::alloc(u32 byteCount, int padding, JKRHeap *heap)
{
void *memory = nullptr;
if (heap)
{
memory = heap->do_alloc(byteCount, padding);
}
else if (sCurrentHeap)
{
memory = sCurrentHeap->do_alloc(byteCount, padding);
}
return memory;
}
void *JKRHeap::alloc(u32 byteCount, int padding)
{
JUT_WARNING_F(317, !mInitFlag, "alloc %x byte in heap %x", byteCount, this);
return do_alloc(byteCount, padding);
}
void JKRHeap::free(void *memory, JKRHeap *heap)
{
if ((heap) || (heap = findFromRoot(memory), heap))
{
heap->free(memory);
}
}
void JKRHeap::free(void *memory)
{
JUT_WARNING_F(365, !mInitFlag, "free %x in heap %x", memory, this);
do_free(memory);
}
void JKRHeap::callAllDisposer()
{
JSUListIterator<JKRDisposer> iterator;
while (iterator = mDisposerList.getFirst(), iterator != mDisposerList.getEnd())
{
iterator->~JKRDisposer();
}
}
void JKRHeap::freeAll()
{
JUT_WARNING_F(417, !mInitFlag, "freeAll in heap %x", this);
do_freeAll();
}
void JKRHeap::freeTail()
{
JUT_WARNING_F(431, !mInitFlag, "freeTail in heap %x", this);
do_freeTail();
}
void JKRHeap::resize(void *memoryBlock, u32 newSize)
{
JUT_WARNING_F(491, !mInitFlag, "resize block %x into %x in heap %x", memoryBlock, newSize, this);
do_resize(memoryBlock, newSize);
}
s32 JKRHeap::getSize(void *memoryBlock, JKRHeap *heap)
{
if (heap == nullptr && (heap = findFromRoot(memoryBlock), heap == nullptr))
{
return -1;
}
else
return heap->getSize(memoryBlock);
}
s32 JKRHeap::getSize(void *memoryBlock) { return do_getSize(memoryBlock); }
s32 JKRHeap::getFreeSize() { return do_getFreeSize(); }
s32 JKRHeap::getTotalFreeSize() { return do_getTotalFreeSize(); }
s32 JKRHeap::changeGroupID(u8 newGroupID)
{
JUT_WARNING_F(570, !mInitFlag, "change heap ID into %x in heap %x", newGroupID, this);
return do_changeGroupID(newGroupID);
}
u8 JKRHeap::getCurrentGroupId() { return do_getCurrentGroupId(); }
JKRHeap *JKRHeap::findFromRoot(void *ptr)
{
if (sRootHeap != nullptr)
return sRootHeap->find(ptr);
return nullptr;
}
JKRHeap *JKRHeap::find(void *memory) const
{
if ((mStart <= memory) && (memory <= mEnd))
{
if (mChildTree.getNumChildren() != 0)
{
for (JSUTreeIterator<JKRHeap> iterator(mChildTree.getFirstChild()); iterator != mChildTree.getEndChild(); ++iterator)
{
JKRHeap *result = iterator->find(memory);
if (result)
{
return result;
}
}
}
return const_cast<JKRHeap *>(this);
}
return nullptr;
}
JKRHeap *JKRHeap::findAllHeap(void *memory) const
{
if (mChildTree.getNumChildren() != 0)
{
for (JSUTreeIterator<JKRHeap> iterator(mChildTree.getFirstChild()); iterator != mChildTree.getEndChild(); ++iterator)
{
JKRHeap *result = iterator->findAllHeap(memory);
if (result)
{
return result;
}
}
}
if (mStart <= memory && memory < mEnd)
{
return const_cast<JKRHeap *>(this);
}
return nullptr;
}
// generates __as__25JSUTreeIterator<7JKRHeap>FP17JSUTree<7JKRHeap> and __ct__25JSUTreeIterator<7JKRHeap>Fv, remove this
void JKRHeap::dispose_subroutine(u32 begin, u32 end)
{
JSUListIterator<JKRDisposer> last_iterator;
JSUListIterator<JKRDisposer> next_iterator;
JSUListIterator<JKRDisposer> iterator;
for (iterator = mDisposerList.getFirst(); iterator != mDisposerList.getEnd();
iterator = next_iterator)
{
JKRDisposer *disposer = iterator.getObject();
if ((void *)begin <= disposer && disposer < (void *)end)
{
disposer->~JKRDisposer();
if (last_iterator == nullptr)
{
next_iterator = mDisposerList.getFirst();
}
else
{
next_iterator = last_iterator;
next_iterator++;
}
}
else
{
last_iterator = iterator;
next_iterator = iterator;
next_iterator++;
}
}
}
bool JKRHeap::dispose(void *memory, u32 size)
{
u32 begin = (u32)memory;
u32 end = (u32)memory + size;
dispose_subroutine(begin, end);
return false;
}
void JKRHeap::dispose(void *begin, void *end)
{
dispose_subroutine((u32)begin, (u32)end);
}
void JKRHeap::dispose()
{
JSUListIterator<JKRDisposer> iterator;
while (iterator = mDisposerList.getFirst(), iterator != mDisposerList.getEnd())
{
iterator->~JKRDisposer();
}
}
void JKRHeap::copyMemory(void *dst, void *src, u32 size)
{
u32 count = (size + 3) / 4;
u32 *dst_32 = (u32 *)dst;
u32 *src_32 = (u32 *)src;
while (count > 0)
{
*dst_32 = *src_32;
dst_32++;
src_32++;
count--;
}
}
void JKRDefaultMemoryErrorRoutine(void *heap, u32 size, int alignment)
{
// OSReport("Error: Cannot allocate memory %d(0x%x)byte in %d byte alignment from %08x\n", size, size, alignment, heap);
OSErrorLine(710, "abort\n");
}
JKRHeapErrorHandler *JKRHeap::setErrorHandler(JKRHeapErrorHandler *newHandler)
{
JKRHeapErrorHandler *oldHandler = mErrorHandler;
if (!newHandler)
{
newHandler = JKRDefaultMemoryErrorRoutine;
}
mErrorHandler = newHandler;
return oldHandler;
}
bool JKRHeap::isSubHeap(JKRHeap *heap) const
{
if (!heap)
return false;
if (mChildTree.getNumChildren() != 0)
{
JSUTreeIterator<JKRHeap> iterator;
for (iterator = mChildTree.getFirstChild(); iterator != mChildTree.getEndChild(); ++iterator)
{
if (iterator.getObject() == heap)
{
return true;
}
if (iterator.getObject()->isSubHeap(heap))
{
return true;
}
}
}
return false;
}
void *operator new(u32 byteCount)
{
return JKRHeap::alloc(byteCount, 4, nullptr);
}
void *operator new(u32 byteCount, int alignment)
{
return JKRHeap::alloc(byteCount, alignment, nullptr);
}
void *operator new(u32 byteCount, JKRHeap *heap, int alignment)
{
return JKRHeap::alloc(byteCount, alignment, heap);
}
void *operator new[](u32 byteCount)
{
return JKRHeap::alloc(byteCount, 4, nullptr);
}
void *operator new[](u32 byteCount, int alignment)
{
return JKRHeap::alloc(byteCount, alignment, nullptr);
}
void *operator new[](u32 byteCount, JKRHeap *heap, int alignment)
{
return JKRHeap::alloc(byteCount, alignment, heap);
}
// this is not needed without the other pragma and asm bs
void operator delete(void *memory) { JKRHeap::free(memory, nullptr); }
void operator delete[](void *memory) { JKRHeap::free(memory, nullptr); }
/*JKRHeap::TState::TState(const JKRHeap::TState::TArgument &arg, const JKRHeap::TState::TLocation &location)
{
// UNUSED FUNCTION
}
JKRHeap::TState::TState(const JKRHeap::TState &other, bool p2)
{
// UNUSED FUNCTION
}
JKRHeap::TState::TState(const JKRHeap::TState &other, const JKRHeap::TState::TLocation &location, bool p3)
{
// UNUSED FUNCTION
}*/
JKRHeap::TState::~TState()
{
// Unused, however might need it
}
void JKRHeap::state_register(JKRHeap::TState *p, u32) const
{
JUT_ASSERT(1132, p != 0);
JUT_ASSERT(1133, p->getHeap() == this);
}
bool JKRHeap::state_compare(const JKRHeap::TState &r1, const JKRHeap::TState &r2) const
{
JUT_ASSERT(1141, r1.getHeap() == r2.getHeap());
return (r1.getCheckCode() == r2.getCheckCode());
}
// fabricated, but probably matches(except for line numbers)
void JKRHeap::state_dumpDifference(const JKRHeap::TState &r1, const JKRHeap::TState &r2)
{
JUT_LOG_F(1157, "heap : %p / %p", r1.getHeap(), r2.getHeap());
JUT_LOG_F(1158, "check-code : 0x%08x / 0x%08x", r1.getCheckCode(), r2.getCheckCode());
JUT_LOG_F(1159, "id : 0x%08x / 0x%08x", r1.getId(), r2.getId());
JUT_LOG_F(1160, "used size : %10u / %10u", r1.getUsedSize(), r2.getUsedSize());
}
void JKRHeap::state_dump(const TState &state) const
{
JUT_LOG_F(1165, "check-code : 0x%08x", state.getCheckCode());
JUT_LOG_F(1166, "id : 0x%08x", state.getId());
JUT_LOG_F(1167, "used size : %u", state.getUsedSize());
}