# structs, classes, and unions are shown on a separate page (for HTML and Man
# pages) or section (for LaTeX and RTF).
-INLINE_SIMPLE_STRUCTS = NO
+#INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
# of the bibliography can be controlled using LATEX_BIB_STYLE.
-CITE_BIB_FILES =
+#CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
# with spaces.
INPUT = include/apidoc_mainpage.h \
+ include/acess.h \
+ include/hal_proc.h \
include/binary.h \
include/modules.h \
include/vfs.h \
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
# names that should be enabled during MathJax rendering.
-MATHJAX_EXTENSIONS =
+#MATHJAX_EXTENSIONS =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
# http://en.wikipedia.org/wiki/BibTeX for more info.
-LATEX_BIB_STYLE = plain
+#LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# configuration options related to the RTF output
# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
# visible. Older versions of IE do not have SVG support.
-INTERACTIVE_SVG = NO
+#INTERACTIVE_SVG = NO
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
if( MM_int_GetPageInfo(ret, &pi) == 0 )
continue;
-// Log("MapTemp %P at %p", PAddr, ret);
+ Log("MapTemp %P at %p by %p", PAddr, ret, __builtin_return_address(0));
MM_RefPhys(PAddr); // Counter the MM_Deallocate in FreeTemp
MM_Map(ret, PAddr);
range_start = Start;
for( addr = Start; i == 0 || (addr && addr < End); i = 1 )
{
+ int rv;
// Log("addr = %p", addr);
- int rv = MM_int_GetPageInfo(addr, &pi);
+ rv = MM_int_GetPageInfo(addr, &pi);
if( rv
|| pi.Size != pi_old.Size
|| pi.Domain != pi_old.Domain
Proc_CloneInt_new:
@ cps #18
- mov r0, #0
- mvn r1, #0
- bl MM_DumpTables
+@ mov r0, #0
+@ mvn r1, #0
+@ bl MM_DumpTables
ldr r0, =csProc_CloneInt_NewTaskMessage
bl Log
// === PROTOTYPES ===
void Proc_IdleThread(void *unused);
-tTID Proc_NewKThread(void (*Fnc)(void*), void *Ptr);
// === GLOBALS ===
tThread *gpCurrentThread = &gThreadZero;
@
.section .init
interrupt_vector_table:
-ivt_reset: b _start @ Reset
-ivt_undef: b . @ #UD
-ivt_svc: b SVC_Handler @ SVC (used to be called SWI)
-ivt_prefetch: b PrefetchAbort @ Prefetch abort
-ivt_data: b DataAbort @ Data abort
-ivt_unused: b . @ Not Used
-ivt_irq: b IRQHandler @ IRQ
-ivt_fiq: b . @ FIQ (Fast interrupt)
+ivt_reset: b _start @ 0x00 Reset
+ivt_undef: b . @ 0x04 #UD
+ivt_svc: b SVC_Handler @ 0x08 SVC (used to be called SWI)
+ivt_prefetch: b PrefetchAbort @ 0x0C Prefetch abort
+ivt_data: b DataAbort @ 0x10 Data abort
+ivt_unused: b . @ 0x14 Not Used
+ivt_irq: b IRQHandler @ 0x18 IRQ
+ivt_fiq: b . @ 0x1C FIQ (Fast interrupt)
.globl _start
_start:
PUSH_GPRS
-@ ldr r0, =csIRQ_Tag
-@ ldr r1, =csIRQ_Fmt
-@ ldr r4, =Log_Debug
-@ blx r4
+ ldr r0, =csIRQ_Tag
+ ldr r1, =csIRQ_Fmt
+ ldr r4, =Log_Debug
+ blx r4
@ Call the registered handler
ldr r0, gpIRQHandler
//void Proc_Start(void);
//tThread *Proc_GetCurThread(void);
void Proc_ChangeStack(void);
- int Proc_NewKThread(void (*Fcn)(void*), void *Data);
+// int Proc_NewKThread(void (*Fcn)(void*), void *Data);
// int Proc_Clone(Uint *Err, Uint Flags);
Uint Proc_MakeUserStack(void);
//void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize);
void Proc_IdleTask(void *unused);
//void Proc_Start(void);
//tThread *Proc_GetCurThread(void);
- int Proc_NewKThread(void (*Fcn)(void*), void *Data);
+// int Proc_NewKThread(void (*Fcn)(void*), void *Data);
// int Proc_Clone(Uint *Err, Uint Flags);
// int Proc_SpawnWorker(void);
Uint Proc_MakeUserStack(void);
/**
* \brief Finds a matching binary entry
- * \param TruePath File Identifier (True path name)
+ * \param MountID Mountpoint ID of binary file
+ * \param InodeID Inode ID of the file
+ * \return Pointer to the binary definition (if already loaded)
*/
tBinary *Binary_GetInfo(tMount MountID, tInode InodeID)
{
tBinary *pBinary;
- pBinary = glLoadedBinaries;
- while(pBinary)
+ for(pBinary = glLoadedBinaries; pBinary; pBinary = pBinary->Next)
{
if(pBinary->MountID == MountID && pBinary->Inode == InodeID)
return pBinary;
- pBinary = pBinary->Next;
}
return NULL;
}
/**
- \fn Uint Binary_MapIn(tBinary *binary)
- \brief Maps an already-loaded binary into an address space.
- \param binary Pointer to globally stored data.
-*/
+ * \brief Maps an already-loaded binary into an address space.
+ * \param Binary Pointer to globally stored binary definition
+ * \param Path Path to the binary's file (for debug)
+ * \param LoadMin Lowest location to map to
+ * \param LoadMax Highest location to map to
+ * \return Base load address
+ */
tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr LoadMax)
{
tVAddr base;
if(base != 0)
{
LOG("Checking base %p", base);
- for(i=0;i<Binary->NumSections;i++)
+ for( i = 0; i < Binary->NumSections; i ++ )
{
if( Binary_int_CheckMemFree( Binary->LoadSections[i].Virtual, Binary->LoadSections[i].MemSize ) )
{
if( sect->Flags & BIN_SECTFLAG_EXEC )
protflags |= MMAP_PROT_EXEC;
+ // Read only pages are COW
if( sect->Flags & BIN_SECTFLAG_RO ) {
VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_SHARED|mapflags, fd, sect->Offset );
}
protflags |= MMAP_PROT_WRITE;
VFS_MMap( (void*)addr, sect->FileSize, protflags, MMAP_MAP_PRIVATE|mapflags, fd, sect->Offset );
}
+
+ // Apply anonymous memory for BSS
if( sect->FileSize < sect->MemSize ) {
mapflags |= MMAP_MAP_ANONYMOUS;
VFS_MMap(
protflags, MMAP_MAP_PRIVATE|mapflags,
0, 0
);
-// memset((void*)(addr + sect->FileSize), 0, sect->MemSize - sect->FileSize);
}
}
Log_Debug("Binary", "PID %i - Mapped '%s' to 0x%x", Threads_GetPID(), Path, base);
VFS_Close(fd);
- //LOG("*0x%x = 0x%x\n", binary->Pages[0].Virtual, *(Uint*)binary->Pages[0].Virtual);
-
LEAVE('p', base);
return base;
}
}
/**
- * \fn void *Heap_Extend(int Bytes)
* \brief Extend the size of the heap
*/
void *Heap_Extend(int Bytes)
}
/**
- * \fn void *Heap_Merge(tHeapHead *Head)
* \brief Merges two ajacent heap blocks
*/
void *Heap_Merge(tHeapHead *Head)
}
/**
- * \brief Allocate memory from the heap
* \param File Allocating source file
* \param Line Source line
- * \param Bytes Size of region to allocate
+ * \param __Bytes Size of region to allocate
*/
void *Heap_Allocate(const char *File, int Line, size_t __Bytes)
{
head->AllocateTime = now();
Mutex_Release(&glHeap); // Release spinlock
#if DEBUG_TRACE
- Debug("[Heap ] Malloc'd %p (%i bytes), returning to %p", head->Data, head->Size, __builtin_return_address(0));
+ Debug("[Heap ] Malloc'd %p (%i bytes), returning to %p",
+ head->Data, head->Size, __builtin_return_address(0));
#endif
return head->Data;
}
}
/**
- * \fn void Heap_Deallocate(void *Ptr)
* \brief Free an allocated memory block
*/
void Heap_Deallocate(void *Ptr)
*/
#ifndef _ACESS_H
#define _ACESS_H
+/**
+ * \file acess.h
+ * \brief Acess2 Kernel API Core
+ */
+//! NULL Pointer
#define NULL ((void*)0)
+//! Pack a structure
#define PACKED __attribute__((packed))
+//! Mark a function as not returning
#define NORETURN __attribute__((noreturn))
+//! Mark a parameter as unused
#define UNUSED(x) UNUSED_##x __attribute__((unused))
+//! Get the offset of a member in a structure
#define offsetof(st, m) ((Uint)((char *)&((st *)(0))->m - (char *)0 ))
+/**
+ * \name Boolean constants
+ * \{
+ */
#define TRUE 1
#define FALSE 0
+/**
+ * \}
+ */
#include <arch.h>
#include <stdarg.h>
#include "errno.h"
// --- Types ---
-typedef int tPID;
-typedef int tTID;
-typedef Uint tUID;
-typedef Uint tGID;
-typedef Sint64 tTimestamp;
-typedef Sint64 tTime;
-typedef struct sShortSpinlock tShortSpinlock;
-typedef int bool;
+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 Sint64 tTimestamp; //!< Timestamp (miliseconds since 00:00 1 Jan 1970)
+typedef Sint64 tTime; //!< Same again
+typedef struct sShortSpinlock tShortSpinlock; //!< Opaque (kinda) spinlock
+typedef int bool; //!< Boolean type
// --- Helper Macros ---
/**
* \}
*/
// --- Interface Flags & Macros
+/**
+ * \name Flags for Proc_Clone
+ * \{
+ */
+//! Clone the entire process
#define CLONE_VM 0x10
+/**
+ * \}
+ */
// === Types ===
+/**
+ * \brief Thread root function
+ *
+ * Function pointer prototype of a thread entrypoint. When it
+ * returns, Threads_Exit is called
+ */
typedef void (*tThreadFunction)(void*);
// === Kernel Export Macros ===
/**
- * \name Kernel Function
+ * \name Kernel exports
* \{
*/
+//! Kernel symbol definition
typedef struct sKernelSymbol {
- const char *Name;
- tVAddr Value;
+ const char *Name; //!< Symbolic name
+ tVAddr Value; //!< Value of the symbol
} tKernelSymbol;
+//! Export a pointer symbol (function/array)
#define EXPORT(_name) tKernelSymbol _kexp_##_name __attribute__((section ("KEXPORT"),unused))={#_name, (tVAddr)_name}
+//! Export a variable
#define EXPORTV(_name) tKernelSymbol _kexp_##_name __attribute__((section ("KEXPORT"),unused))={#_name, (tVAddr)&_name}
+//! Export a symbol under another name
#define EXPORTAS(_sym,_name) tKernelSymbol _kexp_##_name __attribute__((section ("KEXPORT"),unused))={#_name, (tVAddr)_sym}
/**
* \}
// === FUNCTIONS ===
// --- IRQs ---
+/**
+ * \name IRQ hander registration
+ * \{
+ */
extern int IRQ_AddHandler(int Num, void (*Callback)(int, void*), void *Ptr);
extern void IRQ_RemHandler(int Handle);
+/**
+ * \}
+ */
// --- Logging ---
+/**
+ * \name Logging to kernel ring buffer
+ * \{
+ */
extern void Log_KernelPanic(const char *Ident, const char *Message, ...);
extern void Log_Panic(const char *Ident, const char *Message, ...);
extern void Log_Error(const char *Ident, const char *Message, ...);
extern void Log_Notice(const char *Ident, const char *Message, ...);
extern void Log_Log(const char *Ident, const char *Message, ...);
extern void Log_Debug(const char *Ident, const char *Message, ...);
+/**
+ * \}
+ */
// --- Debug ---
/**
* \}
*/
+/**
+ * \brief Get a random number
+ * \return Random number
+ * \note Current implementation is a linear congruency
+ */
extern int rand(void);
+/**
+ * \brief Call a function with a variable number of arguments
+ * \param Function Function address
+ * \param NArgs Number of entries in \a Args
+ * \param Args Array of arguments
+ * \return Integer from called Function
+ */
extern int CallWithArgArray(void *Function, int NArgs, Uint *Args);
// --- Heap ---
*/
// --- Simple Math ---
+//! Divide and round up
extern int DivUp(int num, int dem);
+//! Divide and Modulo 64-bit unsigned integer
extern Uint64 DivMod64U(Uint64 Num, Uint64 Den, Uint64 *Rem);
#include <binary_ext.h>
*/
#ifndef _HAL_PROC_H_
#define _HAL_PROC_H_
+/**
+ * \file hal_proc.h
+ * \brief Achitecture defined thread/process management functions
+ */
#include <threads_int.h>
+/**
+ * \brief Initialise the architecture dependent side of threading
+ */
extern void ArchThreads_Init(void);
+/**
+ * \brief Start preemptive multithreading (if needed)
+ */
extern void Proc_Start(void);
+/**
+ * \brief Get the ID of this CPU
+ * \return Zero based CPU ID
+ */
extern int GetCPUNum(void);
+/**
+ * \brief Create a copy of the current process
+ * \param Flags Options for the clone
+ * \return ID of the new thread/process
+ */
extern tTID Proc_Clone(Uint Flags);
+/**
+ * \brief Create a new kernel thread for the process
+ * \param Fnc Thread root function
+ * \param Ptr Argument to pass the root function
+ * \return ID of new thread
+ */
+extern tTID Proc_NewKThread( void (*Fnc)(void*), void *Ptr );
/**
* \brief Start a user task
* \param Entrypoint User entrypoint
* \note This function should free \a ArgV
*/
extern void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataSize) NORETURN;
+/**
+ * \brief Call the fault handler for a thread
+ * \param Thread Thread that is at fault :)
+ */
extern void Proc_CallFaultHandler(tThread *Thread);
+/**
+ * \brief Dump the CPU state for a thread
+ */
extern void Proc_DumpThreadCPUState(tThread *Thread);
+/**
+ * \brief Select a new task and run it, suspending this
+ */
extern void Proc_Reschedule(void);
-
+/**
+ * \brief Clear the user's memory space back to the minimum required to run
+ */
extern tPAddr MM_ClearUser(void);
+/**
+ * \brief Dump the address space to the debug channel
+ * \param Start First address
+ * \param End Last address
+ */
extern void MM_DumpTables(tVAddr Start, tVAddr End);
-
#endif
/**
* \brief Initialise the semaphore
* \param Sem Semaphore structure to initialsie
- * \param Value Initial value of the semaphore
+ * \param InitValue Initial value of the semaphore
+ * \param MaxValue Maximum value for the semaphore
* \param Module Module name
* \param Name Symbolic name
* \note Not always needed, as initialising to 0 is valid, but it is preferred
extern void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name);
/**
* \brief Acquire items from the semaphore
- * \param Semaphore Semaphore structure to use
+ * \param Sem Semaphore structure to use
* \param MaxToTake Maximum number of items to take off the list (if zero, as much as possible is taken)
* \return Number of items fetched
* \retval 0 Semaphore interrupted (signal/message)
#define DEBUG 0
/**
- * \file tpl_mm_phys.h
+ * \file tpl_mm_phys_stack.h
* \brief Template physical memory manager
*
* An extensible physical memory manager