--- /dev/null
+#ifndef __CORAX_IPC_H
+#define __CORAX_IPC_H
+
+struct cxmsg {
+ u32_t cm_src;
+ u32_t cm_dst;
+ u32_t cm_len;
+
+ u32_t cm_type;
+
+ union {
+ u8_t CM_data[CONFIG_IPC_MSGSIZE];
+ } CM_dat;
+};
+
+#define cm_data CM_dat.CM_data
+
+#endif /* __CORAX_IPC_H */
#define SYS_POLL 11
#define SYS_BIND 12
+#define IPC_SEND 0
+#define IPC_RECV 1
+#define IPC_SENDRECV 2
+
#define SYSCALL_CORAX 0xCC
#define SYSCALL_CXNET 0xCD
+#define SYSCALL_CXIPC 0xCE
#define SYSCALL_POSIX 0x80
#endif /* __CORAX_SYSCALL_H */
typedef u32_t pid_t;
+#define PID_ANY ((pid_t)-1)
+
#endif /* __TYPES_H */
#define SYS_VECTOR_CORAX 0xCC
#define SYS_VECTOR_CXNET 0xCD
+#define SYS_VECTOR_CXIPC 0xCE
#if FEATURE(POSIX)
#define SYS_VECTOR_POSIX 0x80
#endif /* FEATURE(POSIX) */
.global _sys_entryCC
.global _sys_entryCN
+.global _sys_entryCX
.global _int_entry_common
.global _int_restore
_sys_entryCN:
pushl $0
pushl $SYS_VECTOR_CXNET
- /* fall through */
+ jmp _int_entry_common
+
+_sys_entryCX:
+ pushl $0
+ pushl $SYS_VECTOR_CXIPC
+ jmp _int_entry_common
_int_entry_common:
pusha
.extern _sys_entryCC
.extern _sys_entryCN
+.extern _sys_entryCX
#if FEATURE(POSIX)
.extern _sys_entryPX
#endif /* FEATURE(POSIX) */
addl $8, (%esp)
call _segment_descriptor_set
+ /* add an entry for Corax IPC syscalls */
+ movl $_sys_entryCX, 12(%esp)
+ addl $8, (%esp)
+ call _segment_descriptor_set
+
movw $((IDT_ENTRIES * 8) + 1), (%esp)
movl $_cpu, %eax
addl $IDT_OFFSET, %eax
void sched_tick(void);
extern int sys_cxnet(long, long, long, long, long, long, long);
+extern int sys_cxipc(long, long, long);
static const char *_exc_name[] = {
"#DE", "#DB", "NMI", "#BP", "#OF", "#BR", "#UD", "#NM", "#DF", "#MF",
dbg_printf("_corax_call(0x%x, 0x%x, 0x%x);\n", ctx.eax, ctx.ebx, ctx.ecx);
break;
+ case SYS_VECTOR_CXIPC:
+ ret_val = sys_cxipc(ctx.eax, ctx.ebx, ctx.ecx);
+ break;
+
case SYS_VECTOR_CXNET:
ret_val = sys_cxnet(ctx.eax, ctx.ebx, ctx.ecx, ctx.edx, ctx.esi, ctx.edi, ctx.ebp);
break;
-OBJECTS = main.o process.o sched.o cxnet.o socket.o mbuf.o
+OBJECTS = main.o process.o sched.o cxnet.o socket.o cxipc.o
OUTPUT = core.o
INCLUDES = -I../include -I../../include -I../..
CFLAGS += $(INCLUDES)
--- /dev/null
+#include <config.h>
+#include <corax/types.h>
+#include <corax/errno.h>
+#include <corax/syscall.h>
+#include <corax/ipc.h>
+#include <corax/heap.h>
+#include <process.h>
+
+int sys_cxsend(pid_t to, struct cxmsg *msg)
+{
+ process_t *sproc;
+ process_t *dproc;
+ int ret_val;
+
+ ret_val = -EFAULT;
+ sproc = process_get_current();
+ dproc = process_lookup(to);
+
+ if(sproc && dproc) {
+ struct cxmsg *kmsg;
+
+ kmsg = kmalloc(sizeof(*kmsg));
+
+ if(!kmsg) {
+ ret_val = -ENOMEM;
+ } else {
+ /*
+ * We can't copy the message directly into the address space of the destination
+ * process since we don't know the address of the user-space buffer yet. That's
+ * why we store the message in a kernel-space buffer, from where it will be
+ * dispatched once the receiving process calls cxrecv().
+ */
+ process_memcpy_ptok(sproc, kmsg, msg, sizeof(*kmsg));
+
+ kmsg->cm_src = process_get_id(sproc);
+ kmsg->cm_dst = to;
+
+ /* make sure cm_len doesn't exceed the size of the message */
+ if(kmsg->cm_len > CONFIG_IPC_MSGSIZE) {
+ kmsg->cm_len = CONFIG_IPC_MSGSIZE;
+ }
+
+ /* place the message somewhere the destination process can find it */
+ ret_val = process_inbox_put(dproc, kmsg);
+
+ if(ret_val < 0) {
+ kfree(kmsg);
+ } else {
+ /* wait for destination process to pick up the message */
+
+ process_wait(to);
+ }
+ }
+ }
+
+ return(ret_val);
+}
+
+int sys_cxrecv(pid_t from, struct cxmsg *msg)
+{
+ process_t *cproc;
+ int ret_val;
+
+ ret_val = -EFAULT;
+ cproc = process_get_current();
+
+ if(cproc) {
+ struct cxmsg *kmsg;
+
+ /* process_inbox_get() always returns a valid message (or waits forever) */
+ kmsg = process_inbox_get(from);
+
+ process_memcpy_ktop(cproc, msg, kmsg, sizeof(*msg));
+
+ /* signal source that their message was picked up */
+ process_signal(kmsg->cm_src);
+
+ /* we don't need the kernel-space buffer anymore */
+ kfree(kmsg);
+
+ ret_val = 0;
+ }
+
+ return(ret_val);
+}
+
+int sys_cxsendrecv(pid_t tofrom, struct cxmsg *msg)
+{
+ return(-ENOSYS);
+}
+
+int sys_cxipc(long arg0, long arg1, long arg2)
+{
+ int ret_val;
+
+ ret_val = -EOPNOTSUPP;
+
+ switch(arg0) {
+ case IPC_SEND:
+ ret_val = sys_cxsend((pid_t)arg1, (struct cxmsg*)arg2);
+ break;
+
+ case IPC_RECV:
+ ret_val = sys_cxrecv((pid_t)arg1, (struct cxmsg*)arg2);
+ break;
+
+ case IPC_SENDRECV:
+ ret_val = sys_cxsendrecv((pid_t)arg1, (struct cxmsg*)arg2);
+ break;
+
+ default:
+ break;
+ }
+
+ return(ret_val);
+}
#include <corax/types.h>
#include <corax/errno.h>
#include <corax/heap.h>
+#include <corax/ipc.h>
#include <arch.h>
#include <debug.h>
#include <process.h>
-#include "sched.h"
#include "fd.h"
struct process {
struct pagedir *p_pgdir;
struct task *p_tasks;
u32_t p_privl;
+ pid_t p_id;
+
+ struct {
+ struct cxmsg *msg;
+ pid_t sender;
+ } p_inbox[32];
struct fd p_fds[16];
};
-extern int sched_enqueue(task_t*);
+struct proc_list {
+ struct proc_list *next;
+ process_t *proc;
+};
+
+static pid_t _next_pid = 100;
+static struct proc_list *_procs;
+
+extern int sched_enqueue(task_t*);
+extern void sched_wait(pid_t);
+extern int sched_signal(pid_t);
+
+static inline int NQ(process_t *p)
+{
+ struct proc_list *pl;
+ int ret_val;
+
+ ret_val = -ENOMEM;
+ pl = kmalloc(sizeof(*pl));
+
+ if(pl) {
+ pl->next = _procs;
+ pl->proc = p;
+ _procs = pl;
+ ret_val = 0;
+ }
+
+ return(ret_val);
+}
+
+static inline int DQ(process_t *p)
+{
+ struct proc_list **pl;
+ int ret_val;
+
+ ret_val = -ENOENT;
+
+ for(pl = &_procs; *pl; pl = &((*pl)->next)) {
+ if((*pl)->proc == p) {
+ struct proc_list *freeme;
+
+ freeme = *pl;
+ *pl = (*pl)->next;
+
+ kfree(freeme);
+ ret_val = 0;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
int process_create(process_t **dst, u32_t ppl, void *entry)
{
}
proc->p_privl = ppl;
+ proc->p_id = _next_pid++;
task_prepare(proc->p_tasks, (u32_t)pdbr, (u32_t)entry,
(u32_t)kstack + CONFIG_KERNEL_STACK_SIZE,
proc->p_tasks->t_tslice = 50;
proc->p_tasks->t_rslice = 50;
proc->p_tasks->t_proc = proc;
+ proc->p_tasks->t_pid = proc->p_id;
+
+ ret_val = NQ(proc);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
if(sched_enqueue(proc->p_tasks) != 0) {
PANIC("sched_enqueue() failed for a new task\n");
return(ret_val);
}
+process_t* process_lookup(pid_t pid)
+{
+ struct proc_list *lst;
+ process_t *ret_val;
+
+ for(ret_val = NULL, lst = _procs; lst; lst = lst->next) {
+ if(lst->proc->p_id == pid) {
+ ret_val = lst->proc;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
int process_memcpy_ptok(process_t *proc, void *dst, void *src, u32_t bytes)
{
int ret_val;
return(ret_val);
}
+
+int process_inbox_put(process_t *proc, struct cxmsg *msg)
+{
+ process_t *cproc;
+ int ret_val;
+ int i;
+
+ cproc = process_get_current();
+
+ for(ret_val = -ENOMEM, i = 0; i < 32; i++) {
+ if(!(proc->p_inbox[i].sender)) {
+ proc->p_inbox[i].sender = cproc->p_id;
+ proc->p_inbox[i].msg = msg;
+
+ ret_val = 0;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
+struct cxmsg* process_inbox_get(pid_t from)
+{
+ process_t *proc;
+ void *ret_val;
+
+ proc = process_get_current();
+
+ do {
+ int i;
+
+ for(ret_val = NULL, i = 0; i < 32; i++) {
+ /* skip empty entries */
+ if(!proc->p_inbox[i].sender) {
+ continue;
+ }
+
+ if(proc->p_inbox[i].sender == from || from == PID_ANY) {
+ ret_val = proc->p_inbox[i].msg;
+ proc->p_inbox[i].msg = NULL;
+ proc->p_inbox[i].sender = 0;
+
+ break;
+ }
+ }
+
+ if(!ret_val) {
+ process_wait(from);
+ }
+ } while(!ret_val);
+
+ return(ret_val);
+}
+
+int process_wait(pid_t pid)
+{
+ process_t *cproc;
+ int ret_val;
+
+ ret_val = -EFAULT;
+ cproc = process_get_current();
+
+ if(cproc) {
+ sched_wait(pid);
+ }
+
+ return(ret_val);
+}
+
+int process_signal(pid_t pid)
+{
+ process_t *dproc;
+ int ret_val;
+
+ ret_val = -ENOENT;
+ dproc = process_lookup(pid);
+
+ if(dproc) {
+ sched_signal(pid);
+ ret_val = 0;
+ }
+
+ return(ret_val);
+}
+
+void* process_get_tasks(process_t *proc)
+{
+ return(proc->p_tasks);
+}
+
+pid_t process_get_id(process_t *proc)
+{
+ return(proc->p_id);
+}
#include <corax/types.h>
#include <corax/heap.h>
#include <corax/errno.h>
+#include <process.h>
#include <debug.h>
#include <arch.h>
/* FIXME: This should be per-processor */
static struct task_queue *_readyq = NULL;
+static struct task_queue *_waitq = NULL;
static void _nq(struct task_queue **q, task_t *t)
{
return(ret_val);
}
+static void _unq(struct task_queue **q, task_t *t)
+{
+ while(*q) {
+ if((*q)->data == t) {
+ struct task_queue *freeme;
+
+ freeme = *q;
+ *q = freeme->next;
+
+ kfree(freeme);
+ break;
+ }
+
+ q = &((*q)->next);
+ }
+
+ return;
+}
+
void sched_tick(void)
{
task_t *cur_task;
return;
}
+void sched_wait(pid_t pid)
+{
+ task_t *cur_task;
+
+ cur_task = task_get_current();
+
+ cur_task->t_waitpid = pid;
+ cur_task->t_state = TASK_STATE_WAITING;
+
+ /* put the current task on the wait queue */
+ _nq(&_waitq, cur_task);
+
+ /* get a task from the ready queue and execute it */
+ cur_task = _dq(&_readyq);
+
+ if(cur_task) {
+ task_switch(cur_task);
+ } else {
+ dbg_printf("This should not have happened\n");
+ }
+
+ return;
+}
+
int sched_enqueue(task_t *t)
{
int ret_val;
return(ret_val);
}
+
+int sched_signal(pid_t pid)
+{
+ task_t *cur_task;
+ process_t *proc;
+ int ret_val;
+
+ ret_val = -ENOENT;
+
+ cur_task = task_get_current();
+ proc = process_lookup(pid);
+
+ if(proc) {
+ task_t *t;
+
+ /* FIXME: Implement processes with multiple tasks */
+ for(t = process_get_tasks(proc); t; t = NULL) {
+ if(t->t_state != TASK_STATE_WAITING) {
+ continue;
+ }
+
+ if(t->t_waitpid == cur_task->t_pid || t->t_waitpid == PID_ANY) {
+ /* remove task from waitq */
+ _unq(&_waitq, t);
+
+ t->t_waitpid = 0;
+ t->t_state = TASK_STATE_READY;
+
+ /* put task on readyq */
+ _nq(&_readyq, t);
+ ret_val = 0;
+
+ break;
+ }
+ }
+ }
+
+ return(ret_val);
+}
u32_t t_tslice;
u32_t t_rslice;
void *t_proc;
+ pid_t t_waitpid;
+ pid_t t_pid;
} __attribute__((packed));
int cpu_get_id(void);
#define __PROCESS_H
#include <corax/types.h>
+#include <corax/ipc.h>
typedef struct process process_t;
int process_flookup(process_t*, int);
process_t* process_get_current(void);
+process_t* process_lookup(pid_t);
int process_memcpy_ptok(process_t*, void*, void*, u32_t);
int process_memcpy_ktop(process_t*, void*, void*, u32_t);
int process_memcpy_ptop(process_t*, void*, process_t*, void*, u32_t);
+int process_inbox_put(process_t*, struct cxmsg*);
+struct cxmsg* process_inbox_get(pid_t);
+
+int process_wait(pid_t);
+int process_signal(pid_t);
+
+void* process_get_tasks(process_t*);
+pid_t process_get_id(process_t*);
+
#endif /* __PROCESS_H */
popl %ebx
ret
+
+.global cxsend
+cxsend:
+ pushl %ebx
+
+ movl $IPC_SEND, %eax
+ movl 8(%esp), %ebx
+ movl 12(%esp), %ecx
+ int $SYSCALL_CXIPC
+
+ popl %ebx
+ ret
+
+.global cxrecv
+cxrecv:
+ pushl %ebx
+
+ movl $IPC_RECV, %eax
+ movl 8(%esp), %ebx
+ movl 12(%esp), %ecx
+ int $SYSCALL_CXIPC
+
+ popl %ebx
+ ret
+
+.global cxsendrecv
+cxsendrecv:
+ pushl %ebx
+
+ movl $IPC_SENDRECV, %eax
+ movl 8(%esp), %ebx
+ movl 12(%esp), %ecx
+ int $SYSCALL_CXIPC
+
+ popl %ebx
+ ret