* Multi-process management
	* Many syscall implementations
	* Sheared object creation
	* Fix process creation
	* Fix process return

Implemented syscall list:
	* wait
	* waitpid
	* _exit
	* getpid
	* getppid
	* getpgid
	* setpgid

Bugs found (but not fixed):
	* TTY cursor drawing crash.
	* Loader relocatable sections management (unable to load the file)
	* Loader relocatable sections management (symbols not relocalized, crash)
This commit is contained in:
Yann MAGNIN 2020-03-23 15:58:48 +01:00
parent 2f34cf4d48
commit 97fb770fe1
48 changed files with 749 additions and 498 deletions

View File

@ -23,6 +23,14 @@ struct tty_s
char **output;
} buffers;
// Window size informations used by the write primitive
struct {
unsigned short ws_col;
unsigned short ws_row;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
} winsize;
// Cursor informations
struct {
int16_t x;

View File

@ -64,7 +64,8 @@ struct casio_smem_fragment_s
uint16_t data_block_id; // ID of blocks containing data for this fragment
uint16_t data_offset; // offset of fragment data in the given block
// WARNING : the size is (real_size-1), so *do not forget* to add 1 to
// WARNING :
// The size is (real_size-1), so *do not forget* to add 1 to
// have the real size of data!
uint16_t data_size; // size of this fragment data
@ -75,6 +76,7 @@ struct casio_smem_fragment_s
typedef struct casio_smem_block_s smemfs_sector_t;
typedef struct casio_smem_header_s smemfs_inode_t;
typedef struct casio_smem_fragment_s smemfs_fragdata_t;
typedef struct casio_smem_header_s smemfs_header_t;
// Define internal superblock

View File

@ -22,22 +22,17 @@ struct process
// Used when interrupt or exception occur
//---
struct {
uint32_t kernel;
uint32_t user;
void *kernel;
void *user;
} stack;
//---
// Context management
//---
common_context_t context;
//---
// Private data
//---
char name[PROCESS_NAME_LENGHT];
//---
// Shared (child / parent) data informations
//---
@ -51,11 +46,12 @@ struct process
struct dentry *working_dir;
FILE tty;
//---
// Signals management.
//---
//sighandler_t signal[NSIG];
//---
// Virtual / Physical memory management.
@ -67,20 +63,20 @@ struct process
//---
struct {
struct {
uint32_t user;
uint32_t kernel;
void *user;
void *kernel;
struct {
uint32_t user;
uint32_t kernel;
size_t user;
size_t kernel;
} size;
} stack;
struct {
uint32_t start;
uint32_t size;
void *start;
size_t size;
} program;
struct {
uint32_t start;
uint32_t size;
void *start;
size_t size;
} exit;
} memory;
@ -89,35 +85,43 @@ struct process
// Other process management.
//---
struct process *parent;
struct process *sibling;
struct process *child;
//---
// Private data
//---
// Process ID
pid_t pid;
pid_t pgid;
// Indicate process status
enum {
PROC_INIT,
PROC_RUNNING,
PROC_SLEEP,
PROC_STOP,
PROC_ZOMBIE,
PROC_DEAD
} status;
// Used to by the _exit() syscall
uint32_t __stat_loc;
// Used by the allocator
struct process *next;
};
// Internal struct used by the
// static process stack
struct process_stack
{
// Indicate process slot status
enum {
PROC_USED,
PROC_UNUSED
} status;
// Internal process data
struct process process;
};
// Functions.
extern struct process *process_create(const char *name);
extern struct process *process_get(pid_t pid);
extern pid_t process_get_pid(struct process *process);
extern struct process *process_create(void);
extern int process_switch(pid_t pid);
// Internal function.
extern pid_t process_alloc(struct process **process);
// Internals
extern struct process *process_alloc(void);
extern struct process *process_get(pid_t pid);
extern int process_free(struct process *process);
#endif /*__KERNEL_PROCESS_H__*/

View File

@ -5,15 +5,12 @@
#include <stddef.h>
#include <kernel/util/types.h>
//---
//
// Vhex part !!
//
//---
// Process
extern pid_t sys_fork(void);
extern pid_t sys_getpid(void);
extern pid_t sys_getppid(void);
extern pid_t sys_getpgid(void);
extern pid_t sys_wait(int *wstatus);
extern int sys_setpgid(pid_t pid, pid_t pgid);
extern pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
extern pid_t sys_fexecve(const char *pathname);
extern void sys_exit(int status);

View File

@ -26,12 +26,9 @@ typedef enum mpu_e
MPU_UNKNOWN,
} mpu_t;
typedef int pid_t;
typedef int32_t pid_t;
typedef int16_t mode_t;
typedef uint16_t dev_t;
typedef uint16_t umode_t;
// Force inline function.
#define INLINE __attribute__((always_inline)) inline
#endif /*__TYPES_H__*/

View File

@ -1,6 +1,9 @@
#ifndef __KERNEL_UNISTD_32_H__
# define __KERNEL_UNISTD_32_H__
// Define the number of syscall
#define __NR_MAX 14
// Kernel Test
#define __NR_test_syscall 0
@ -8,27 +11,17 @@
#define __NR_exit 1
#define __NR_fexecve 2
#define __NR_waitpid 3
#define __NR_wait 4
#define __NR_getpid 5
#define __NR_getppid 6
#define __NR_getpgid 7
#define __NR_setpgid 8
// VFS
#define __NR_read 4
#define __NR_write 5
#define __NR_open 6
#define __NR_close 7
#define __NR_lseek 8
//--
// Custom !
//--
// Display
#define __NR_kvram_display 9
#define __NR_kvram_clear 10
#define __NR_kvram_print 11
#define __NR_kvram_ascii 12
#define __NR_kvram_reverse 13
#define __NR_kvram_scroll 14
#define __NR_kvram_clr_str_area 15
//TODO: keyboard
#define __NR_read 9
#define __NR_write 10
#define __NR_open 11
#define __NR_close 12
#define __NR_lseek 13
#endif /*__KERNEL_UNISTD_32_H__*/

View File

@ -17,6 +17,16 @@
#define WNOHANG 0
#define WUNTRACED 1
#define WCONTINUED 2
//TODO: move me
#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
#define WEXITSTATUS(status) __WEXITSTATUS(status)
extern pid_t getpid(void);
extern pid_t getpgid(void);
extern pid_t getppid(void);
extern int setpgid(pid_t pid, pid_t pgid);
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
extern pid_t fexecve(const char *pathname);

View File

