Match and link OSLink

Former-commit-id: 63e08c42a2
This commit is contained in:
Phillip Stephens 2022-12-17 20:08:25 -08:00
parent 0fc686018f
commit 6d5f3fae1c
7 changed files with 911 additions and 3 deletions

View File

@ -44,7 +44,8 @@
"gxenum.h": "c",
"trees.h": "c",
"musyx.h": "c",
"dsp_import.h": "c"
"dsp_import.h": "c",
"osinterrupt.h": "c"
},
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,

View File

@ -814,9 +814,9 @@ LIBS = [
"Dolphin/os/OSFatal",
"Dolphin/os/OSFont",
"Dolphin/os/OSInterrupt",
"Dolphin/os/OSLink",
["Dolphin/os/OSLink", True],
"Dolphin/os/OSMemory",
"Dolphin/os/OSMutex",
["Dolphin/os/OSMutex", True],
"Dolphin/os/OSReboot",
["Dolphin/os/OSReset", True],
"Dolphin/os/OSResetSW",

View File

@ -158,6 +158,7 @@ void OSFatal(GXColor fg, GXColor bg, const char* msg);
#include <dolphin/os/OSFastCast.h>
#include <dolphin/os/OSFont.h>
#include <dolphin/os/OSInterrupt.h>
#include <dolphin/os/OSModule.h>
#include <dolphin/os/OSMutex.h>
#include <dolphin/os/OSReset.h>
#include <dolphin/os/OSSerial.h>

View File

@ -0,0 +1,115 @@
#ifndef _DOLPHIN_OSMODULE
#define _DOLPHIN_OSMODULE
#include <dolphin/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OS_MODULE_VERSION 2
typedef struct OSModuleHeader OSModuleHeader;
typedef u32 OSModuleID;
typedef struct OSModuleQueue OSModuleQueue;
typedef struct OSModuleLink OSModuleLink;
typedef struct OSModuleInfo OSModuleInfo;
typedef struct OSSectionInfo OSSectionInfo;
typedef struct OSImportInfo OSImportInfo;
typedef struct OSRel OSRel;
struct OSModuleQueue {
OSModuleInfo* head;
OSModuleInfo* tail;
};
struct OSModuleLink {
OSModuleInfo* next;
OSModuleInfo* prev;
};
struct OSModuleInfo {
OSModuleID id; // unique identifier for the module
OSModuleLink link; // doubly linked list of modules
u32 numSections; // # of sections
u32 sectionInfoOffset; // offset to section info table
u32 nameOffset; // offset to module name
u32 nameSize; // size of module name
u32 version; // version number
};
struct OSModuleHeader {
// CAUTION: info must be the 1st member
OSModuleInfo info;
// OS_MODULE_VERSION == 1
u32 bssSize; // total size of bss sections in bytes
u32 relOffset;
u32 impOffset;
u32 impSize; // size in bytes
u8 prologSection; // section # for prolog function
u8 epilogSection; // section # for epilog function
u8 unresolvedSection; // section # for unresolved function
u8 bssSection; // section # for bss section (set at run-time)
u32 prolog; // prolog function offset
u32 epilog; // epilog function offset
u32 unresolved; // unresolved function offset
// OS_MODULE_VERSION == 2
#if (2 <= OS_MODULE_VERSION)
u32 align; // module alignment constraint
u32 bssAlign; // bss alignment constraint
#endif
// OS_MODULE_VERSION == 3
#if (3 <= OS_MODULE_VERSION)
u32 fixSize;
#endif
};
#define OSGetSectionInfo(module) ((OSSectionInfo*)(((OSModuleInfo*)(module))->sectionInfoOffset))
struct OSSectionInfo {
u32 offset;
u32 size;
};
// OSSectionInfo.offset bit
#define OS_SECTIONINFO_EXEC 0x1
#define OS_SECTIONINFO_OFFSET(offset) ((offset) & ~0x1)
struct OSImportInfo {
OSModuleID id; // external module id
u32 offset; // offset to OSRel instructions
};
struct OSRel {
u16 offset; // byte offset from the previous entry
u8 type;
u8 section;
u32 addend;
};
#define R_DOLPHIN_NOP 201 // C9h current offset += OSRel.offset
#define R_DOLPHIN_SECTION 202 // CAh current section = OSRel.section
#define R_DOLPHIN_END 203 // CBh
#define R_DOLPHIN_MRKREF 204 // CCh
void OSSetStringTable(const void* stringTable);
BOOL OSLink(OSModuleInfo* newModule, void* bss);
#if (3 <= OS_MODULE_VERSION)
BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss);
#endif
BOOL OSUnlink(OSModuleInfo* oldModule);
OSModuleInfo* OSSearchModule(void* ptr, u32* section, u32* offset);
// debugger notification
void OSNotifyLink(OSModuleInfo* module);
void OSNotifyUnlink(OSModuleInfo* module);
#ifdef __cplusplus
}
#endif
#endif // _DOLPHIN_OSMODULE

