}
// Check if it's a user mode fault
- if( Regs->eip < KERNEL_BASE || (Regs->cs & 3) == 3 ) {
+ if( (Regs->cs & 3) == 3 ) {
Log_Warning("Arch", "User Fault - %s, Code: 0x%x",
csaERROR_NAMES[Regs->int_num], Regs->err_code);
Log_Warning("Arch", "at CS:EIP %04x:%08x",
Debug_KernelPanic();
- LogF("CPU %i Error %i - %s, Code: 0x%x - At %08x",
+ LogF("CPU %i Error %i - %s, Code: 0x%x - At %08x\n",
GetCPUNum(),
Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code,
Regs->eip);
{
case 6: // #UD
Warning(" Offending bytes: %02x %02x %02x %02x",
- *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1,
- *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3);
+ *(Uint8*)(Regs->eip+0), *(Uint8*)(Regs->eip+1),
+ *(Uint8*)(Regs->eip+2), *(Uint8*)(Regs->eip+3));
break;
}
.parent:
ret
-; void Proc_ReturnToUser(void *Method, Uint Parameter)
+; void Proc_ReturnToUser(void *Method, Uint Parameter, tVAddr KernelStack)
; Calls a user fault handler
;
[global Proc_ReturnToUser]
; [EBP+12]: parameter
; [EBP+16]: kernel stack top
- ;call Proc_GetCurThread
-
- ; EAX is the current thread
- ;mov ebx, eax
- ;mov eax, [ebx+12*4] ; Get Kernel Stack
- mov eax, [ebp+16] ; Get Kernel Stack
+ ; Get kernel stack
+ mov eax, [ebp+16]
sub eax, KSTACK_USERSTATE_SIZE
;
[global GetCPUNum]
GetCPUNum: ; TODO: Store in debug registers
-; xor eax, eax
-; str ax
-; sub ax, 0x30
-; shr ax, 3 ; ax /= 8
mov eax, dr1
ret
extern int giNumCPUs;
extern int giNextTID;
extern tThread gThreadZero;
+extern tProcess gProcessZero;
extern void Isr8(void); // Double Fault
extern void Proc_ReturnToUser(tVAddr Handler, Uint Argument, tVAddr KernelStack);
extern char scheduler_return[]; // Return address in SchedulerBase
gaCPUs[0].Current = &gThreadZero;
gThreadZero.CurCPU = 0;
- gThreadZero.MemState.CR3 = (Uint)gaInitPageDir - KERNEL_BASE;
+ gProcessZero.MemState.CR3 = (Uint)gaInitPageDir - KERNEL_BASE;
// Create Per-Process Data Block
if( !MM_Allocate(MM_PPD_CFG) )
__asm__ __volatile__ ("mov %0, %%ebp"::"r"(ebp));
}
+void Proc_ClearProcess(tProcess *Process)
+{
+ MM_ClearSpace(Process->MemState.CR3);
+}
+
void Proc_ClearThread(tThread *Thread)
{
- MM_ClearSpace(Thread->MemState.CR3);
if(Thread->SavedState.SSE) {
free(Thread->SavedState.SSE);
Thread->SavedState.SSE = NULL;
}
}
-int Proc_NewKThread(void (*Fcn)(void*), void *Data)
+tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
{
Uint esp;
tThread *newThread, *cur;
newThread = Threads_CloneTCB(0);
if(!newThread) return -1;
- // Set CR3
- MM_RefPhys( cur->MemState.CR3 );
- newThread->MemState.CR3 = cur->MemState.CR3;
-
// Create new KStack
newThread->KernelStack = MM_NewKStack();
// Check for errors
* \fn int Proc_Clone(Uint *Err, Uint Flags)
* \brief Clone the current process
*/
-int Proc_Clone(Uint Flags)
+tPID Proc_Clone(Uint Flags)
{
tThread *newThread;
tThread *cur = Proc_GetCurThread();
newThread->KernelStack = cur->KernelStack;
// Clone state
- eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->MemState.CR3);
+ eip = Proc_CloneInt(&newThread->SavedState.ESP, &newThread->Process->MemState.CR3);
if( eip == 0 ) {
// ACK the interrupt
return 0;
newThread->SavedState.bSSEModified = 0;
// Check for errors
- if( newThread->MemState.CR3 == 0 ) {
+ if( newThread->Process->MemState.CR3 == 0 ) {
Log_Error("Proc", "Proc_Clone: MM_Clone failed");
Threads_Delete(newThread);
return -1;
LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n",
GetCPUNum(),
nextthread, nextthread->TID, nextthread->ThreadName,
- nextthread->MemState.CR3,
+ nextthread->Process->MemState.CR3,
nextthread->SavedState.EIP,
nextthread->SavedState.ESP
);
+ LogF("OldCR3 = %P\n", curthread->Process->MemState.CR3);
}
#endif
SwitchTasks(
nextthread->SavedState.ESP, &curthread->SavedState.ESP,
nextthread->SavedState.EIP, &curthread->SavedState.EIP,
- nextthread->MemState.CR3
+ nextthread->Process->MemState.CR3
);
}
else
SwitchTasks(
nextthread->SavedState.ESP, 0,
nextthread->SavedState.EIP, 0,
- nextthread->MemState.CR3
+ nextthread->Process->MemState.CR3
);
}
&& Threads_GetPID() == gVM8086_WorkerPID)
{
if( gpVM8086_State == (void*)-1 ) {
-// Log_Log("VM8086", "Worker thread ready and waiting");
+ Log_Log("VM8086", "Worker thread ready and waiting");
gpVM8086_State = NULL;
Mutex_Release( &glVM8086_Process ); // Release lock obtained in VM8086_Install
}
#include "errno.h"
// --- Types ---
-typedef int tPID; //!< Process ID type
-typedef int tTID; //!< Thread ID Type
-typedef Uint tUID; //!< User ID Type
-typedef Uint tGID; //!< Group ID Type
+typedef Uint32 tPID; //!< Process ID type
+typedef Uint32 tTID; //!< Thread ID Type
+typedef Uint32 tUID; //!< User ID Type
+typedef Uint32 tGID; //!< Group ID Type
typedef Sint64 tTimestamp; //!< Timestamp (miliseconds since 00:00 1 Jan 1970)
typedef Sint64 tTime; //!< Same again
typedef struct sShortSpinlock tShortSpinlock; //!< Opaque (kinda) spinlock
* \}
*/
-/**
- * \name Per-Thread Configuration Settings
- * \{
- */
-enum eConfigTypes {
- CFGT_NULL,
- CFGT_INT,
- CFGT_HEAPSTR,
- CFGT_PTR
-};
-enum eConfigs {
- CFG_VFS_CWD,
- CFG_VFS_MAXFILES,
- CFG_VFS_CHROOT,
- CFG_ERRNO,
- NUM_CFG_ENTRIES
-};
-#define CFGINT(id) (*Threads_GetCfgPtr(id))
-#define CFGPTR(id) (*(void**)Threads_GetCfgPtr(id))
-
-#define errno (CFGINT(CFG_ERRNO))
-/**
- * \}
- */
+//! \brief Error number
+#define errno (*Threads_GetErrno())
// === CONSTANTS ===
// --- Memory Flags --
// --- IO ---
#if NO_IO_BUS
-#define inb(a) (Log_Panic("Arch", "ARMv7 does not support in*/out* (%s:%i)", __FILE__, __LINE__),0)
+#define inb(a) (Log_Panic("Arch", STR(ARCHDIR)" does not support in*/out* (%s:%i)", __FILE__, __LINE__),0)
#define inw(a) inb(a)
#define ind(a) inb(a)
#define inq(a) inb(a)
extern tUID Threads_GetUID(void);
extern tGID Threads_GetGID(void);
extern int SpawnTask(tThreadFunction Function, void *Arg);
-extern Uint *Threads_GetCfgPtr(int Id);
+extern int *Threads_GetErrno(void);
extern int Threads_SetName(const char *NewName);
/**
* \}
* \brief Called just before a thread is freed
*/
extern void Proc_ClearThread(tThread *Thread);
+/**
+ * \brief Called just before a process is freed
+ */
+extern void Proc_ClearProcess(tProcess *Process);
/**
* \brief Get the ID of this CPU
* \return Zero based CPU ID
// === FUNCTIONS ===
extern void Threads_SetFaultHandler(Uint Handler);
-extern int Threads_SetUID(Uint *Errno, tUID ID);
-extern int Threads_SetGID(Uint *Errno, tUID ID);
-extern int Threads_WaitTID(int TID, int *Status);
+extern int Threads_SetUID(tUID ID);
+extern int Threads_SetGID(tUID ID);
+extern tTID Threads_WaitTID(int TID, int *Status);
-extern int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data);
-extern int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer);
+
+extern int *Threads_GetMaxFD(void);
+extern char **Threads_GetCWD(void);
+extern char **Threads_GetChroot(void);
+
+extern int Proc_SendMessage(Uint Dest, int Length, void *Data);
+extern int Proc_GetMessage(Uint *Source, void *Buffer);
#endif
#include <threads.h>
#include <proc.h>
+
+typedef struct sProcess tProcess;
+
/**
* \brief IPC Message
*/
Uint8 Data[]; //!< Message data
} tMsg;
+/**
+ * \brief Process state
+ */
+struct sProcess
+{
+ tPID PID;
+ int nThreads;
+
+ tUID UID; //!< User ID
+ tGID GID; //!< User and Group
+ tMemoryState MemState;
+
+ int MaxFD;
+ char *CurrentWorkingDir;
+ char *RootDir;
+};
+
/**
* \brief Core threading structure
*
void *WaitPointer; //!< What (Mutex/Thread/other) is the thread waiting on
int RetStatus; //!< Return Status
- Uint TID; //!< Thread ID
- Uint TGID; //!< Thread Group (Process)
+ tTID TID; //!< Thread ID
+ struct sProcess *Process; //!< Thread Group / Process
struct sThread *Parent; //!< Parent Thread
- Uint UID, GID; //!< User and Group
char *ThreadName; //!< Name of thread
// --- arch/proc.c's responsibility
//! Kernel Stack Base
tVAddr KernelStack;
- //! Memory Manager State
- tMemoryState MemState;
-
//! State on task switch
tTaskState SavedState;
int Quantum, Remaining; //!< Quantum Size and remaining timesteps
int Priority; //!< Priority - 0: Realtime, higher means less time
- Uint Config[NUM_CFG_ENTRIES]; //!< Per-process configuration
+ int _errno;
volatile int CurCPU;
- int bInstrTrace;
+ bool bInstrTrace;
// --- event.c
Uint32 EventState;
// === CODE ===
/**
- * \fn int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
+ * \fn int Proc_SendMessage(Uint Dest, int Length, void *Data)
* \brief Send an IPC message
- * \param Err Pointer to the errno variable
* \param Dest Destination Thread
* \param Length Length of the message
* \param Data Message data
*/
-int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
+int Proc_SendMessage(Uint Dest, int Length, void *Data)
{
tThread *thread;
tMsg *msg;
ENTER("pErr iDest iLength pData", Err, Dest, Length, Data);
if(Length <= 0 || !Data) {
- *Err = -EINVAL;
+ errno = -EINVAL;
LEAVE_RET('i', -1);
}
}
/**
- * \fn int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
+ * \fn int Proc_GetMessage(Uint *Source, void *Buffer)
* \brief Gets a message
- * \param Err Pointer to \a errno
* \param Source Where to put the source TID
* \param Buffer Buffer to place the message data (set to NULL to just get message length)
* \return Message length
*/
-int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer)
+int Proc_GetMessage(Uint *Source, void *Buffer)
{
int ret;
void *tmp;
if( !CheckMem( Buffer, cur->Messages->Length ) )
{
LOG("Invalid buffer");
- *Err = -EINVAL;
+ errno = -EINVAL;
SHORTREL( &cur->IsLocked );
LEAVE('i', -1);
return -1;
case SYS_GETGID: ret = Threads_GetGID(); break;
// -- Set User/Group IDs
- case SYS_SETUID: ret = Threads_SetUID(&err, Regs->Arg1); break;
- case SYS_SETGID: ret = Threads_SetGID(&err, Regs->Arg1); break;
+ case SYS_SETUID: ret = Threads_SetUID(Regs->Arg1); break;
+ case SYS_SETGID: ret = Threads_SetGID(Regs->Arg1); break;
// -- Send Message
case SYS_SENDMSG:
CHECK_NUM_NONULL( (void*)Regs->Arg3, Regs->Arg2 );
// Destination, Size, *Data
- ret = Proc_SendMessage(&err, Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
+ ret = Proc_SendMessage(Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
break;
// -- Check for messages
case SYS_GETMSG:
err = -EINVAL; ret = -1; break;
}
// *Source, *Data
- ret = Proc_GetMessage(&err, (Uint*)Regs->Arg1, (void*)Regs->Arg2);
+ ret = Proc_GetMessage((Uint*)Regs->Arg1, (void*)Regs->Arg2);
break;
// -- Get the current timestamp
#define DEFAULT_QUANTUM 5
#define DEFAULT_PRIORITY 5
#define MIN_PRIORITY 10
-const enum eConfigTypes cCONFIG_TYPES[NUM_CFG_ENTRIES] = {
- CFGT_HEAPSTR, // e.g. CFG_VFS_CWD
- CFGT_INT, // e.g. CFG_VFS_MAXFILES
- CFGT_NULL
-};
// === IMPORTS ===
void Threads_Delete(tThread *Thread);
int Threads_SetName(const char *NewName);
#endif
-char *Threads_GetName(int ID);
+char *Threads_GetName(tTID ID);
#if 0
void Threads_SetPriority(tThread *Thread, int Pri);
tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
// === GLOBALS ===
// -- Core Thread --
+struct sProcess gProcessZero = {
+ };
// Only used for the core kernel
tThread gThreadZero = {
.Status = THREAD_STAT_ACTIVE, // Status
gAllThreads = &gThreadZero;
giNumActiveThreads = 1;
+ gThreadZero.Process = &gProcessZero;
Proc_Start();
}
// Clear out process state
Proc_ClearThread(Thread);
+
+ Thread->Process->nThreads --;
+ if( Thread->Process->nThreads == 0 )
+ {
+ Proc_ClearProcess( Thread->Process );
+ free( Thread->Process->CurrentWorkingDir );
+ free( Thread->Process->RootDir );
+ free( Thread->Process );
+ }
// Free name
if( IsHeap(Thread->ThreadName) )
cur->ThreadName = NULL;
- if( IsHeap(oldname) ) free( oldname );
-
+ if( IsHeap(oldname) ) free( oldname );
cur->ThreadName = strdup(NewName);
+
+ Log_Debug("Threads", "Thread renamed to '%s'", NewName);
+
return 0;
}
tThread *Threads_CloneTCB(Uint Flags)
{
tThread *cur, *new;
- int i;
cur = Proc_GetCurThread();
// Allocate and duplicate
new->ThreadName = strdup(cur->ThreadName);
// Set Thread Group ID (PID)
- if(Flags & CLONE_VM)
- new->TGID = new->TID;
- else
- new->TGID = cur->TGID;
+ if(Flags & CLONE_VM) {
+ tProcess *newproc, *oldproc;
+ oldproc = cur->Process;
+ new->Process = malloc( sizeof(struct sProcess) );
+ newproc = new->Process;
+ newproc->PID = new->TID;
+ newproc->UID = oldproc->UID;
+ newproc->GID = oldproc->GID;
+ newproc->MaxFD = oldproc->MaxFD;
+ if( oldproc->CurrentWorkingDir )
+ newproc->CurrentWorkingDir = strdup( oldproc->CurrentWorkingDir );
+ else
+ newproc->CurrentWorkingDir = NULL;
+ if( oldproc->RootDir )
+ newproc->RootDir = strdup( oldproc->RootDir );
+ else
+ newproc->RootDir = NULL;
+ newproc->nThreads = 1;
+ }
+ else {
+ new->Process->nThreads ++;
+ }
// Messages are not inherited
new->Messages = NULL;
// Set State
new->Remaining = new->Quantum = cur->Quantum;
new->Priority = cur->Priority;
+ new->_errno = 0;
// Set Signal Handlers
new->CurFaultNum = 0;
new->FaultHandler = cur->FaultHandler;
- for( i = 0; i < NUM_CFG_ENTRIES; i ++ )
- {
- switch(cCONFIG_TYPES[i])
- {
- default:
- new->Config[i] = cur->Config[i];
- break;
- case CFGT_HEAPSTR:
- if(cur->Config[i])
- new->Config[i] = (Uint) strdup( (void*)cur->Config[i] );
- else
- new->Config[i] = 0;
- break;
- }
- }
-
// Maintain a global list of threads
SHORTLOCK( &glThreadListLock );
new->GlobalPrev = NULL; // Protect against bugs
tThread *Threads_CloneThreadZero(void)
{
tThread *new;
- int i;
// Allocate and duplicate
new = malloc(sizeof(tThread));
return NULL;
}
memcpy(new, &gThreadZero, sizeof(tThread));
+
+ new->Process->nThreads ++;
new->CurCPU = -1;
new->Next = NULL;
new->CurFaultNum = 0;
new->FaultHandler = 0;
- for( i = 0; i < NUM_CFG_ENTRIES; i ++ )
- {
- new->Config[i] = 0;
- }
-
// Maintain a global list of threads
SHORTLOCK( &glThreadListLock );
new->GlobalPrev = NULL; // Protect against bugs
return new;
}
-/**
- * \brief Get a configuration pointer from the Per-Thread data area
- * \param ID Config slot ID
- * \return Pointer at ID
- */
-Uint *Threads_GetCfgPtr(int ID)
-{
- if(ID < 0 || ID >= NUM_CFG_ENTRIES) {
- Warning("Threads_GetCfgPtr: Index %i is out of bounds", ID);
- return NULL;
- }
-
- return &Proc_GetCurThread()->Config[ID];
-}
-
/**
* \brief Wait for a task to change state
* \param TID Thread ID to wait on (-1: Any child thread, 0: Any Child/Sibling, <-1: -PID)
// --- Process Structure Access Functions ---
tPID Threads_GetPID(void)
{
- return Proc_GetCurThread()->TGID;
+ return Proc_GetCurThread()->Process->PID;
}
tTID Threads_GetTID(void)
{
}
tUID Threads_GetUID(void)
{
- return Proc_GetCurThread()->UID;
+ return Proc_GetCurThread()->Process->UID;
}
tGID Threads_GetGID(void)
{
- return Proc_GetCurThread()->GID;
+ return Proc_GetCurThread()->Process->GID;
}
-int Threads_SetUID(Uint *Errno, tUID ID)
+int Threads_SetUID(tUID ID)
{
tThread *t = Proc_GetCurThread();
- if( t->UID != 0 ) {
- *Errno = -EACCES;
+ if( t->Process->UID != 0 ) {
+ errno = -EACCES;
return -1;
}
- Log_Debug("Threads", "TID %i's UID set to %i", t->TID, ID);
- t->UID = ID;
+ Log_Debug("Threads", "PID %i's UID set to %i", t->Process->PID, ID);
+ t->Process->UID = ID;
return 0;
}
-int Threads_SetGID(Uint *Errno, tGID ID)
+int Threads_SetGID(tGID ID)
{
tThread *t = Proc_GetCurThread();
- if( t->UID != 0 ) {
- *Errno = -EACCES;
+ if( t->Process->UID != 0 ) {
+ errno = -EACCES;
return -1;
}
- Log_Debug("Threads", "TID %i's GID set to %i", t->TID, ID);
- t->GID = ID;
+ Log_Debug("Threads", "PID %i's GID set to %i", t->Process->PID, ID);
+ t->Process->GID = ID;
return 0;
}
+// --- Per-thread storage ---
+int *Threads_GetErrno(void)
+{
+ return &Proc_GetCurThread()->_errno;
+}
+
+// --- Configuration ---
+int *Threads_GetMaxFD(void)
+{
+ return &Proc_GetCurThread()->Process->MaxFD;
+}
+char **Threads_GetChroot(void)
+{
+ return &Proc_GetCurThread()->Process->RootDir;
+}
+char **Threads_GetCWD(void)
+{
+ return &Proc_GetCurThread()->Process->CurrentWorkingDir;
+}
+// ---
+
/**
* \fn void Threads_Dump(void)
*/
for(thread=list->Head;thread;thread=thread->Next)
{
Log(" %p %i (%i) - %s (CPU %i)",
- thread, thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU);
+ thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU);
if(thread->Status != THREAD_STAT_ACTIVE)
Log(" ERROR State (%i) != THREAD_STAT_ACTIVE (%i)",
thread->Status, THREAD_STAT_ACTIVE);
for(thread=gAllThreads;thread;thread=thread->GlobalNext)
{
Log(" %p %i (%i) - %s (CPU %i)",
- thread, thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU);
+ thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU);
Log(" State %i (%s)", thread->Status, casTHREAD_STAT[thread->Status]);
switch(thread->Status)
{
#include "vfs.h"
#include "vfs_int.h"
#include "vfs_ext.h"
+#include <threads.h> // GetMaxFD
// === CONSTANTS ===
#define MAX_KERNEL_FILES 128
if(FD >= MAX_KERNEL_FILES) return NULL;
h = &gaKernelHandles[ FD ];
} else {
- if(FD >= CFGINT(CFG_VFS_MAXFILES)) return NULL;
+ if(FD >= *Threads_GetMaxFD()) return NULL;
h = &gaUserHandles[ FD ];
}
// Check for a user open
if(bIsUser)
{
+ int max_handles = *Threads_GetMaxFD();
// Allocate Buffer
- if( MM_GetPhysAddr( (Uint)gaUserHandles ) == 0 )
+ if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 )
{
Uint addr, size;
- size = CFGINT(CFG_VFS_MAXFILES) * sizeof(tVFS_Handle);
+ size = max_handles * sizeof(tVFS_Handle);
for(addr = 0; addr < size; addr += 0x1000)
{
- if( !MM_Allocate( (Uint)gaUserHandles + addr ) )
+ if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) )
{
Warning("OOM - VFS_AllocHandle");
Threads_Exit(0, 0xFF); // Terminate user
memset( gaUserHandles, 0, size );
}
// Get a handle
- for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
+ for( i = 0; i < max_handles; i ++ )
{
if(gaUserHandles[i].Node) continue;
gaUserHandles[i].Node = Node;
else
{
// Allocate space if not already
- if( MM_GetPhysAddr( (Uint)gaKernelHandles ) == 0 )
+ if( MM_GetPhysAddr( (tVAddr)gaKernelHandles ) == 0 )
{
Uint addr, size;
size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
for(addr = 0; addr < size; addr += 0x1000)
{
- if( !MM_Allocate( (Uint)gaKernelHandles + addr ) )
+ if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) )
{
Panic("OOM - VFS_AllocHandle");
Threads_Exit(0, 0xFF); // Terminate application (get some space back)
*/
#include <acess.h>
#include <fs_sysfs.h>
-#include "vfs.h"
-#include "vfs_int.h"
-#include "vfs_ext.h"
+#include <threads.h>
+#include <vfs.h>
+#include <vfs_int.h>
+#include <vfs_ext.h>
// === IMPORTS ===
extern tVFS_Driver gRootFS_Info;
VFS_Mount("dev", "/Devices", "devfs", "");
Log_Debug("VFS", "Setting max files");
- CFGINT(CFG_VFS_MAXFILES) = 32;
+ *Threads_GetMaxFD() = 32;
return 0;
}
#include "vfs.h"
#include "vfs_int.h"
#include "vfs_ext.h"
+#include <threads.h>
// === CONSTANTS ===
#define OPEN_MOUNT_ROOT 1
char *tmpStr;
int iPos = 0;
int iPos2 = 0;
- const char *chroot = CFGPTR(CFG_VFS_CHROOT);
+ const char *chroot = *Threads_GetChroot();
int chrootLen;
- const char *cwd = CFGPTR(CFG_VFS_CWD);
+ const char *cwd = *Threads_GetCWD();
int cwdLen;
ENTER("sPath", Path);
// Close file
VFS_Close(fd);
- // Free old working directory
- if( CFGPTR(CFG_VFS_CWD) )
- free( CFGPTR(CFG_VFS_CWD) );
- // Set new
- CFGPTR(CFG_VFS_CWD) = buf;
+ {
+ char **cwdptr = Threads_GetCWD();
+ // Free old working directory
+ if( *cwdptr ) free( *cwdptr );
+ // Set new
+ *cwdptr = buf;
+ }
Log("Updated CWD to '%s'", buf);
// Close file
VFS_Close(fd);
-
- // Free old working directory
- if( CFGPTR(CFG_VFS_CHROOT) )
- free( CFGPTR(CFG_VFS_CHROOT) );
- // Set new
- CFGPTR(CFG_VFS_CHROOT) = buf;
+
+ // Update
+ {
+ char **chroot_ptr = Threads_GetChroot();
+ if( *chroot_ptr ) free( *chroot_ptr );
+ *chroot_ptr = buf;
+ }
LOG("Updated Root to '%s'", buf);