@ -76,18 +76,18 @@ static void rom_explore(volatile void *rom, int32_t size)
while (size >= 0)
{
unused = *(volatile uint8_t*)rom;
rom = (void*)((uint32_t)rom + 1024);
size = size - 1024;
rom = rom + 1024;
}
}
/* section_execute() - Used to execute contructors and destructors */
static void section_execute(void *bsection, void *esection)
{
while ((uintptr_t)bsection < (uintptr_t)esection)
while (bsection < esection)
{
((void (*)(void))*((uint32_t*)bsection))();
bsection = (void*)((uint32_t)bsection + 4);
((void (*)(void))*((void**)bsection))();
bsection = bsection + sizeof(void (*)(void));
}
}
@ -107,9 +107,7 @@ int start(void)
// Check MPU hardware.
current_mpu = mpu_get();
if (current_mpu != MPU_SH7305)
{
return (0);
}
// Execute constructor.
section_execute(&bctors, &ectors);
@ -169,8 +167,8 @@ int start(void)
vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mkdir("/home", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mkdir("/mnt/smemfs", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL);
vfs_mkdir("/mnt/casio", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
vfs_mount(NULL, "/mnt/casio", "smemfs", /*MS_RDONLY*/0, NULL);
// Add devices
earlyterm_write("Add devices...\n");
@ -182,24 +180,10 @@ int start(void)
// Start first process !
//---
// Create first process: Vhex.
//earlyterm_write("Create first process...\n");
//struct process *vhex_process = process_create("Vhex");
/*if (vhex_process == NULL)
{
earlyterm_clear();
earlyterm_write("Vhex fatal error !\n");
earlyterm_write("First process error !\n");
earlyterm_write("Press [MENU] key...\n");
while (1) { __asm__ volatile ("sleep"); }
}*/
// Load programe.
//vhex_process->context.spc = (uint32_t)loader("/mnt/smemfs/VHEX/shell.elf", vhex_process);
//if (vhex_process->context.spc == 0x00000000)
earlyterm_write("Create first process...\n");
struct process *vhex_process = process_create("Vhex");
if (vhex_process == NULL || loader(vhex_process, "/mnt/smemfs/VHEX/shell.elf") != 0)
struct process *vhex_process = process_create();
if (vhex_process == NULL || loader(vhex_process, "/mnt/casio/VHEX/shell.elf") != 0)
{
// Display message.
earlyterm_clear();
@ -208,8 +192,8 @@ int start(void)
if (vhex_process->context.spc == 0xffffffff)
earlyterm_write("process_create() error\n");
else
earlyterm_write("File \"VHEX/shell.elf\" not found !");
earlyterm_write("Press [MENU key]...");
earlyterm_write("File \"VHEX/shell.elf\" not found !\n");
earlyterm_write("Press [MENU key]...\n");
// Restore Casio context.
fx9860_context_restore(&casio_context);

View File

@ -26,6 +26,12 @@ void *tty_open(dev_t major, dev_t minor)
return (NULL);
}
// Generate "visible" informations for the write primitive
tty->winsize.ws_xpixel = screen_get(SCREEN_WIDTH);
tty->winsize.ws_ypixel = screen_get(SCREEN_HEIGHT);
tty->winsize.ws_col = tty->winsize.ws_xpixel / (tty->disp.font->font.width + 1);
tty->winsize.ws_row = tty->winsize.ws_ypixel / (tty->disp.font->font.height + 1);
// Generate formated output buffer indicator
tty->cursor.max.x = screen_get(SCREEN_WIDTH) / (tty->disp.font->font.width + 1);
tty->cursor.max.y = screen_get(SCREEN_HEIGHT) / (tty->disp.font->font.height + 1);

View File

@ -90,6 +90,7 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
return (keyboard.buffer.clen);
}
//TODO: move me
static int check_signal(struct keyboard_obj_s *keyboard, key_t key)
{
//TODO
@ -98,111 +99,103 @@ static int check_signal(struct keyboard_obj_s *keyboard, key_t key)
return (0);
}
// TODO: move me
// TODO: update me
static int check_special(struct keyboard_obj_s *keyboard, key_t key)
{
extern fx9860_context_t casio_context;
extern fx9860_context_t vhex_context;
switch (key)
{
// Check MAJ.
case KEY_ALPHA:
{
keyboard->mode = keyboard->mode ^ 0x02;
return (1);
}
if (key == KEY_ALPHA) {
keyboard->mode = keyboard->mode ^ 0x02;
return (1);
}
// Check Alpha / num mode.
case KEY_SHIFT:
{
keyboard->mode = keyboard->mode ^ 0x01;
return (1);
}
// Check Alpha / num mode.
if (key == KEY_SHIFT) {
keyboard->mode = keyboard->mode ^ 0x01;
return (1);
}
// Check DEL key.
case KEY_DEL:
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
// Move seconde part.
memcpy(
&keyboard->buffer.addr[keyboard->buffer.cursor - 1],
&keyboard->buffer.addr[keyboard->buffer.cursor],
keyboard->buffer.clen - keyboard->buffer.cursor
);
// Add null char and update clen.
keyboard->buffer.clen = keyboard->buffer.clen - 1;
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
if (key == KEY_DEL)
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
}
// Move seconde part.
memcpy(
&keyboard->buffer.addr[keyboard->buffer.cursor - 1],
&keyboard->buffer.addr[keyboard->buffer.cursor],
keyboard->buffer.clen - keyboard->buffer.cursor
);
// Check MENU key.
// TODO: fix me !
case KEY_MENU:
{
// Save current Vhex context and restore Casio's context.
atomic_start();
fx9860_context_save(&vhex_context);
fx9860_context_restore(&casio_context);
atomic_stop();
// Add null char and update clen.
keyboard->buffer.clen = keyboard->buffer.clen - 1;
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
return (1);
}
// Inject MENU key and call GetKey().
// TODO !!!
//int row = 0;
//int column = 0;
//uint16_t keymatrix = 0x0308;
//casio_Bkey_PutKeymatrix(&keymatrix);
//casio_GetKeyWait(&row, &column, 0, 0, 0, &key);
casio_GetKey(&key);
// Check MENU key.
// TODO: fix me !
if (key == KEY_MENU)
{
// Save current Vhex context and restore Casio's context.
atomic_start();
fx9860_context_save(&vhex_context);
fx9860_context_restore(&casio_context);
atomic_stop();
// Inject MENU key and call GetKey().
// TODO !!!
//casio_GetKeyWait(&row, &column, 0, 0, 0, &key);
casio_GetKey(&key);
// Save current Casio's context and restore Vhex's context.
atomic_start();
fx9860_context_save(&casio_context);
fx9860_context_restore(&vhex_context);
atomic_stop();
return (1);
}
// Save current Casio's context and restore Vhex's context.
atomic_start();
fx9860_context_save(&casio_context);
fx9860_context_restore(&vhex_context);
atomic_stop();
return (1);
}
// Check EXE key.
case KEY_EXE:
{
// Add new line character.
keyboard->buffer.addr[keyboard->buffer.clen] = '\n';
keyboard->buffer.clen = keyboard->buffer.clen + 1;
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
// Check EXE key.
if (key == KEY_EXE)
{
// Add new line character.
keyboard->buffer.addr[keyboard->buffer.clen] = '\n';
keyboard->buffer.clen = keyboard->buffer.clen + 1;
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
// indicate that the EXE has been pressed.
keyboard->mode = keyboard->mode | 0x04;
// indicate that the EXE has been pressed.
keyboard->mode = keyboard->mode | 0x04;
return (1);
}
// Check LEFT key.
if (key == KEY_LEFT)
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
}
// Check LEFT key.
case KEY_LEFT:
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
return (1);
}
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
// Check RIGHT key.
if (key == KEY_RIGHT)
{
// Check limit
if (keyboard->buffer.cursor >= keyboard->buffer.clen)
return (1);
}
// Check RIGHT key.
case KEY_RIGHT:
{
if (keyboard->buffer.cursor >= keyboard->buffer.clen)
return (1);
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor + 1;
return (1);
}
default: break;
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor + 1;
return (1);
}
return (0);
}
@ -323,12 +316,13 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
y = y * (keyboard->tty->disp.font->font.height + 1);
// Display cursor.
dreverse(
/* dreverse(
&keyboard->tty->disp, x, y,
(keyboard->tty->disp.font->font.width + 1),
(keyboard->tty->disp.font->font.height + 1)
);
(*screen_update)(keyboard->tty->disp.vram);
*/
// Restore TTY cursor position
keyboard->tty->cursor.x = sttyx;

View File

@ -7,7 +7,7 @@
static void tty_vertical_update(struct tty_s *tty)
{
// Get next line.
if (tty->cursor.y + 1 <= tty->cursor.max.y)
if (tty->cursor.y + 1 < tty->cursor.max.y)
tty->cursor.y = tty->cursor.y + 1;
else
tty->cursor.y = 0;
@ -117,7 +117,7 @@ static void tty_display(struct tty_s *tty)
// @note: circular buffer.
line = 0;
start = tty->cursor.y;
while (++line < tty->cursor.max.y)
while (++line < tty->winsize.ws_row)
{
// Update check line.
saved_start = start;

View File

@ -1,5 +1,6 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/file.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
#include <lib/string.h>
@ -13,51 +14,64 @@ static void *casio_smem_get_data_base_address(smemfs_fragdata_t *fragment)
while (block->magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC &&
block->info.id != fragment->data_block_id)
{
block = block + 1;
block = &block[1];
}
if (block->info.id != fragment->data_block_id)
return (NULL);
return ((void *)(uint32_t)(block->offset + fragment->data_offset));
return ((void *)(block->offset + fragment->data_offset));
}
/* casio_smem_read() - Read the file data (based on internal cursor) */
ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos)
{
smemfs_fragdata_t *fragment;
smemfs_header_t *header;
off_t fragment_data_offset;
void *data_base_addr;
ssize_t current_size;
size_t current_size;
size_t real_size;
// Get Check obvious error.
if (inode == NULL || buf == NULL)
return (-1);
// Check file type
header = inode;
if (header->info != CASIO_SMEM_HEADER_INFO_EXIST ||
header->type != CASIO_SMEM_HEADER_TYPE_FILE) {
earlyterm_write("smemfs: header error !\n");
return (-1);
}
// Start atomic operation
atomic_start();
// Get the current data fragment.
current_size = 0;
fragment = (void *)((uint32_t)inode + sizeof(struct casio_smem_header_s));
fragment = inode + sizeof(struct casio_smem_header_s);
while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC &&
pos > (off_t)(current_size + fragment->data_size + 1))
fragment->info == CASIO_SMEM_FRAGMENT_INFO_EXIST &&
(off_t)(current_size + fragment->data_size + 1) < pos)
{
current_size = current_size + fragment->data_size + 1;
fragment = fragment + 1;
fragment = &fragment[1];
}
// Check fragment error
if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC)
if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC ||
fragment->info != CASIO_SMEM_FRAGMENT_INFO_EXIST)
{
atomic_stop();
earlyterm_write("smemfs: fragment error !\n");
return (-1);
}
// Read file data
current_size = 0;
fragment_data_offset = pos - current_size;
while (current_size < (ssize_t)count &&
fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
while (current_size < count &&
fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC &&
fragment->info == CASIO_SMEM_FRAGMENT_INFO_EXIST)
{
// Calculate the real size to read.
real_size = fragment->data_size + 1 - fragment_data_offset;
@ -72,16 +86,16 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos)
// Handle fragment data offset.
if (fragment_data_offset != 0)
{
data_base_addr = (void *)(((uint32_t)data_base_addr) + fragment_data_offset);
data_base_addr = data_base_addr + fragment_data_offset;
fragment_data_offset = 0;
}
// Fill the buffer
memcpy((void*)(buf + current_size), (void*)(0xa0000000 + data_base_addr), real_size);
memcpy(buf + current_size, (void*)(0xa0000000 + data_base_addr), real_size);
// Update informations.
current_size = current_size + real_size;
fragment = fragment + 1;
fragment = &fragment[1];
}
// Stop atomic operation