View File

@ -16,6 +16,18 @@ struct OSMutex {
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

556
src/Dolphin/os/OSLink.c Normal file
View File

@ -0,0 +1,556 @@
#include "dolphin/os.h"
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_LOPROC 0xff00
#define SHN_HIPROC 0xff1f
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
// Name Value Field Calculation
#define R_PPC_NONE 0 // none none
#define R_PPC_ADDR32 1 // word32 S + A
#define R_PPC_ADDR24 2 // low24* (S + A) >> 2
#define R_PPC_ADDR16 3 // half16* S + A
#define R_PPC_ADDR16_LO 4 // half16 #lo(S + A)
#define R_PPC_ADDR16_HI 5 // half16 #hi(S + A)
#define R_PPC_ADDR16_HA 6 // half16 #ha(S + A)
#define R_PPC_ADDR14 7 // low14* (S + A) >> 2
#define R_PPC_ADDR14_BRTAKEN 8 // low14* (S + A) >> 2
#define R_PPC_ADDR14_BRNTAKEN 9 // low14* (S + A) >> 2
#define R_PPC_REL24 10 // low24* (S + A - P) >> 2
#define R_PPC_REL14 11 // low14* (S + A - P) >> 2
#define R_PPC_REL14_BRTAKEN 12 // low14* (S + A - P) >> 2
#define R_PPC_REL14_BRNTAKEN 13 // low14* (S + A - P) >> 2
#define R_PPC_GOT16 14 // half16* G + A
#define R_PPC_GOT16_LO 15 // half16 #lo(G + A)
#define R_PPC_GOT16_HI 16 // half16 #hi(G + A)
#define R_PPC_GOT16_HA 17 // half16 #ha(G + A)
#define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2
#define R_PPC_COPY 19 // none none
#define R_PPC_GLOB_DAT 20 // word32 S + A
#define R_PPC_JMP_SLOT 21 // none
#define R_PPC_RELATIVE 22 // word32 B + A
#define R_PPC_LOCAL24PC 23 // low24*
#define R_PPC_UADDR32 24 // word32 S + A
#define R_PPC_UADDR16 25 // half16* S + A
#define R_PPC_REL32 26 // word32 S + A - P
#define R_PPC_PLT32 27 // word32 L + A
#define R_PPC_PLTREL32 28 // word32 L + A - P
#define R_PPC_PLT16_LO 29 // half16 #lo(L + A)
#define R_PPL_PLT16_HI 30 // half16 #hi(L + A)
#define R_PPC_PLT16_HA 31 // half16 #ha(L + A)
#define R_PPC_SDAREL16 32 // half16* S + A - _SDA_BASE_
#define R_PPC_SECTOFF 33 // half16* R + A
#define R_PPC_SECTOFF_LO 34 // half16 #lo(R + A)
#define R_PPC_SECTOFF_HI 35 // half16 #hi(R + A)
#define R_PPC_SECTOFF_HA 36 // half16 #ha(R + A)
#define R_PPC_ADDR30 37 // word30 (S + A - P) >> 2
#define R_PPC_EMB_NADDR32 101 // uword32 N (A - S)
#define R_PPC_EMB_NADDR16 102 // uhalf16 Y (A - S)
#define R_PPC_EMB_NADDR16_LO 103 // uhalf16 N #lo(A - S)
#define R_PPC_EMB_NADDR16_HI 104 // uhalf16 N #hi(A - S)
#define R_PPC_EMB_NADDR16_HA 105 // uhalf16 N #ha(A - S)
#define R_PPC_EMB_SDAI16 106 // uhalf16 Y T
#define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U
#define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_
#define R_PPC_EMB_SDA21 109 // ulow21 N
#define R_PPC_EMB_MRKREF 110 // none N
#define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A
#define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A)
#define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A)
#define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A)
#define R_PPC_EMB_BIT_FLD 115 // uword32 Y
#define R_PPC_EMB_RELSDA 116 // uhalf16 Y
OSModuleQueue __OSModuleInfoList : (OS_BASE_CACHED | 0x30C8);
const void* __OSStringTable : (OS_BASE_CACHED | 0x30D0);
#pragma dont_inline on
__declspec(weak) void OSNotifyLink(OSModuleInfo* module) {}
__declspec(weak) void OSNotifyUnlink(OSModuleInfo* module) {}
#pragma dont_inline reset
#define EnqueueTail(queue, moduleInfo, link) \
do { \
OSModuleInfo* __prev; \
\
__prev = (queue)->tail; \
if (__prev == NULL) \
(queue)->head = (moduleInfo); \
else \
__prev->link.next = (moduleInfo); \
(moduleInfo)->link.prev = __prev; \
(moduleInfo)->link.next = NULL; \
(queue)->tail = (moduleInfo); \
} while (0)
#define DequeueItem(queue, moduleInfo, link) \
do { \
OSModuleInfo* __next; \
OSModuleInfo* __prev; \
\
__next = (moduleInfo)->link.next; \
__prev = (moduleInfo)->link.prev; \
\
if (__next == NULL) \
(queue)->tail = __prev; \
else \
__next->link.prev = __prev; \
\
if (__prev == NULL) \
(queue)->head = __next; \
else \
__prev->link.next = __next; \
} while (0)
void OSSetStringTable(const void* stringTable) { __OSStringTable = stringTable; }
static BOOL Relocate(OSModuleHeader* newModule, OSModuleHeader* module) {
OSModuleID idNew;
OSImportInfo* imp;
OSRel* rel;
OSSectionInfo* si;
OSSectionInfo* siFlush;
u32* p;
u32 offset;
u32 x;
idNew = newModule ? newModule->info.id : 0;
for (imp = (OSImportInfo*)module->impOffset;
imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) {
if (imp->id == idNew) {
goto Found;
}
}
return FALSE;
Found:
siFlush = 0;
for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) {
(u8*)p += rel->offset;
if (idNew) {
si = &OSGetSectionInfo(newModule)[rel->section];
offset = OS_SECTIONINFO_OFFSET(si->offset);
} else {
offset = 0;
}
switch (rel->type) {
case R_PPC_NONE:
break;
case R_PPC_ADDR32:
x = offset + rel->addend;
*p = x;
break;
case R_PPC_ADDR24:
x = offset + rel->addend;
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_ADDR16:
x = offset + rel->addend;
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_LO:
x = offset + rel->addend;
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_HI:
x = offset + rel->addend;
*(u16*)p = (u16)(((x >> 16) & 0xffff));
break;
case R_PPC_ADDR16_HA:
x = offset + rel->addend;
*(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff);
break;
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
x = offset + rel->addend;
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_PPC_REL24:
x = offset + rel->addend - (u32)p;
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
x = offset + rel->addend - (u32)p;
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_DOLPHIN_NOP:
break;
case R_DOLPHIN_SECTION:
si = &OSGetSectionInfo(module)[rel->section];
p = (u32*)OS_SECTIONINFO_OFFSET(si->offset);
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0;
break;
default:
OSReport("OSLink: unknown relocation type %3d\n", rel->type);
break;
}
}
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
return TRUE;
}
#if OS_MODULE_VERSION >= 3
static BOOL Link(OSModuleInfo* newModule, void* bss, BOOL fixed) {
u32 i;
OSSectionInfo* si;
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)newModule;
moduleHeader->bssSection = 0;
if (OS_MODULE_VERSION < newModule->version ||
2 <= newModule->version &&
(moduleHeader->align && (u32)newModule % moduleHeader->align != 0 ||
moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) {
return FALSE;
}
EnqueueTail(&__OSModuleInfoList, newModule, link);
newModule->sectionInfoOffset += (u32)moduleHeader;
moduleHeader->relOffset += (u32)moduleHeader;
moduleHeader->impOffset += (u32)moduleHeader;
if (3 <= newModule->version) {
moduleHeader->fixSize += (u32)moduleHeader;
}
for (i = 1; i < newModule->numSections; i++) {
si = &OSGetSectionInfo(newModule)[i];
if (si->offset != 0) {
si->offset += (u32)moduleHeader;
} else if (si->size != 0) {
moduleHeader->bssSection = (u8)i;
si->offset = (u32)bss;
bss = (void*)((u32)bss + si->size);
}
}
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) {
imp->offset += (u32)moduleHeader;
}
if (moduleHeader->prologSection != SHN_UNDEF) {
moduleHeader->prolog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset);
}
if (moduleHeader->epilogSection != SHN_UNDEF) {
moduleHeader->epilog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset);
}
if (moduleHeader->unresolvedSection != SHN_UNDEF) {
moduleHeader->unresolved +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset);
}
if (__OSStringTable) {
newModule->nameOffset += (u32)__OSStringTable;
}
Relocate(0, moduleHeader);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Relocate(moduleHeader, (OSModuleHeader*)moduleInfo);
if (moduleInfo != newModule) {
Relocate((OSModuleHeader*)moduleInfo, moduleHeader);
}
}
if (fixed) {
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) {
if (imp->id == 0 || imp->id == newModule->id) {
moduleHeader->impSize = (u32)((u8*)imp - (u8*)moduleHeader->impOffset);
break;
}
}
}
memset(bss, 0, moduleHeader->bssSize);
OSNotifyLink(newModule);
return TRUE;
}
BOOL OSLink(OSModuleInfo* newModule, void* bss) { return Link(newModule, bss, FALSE); }
BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss) {
if (OS_MODULE_VERSION < newModule->version || newModule->version < 3) {
return FALSE;
}
return Link(newModule, bss, TRUE);
}
#else
BOOL OSLink(OSModuleInfo* newModule, void* bss) {
u32 i;
OSSectionInfo* si;
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)newModule;
moduleHeader->bssSection = 0;
if (OS_MODULE_VERSION < newModule->version ||
2 <= newModule->version &&
(moduleHeader->align && (u32)newModule % moduleHeader->align != 0 ||
moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) {
return FALSE;
}
EnqueueTail(&__OSModuleInfoList, newModule, link);
memset(bss, 0, moduleHeader->bssSize);
newModule->sectionInfoOffset += (u32)moduleHeader;
moduleHeader->relOffset += (u32)moduleHeader;
moduleHeader->impOffset += (u32)moduleHeader;
for (i = 1; i < newModule->numSections; i++) {
si = &OSGetSectionInfo(newModule)[i];
if (si->offset != 0) {
si->offset += (u32)moduleHeader;
} else if (si->size != 0) {
moduleHeader->bssSection = (u8)i;
si->offset = (u32)bss;
bss = (void*)((u32)bss + si->size);
}
}
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) {
imp->offset += (u32)moduleHeader;
}
if (moduleHeader->prologSection != SHN_UNDEF) {
moduleHeader->prolog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset);
}
if (moduleHeader->epilogSection != SHN_UNDEF) {
moduleHeader->epilog +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset);
}
if (moduleHeader->unresolvedSection != SHN_UNDEF) {
moduleHeader->unresolved +=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset);
}
if (__OSStringTable) {
newModule->nameOffset += (u32)__OSStringTable;
}
Relocate(0, moduleHeader);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Relocate(moduleHeader, (OSModuleHeader*)moduleInfo);
if (moduleInfo != newModule) {
Relocate((OSModuleHeader*)moduleInfo, moduleHeader);
}
}
OSNotifyLink(newModule);
return TRUE;
}
#endif
static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) {
OSModuleID idNew;
OSImportInfo* imp;
OSRel* rel;
OSSectionInfo* si;
OSSectionInfo* siFlush;
u32* p;
u32 offset;
u32 x;
idNew = newModule->info.id;
for (imp = (OSImportInfo*)module->impOffset;
imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) {
if (imp->id == idNew) {
goto Found;
}
}
return FALSE;
Found:
siFlush = 0;
for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) {
(u8*)p += rel->offset;
si = &OSGetSectionInfo(newModule)[rel->section];
offset = OS_SECTIONINFO_OFFSET(si->offset);
x = 0;
switch (rel->type) {
case R_PPC_NONE:
break;
case R_PPC_ADDR32:
*p = x;
break;
case R_PPC_ADDR24:
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_ADDR16:
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_LO:
*(u16*)p = (u16)(x & 0xffff);
break;
case R_PPC_ADDR16_HI:
*(u16*)p = (u16)(((x >> 16) & 0xffff));
break;
case R_PPC_ADDR16_HA:
*(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff);
break;
case R_PPC_ADDR14:
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_PPC_REL24:
if (module->unresolvedSection != SHN_UNDEF) {
x = (u32)module->unresolved - (u32)p;
}
*p = (*p & ~0x03fffffc) | (x & 0x03fffffc);
break;
case R_PPC_REL14:
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
*p = (*p & ~0x0000fffc) | (x & 0x0000fffc);
break;
case R_DOLPHIN_NOP:
break;
case R_DOLPHIN_SECTION:
si = &OSGetSectionInfo(module)[rel->section];
p = (u32*)OS_SECTIONINFO_OFFSET(si->offset);
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0;
break;
default:
OSReport("OSUnlink: unknown relocation type %3d\n", rel->type);
break;
}
}
if (siFlush) {
offset = OS_SECTIONINFO_OFFSET(siFlush->offset);
DCFlushRange((void*)offset, siFlush->size);
ICInvalidateRange((void*)offset, siFlush->size);
}
return TRUE;
}
BOOL OSUnlink(OSModuleInfo* oldModule) {
OSModuleHeader* moduleHeader;
OSModuleInfo* moduleInfo;
u32 i;
OSSectionInfo* si;
OSImportInfo* imp;
moduleHeader = (OSModuleHeader*)oldModule;
DequeueItem(&__OSModuleInfoList, oldModule, link);
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
Undo(moduleHeader, (OSModuleHeader*)moduleInfo);
}
OSNotifyUnlink(oldModule);
if (__OSStringTable) {
oldModule->nameOffset -= (u32)__OSStringTable;
}
if (moduleHeader->prologSection != SHN_UNDEF) {
moduleHeader->prolog -=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->prologSection].offset);
}
if (moduleHeader->epilogSection != SHN_UNDEF) {
moduleHeader->epilog -=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->epilogSection].offset);
}
if (moduleHeader->unresolvedSection != SHN_UNDEF) {
moduleHeader->unresolved -=
OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->unresolvedSection].offset);
}
for (imp = (OSImportInfo*)moduleHeader->impOffset;
imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) {
imp->offset -= (u32)moduleHeader;
}
for (i = 1; i < oldModule->numSections; i++) {
si = &OSGetSectionInfo(oldModule)[i];
if (i == moduleHeader->bssSection) {
moduleHeader->bssSection = 0;
si->offset = 0;
} else if (si->offset != 0) {
si->offset -= (u32)moduleHeader;
}
}
moduleHeader->relOffset -= (u32)moduleHeader;
moduleHeader->impOffset -= (u32)moduleHeader;
oldModule->sectionInfoOffset -= (u32)moduleHeader;
return TRUE;
}
void __OSModuleInit(void) {
__OSModuleInfoList.head = __OSModuleInfoList.tail = 0;
__OSStringTable = 0;
}
OSModuleInfo* OSSearchModule(void* ptr, u32* section, u32* offset) {
OSModuleInfo* moduleInfo;
OSSectionInfo* sectionInfo;
u32 i;
u32 baseSection;
if (ptr == NULL) {
return NULL;
}
for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) {
sectionInfo = OSGetSectionInfo(moduleInfo);
for (i = 0; i < moduleInfo->numSections; ++i) {
if (sectionInfo->size) {
baseSection = OS_SECTIONINFO_OFFSET(sectionInfo->offset);
if (baseSection <= (u32)ptr && (u32)ptr < baseSection + sectionInfo->size) {
if (section) {
*section = i;
}
if (offset) {
*offset = (u32)ptr - baseSection;
}
return moduleInfo;
}
}
sectionInfo++;
}
}
return NULL;
}

