--- /dev/null
+
+all:
+ @$(MAKE) -C acesskernel_src
+ @$(MAKE) -C ld-acess_src
#!/bin/sh
trap '' 2
-./AcessKernel --rootapp /Acess/SBin/login
+$1 ./AcessKernel --rootapp /Acess/SBin/login
trap 2
killall ld-acess
BUILDINFO_OBJ := obj-$(PLATFORM)/buildinfo.o\r
BUILDINFO_SRC := $(BUILDINFO_OBJ:%.o=%.c)\r
\r
-OBJ := helpers.o threads.o server.o syscalls.o\r
+OBJ := helpers.o threads.o server.o syscalls.o time.o\r
OBJ += video.o keyboard.o mouse.o nativefs.o vfs_handle.o ui_sdl.o\r
OBJ := $(addprefix obj-$(PLATFORM)/,$(OBJ))\r
N_OBJ := $(addprefix obj-$(PLATFORM)/,$(N_OBJ))\r
//#define NUM_CFG_ENTRIES 10
+extern void Debug_PutCharDebug(char ch);
+extern void Debug_PutStringDebug(const char *str);
+
#endif
--- /dev/null
+#ifndef _THREADS_INT_H_
+#define _THREADS_INT_H_
+
+/**
+ * \brief IPC Message
+ */
+typedef struct sMessage
+{
+ struct sMessage *Next; //!< Next message in thread's inbox
+ tTID Source; //!< Source thread ID
+ Uint Length; //!< Length of message data in bytes
+ Uint8 Data[]; //!< Message data
+} tMsg;
+
+typedef struct sProcess
+{
+ int nThreads;
+ int NativePID;
+ char *CWD;
+ char *Chroot;
+ int MaxFD;
+} tProcess;
+
+struct sThread
+{
+ struct sThread *GlobalNext;
+ struct sThread *Next;
+
+ int KernelTID;
+
+ tTID TID, PID;
+ tUID UID, GID;
+
+ struct sThread *Parent;
+
+ char *ThreadName;
+
+ int Status; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
+ int ExitStatus;
+ int _errno;
+
+ // Threads waiting for this thread to exit.
+ // Quit logic:
+ // - Wait for `WaitingThreads` to be non-null (maybe?)
+ // - Wake first in the queue, wait for it to be removed
+ // - Repeat
+ // - Free thread and quit kernel thread
+ struct sThread *WaitingThreads;
+ struct sThread *WaitingThreadsEnd;
+
+ tProcess *Process;
+
+ Uint32 Events, WaitMask;
+ void *EventSem; // Should be SDL_sem, but I don't want SDL in this header
+
+ // Message queue
+ tMsg * volatile Messages; //!< Message Queue
+ tMsg *LastMessage; //!< Last Message (speeds up insertion)
+};
+
+enum {
+ THREAD_STAT_NULL, // Invalid process
+ THREAD_STAT_ACTIVE, // Running and schedulable process
+ THREAD_STAT_SLEEPING, // Message Sleep
+ THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
+ THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
+ THREAD_STAT_QUEUESLEEP, // Queue
+ THREAD_STAT_EVENTSLEEP, // Event sleep
+ THREAD_STAT_WAITING, // ??? (Waiting for a thread)
+ THREAD_STAT_PREINIT, // Being created
+ THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
+ THREAD_STAT_DEAD, // Awaiting burial (free)
+ THREAD_STAT_BURIED // If it's still on the list here, something's wrong
+};
+extern tThread *Threads_GetThread(Uint TID);
+
+#endif
+
while( Client->CurrentRequest == NULL )
SDL_CondWait(Client->WaitFlag, Client->Mutex);
+ Log_Debug("AcessSrv", "Worker got message %p", Client->CurrentRequest);
+
if(Client->ClientID != cur_client_id) {
Threads_SetThread( Client->ClientID );
cur_client_id = Client->ClientID;
}
- // Get the response
- retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
-
+ // Debug
{
int callid = Client->CurrentRequest->CallID;
Log_Debug("AcessSrv", "Client %i request %i %s",
);
}
-
+ // Get the response
+ retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
+
if( !retHeader ) {
// Return an error to the client
printf("ERROR: SyscallRecieve failed\n");
return Proc_SendMessage(a0, Sizes[1], a1);
);
-SYSCALL2(Syscall_GetMessage, "dd", Uint *, void *,
- if( Sizes[0] < sizeof(*a0) )
+SYSCALL2(Syscall_GetMessage, "dd", uint32_t *, void *,
+ if( a0 && Sizes[0] < sizeof(*a0) ) {
+ Log_Notice("Syscalls", "Syscall_GetMessage - Arg 1 Undersize (%i < %i)",
+ Sizes[0], sizeof(*a0));
return -1;
- return Proc_GetMessage(a0, a1);
+ }
+ Uint tmp;
+ int rv;
+ if( a0 ) {
+ rv = Proc_GetMessage(&tmp, a1);
+ *a0 = tmp;
+ }
+ else
+ rv = Proc_GetMessage(NULL, a1);
+ return rv;
);
SYSCALL1(Syscall_WaitEvent, "i", int,
}
formatString[i] = '\0';
- //LOG("Request %i(%s) '%s'", Request->CallID, casSYSCALL_NAMES[Request->CallID], formatString);
+ LOG("Request %i(%s) '%s'", Request->CallID, casSYSCALL_NAMES[Request->CallID], formatString);
{
char argListData[argListLen];
}
// Check for non-resident data
- if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
+ if( Request->Params[i].Length == 0 )
+ {
+ returnData[i] = NULL;
+ *(void**)&argListData[argListLen] = NULL;
+ argListLen += sizeof(void*);
+ }
+ else if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
{
// Allocate and zero the buffer
returnData[i] = calloc(1, Request->Params[i].Length);
#include <mutex.h>
#include <semaphore.h>
#include <events.h>
+#include <threads_int.h>
#undef CLONE_VM // Such a hack
#undef off_t
} tState;
#endif
-typedef struct sProcess
-{
- int nThreads;
- int NativePID;
- char *CWD;
- char *Chroot;
- int MaxFD;
-} tProcess;
-
-struct sThread
-{
- struct sThread *GlobalNext;
- struct sThread *Next;
-
- int KernelTID;
-
- tTID TID, PID;
- tUID UID, GID;
-
- struct sThread *Parent;
-
- char *ThreadName;
-
- int State; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
- int ExitStatus;
- int _errno;
-
- // Threads waiting for this thread to exit.
- // Quit logic:
- // - Wait for `WaitingThreads` to be non-null (maybe?)
- // - Wake first in the queue, wait for it to be removed
- // - Repeat
- // - Free thread and quit kernel thread
- struct sThread *WaitingThreads;
- struct sThread *WaitingThreadsEnd;
-
- tProcess *Process;
-
- Uint32 Events, WaitMask;
- SDL_sem *EventSem;
-
-};
-
// === PROTOTYPES ===
int Threads_Wake(tThread *Thread);
.MaxFD = 100
};
tThread gThreadZero = {
- .State=1,
+ .Status=THREAD_STAT_ACTIVE,
.ThreadName="ThreadZero",
.Process = &gProcessZero
};
Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
}
-tThread *Threads_GetThread(int TID)
+tThread *Threads_GetThread(Uint TID)
{
tThread *thread;
+ Log_Debug("Threads", "Looking for TID %i", TID);
for( thread = gpThreads; thread; thread = thread->GlobalNext )
{
- if( thread->TID == TID )
+ if( thread->TID == TID ) {
+ Log_Debug("Threads", "Found %p", thread);
+ Log_Debug("Threads", "- Name = %s", thread->ThreadName);
return thread;
+ }
}
return NULL;
}
if(!thread) return -1;
us->Next = NULL;
- us->State = 3;
+ us->Status = THREAD_STAT_WAITING;
// TODO: Locking
if(thread->WaitingThreadsEnd)
{
int Threads_Wake(tThread *Thread)
{
- Thread->State = 0;
+ Thread->Status = THREAD_STAT_ACTIVE;
Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
return 0;
}
return thread->PID;
}
+// --------------------------------------------------------------------
+// Mutexes
+// --------------------------------------------------------------------
int Mutex_Acquire(tMutex *Mutex)
{
if(!Mutex->Protector.IsValid) {
pthread_mutex_unlock( &Mutex->Protector.Mutex );
}
+// --------------------------------------------------------------------
+// Semaphores
+// --------------------------------------------------------------------
void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
{
memset(Sem, 0, sizeof(tSemaphore));
return AmmountToAdd;
}
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
Uint32 Threads_WaitEvents(Uint32 Mask)
{
Uint32 rv;
}
}
+void Threads_ClearEvent(Uint32 EventMask)
+{
+ gpCurrentThread->Events &= ~EventMask;
+}
+
--- /dev/null
+/*
+ * Acess2 Native Kernel
+ * - Acess kernel emulation on another OS using SDL and UDP
+ *
+ * time.c
+ * - Timer code
+ */
+#include <acess.h>
+#include <timers.h>
+
+struct sTimer {
+ tTimer *Next;
+ Sint64 FiresAfter;
+ void (*Callback)(void*);
+ void *Argument;
+ BOOL bActive;
+};
+
+// === CODE ===
+tTimer *Time_CreateTimer(int Delta, tTimerCallback *Callback, void *Argument)
+{
+ return NULL;
+}
+
+tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument)
+{
+ return NULL;
+}
+
+void Time_FreeTimer(tTimer *Timer)
+{
+}
+
+void Time_ScheduleTimer(tTimer *Timer, int Delta)
+{
+}
+
+void Time_RemoveTimer(tTimer *Timer)
+{
+}
extern int ElfGetSymbol(void *Base, char *Name, uintptr_t *ret, size_t *size);
extern int ciNumBuiltinSymbols;
extern tSym caBuiltinSymbols[];
+extern char **gEnvP;
// === PROTOTYPES ===
void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format);
#if DEBUG
printf("Calling '%s' entry point %p\n", Name, entry);
#endif
- entry(ret, 0, argv, NULL);
+ entry(ret, 0, argv, gEnvP);
}
return ret;
\r
ENTER("iFD", FD);\r
\r
- #if BITS <= 32\r
- Warning("ELF64 being loaded in 32-bit env, this may not work");\r
- #endif\r
+ if( sizeof(void*) == 4) {\r
+ Warning("ELF64 being loaded in 32-bit env, this may not work");\r
+ }\r
\r
// Check for a program header\r
if(hdr->e_phoff == 0) {\r
* - Exported functions
*/
#define DONT_INCLUDE_SYSCALL_NAMES 1
-#include "../../Usermode/include/acess/sys.h"
+#include "../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h"
#include "../syscalls.h"
#include "exports.h"
#include <stdarg.h>
size_t acess_read(int FD, void *Dest, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_read(FD & (NATIVE_FILE_MASK-1), Dest, Bytes);
- DEBUG("read(0x%x, 0x%x, *%p)", FD, Bytes, Dest);
+ if( FD > 2 )
+ DEBUG("read(0x%x, 0x%x, *%p)", FD, Bytes, Dest);
return _Syscall(SYS_READ, ">i >i <d", FD, Bytes, Bytes, Dest);
}
size_t acess_write(int FD, const void *Src, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_write(FD & (NATIVE_FILE_MASK-1), Src, Bytes);
- DEBUG("write(0x%x, 0x%x, %p\"%.*s\")", FD, Bytes, Src, Bytes, (char*)Src);
+ if( FD > 2 )
+ DEBUG("write(0x%x, 0x%x, %p\"%.*s\")", FD, Bytes, Src, Bytes, (char*)Src);
return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
}
int acess_ioctl(int fd, int id, void *data) {
int len;
- // NOTE: 1024 byte size is a hack
DEBUG("ioctl(%i, %i, %p)", fd, id, data);
+ // NOTE: The length here is hacky and could break
if( data == NULL )
len = 0;
else
int lastlen;
lastlen = _Syscall(SYS_GETMSG, "<d <d",
- SourceTID ? sizeof(int) : 0, SourceTID,
+ SourceTID ? sizeof(uint32_t) : 0, SourceTID,
Data ? 1024 : 0, Data
);
return lastlen;
// === PROTOTYPES ===
void CallUser(void *Entry, int argc, char *argv[], char **envp) __attribute__((noreturn));
+// === GLOBALS ===
+char **gEnvP;
+
// === CODE ===
int main(int argc, char *argv[], char **envp)
{
int (*appMain)(int, char *[], char **);
void *base;
int rv;
+
+ gEnvP = envp;
Request_Preinit();