View File

@ -3,37 +3,34 @@
/* smemfs_walk() - Find inode based on directory ID and flags */
/* @note: This function is internal of smemFS, do not call it ! */
smemfs_inode_t *smemfs_walk(smemfs_inode_t *current,
smemfs_inode_t *entry, uint16_t folder_id, int flags)
smemfs_inode_t *file, uint16_t folder_id, int flags)
{
smemfs_fragdata_t *fragdata;
// Check current inode validity.
if (entry == NULL)
if (file == NULL)
return (NULL);
// Walk entry
while (entry->info == CASIO_SMEM_HEADER_INFO_EXIST ||
entry->info == CASIO_SMEM_HEADER_INFO_DELETE)
// Walk file
while (file->info == CASIO_SMEM_HEADER_INFO_EXIST ||
file->info == CASIO_SMEM_HEADER_INFO_DELETE)
{
// New inode validity check.
if (entry != current &&
entry->info == CASIO_SMEM_HEADER_INFO_EXIST &&
(((flags & WALK_FLAG_ID_CHECK_PARENT) != 0 && entry->parent.id == folder_id) ||
((flags & WALK_FLAG_ID_CHECK_PARENT) == 0 && entry->id == folder_id)))
if (file != current &&
file->info == CASIO_SMEM_HEADER_INFO_EXIST &&
(((flags & WALK_FLAG_ID_CHECK_PARENT) != 0 && file->parent.id == folder_id) ||
((flags & WALK_FLAG_ID_CHECK_PARENT) == 0 && file->id == folder_id)))
{
return (entry);
return (file);
}
// Fast fragmentation skip
fragdata = (void *)((uint32_t)(entry) + sizeof(struct casio_smem_header_s));
fragdata = (void *)&file[1];
if (fragdata->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
fragdata = (void *)((uint32_t)fragdata +
(sizeof(struct casio_smem_fragment_s) * fragdata->frag_total));
}
fragdata = &fragdata[fragdata->frag_total];
// Update current inode
entry = (void*)fragdata;
file = (void*)fragdata;
}
return (NULL);
}