223
src/Dolphin/os/OSMutex.c Normal file
View File

@ -0,0 +1,223 @@
#include "dolphin/os.h"
#define PushTail(queue, mutex, link) \
do { \
OSMutex* __prev; \
\
__prev = (queue)->tail; \
if (__prev == NULL) \
(queue)->head = (mutex); \
else \
__prev->link.next = (mutex); \
(mutex)->link.prev = __prev; \
(mutex)->link.next = NULL; \
(queue)->tail = (mutex); \
} while (0)
#define PopHead(queue, mutex, link) \
do { \
OSMutex* __next; \
\
(mutex) = (queue)->head; \
__next = (mutex)->link.next; \
if (__next == NULL) \
(queue)->tail = NULL; \
else \
__next->link.prev = NULL; \
(queue)->head = __next; \
} while (0)
#define PopItem(queue, mutex, link) \
do { \
OSMutex* __next; \
OSMutex* __prev; \
\
__next = (mutex)->link.next; \
__prev = (mutex)->link.prev; \
\
if (__next == NULL) \
(queue)->tail = __prev; \
else \
__next->link.prev = __prev; \
\
if (__prev == NULL) \
(queue)->head = __next; \
else \
__prev->link.next = __next; \
} while (0)
void OSInitMutex(OSMutex* mutex) {
OSInitThreadQueue(&mutex->queue);
mutex->thread = 0;
mutex->count = 0;
}
void OSLockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
OSThread* ownerThread;
while (TRUE) {
ownerThread = ((OSMutex*)mutex)->thread;
if (ownerThread == 0) {
mutex->thread = currentThread;
mutex->count++;
PushTail(&currentThread->queueMutex, mutex, link);
break;
} else if (ownerThread == currentThread) {
mutex->count++;
break;
} else {
currentThread->mutex = mutex;
__OSPromoteThread(mutex->thread, currentThread->priority);
OSSleepThread(&mutex->queue);
currentThread->mutex = 0;
}
}
OSRestoreInterrupts(enabled);
}
void OSUnlockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
if (mutex->thread == currentThread && --mutex->count == 0) {
PopItem(&currentThread->queueMutex, mutex, link);
mutex->thread = NULL;
if (currentThread->priority < currentThread->base) {
currentThread->priority = __OSGetEffectivePriority(currentThread);
}
OSWakeupThread(&mutex->queue);
}
OSRestoreInterrupts(enabled);
}
void __OSUnlockAllMutex(OSThread* thread) {
OSMutex* mutex;
while (thread->queueMutex.head) {
PopHead(&thread->queueMutex, mutex, link);
mutex->count = 0;
mutex->thread = NULL;
OSWakeupThread(&mutex->queue);
}
}
BOOL OSTryLockMutex(OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
BOOL locked;
if (mutex->thread == 0) {
mutex->thread = currentThread;
mutex->count++;
PushTail(&currentThread->queueMutex, mutex, link);
locked = TRUE;
} else if (mutex->thread == currentThread) {
mutex->count++;
locked = TRUE;
} else {
locked = FALSE;
}
OSRestoreInterrupts(enabled);
return locked;
}
void OSInitCond(OSCond* cond) { OSInitThreadQueue(&cond->queue); }
void OSWaitCond(OSCond* cond, OSMutex* mutex) {
BOOL enabled = OSDisableInterrupts();
OSThread* currentThread = OSGetCurrentThread();
s32 count;
if (mutex->thread == currentThread) {
count = mutex->count;
mutex->count = 0;
PopItem(&currentThread->queueMutex, mutex, link);
mutex->thread = NULL;
if (currentThread->priority < currentThread->base) {
currentThread->priority = __OSGetEffectivePriority(currentThread);
}
OSDisableScheduler();
OSWakeupThread(&mutex->queue);
OSEnableScheduler();
OSSleepThread(&cond->queue);
OSLockMutex(mutex);
mutex->count = count;
}
OSRestoreInterrupts(enabled);
}
void OSSignalCond(OSCond* cond) { OSWakeupThread(&cond->queue); }
static BOOL IsMember(OSMutexQueue* queue, OSMutex* mutex) {
OSMutex* member;
for (member = queue->head; member; member = member->link.next) {
if (mutex == member)
return TRUE;
}
return FALSE;
}
BOOL __OSCheckMutex(OSMutex* mutex) {
OSThread* thread;
OSThreadQueue* queue;
OSPriority priority = 0;
queue = &mutex->queue;
if (!(queue->head == NULL || queue->head->link.prev == NULL))
return FALSE;
if (!(queue->tail == NULL || queue->tail->link.next == NULL))
return FALSE;
for (thread = queue->head; thread; thread = thread->link.next) {
if (!(thread->link.next == NULL || thread == thread->link.next->link.prev))
return FALSE;
if (!(thread->link.prev == NULL || thread == thread->link.prev->link.next))
return FALSE;
if (thread->state != OS_THREAD_STATE_WAITING)
return FALSE;
if (thread->priority < priority)
return FALSE;
priority = thread->priority;
}
if (mutex->thread) {
if (mutex->count <= 0)
return FALSE;
} else {
if (0 != mutex->count)
return FALSE;
}
return TRUE;
}
BOOL __OSCheckDeadLock(OSThread* thread) {
OSMutex* mutex;
mutex = thread->mutex;
while (mutex && mutex->thread) {
if (mutex->thread == thread)
return TRUE;
mutex = mutex->thread->mutex;
}
return FALSE;
}
BOOL __OSCheckMutexes(OSThread* thread) {
OSMutex* mutex;
for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) {
if (mutex->thread != thread)
return FALSE;
if (!__OSCheckMutex(mutex))
return FALSE;
}
return TRUE;
}