-OBJECTS = main.o process.o cxipc.o syscall.o posixcall.o net.o signal.o \
- mailbox.o elf.o
+OBJECTS = main.o process.o cxipc.o posixcall.o signal.o mailbox.o elf.o
OUTPUT = core.o
INCLUDES = -I../include -I../../include -I../..
CFLAGS += $(INCLUDES) -nostdinc -fno-builtin -fno-builtin-memcpy
+++ /dev/null
-#include <config.h>
-#include <corax/types.h>
-#include <corax/errno.h>
-#include <corax/syscall.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <poll.h>
-#include <debug.h>
-#include "socket.h"
-#include <process.h>
-#include <sys/mbuf.h>
-
-int sys_socket(int domain, int type, int protocol)
-{
- int ret_val;
-
- /*
- * The Corax network stack isn't as complicated as the
- * BSD or Linux network stacks, so this is all we have
- * to do here.
- */
- ret_val = socreate(domain, type, protocol);
-
-#if FEATURE(DEBUG_NET)
- dbg_printf("socreate(0x%08x, 0x%08x, 0x%08x) = 0x%08x\n", domain, type, protocol, ret_val);
-#endif /* FEATURE(DEBUG_NET) */
-
- return(ret_val);
-}
-
-int sys_close(int procfd)
-{
- process_t *cproc;
- int ret_val;
-
- /*
- * The fd that was passed is a per-process "procfd", but soclose() needs
- * the global "sockfd" - so we have to look it up first.
- */
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- ret_val = process_flookup(cproc, procfd);
-
- /*
- * If ret_val is not negative, it holds the sockfd to be
- * closed. Otherwise it holds an error number that we're
- * going to return to the caller.
- */
- if(ret_val >= 0) {
-#if FEATURE(DEBUG_NET)
- dbg_printf("soclose(0x%08x)\n", ret_val);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = soclose(ret_val);
- }
- }
-
- return(ret_val);
-}
-
-int sys_sendto(int procfd, const void *buf, size_t len, int flags,
- const struct sockaddr *dest_addr, socklen_t addrlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
-#if 0
- struct mbuf *m;
-
- m = mbuf_alloc();
-
- if(m) {
- /* FIXME: implement sosend() function and call it from here */
- ret_val = -ENOSYS;
- } else {
- ret_val = -ENOMEM;
- }
-#endif
- }
- }
-
- return(ret_val);
-}
-
-int sys_recvfrom(int procfd, void *buf, size_t len, int flags,
- struct sockaddr *src_addr, socklen_t *addrlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- /* FIXME: Implement sorecv() function and call it from here */
- ret_val = -ENOSYS;
- }
- }
-
- return(ret_val);
-}
-
-int sys_connect(int procfd, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- /* FIXME: Implement soconnect() */
- ret_val = -ENOSYS;
- }
- }
-
- return(ret_val);
-}
-
-int sys_listen(int procfd, int backlog)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- /* FIXME: Implement solisten() */
- ret_val = -ENOSYS;
- }
- }
-
- return(ret_val);
-}
-
-int sys_accept(int procfd, struct sockaddr *addr, socklen_t *addrlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- /* FIXME: Implement soaccept() */
- ret_val = -ENOSYS;
- }
- }
-
- return(ret_val);
-}
-
-int sys_setsockopt(int procfd, int level, int optname,
- const void *optval, socklen_t optlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- if(level != SOL_SOCKET) {
- ret_val = -EINVAL;
- goto gtfo;
- }
-
- ret_val = -EFAULT;
- cproc = process_get_current();
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- char koptbuf[128];
- socklen_t koptlen;
-
- /*
- * The memory referenced by `optval' is in the process's
- * address space, so we have to copy it into the kernel's
- * address space before being able to use it. Since the
- * process's buffer may sit on the boundary of two non-
- * consecutive pages, we can't just use the linear
- * address.
- */
-
- koptlen = optlen < sizeof(koptbuf) ? optlen : sizeof(koptbuf);
- process_memcpy_ptok(cproc, koptbuf, (void*)optval, koptlen);
-
- ret_val = sosetopt(sockfd, optname, koptbuf, koptlen);
- }
- }
-
-gtfo:
- return(ret_val);
-}
-
-int sys_getsockopt(int procfd, int level, int optname,
- void *optval, socklen_t *optlen)
-{
- process_t *cproc;
- int sockfd;
- int ret_val;
-
- /*
- * This function is essentially the same as sys_setsockopt(), except that it
- * calls sogetopt() instead of sosetopt(), and the buffer is copied after that
- * call, in the opposite direction.
- */
-
- if(level != SOL_SOCKET) {
- ret_val = -EINVAL;
- goto gtfo;
- }
-
- ret_val = -EFAULT;
- cproc = process_get_current();
-
- if(cproc) {
- sockfd = process_flookup(cproc, procfd);
-
- if(sockfd < 0) {
- ret_val = sockfd;
- } else {
- char koptbuf[128];
- socklen_t koptlen;
-
- koptlen = *optlen < sizeof(koptbuf) ? *optlen : sizeof(koptbuf);
-
- ret_val = sogetopt(sockfd, optname, koptbuf, &koptlen);
-
- if(!ret_val) {
- /* return data to user-space if the call was successful */
-
- process_memcpy_ktop(cproc, optval, koptbuf, koptlen);
- /* as annoying (and unlikely) as it may be, optlen may also sit on a page-boundary */
- process_memcpy_ktop(cproc, optlen, &koptlen, sizeof(koptlen));
- }
- }
- }
-
-gtfo:
- return(ret_val);
-}
-
-int sys_shutdown(int procfd, int how)
-{
- process_t *cproc;
- int ret_val;
-
- ret_val = -EFAULT;
- cproc = process_get_current();
-
- if(cproc) {
- /* attempt to look up the system-wide sockfd for this procfd */
- ret_val = process_flookup(cproc, procfd);
-
- /* pass on the arguments to soshutdown(), if the lookup was successful */
- if(ret_val >= 0) {
- ret_val = soshutdown(ret_val, how);
- }
- }
-
- return(ret_val);
-}
-
-int sys_select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout)
-{
- return(-ENOSYS);
-}
-
-int sys_poll(struct pollfd *fds, nfds_t nfds, int timeout)
-{
- return(-ENOSYS);
-}
-
-int sys_bind(int procfd, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- process_t *cproc;
- int ret_val;
-
- cproc = process_get_current();
- ret_val = -EFAULT;
-
- if(cproc) {
- ret_val = process_flookup(cproc, procfd);
-
- if(ret_val > 0) {
- struct sockaddr kaddr;
- socklen_t kaddrlen;
-
- /* copy address structure to the kernel space */
- kaddrlen = addrlen < sizeof(kaddr) ? addrlen : sizeof(kaddr);
- process_memcpy_ptok(cproc, &kaddr, (void*)addr, kaddrlen);
-
- ret_val = sobind(ret_val, &kaddr, kaddrlen);
- }
- }
-
- return(ret_val);
-}
-
-int sys_cxnet(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
-{
- int ret_val;
-
- ret_val = -EFAULT;
-
- switch(arg0) {
- case SYS_SOCKET:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_socket(0x%08x, 0x%08x, 0x%08x)\n",
- arg1, arg2, arg3);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_socket((int)arg1, (int)arg2, (int)arg3);
-
- break;
-
- case SYS_CLOSE:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_close(0x%08x)\n",
- arg1);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_close((int)arg1);
-
- break;
-
- case SYS_SENDTO:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_sendto(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
- arg1, arg2, arg3, arg4, arg5, arg6);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_sendto((int)arg1, (const void*)arg2, (size_t)arg3, (int)arg4,
- (const struct sockaddr*)arg5, (socklen_t)arg6);
-
- break;
-
- case SYS_RECVFROM:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_recvfrom(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
- arg1, arg2, arg3, arg4, arg5, arg6);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_recvfrom((int)arg1, (void*)arg2, (size_t)arg3, (int)arg4,
- (struct sockaddr*)arg5, (socklen_t*)arg6);
-
- break;
-
- case SYS_CONNECT:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_connect(0x%08x, %p, 0x%08x)\n",
- arg1, arg2, arg3);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_connect((int)arg1, (const struct sockaddr*)arg2,
- (socklen_t)arg3);
-
- break;
-
- case SYS_LISTEN:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_listen(0x%08x, 0x%08x)\n",
- arg1, arg2);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_listen((int)arg1, (int)arg2);
-
- break;
-
- case SYS_ACCEPT:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_accept(0x%08x, %p, %p)\n",
- arg1, arg2, arg3);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_accept((int)arg1, (struct sockaddr*)arg2,
- (socklen_t*)arg3);
-
- break;
-
- case SYS_SETSOCKOPT:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_setsockopt(0x%08x, 0x%08x, 0x%08x, %p, 0x%08x)\n",
- arg1, arg2, arg3, arg4, arg5);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_setsockopt((int)arg1, (int)arg2, (int)arg3,
- (const void*)arg4, (socklen_t)arg5);
-
- break;
-
- case SYS_GETSOCKOPT:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_getsockopt(0x%08x, 0x%08x, 0x%08x, %p, %p)\n",
- arg1, arg2, arg3, arg4, arg5);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_getsockopt((int)arg1, (int)arg2, (int)arg3,
- (void*)arg4, (socklen_t*)arg5);
-
- break;
-
- case SYS_SHUTDOWN:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_shutdown(0x%08x, 0x%08x)\n",
- arg1, arg2);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_shutdown((int)arg1, (int)arg2);
-
- break;
-
- case SYS_SELECT:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_select(0x%08x, %p, %p, %p, %p)\n",
- arg1, arg2, arg3, arg4, arg5);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_select((int)arg1, (fd_set*)arg2, (fd_set*)arg3,
- (fd_set*)arg4, (struct timeval*)arg5);
-
- break;
-
- case SYS_POLL:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_poll(%p, 0x%08x, 0x%08x)\n",
- arg1, arg2, arg3);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_poll((struct pollfd*)arg1, (nfds_t)arg2, (int)arg3);
-
- break;
-
- case SYS_BIND:
-#if FEATURE(DEBUG_NET)
- dbg_printf("sys_bind(0x%08x, %p, 0x%08x)\n",
- arg1, arg2, arg3);
-#endif /* FEATURE(DEBUG_NET) */
-
- ret_val = sys_bind((int)arg1, (const struct sockaddr*)arg2,
- (socklen_t)arg3);
-
- break;
-
- default:
- ret_val = -ENOSYS;
- break;
- }
-
- return(ret_val);
-}
+++ /dev/null
-#ifndef __FD_H
-#define __FD_H
-
-#define FD_VALID (1 << 0)
-
-struct fd {
- int fd_flags;
- int fd_socknum;
-};
-
-#endif /* __FD_H */
+++ /dev/null
-#include <config.h>
-#include <corax/types.h>
-#include <corax/errno.h>
-#include <sys/mbuf.h>
-#include <debug.h>
-#define ALLOC_SIZE 128
-
-static struct mbuf *_unused;
-
-static struct mbuf* _alloc_mbufs(void)
-{
- struct mbuf *m;
-
- m = kmalloc(sizeof(*m) * ALLOC_SIZE);
-
- if(m) {
- int n;
-
- /* skip the last mbuf so its m_next member remains NULL */
- for(n = 0; n < (ALLOC_SIZE - 1); n++) {
- m[n].m_next = m + 1;
- }
- }
-
- return(m);
-}
-
-struct mbuf* mbuf_alloc(void)
-{
- struct mbuf *m;
-
- if(!_unused) {
- /* need to allocate more mbufs */
- _unused = _alloc_mbufs();
- }
-
- m = _unused;
-
- if(m) {
- _unused = m->m_next;
-
- /*
- * Clear the mbuf's m_next member so the caller can't access more
- * mbufs than they're supposed to
- */
- m->m_next = NULL;
- }
-
- return(m);
-}
-
-void mbuf_free(struct mbuf *m)
-{
- /* clear the mbuf and prepend it to the list of unused mbufs */
- memset(m, 0, sizeof(*m));
-
- m->m_next = _unused;
- _unused = m;
-
- return;
-}
+++ /dev/null
-#include <config.h>
-#include <crxstd.h>
-#include <unistd.h>
-#include <corax/errno.h>
-#include <corax/heap.h>
-
-extern int wait(int*);
-extern void heap_init(void*, u32_t);
-
-static inline void _init_heap(void)
-{
- u32_t init_size;
- u32_t base, end;
-
- init_size = 0x1000;
- end = (unsigned)sbrk(init_size);
- base = end - 0x1000;
-
- heap_init((void*)base, init_size);
-
- return;
-}
-
-void _net(void)
-{
- struct cxmsg msg;
- int len;
-
- /* initialize the heap */
- _init_heap();
-
- while(1) {
- len = cxrecv(PID_ANY, &msg);
-
- len = 0;
-
- if(len > 0) {
- /* FIXME: handle message */
-
- msg.cm_type = (u32_t)-ENOSYS;
- msg.cm_dst = msg.cm_src;
- cxsend(msg.cm_dst, &msg);
- }
- }
-
- return;
-}
#include <unistd.h>
#include <debug.h>
#include <crxstd.h>
-#include "fd.h"
#include "sched.h"
#include "mailbox.h"
+++ /dev/null
-#include <config.h>
-#include <corax/types.h>
-#include <corax/heap.h>
-#include <corax/errno.h>
-#include <process.h>
-#include <debug.h>
-#include <arch.h>
-
-struct task_queue {
- struct task_queue *next;
- task_t *data;
-};
-
-/* 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)
-{
- struct task_queue *item;
-
- item = kmalloc(sizeof(*item));
-
- if(item) {
- item->data = t;
- item->next = NULL;
-
- /* get a pointer to the end of the queue */
- while(*q) {
- q = &((*q)->next);
- }
-
- *q = item;
- }
-
- return;
-}
-
-static task_t* _dq(struct task_queue **q)
-{
- struct task_queue *cur;
- task_t *ret_val;
-
- cur = *q;
- ret_val = NULL;
-
- if(cur) {
- *q = cur->next;
- ret_val = cur->data;
-
- kfree(cur);
- }
-
- return(ret_val);
-}
-
-static int _unq(struct task_queue **q, task_t *t)
-{
- int ret_val;
-
- ret_val = -ENOENT;
-
- while(*q) {
- if((*q)->data == t) {
- struct task_queue *freeme;
-
- freeme = *q;
- *q = freeme->next;
-
- kfree(freeme);
- ret_val = 0;
- break;
- }
-
- q = &((*q)->next);
- }
-
- return(ret_val);
-}
-
-void sched_tick(void)
-{
- task_t *cur_task;
-
- cur_task = task_get_current();
-
- /* skip all this if the task is exitting */
- if(cur_task && cur_task->t_state != TASK_STATE_EXIT) {
- /* check if running task has not used up it's quantum yet */
- if(cur_task->t_rslice) {
- cur_task->t_rslice--;
- return;
- }
-
- /* task's time is up - reschedule */
- cur_task->t_rslice = cur_task->t_tslice;
- cur_task->t_state = TASK_STATE_READY;
-
- /* put the task back on the ready queue */
- _nq(&_readyq, cur_task);
- }
-
- /* get the next task from the ready queue */
- cur_task = _dq(&_readyq);
-
- if(cur_task) {
-#if FEATURE(DEBUG_SCHED)
- dbg_printf("Switch to task %p [%02x]\n", cur_task, cur_task->t_state);
-#endif /* FEATURE(DEBUG_SCHED) */
- task_switch(cur_task);
-#if FEATURE(DEBUG_SCHED)
- dbg_printf("Returned to task %p\n", task_get_current());
-#endif /* FEATURE(DEBUG_SCHED) */
- cur_task = task_get_current();
-
- dbg_printf("Returned to task %p [state=%u]\n", cur_task, cur_task->t_state);
- /* the task state may have been set to TASK_STATE_SIGNAL */
- cur_task->t_state = TASK_STATE_RUNNING;
-
- } else {
- dbg_printf("This should not have happened\n");
- }
-
- 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;
-
- ret_val = -EINVAL;
-
- /*
- * Don't allow tasks to be enqueued unless they are in
- * state TASK_STATE_NEW or TASK_STATE_FORKED
- */
-
- if(t->t_state == TASK_STATE_NEW ||
- t->t_state == TASK_STATE_FORKED) {
- _nq(&_readyq, t);
- ret_val = 0;
- }
-
- return(ret_val);
-}
-
-int sched_dequeue(task_t *t)
-{
- int ret_val;
-
- ret_val = -EINVAL;
-
- if(t) {
- /* remove the task from the ready queue */
- ret_val = _unq(&_readyq, t);
-
- /*
- * Attempt to remove the task from the wait queue
- * if it wasn't on the ready queue.
- */
- if(ret_val < 0) {
- ret_val = _unq(&_waitq, t);
- }
- }
-
- 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);
-}
-
-static int __sched_raise_all(process_t *proc, task_t *task, void *data)
-{
- return(sched_task_raise(task));
-}
-
-int sched_raise(pid_t pid)
-{
- process_t *proc;
- int ret_val;
-
- ret_val = -ENOENT;
- proc = process_lookup(pid);
-
- if(proc) {
- ret_val = process_task_foreach(proc, __sched_raise_all, NULL);
- }
-
- return(ret_val);
-}
-
-int sched_task_raise(task_t *t)
-{
- int ret_val;
-
- ret_val = -EINVAL;
-
- if(t) {
- ret_val = -EBADFD;
-
- task_lock(t);
-
- if(t->t_state == TASK_STATE_WAITING) {
- ret_val = _unq(&_waitq, t);
-
- if(!ret_val) {
- _nq(&_readyq, t);
- t->t_state = TASK_STATE_SIGNAL;
- }
- }
-
- task_unlock(t);
- }
-
- return(ret_val);
-}
-
-int sched_task_suspend(task_t *t)
-{
- task_t *ctask;
- int ret_val;
-
- ret_val = -EALREADY;
- ctask = task_get_current();
-
- if(!t) {
- t = ctask;
- }
-
- task_lock(t);
-
- if(t->t_state != TASK_STATE_WAITING) {
- t->t_state = TASK_STATE_WAITING;
-
- /* remove the task from the ready queue and put it on the wait queue */
- ret_val = _unq(&_readyq, t);
-
- if(ret_val >= 0) {
- _nq(&_waitq, t);
- }
- }
-
- task_unlock(t);
-
- if(t == ctask) {
- /* schedule a different task */
- sched_tick();
- }
-
- return(ret_val);
-}
-
-int sched_task_resume(task_t *t)
-{
- int ret_val;
-
- /*
- * Make sure the task is currently in the TASK_STATE_WAITING state.
- * If it is, change its state to TASK_STATE_READY.
- */
- task_lock(t);
-
- if(t->t_state == TASK_STATE_WAITING) {
- t->t_state = TASK_STATE_READY;
- ret_val = 0;
- } else {
- ret_val = -EBUSY;
- }
-
- task_unlock(t);
-
- /* if the task was waiting, remove it from the waitq and add it to the readyq */
- if(!ret_val) {
- ret_val = _unq(&_waitq, t);
-
- if(ret_val >= 0) {
- _nq(&_readyq, t);
- }
- }
-
- return(ret_val);
-}
+++ /dev/null
-#include <config.h>
-#include <corax/types.h>
-#include <corax/heap.h>
-#include <corax/errno.h>
-#include <sys/socket.h>
-#include <arch.h>
-#include "socket.h"
-#include "process.h"
-
-static struct socket *_sockets[CONFIG_SOCKET_MAX];
-static int _nsockets;
-
-#define SOCKET_PREALLOC ((void*)0xffffffff)
-
-static inline int allocsockfd(void)
-{
- int ret_val;
- int i;
-
- ret_val = -ENFILE;
-
- if(_nsockets < CONFIG_SOCKET_MAX) {
- _nsockets++;
-
- for(i = 0; i < CONFIG_SOCKET_MAX; i++) {
- if(!_sockets[i]) {
- _sockets[i] = SOCKET_PREALLOC;
- ret_val = i;
- break;
- }
- }
- }
-
- return(ret_val);
-}
-
-static inline int freesockfd(int fd)
-{
- int ret_val;
-
- ret_val = -EINVAL;
-
- if(fd >= 0 && fd < CONFIG_SOCKET_MAX) {
- ret_val = -EBADF;
-
- if(_sockets[fd]) {
- _sockets[fd] = NULL;
- _nsockets--;
- ret_val = 0;
- }
- }
-
- return(ret_val);
-}
-
-int socreate(int dom, int type, int proto)
-{
- struct task *cur_task;
- struct process *cur_proc;
-#if 0
- struct protosw *psw;
-#endif
- struct socket *so;
- int ret_val;
- int sfd;
- int pfd;
-
- sfd = -1;
- pfd = -1;
- ret_val = -EINVAL;
-
- /* first of all, make sure all input makes sense */
- if(!PF_VALID(dom) || !SOCK_VALID(type)) {
- goto gtfo;
- }
-
- ret_val = -ENFILE;
-
- /* check if the system-wide socket limit has been hit */
- if(_nsockets >= CONFIG_SOCKET_MAX) {
- goto gtfo;
- }
-
- /*
- * This function is only executed as a result of a syscall,
- * so it's safe to assume that task_get_current() will never
- * return NULL.
- */
- cur_task = task_get_current();
- cur_proc = cur_task->t_proc;
-
- sfd = allocsockfd();
-
- if(sfd < 0) {
- ret_val = sfd;
- goto gtfo;
- }
-
- pfd = process_falloc(cur_proc, sfd);
-
- if(pfd < 0) {
- ret_val = pfd;
- goto gtfo;
- }
-
-#if 0
- /* FIXME: Look up the domain/protocol */
- if(proto) {
- psw = pffindproto(dom, proto, type);
- } else {
- psw = pffindtype(dom, type);
- }
-
- if(!psw) {
- ret_val = -EPROTONOSUPPORT;
- goto gtfo;
- }
-
- if(psw->pr_type != type) {
- ret_val = -EPROTOTYPE;
- goto gtfo;
- }
-#endif
-
- so = kmalloc(sizeof(*so));
-
- if(!so) {
- ret_val = -ENOMEM;
- goto gtfo;
- }
-
- so->so_type = type;
- so->so_refs = 1;
-#if 0
- so->so_proto = psw;
-#endif
-
- /*
- * FIXME: set SS_PRIV on so->so_state if the calling process is
- * executing as root; initialize remaining members, attach the
- * socket by meansof psw->pr_usrreq(so, PRU_ATTACH, ...).
- * ref: TCP/IP Illustrated Vol. 2, p. 426
- */
-
- _sockets[sfd] = so;
- ret_val = pfd;
-
-gtfo:
- if(ret_val < 0) {
- if(sfd > 0) {
- freesockfd(sfd);
- sfd = -1;
- }
-
- if(cur_proc && pfd > 0) {
- process_ffree(cur_proc, pfd);
- pfd = -1;
- }
-
- if(so) {
- kfree(so);
- so = NULL;
- }
- }
-
- return(ret_val);
-}
-
-int soclose(int sockfd)
-{
- int ret_val;
-
- ret_val = -EINVAL;
-
- if(sockfd >= 0 && sockfd < (sizeof(_sockets) / sizeof(_sockets[0]))) {
- struct socket *so;
-
- ret_val = -EBADF;
- so = _sockets[sockfd];
-
- /*
- * `so' may be SOCKET_PREALLOC, if it is currently being
- * allocated by a different thread - in which case we must
- * leave it alone.
- */
- if(so && so != SOCKET_PREALLOC) {
- /*
- * Reduce the socket's refcount and free it if
- * there are no more references to it.
- */
- so->so_refs--;
-
- if(!so->so_refs) {
- ret_val = sofree(sockfd);
- } else {
- ret_val = 0;
- }
- }
- }
-
- return(ret_val);
-}
-
-int sofree(int sockfd)
-{
- int ret_val;
-
- ret_val = -EINVAL;
-
- /*
- * The same checks should already have been performed by the caller, but
- * better safe than sorry.
- */
- if(sockfd >= 0 && sockfd < (sizeof(_sockets) / sizeof(_sockets[0]))) {
- struct socket *so;
-
- ret_val = -EBADF;
- so = _sockets[sockfd];
-
- if(so && so != SOCKET_PREALLOC) {
- _sockets[sockfd] = NULL;
- _nsockets--;
-
- /* TODO: PRU_DETACH */
- kfree(so);
- }
- }
-
- return(ret_val);
-}
-
-int sosetopt(int sockfd, int opt, const void *data, size_t dlen)
-{
- struct socket *so;
- int ret_val;
-
- /* sanity-check input */
- if(sockfd < 0 || sockfd >= (sizeof(_sockets) / sizeof(_sockets[0])) ||
- !SO_VALID(opt) || !data || !dlen) {
- ret_val = -EINVAL;
- goto gtfo;
- }
-
- so = _sockets[sockfd];
-
- /* make sure sockfd refers to a valid socket */
- if(!so) {
- ret_val = -EBADF;
- goto gtfo;
- }
-
- switch(opt) {
- case SO_SNDBUF:
- case SO_RCVBUF:
- case SO_SNDLOWAT:
- case SO_RCVLOWAT:
- case SO_SNDTIMEO:
- case SO_RCVTIMEO:
- case SO_DEBUG:
- case SO_REUSEADDR:
- case SO_KEEPALIVE:
- case SO_DONTROUTE:
- case SO_BROADCAST:
- case SO_USELOOPBACK:
- case SO_OOBINLINE:
- case SO_LINGER:
- case SO_ERROR:
- case SO_TYPE:
- ret_val = -ENOSYS;
- break;
-
- default:
- /* *should* not be reachable */
- ret_val = -EINVAL;
- break;
- }
-
-gtfo:
- return(ret_val);
-}
-
-int sogetopt(int sockfd, int opt, void *data, size_t *dlen)
-{
- return(-ENOSYS);
-}
-
-int soshutdown(int sockfd, int how)
-{
- return(-ENOSYS);
-}
-
-int sobind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
-{
- return(-ENOSYS);
-}
+++ /dev/null
-#ifndef __SOCKET_H
-#define __SOCKET_H
-
-#include <corax/types.h>
-#if 0
-#include "protocol.h"
-#endif
-
-struct socket {
- u16_t so_type;
- u16_t so_refs;
- /* that's all for now */
-#if 0
- u16_t so_options;
- u16_t so_state;
- u16_t so_linger;
-
- void *so_pcb;
- struct protosw *so_protosw;
-#endif
-};
-
-int socreate(int, int, int);
-int soclose(int);
-int sofree(int);
-
-int sosetopt(int, int, const void*, size_t);
-int sogetopt(int, int, void*, size_t*);
-int soshutdown(int, int);
-int sobind(int, struct sockaddr*, socklen_t);
-
-#endif /* __SOCKET_H */
+++ /dev/null
-#include <config.h>
-#include <crxstd.h>
-#include <corax/errno.h>
-#include <stddef.h>
-
-#define STDIN 0
-#define STDOUT 1
-#define STDERR 2
-
-static int stdio_read(int fd, char *dst, size_t dsize)
-{
- return(-ENOSYS);
-}
-
-static int stdio_write(int fd, const char *src, const size_t slen)
-{
- return(-ENOSYS);
-}
-
-static int stdio_flush(int fd)
-{
- if(fd < STDIN) {
- return(-EINVAL);
- }
-
- if(fd > STDERR) {
- return(-EBADF);
- }
-
- return(0);
-}
-
-struct fd {
- int f_id;
-};
-
-struct proc {
- pid_t p_pid;
- int p_nfds;
-
- struct fd *p_fds;
-};
-
-void _stdio(void)
-{
- struct state state;
- struct cxmsg msg;
- int err;
-
- while(1) {
- err = cxrecv(PID_ANY, &msg);
- err = 0;
-
- /*
- * The `cm_len' member includes the number of bytes consumed by the header
- * of the message, so we need to substract offsetof(struct cxmsg, cm_data)
- * to get the number of bytes that are supposed to be in the payload.
- */
-
- if((msg.cm_len - offsetof(struct cxmsg, cm_stdio.sio_data)) > msg.cm_len) {
- /* underflow - discard message */
- continue;
- }
-
- msg.cm_len -= offsetof(struct cxmsg, cm_stdio.sio_data);
-
- if(msg.cm_len > (sizeof(msg.cm_data) - offsetof(struct cxmsg, cm_stdio.sio_data))) {
- /* message allegedly contains more data than possible - malicious input? */
- continue;
- }
-
- /* msg.cm_len now contains the number of bytes in sio_data */
- if(err > 0) {
- msg.cm_dst = msg.cm_src;
- msg.cm_type = CX_MSG_RETVAL;
- msg.cm_retval = _handle_msg(&msg);
- msg.cm_len = sizeof(msg.cm_hdr) + sizeof(int);
-
- cxsend(msg.cm_dst, &msg);
- }
- }
-
- return;
-}
-
-static int _handle_msg(struct cxmsg *msg)
-{
- switch(msg->cm_type) {
- case CX_OPEN:
- case CX_CLOSE:
- case CX_READ:
- case CX_WRITE:
- case CX_FCNTL:
- err = -ENOSYS;
- break;
-
- case CX_MSG_READ:
- err = stdio_read(msg->cm_stdio.sio_fd,
- msg->cm_stdio.sio_data,
- msg->cm_len);
- break;
-
- case CX_MSG_WRITE:
- err = stdio_write(msg->cm_stdio.sio_fd,
- msg->cm_stdio.sio_data,
- msg->cm_len);
- break;
-
- case CX_MSG_FLUSH:
- err = stdio_flush(msg->cm_stdio.sio_fd);
- break;
-
- default:
- /* malformed input? */
- err = -EINVAL;
- break;
- }
-}
+++ /dev/null
-#define __ASSEMBLY_SOURCE
-
-#include <corax/syscall.h>
-
-.global socket
-socket:
- pushl %ebx
-
- movl $SYS_SOCKET, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global close
-close:
- pushl %ebx
-
- movl $SYS_CLOSE, %eax
- movl 8(%esp), %ebx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global sendto
-sendto:
- /*
- * sendto() and recvfrom() have 6 arguments, so we also have
- * to preserve the ebp register in order to repurpose it
- */
- pushl %ebx
- pushl %ebp
-
- movl $SYS_SENDTO, %eax
- movl 12(%esp), %ebx
- movl 16(%esp), %ecx
- movl 20(%esp), %edx
- movl 24(%esp), %esi
- movl 28(%esp), %edi
- movl 32(%esp), %ebp
- int $SYSCALL_CXNET
-
- popl %ebp
- popl %ebx
- ret
-
-.global recvfrom
-recvfrom:
- pushl %ebx
- pushl %ebp
-
- movl $SYS_RECVFROM, %eax
- movl 12(%esp), %ebx
- movl 16(%esp), %ecx
- movl 20(%esp), %edx
- movl 24(%esp), %esi
- movl 28(%esp), %edi
- movl 32(%esp), %ebp
- int $SYSCALL_CXNET
-
- popl %ebp
- popl %ebx
- ret
-
-.global connect
-connect:
- pushl %ebx
-
- movl $SYS_CONNECT, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global listen
-listen:
- pushl %ebx
-
- movl $SYS_LISTEN, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global accept
-accept:
- pushl %ebx
-
- movl $SYS_ACCEPT, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global setsockopt
-setsockopt:
- pushl %ebx
-
- movl $SYS_SETSOCKOPT, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- movl 20(%esp), %esi
- movl 24(%esp), %edi
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global getsockopt
-getsockopt:
- pushl %ebx
-
- movl $SYS_GETSOCKOPT, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- movl 20(%esp), %esi
- movl 24(%esp), %edi
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global shutdown
-shutdown:
- pushl %ebx
-
- movl $SYS_SHUTDOWN, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global select
-select:
- pushl %ebx
-
- movl $SYS_SELECT, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- movl 20(%esp), %esi
- movl 24(%esp), %edi
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global poll
-poll:
- pushl %ebx
-
- movl $SYS_POLL, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
-.global bind
-bind:
- pushl %ebx
-
- movl $SYS_BIND, %eax
- movl 8(%esp), %ebx
- movl 12(%esp), %ecx
- movl 16(%esp), %edx
- int $SYSCALL_CXNET
-
- popl %ebx
- ret
-
- .global sleep
-sleep:
- pushl %ebx
-
- movl $SYS_SLEEP, %eax
- movl 8(%esp), %ebx
- int $SYSCALL_POSIX
-
- popl %ebx
- ret
-
- .global wait
-wait:
- pushl %ebx
-
- movl $SYS_WAIT, %eax
- movl 8(%esp), %ebx
- int $SYSCALL_POSIX
-
- popl %ebx
- ret