View File

@ -39,7 +39,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
// Check VFS validity
if (vfs_root_node == NULL)
{
earlyterm_write("VFS root error !");
earlyterm_write("VFS root error !\n");
DBG_WAIT;
return (NULL);
}
@ -105,10 +105,10 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
next = vfs_dentry_find_next_sibling(next);
if (next == NULL)
{
earlyterm_write("vfs_resolve(): sibling error !");
earlyterm_write("* old next: %s$", tmp->name);
earlyterm_write("* file: %s$", file->name);
earlyterm_write("* name: %s$", name);
earlyterm_write("vfs_resolve(): sibling error !\n");
earlyterm_write("* old next: %s$\n", tmp->name);
earlyterm_write("* file: %s$\n", file->name);
earlyterm_write("* name: %s$\n", name);
DBG_WAIT;
return (NULL);
}
@ -124,7 +124,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
if ((file->mode & __S_IFDIR) == 0)
{
// Debug !
earlyterm_write("vfs_resolve(): dir error !");
earlyterm_write("vfs_resolve(): dir error !\n");
DBG_WAIT;
return (NULL);
}

View File

@ -11,13 +11,14 @@ int loader(struct process *process, const char *path)
{
Elf32_Ehdr header;
FILE file;
int err;
// Check error and try to open the file.
if (process == NULL || vfs_open(&file, path, O_RDONLY) != 0)
{
earlyterm_write("loader: Fault error !");
earlyterm_write("* path: %s$", path);
earlyterm_write("* process: %p", process);
earlyterm_write("loader: Fault error !\n");
earlyterm_write("* path: %s$\n", path);
earlyterm_write("* process: %p\n", process);
DBG_WAIT;
return (-1);
}
@ -25,25 +26,43 @@ int loader(struct process *process, const char *path)
//@NOTE: Only ELF supported !!!
// Get / Check ELF header
// FIXME: return the file type (elf, g1a, bin, ...)
if (loader_get_header(&file, &header) != 0)
err = loader_get_header(&file, &header);
if (err != 0)
{
earlyterm_write("loader: ELF file header error !");
earlyterm_write("loader: ELF file header error ! (%d)\n", err);
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
return (-2);
}
// Get / Check program validity
if (loader_load_image(process, &file, &header) != 0)
err = loader_load_image(process, &file, &header);
if (err != 0)
{
earlyterm_write("loader: ELF file image error !");
earlyterm_write("loader: ELF file image error ! (%d)\n", err);
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
return (-3);
}
// Relocalise sections / symbols
if (loader_reloc_sym(process, &file, &header) != 0)
err = loader_reloc_sym(process, &file, &header);
if (err != 0)
{
earlyterm_write("loader: ELF relo error !");
earlyterm_write("loader: ELF relo error ! (%d)\n", err);
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
return (-4);
}

View File

@ -19,18 +19,20 @@ int loader_get_header(FILE *file, Elf32_Ehdr *header)
if (header->e_ident[EI_CLASS] != ELFCLASS32)
return (-3);
//TODO: Check OSABI (?)
// Check data encoding
if (header->e_ident[EI_DATA] != ELFDATA2MSB)
return (-4);
// Check ELF type.
if (header->e_type != ET_DYN)
return (-4);
return (-5);
// Check ELF specifique instruction
if (header->e_machine != EM_SH)
return (-5);
return (-6);
// Check ELF version
if (header->e_version != EV_CURRENT)
return (-6);
return (-7);
return (0);
}

View File

@ -7,7 +7,7 @@
int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
{
Elf32_Phdr program;
uint32_t paddress;
void *paddress;
uint16_t i;
// Walk one time to get program size and
@ -31,7 +31,7 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
// Allocate programe space into
// physical memory.
process->memory.program.start = (uint32_t)pm_alloc(process->memory.program.size);
process->memory.program.start = (void *)pm_alloc(process->memory.program.size);
if (process->memory.program.start == 0x00000000)
return (-3);
@ -49,11 +49,11 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
// p_filesz can be smaller than p_memsz so, we need to wipe the area
// before the dump.
memset((void *)paddress, 0, program.p_memsz);
memset(paddress, 0, program.p_memsz);
// Dump the program.
vfs_lseek(file, program.p_offset, SEEK_SET);
vfs_read(file, (void *)paddress, program.p_filesz);
vfs_read(file, paddress, program.p_filesz);
}
// Generate program entry address

View File

@ -9,10 +9,14 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
char *shstrtab;
// Get sections string header tables
vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(shdr)), SEEK_SET);
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
earlyterm_write(
"off_t = %#x\noff_t = %#x\n",
header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)),
vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)), SEEK_SET)
);;
if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr))
{
earlyterm_write("loader_relo_sym: section header table error\n");
earlyterm_write("relo_sym: section header table error\n");
return (NULL);
}
@ -20,7 +24,7 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
shstrtab = (char*)pm_alloc(shdr.sh_size);
if (shstrtab == NULL)
{
earlyterm_write("loader_relo_sym: memory error\n");
earlyterm_write("relo_sym: mem error (%d)\n", shdr.sh_size);
return (NULL);
}
@ -28,7 +32,7 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
vfs_lseek(file, shdr.sh_offset, SEEK_SET);
if (vfs_read(file, shstrtab, shdr.sh_size) != (ssize_t)shdr.sh_size)
{
earlyterm_write("loader_relo_sym: shstrtab size error\n");
earlyterm_write("relo_sym: shstrtab size error\n");
pm_free(shstrtab);
return (NULL);
}
@ -45,16 +49,16 @@ static int reloc_section(struct process *process, FILE *file, Elf32_Shdr *shdr)
for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i)
{
// Get relocatable entry
vfs_lseek(file, shdr->sh_offset + (i * sizeof(rela)), SEEK_SET);
if (vfs_read(file, &rela, sizeof(rela)) != sizeof(rela))
vfs_lseek(file, shdr->sh_offset + (i * sizeof(Elf32_Rela)), SEEK_SET);
if (vfs_read(file, &rela, sizeof(Elf32_Rela)) != sizeof(Elf32_Rela))
{
earlyterm_write("reloc_section: reloc section size error\n");
earlyterm_write("relo_sym: reloc section size error\n");
return (-1);
}
// Relocalise symbols
//earlyterm_write("* [%d] %p, %#x\n", i, rela.r_offset, rela.r_addend);
prog[rela.r_offset >> 2] = rela.r_addend + process->memory.program.start;
prog[rela.r_offset >> 2] += (uint32_t)process->memory.program.start;
//DBG_WAIT;
}
return (0);
@ -69,8 +73,10 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
(void)process;
// DEBUG
//earlyterm_write("e_shnum = %d\n", header->e_shnum);
//earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx);
earlyterm_write("e_shoff = %d\n", header->e_shoff);
earlyterm_write("e_shnum = %d\n", header->e_shnum);
earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx);
//DBG_WAIT;
// Get the shstrtab
@ -82,10 +88,13 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
for (int i = 1 ; i < header->e_shnum ; ++i)
{
// Get next section header
vfs_lseek(file, header->e_shoff + (i * sizeof(shdr)), SEEK_SET);
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
vfs_lseek(file, header->e_shoff + (i * sizeof(Elf32_Shdr)), SEEK_SET);
if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr))
{
earlyterm_write("loader_reloc_sym: section header\n");
earlyterm_write("loader_reloc_sym: shoff = %#x\n", header->e_shoff);
earlyterm_write("loader_reloc_sym: shnum = %#x\n", header->e_shnum);
earlyterm_write("loader_reloc_sym: off = %#x\n", header->e_shoff + (i * sizeof(Elf32_Shdr)));
return (-2);
}
@ -100,8 +109,8 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
}
pm_free(shstrtab);
//earlyterm_write("start = %p\n", process->memory.program.start);
//DBG_WAIT;
//DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
//DBG_WAIT;
return (0);
}

View File

@ -35,6 +35,9 @@ int sched_add_task(struct process *process)
return (-2);
}
// Change process status
process->status = PROC_RUNNING;
// Initialize new task
// TODO: update quantum ticks management
sched_slot->priority._static = SCHED_QUANTUM_TICKS;

View File

@ -19,7 +19,7 @@ void sched_initialize(void)
}
// Initialize internal process informations
// @note:
// TODO ?
// * process_sched_current Used by the kernel to handle
// interrupt / exception
// * process_user_current Used by the kernel to allow

View File

@ -1,20 +1,61 @@
#include <kernel/process.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
#include <kernel/memory.h>
// This function SHOULD NOT be called
// without atomic operation !!
// TODO: dynamic allocation ?
pid_t process_alloc(struct process **process)
// TODO: return EAGAIN !!
// TODO: return ENOMEM !!
struct process *process_alloc(void)
{
extern struct process_stack process_stack[PROCESS_MAX];
extern struct process *proc_table;
extern uint32_t proc_table_max;
uint32_t proc_table_idx;
struct process **proc;
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
// Start atomic operation
atomic_start();
// Try to find free slot
proc = &proc_table;
proc_table_idx = -1;
while (++proc_table_idx < proc_table_max && *proc != NULL)
{
if (process_stack[i].status == PROC_UNUSED)
{
process_stack[i].status = PROC_USED;
*process = &process_stack[i].process;
return (i);
// Check free slot
if ((*proc)->status != PROC_DEAD) {
proc = &(*proc)->next;
continue;
}
// Indicate init phase, stop atomic
// operations and return the process
(*proc)->status = PROC_INIT;
(*proc)->pgid = 0;
atomic_stop();
return (*proc);
}
return (-1);
// Check error
if (proc_table_idx >= proc_table_max) {
earlyterm_write("proc_alloc: EAGAIN !\n");
atomic_stop();
return (NULL);
}
// Alloc new process manually
*proc = (struct process *)pm_alloc(sizeof(struct process));
if (*proc == NULL) {
earlyterm_write("proc_alloc: ENOMEM !\n");
atomic_stop();
return (NULL);
}
// Init and return the now process
(*proc)->status = PROC_INIT;
(*proc)->pid = proc_table_idx + 1;
(*proc)->pgid = 0;
(*proc)->next = NULL;
// Stop atomic operations
atomic_stop();
return (*proc);
}

View File

@ -4,19 +4,14 @@
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
struct process *process_create(const char *name)
struct process *process_create(void)
{
extern struct process *process_current;
extern struct dentry *vfs_root_node;
struct process *process;
pid_t process_pid;
// Check error
if (name == NULL)
return (NULL);
// Try to find free slot.
process_pid = process_alloc(&process);
process = process_alloc();
if (process == NULL)
{
earlyterm_write("proc_error: alloc error !");
@ -26,7 +21,7 @@ struct process *process_create(const char *name)
// Initialize user stack
process->memory.stack.size.user = PROCESS_USER_STACK_SIZE;
process->memory.stack.user = (uint32_t)pm_alloc(process->memory.stack.size.user);
process->memory.stack.user = (void *)pm_alloc(process->memory.stack.size.user);
if (process->memory.stack.user == 0x00000000)
{
earlyterm_write("proc_error: user stack error !");
@ -34,11 +29,11 @@ struct process *process_create(const char *name)
process_free(process);
return (NULL);
}
process->context.reg[15] = process->memory.stack.user + process->memory.stack.size.user;
process->context.reg[15] = (uint32_t)process->memory.stack.user + process->memory.stack.size.user;
// Initialize kernel stack
process->memory.stack.size.kernel = PROCESS_KERNEL_STACK_SIZE;
process->memory.stack.kernel = (uint32_t)pm_alloc(process->memory.stack.size.kernel);
process->memory.stack.kernel = (void *)pm_alloc(process->memory.stack.size.kernel);
if (process->memory.stack.kernel == 0x00000000)
{
earlyterm_write("proc_error: kernel stack error !");
@ -51,26 +46,23 @@ struct process *process_create(const char *name)
// initialize "exit" part.
uint8_t callexit[8] = {
0b00100100, 0b01001010, // xor r4, r4
0b01100100, 0b00000011, // mov r0, r4
0b11000011, __NR_exit, // trapa #__NR_exit
0b10110000, 0b00000100, // bsr PC + 2 - 4
0b00000000, 0b00001001 // nop
};
process->memory.exit.size = 8;
process->memory.exit.start = (uint32_t)(pm_alloc(process->memory.exit.size));
process->memory.exit.start = (void *)pm_alloc(process->memory.exit.size);
if (process->memory.exit.start == 0x00000000)
{
pm_free((void *)process->memory.stack.user);
pm_free((void *)process->memory.stack.kernel);
pm_free(process->memory.stack.user);
pm_free(process->memory.stack.kernel);
process_free(process);
return (NULL);
}
process->context.pr = process->memory.exit.start;
process->context.pr = (uint32_t)process->memory.exit.start;
memcpy((void *)process->memory.exit.start, callexit, 6);
// Set process name.
strncpy(process->name, name, PROCESS_NAME_LENGHT);
// Initialize context.
for (int i = 0 ; i < 15 ; i = i + 1)
process->context.reg[i] = 0x00000000;
@ -107,7 +99,7 @@ struct process *process_create(const char *name)
// The new process will be visible only
// when it is registered by the sheduler.
process->parent = process_current;
process->sibling = NULL;
process->child = NULL;
process->next = NULL;
return (process);
}

View File

@ -1,14 +1,20 @@
#include <kernel/process.h>
//TODO: free allocated proc ?
int process_free(struct process *process)
{
extern struct process_stack process_stack[PROCESS_MAX];
extern struct process *proc_table;
extern uint32_t proc_table_max;
uint32_t proc_table_idx;
struct process *proc;
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
proc = proc_table;
proc_table_idx = 0;
while (proc != NULL && ++proc_table_idx < proc_table_max)
{
if (&process_stack[i].process == process)
if (proc == process)
{
process_stack[i].status = PROC_UNUSED;
proc->status = PROC_DEAD;
return (0);
}
}

View File

@ -1,27 +1,38 @@
#include <kernel/process.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
struct process *process_get_proc(pid_t pid)
struct process *process_get(pid_t pid)
{
extern struct process_stack process_stack[PROCESS_MAX];
extern struct process *proc_table;
struct process *proc;
// Check error
if (pid < 0 || pid >= PROCESS_MAX)
if (pid <= 0)
return (NULL);
// Return process.
return (&process_stack[pid].process);
}
// Start atomic operation
atomic_start();
pid_t process_get_pid(struct process *target)
{
extern struct process_stack process_stack[PROCESS_MAX];
int i;
i = -1;
while (++i < PROCESS_MAX)
// Proess table walk
proc = proc_table;
while (proc != NULL)
{
if (&process_stack[i].process == target)
return (i);
// Check target process
if (proc->pid != pid) {
proc = proc->next;
continue;
}
// Check if the process is alive
if (proc->status == PROC_DEAD)
proc = NULL;
// Stop atomic operations
atomic_stop();
return (proc);
}
return (-1);
// Stop atomic operation
atomic_stop();
return (NULL);
}

View File

@ -1,15 +1,17 @@
#include <kernel/process.h>
// Create all internal global
// used to handle process.
struct process_stack process_stack[PROCESS_MAX];
// Internal symbols
struct process *proc_table;
uint32_t proc_table_max;
__attribute__((constructor))
void process_constructor(void)
{
// Set all process to idle state.
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
{
process_stack[i].status = PROC_UNUSED;
}
// Initialise dynamic process list
// TODO:
// get the scheduler timing and set the maximal
// number of processes which can be running in the
// same time.
proc_table = NULL;
proc_table_max = PROCESS_MAX;
}

View File

@ -6,12 +6,46 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
{
extern struct sched_task *sched_task_current;
extern struct sched_task *sched_task_queue;
struct sched_task *task_current;
extern struct process *process_current;
struct sched_task *task_next;
// Get the potential next process context
task_next = sched_task_queue;
if (sched_task_current != NULL && sched_task_current->next != NULL)
task_next = sched_task_current->next;
// Check / update next task
while (task_next != sched_task_current)
{
// Check process validity
if (task_next->process->status == PROC_RUNNING)
break;
// Get next task
task_next = task_next->next;
if (task_next == NULL)
task_next = sched_task_queue;
}
// Check error
if (task_next == sched_task_current)
return (-1);
// Get contexts
*context_current = NULL;
if (sched_task_current != NULL)
*context_current = &sched_task_current->process->context;
*context_next = &task_next->process->context;
// Update scheduler task / process current
sched_task_current = task_next;
process_current = sched_task_current->process;
return (0);
// Check current task
// TODO: check process status !!
if (sched_task_current == NULL)
/* if (sched_task_current == NULL)
{
task_current = NULL;
task_next = (sched_task_queue != NULL) ? sched_task_queue : NULL;
@ -28,11 +62,12 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
// Update internal scheduler task cursor
sched_task_current = task_next;
process_current = sched_task_current->process;
// Get context
*context_current = (task_current != NULL) ? &task_current->process->context : NULL;
*context_next = &task_next->process->context;
*/
// DEBUG !
/*kvram_clear();
printk(0, 0, "Scheduler_schudele !");
@ -42,5 +77,5 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
printk(0, 4, "context next = %p", *context_next);
kvram_display();
DBG_WAIT;*/
return (0);
//return (0);
}

View File

@ -1,14 +1,35 @@
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/memory.h>
// TODO: remove / move me ?
#include <lib/unistd.h>
void sys_exit(int status)
{
// TODO handle status
(void)status;
extern struct process *process_current;
// Fow now, just wait manual reset...
earlyterm_clear();
earlyterm_write("PROCESS EXIT SYSCALL !!!!");
earlyterm_write("Wait manual reset...");
//earlyterm_clear();
//earlyterm_write("PROCESS EXIT SYSCALL !!!!\n");
//earlyterm_write("Wait manual reset...");
// Start atomic operation
atomic_start();
// Generate stat_loc
process_current->__stat_loc = __W_EXITCODE(status, 0);
// Frre'd all allocated space
pm_free(process_current->memory.stack.user);
pm_free(process_current->memory.stack.kernel);
pm_free(process_current->memory.program.start);
pm_free(process_current->memory.exit.start);
// Change process state
process_current->status = PROC_ZOMBIE;
// Stop atomic operation
atomic_stop();
while (1);
}

View File

@ -5,6 +5,9 @@
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
//TODO
//TODO COPY-ON-WRITE !!
//TODO
static void proc_dump_shared(struct process *child, struct process *parent)
{
// Dump all opened file
@ -18,17 +21,20 @@ static void proc_dump_shared(struct process *child, struct process *parent)
memcpy(&child->tty, &parent->tty, sizeof(FILE));
}
//TODO
//TODO Return EAGAIN if no proc can be created !!
//TODO Return ENOMEM if no memories can be allocated !!
//TODO
pid_t sys_fexecve(const char *pathname)
{
extern struct process *process_current;
struct process *proc;
pid_t child_pid;
// Start atomic operation
atomic_start();
// Try create new process
proc = process_create(pathname);
proc = process_create();
if (proc == NULL)
{
earlyterm_write("sys_fexecve: process_create error !\n");
@ -51,6 +57,10 @@ pid_t sys_fexecve(const char *pathname)
return (-1);
}
// Release child process
proc->sibling = process_current->child;
process_current->child = proc;
// Add new process into task queue
if (sched_add_task(proc))
{
@ -61,15 +71,12 @@ pid_t sys_fexecve(const char *pathname)
return (-1);
}
// Get child process PID
child_pid = process_get_pid(proc);
// Debug
earlyterm_write("New proc sched added !");
earlyterm_write("New proc PID = %#x !", child_pid);
DBG_WAIT;
//earlyterm_write("New proc sched added !\n");
///earlyterm_write("New proc PID = %#x !\n", proc->pid);
//DBG_WAIT;
// Stop atomic operations
atomic_stop();
return (child_pid);
return (proc->pid);
}

View File

@ -1,42 +0,0 @@
/*#include <kernel/process.h>
pid_t sys_fork(void)
{
extern struct process *process_current;
struct process *process_new;
pid_t process_new_pid;
// Check error
if (process_current == NULL)
return (-1);
// Get the new process slot.
new_pid = process_alloc(&process_new);
if (new_pid != 0)
return (-1);
// Try to create user stack
process_new->memory.stack.size.user = process_current->;
process_new->memory.stack.user = (uint32_t)pm_alloc(process_new->memory.stack.size.user);
if (process_new->memory.stack.user == 0x00000000)
{
process_free(process_new);
return (-1);
}
// Try to create kernel stack
process_new->memory.stack.size.kernel = process_current->memory.stack.size.kernel;
process_new->memory.stack.kernel = (uint32_t)pm_alloc(process_new->memory.stack.size.kernel);
if (process_new->memory.stack.kernel == 0x00000000)
{
pm_free(process_new->memory.stack.user);
process_free(process_new);
return (-1);
}
//TODO: dump stack data
//TODO: dump code data
//TODO: Initialize context.
return (-1);
}*/

View File

@ -0,0 +1,25 @@
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
pid_t sys_getpgid(void)
{
extern struct process *process_current;
pid_t ret;
// Start artomic opetations
atomic_start();
// Check error
if (process_current == NULL) {
atomic_stop();
return (-1);
}
// Get Process Groupe ID
ret = process_current->pgid;
// Stop atomic operation
atomic_stop();
return (ret);
}

View File

@ -0,0 +1,25 @@
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
pid_t sys_getpid(void)
{
extern struct process *process_current;
pid_t ret;
// Start artomic opetations
atomic_start();
// Check error
if (process_current == NULL) {
atomic_stop();
return (-1);
}
// Get Process ID
ret = process_current->pid;
// Stop atomic operation
atomic_stop();
return (ret);
}

View File

@ -0,0 +1,31 @@
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
pid_t sys_getppid(void)
{
extern struct process *process_current;
pid_t ret;
// Start artomic opetations
atomic_start();
// Check error
if (process_current == NULL) {
atomic_stop();
return (-1);
}
// Check first process
if (process_current->parent == NULL) {
atomic_stop();
return (0);
}
// Get Parent Process ID
ret = process_current->parent->pid;
// Stop atomic operation
atomic_stop();
return (ret);
}

View File

@ -0,0 +1,25 @@
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/util/atomic.h>
int sys_setpgid(pid_t pid, pid_t pgid)
{
extern struct process *process_current;
struct process *proc;
// Start atomic operations
atomic_start();
// Get the appropriate process
proc = process_current;
if (pid != 0)
proc = process_get(pid);
// Check error
if (proc == NULL)
return (-1);
// Update Proocess Group ID
proc->pgid = (pgid == 0) ? process_current->pgid : pgid;
return (0);
}

View File

@ -0,0 +1,6 @@
#include <kernel/syscall.h>
pid_t sys_wait(int *wstatus)
{
return (sys_waitpid(-1, wstatus, 0));
}

View File

@ -1,6 +1,78 @@
#include <kernel/process.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
pid_t sys_waitpid(pid_t pid, int *wstatus, int options)
{
extern struct process *process_current;
struct process **proc;
pid_t ret;
// Check useless wait
if (process_current->child == NULL) {
earlyterm_write("waitpid: no child\n");
DBG_WAIT;
return (-1);
}
//TODO: handle options
(void)options;
// Wait util one of its children specified by PID
// has changed state
while (1)
{
// Start atomic operation
atomic_start();
// Find childs to check
proc = &process_current->child;
while (*proc != NULL)
{
// Check terminated child
if ((*proc)->status == PROC_ZOMBIE &&
((pid < -1 && (*proc)->pgid == -pid) ||
pid == -1 ||
(pid == 0 && (*proc)->pgid == process_current->pgid) ||
(pid > 0 && (*proc)->pid == pid)))
{
// Change the child process state
(*proc)->status = PROC_DEAD;
// Get the child process PID and stat_loc
ret = (*proc)->pid;
*wstatus = (*proc)->__stat_loc;
// Remove process form the child list
*proc = (*proc)->sibling;
//DEBUG
//earlyterm_write("waitpid: find %d\n", ret);
//DBG_WAIT;
//DBG_WAIT;
// Stop atomic operation and return
atomic_stop();
return (ret);
}
// Get next child process
proc = &(*proc)->sibling;
}
// Force process to sleep
// TODO:
// Schedule !! and change the niciess of the
// process !!
//
// Stop atomic operation and wait
atomic_stop();
__asm__ volatile ("sleep; nop");
}
// Error
//earlyterm_write("waitpid: error\n");
//DBG_WAIT;
return (-1);
}

View File

@ -1,4 +1,5 @@
#include <kernel/syscall.h>
#include <kernel/util/unistd_32.h>
#include <kernel/devices/earlyterm.h>
static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
@ -12,7 +13,7 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
DBG_WAIT;
}
static const void *sys_handler[9] = {
static const void *sys_handler[__NR_MAX] = {
// Kernel Test
sys_test, // test
@ -20,6 +21,11 @@ static const void *sys_handler[9] = {
sys_exit, // exit
sys_fexecve, // fexecve
sys_waitpid, // waitpid
sys_wait, // wait
sys_getpid, // getpid
sys_getppid, // getppid
sys_getpgid, // getpgid
sys_setpgid, // setpgid
// VFS
sys_read, // read
@ -27,32 +33,18 @@ static const void *sys_handler[9] = {
sys_open, // open
sys_close, // close
sys_lseek, // lseek
// Display
/* kvram_display, // kvram_display
kvram_clear, // kvram_clear
printk, // printk
kvram_ascii, // kvram_ascii
kvram_reverse, // kvram_reverse
kvram_scroll, // kvram_scroll
kvram_clr_str_area // kvram_clr_str_area*/
};
void *sys_get_handler(int sysno)
{
// Check sysno validity
if (sysno < 0 || sysno >= 9)
if (sysno < 0 || sysno >= __NR_MAX)
return (NULL);
// DEBUG
/*kvram_clear();
printk(0, 0, "TRAPA ABI pre_handler !");
printk(0, 1, "sysno = %d", sysno);
printk(0, 2, "handler = %p", sys_handler[sysno]);
kvram_display();
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;*/
//earlyterm_write("syscall (%d)!!\n", sysno);
//DBG_WAIT;
//DBG_WAIT;
// Return syscall
return ((void *)sys_handler[sysno]);

View File

@ -46,7 +46,7 @@ TARGET-LIBS-DYNAMIC := $(patsubst %,lib%_dyn.so,$(TARGET-MODULES))
#------- --------#
all: $(TARGET-LIBS-STATIC) $(TARGET-LIBS-DYNAMIC)
$(BUILD-STATIC) $(BUILD-DYNAMIC):
$(BUILD-STATIC) $(BUILD-DYNAMIC) $(DEBUG-DYNLIB):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
@ -69,13 +69,13 @@ endef
define rule-src-dynamic
$(patsubst %,$(BUILD-DYNAMIC)/%.o,$(subst /,_,$(basename $1))): $1 | $(BUILD-DYNAMIC)
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) -fPIC $(CFLAGS) -c $$< -o $$@ $(HEADER)
@ $(CC) -pie $(CFLAGS) -c $$< -o $$@ $(HEADER)
@ printf "$(green)[ok]$(nocolor)\n"
endef
define rule-link-dynamic
$(patsubst %,lib%_dyn.so,$1): $2 | $(DEBUG-DYNLIB)
@ printf "Link $(green)$$@$(nocolor) lib\n"
$(CC) -shared -o $$@ $$^ -nostdlib -lgcc
$(CC) -T user_shared_lib.ld -Wl,-M -pie -o $$@ $$^ -nostdlib -lgcc > $(DEBUG-DYNLIB)/$$@.map
endef

View File

@ -1,12 +1 @@
#include <kernel/util/unistd_32.h>
.text
.global _dupdate
.type _dupdate, @function
.align 2
_dupdate:
trapa #__NR_kvram_display
rts
nop
.end
# TODO screen syscall handling :D

View File

@ -1,13 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _fork
.type _fork, @function
.align 2
_fork:
!trapa #__NR_fork
mov #-1, r0
rts
nop
.end

View File

@ -0,0 +1,12 @@
#include <kernel/util/unistd_32.h>
.text
.global _getpgid
.type _getpgid, @function
.align 2
_getpgid:
trapa #__NR_getpgid
rts
nop
.end

View File

@ -0,0 +1,12 @@
#include <kernel/util/unistd_32.h>
.text
.global _getpid
.type _getpid, @function
.align 2
_getpid:
trapa #__NR_getpid
rts
nop
.end

View File

@ -0,0 +1,12 @@
#include <kernel/util/unistd_32.h>
.text
.global _getppid
.type _getppid, @function
.align 2
_getppid:
trapa #__NR_getppid
rts
nop
.end

View File

@ -0,0 +1,12 @@
#include <kernel/util/unistd_32.h>
.text
.global _setpgid
.type _setpgid, @function
.align 2
_setpgid:
trapa #__NR_setpgid
rts
nop
.end

View File

@ -9,21 +9,19 @@ int builtin_proc(void)
int wstatus;
puts("proc test entry :)\n");
printf("printf test:\n");
printf("0#10x: %0#10x\n", 0xabcdef);
printf("str: %s\n", "Oui le test oui ! :D");
printf("interger: %d\n", 12345);
printf("interger: %lld\n", 999999999999999999);
printf(" PPID PID PGID\n");
printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid());
// Try to create first child
/*child = fexecve("/mnt/casio/VHEX/test.elf");
child = fexecve("/mnt/casio/VHEX/test.elf");
if (child == -1)
{
puts("fexecve fail :(\n");
printf("fexecve fail :(\n");
return (0);
}
// Wait child death
waitpid(child, &wstatus, WUNTRACED);
*/ return (0);
waitpid(-1, &wstatus, 0);
printf("+++ exited with %d +++\n", WEXITSTATUS(wstatus));
return (0);
}

View File

@ -7,35 +7,6 @@ int main(void)
{
char input[12];
int cmd_size;
//char **argv;
//int argc;
//int STDOUT_FILENO;
// Try to open TTY
// @note:
// We use O_DIRECT to avoid cache
// generation because we do not have a
// lot of memory.
/*STDOUT_FILENO = open("/dev/tty", O_DIRECT);
if (STDOUT_FILENO < 0)
{
// Display error.
display_t disp;
dopen(&disp, "default");
dclear(&disp);
dprint(&disp, 0, 0, "User program fail to open TTY");
dprint(&disp, 0, 1, "Wait user manual reset...");
dupdate(&disp);
// Wait user manual reset.
while (1)
{
// @note: we can use "sleep" because we
// are in privilegied mode.
// TODO: use sleep syscall !
__asm__ volatile ("sleep");
}
}*/
// Shell main loop.
write(STDOUT_FILENO, "Boot Complete !\n", 16);
@ -45,6 +16,10 @@ int main(void)
write(STDOUT_FILENO, ">", 1);
cmd_size = read(STDIN_FILENO, input, 12);
// Check no char
if (cmd_size == 1)
continue;
// Remove '\n' char.
// FIXME: create argc, argv !!
input[cmd_size - 1] = '\0';
@ -54,10 +29,7 @@ int main(void)
{
write(STDOUT_FILENO, input, cmd_size - 1);
write(STDOUT_FILENO, ": command not found\n", 20);
} else {
write(STDOUT_FILENO, input, cmd_size - 1);
write(STDOUT_FILENO, ": command found :D !\n", 21);
}
}
}
return (0);
}

View File

@ -9,7 +9,7 @@ include ../../../global.mk
## Static variables
##--
HEADER := -I../../../include -I../../../include/user
LIBS := -L../../lib/ -lunistd -lstdio -lstring -ldisplay -lgcc
LIBS := -L../../lib/ -llibc -ldisplay -lgcc
BUILD := ../../../build/user/test
DEBUG := ../../../debug_bin
OUTPUT := ../../../output

View File

@ -1,19 +1,11 @@
#include <lib/display.h>
#include <lib/stdio.h>
#include <lib/unistd.h>
int main(void)
{
uint32_t counter = 0;
while (1)
{
// Display data
// dclr_str_area(0, 2, 20, 1);
// dprint(0, 2, "C process: %d", counter);
// dupdate();
// Update counter and "wait"
counter = counter + 1;
if (counter >= 100)
counter = 0;
for (int i = 0 ; i < 300000 ; ++i);
}
setpgid(0, 12);
printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid());
printf("child proc fini...try to exit\n");
for(int i = 0 ; i < 3000000 ; ++i);
return (84);
}

View File

@ -1,23 +0,0 @@
/*.global _test
.type _test, @function
.align 2
_test:
sts.l pr, @-r15
mov.l .syscall_vram, r0
mov.l .syscall_entry, r1
jsr @r1
nop
tst r0, r0
bf _test
nop
lds.l @r15+, pr
rts
nop
.align 4
.syscall_entry: .long 0xa0010070
.syscall_vram: .long 0x00000135
.end*/