Return bool from reset_alarm_* apis.
[akaros.git] / kern / src / frontend.c
index fd9cf78..75f85c9 100644 (file)
 #include <frontend.h>
 #include <syscall.h>
 #include <smp.h>
+#include <slab.h>
+#include <arch/arch.h>
 
 volatile int magic_mem[10];
 
 void
 frontend_proc_init(struct proc *SAFE p)
 {
+#ifdef CONFIG_APPSERVER
        pid_t parent_id = p->ppid, id = p->pid;
        int32_t errno;
        if(frontend_syscall(parent_id,APPSERVER_SYSCALL_proc_init,id,0,0,0,&errno))
                panic("Front-end server couldn't initialize new process!");
+#endif
 }
 
 void
 frontend_proc_free(struct proc *SAFE p)
 {
+#ifdef CONFIG_APPSERVER
        int32_t errno;
        if(frontend_syscall(0,APPSERVER_SYSCALL_proc_free,p->pid,0,0,0,&errno))
                panic("Front-end server couldn't free process!");
+#endif
 }
 
-void* user_memdup(struct proc* p, const void* va, int len)
+struct kmem_cache* struct_file_cache;
+void file_init()
 {
-       void* kva = NULL;
-       if(len < 0 || (kva = kmalloc(len,0)) == NULL)
-               return ERR_PTR(-ENOMEM);
-       if(memcpy_from_user(p,kva,va,len))
-       {
-               kfree(kva);
-               return ERR_PTR(-EINVAL);
-       }
-
-       return kva;
+       struct_file_cache = kmem_cache_create("struct_file",
+                                             sizeof(struct file), 8, 0, 0, 0);
 }
 
-void* user_memdup_errno(struct proc* p, const void* va, int len)
+/* will zero anything in the page after the EOF */
+error_t file_read_page(struct file* f, physaddr_t pa, size_t pgoff)
 {
-       void* kva = user_memdup(p,va,len);
-       if(IS_ERR(kva))
-       {
-               set_errno(current_tf,-PTR_ERR(kva));
-               return NULL;
-       }
-       return kva;
+       int ret = frontend_syscall(0,APPSERVER_SYSCALL_pread,f->fd,pa,PGSIZE,
+                                  pgoff*PGSIZE,NULL);
+       if(ret >= 0)
+               memset(KADDR(pa)+ret,0,PGSIZE-ret);
+       return ret;
 }
 
-void user_memdup_free(struct proc* p, void* va)
+struct file* file_open_from_fd(struct proc* p, int fd)
 {
-       kfree(va);
-}
+       struct file* f = NULL;
+       if(!(f = kmem_cache_alloc(struct_file_cache,0)))
+               goto out;
 
-char* user_strdup(struct proc* p, const char* va0, int max)
-{
-       max++;
-       char* kbuf = (char*)kmalloc(PGSIZE,0);
-       if(kbuf == NULL)
-               return ERR_PTR(-ENOMEM);
-
-       int pos = 0, len = 0;
-       const char* va = va0;
-       while(max > 0 && len == 0)
+       f->fd = frontend_syscall(p->pid,APPSERVER_SYSCALL_kdup,fd,0,0,0,NULL);
+       if(f->fd == -1)
        {
-               int thislen = MIN(PGSIZE-(intptr_t)va%PGSIZE,max);
-               if(memcpy_from_user(p,kbuf,va,thislen))
-               {
-                       kfree(kbuf);
-                       return ERR_PTR(-EINVAL);
-               }
-
-               const char* nullterm = memchr(kbuf,0,thislen);
-               if(nullterm)
-                       len = pos+(nullterm-kbuf)+1;
-
-               pos += thislen;
-               va += thislen;
-               max -= thislen;
+               kmem_cache_free(struct_file_cache,f);
+               f = NULL;
+               goto out;
        }
+       spinlock_init(&f->lock);
+       f->refcnt = 1;
 
-       kfree(kbuf);
-       return len ? user_memdup(p,va0,len) : ERR_PTR(-EINVAL);
+out:
+       return f;
 }
 
-char* user_strdup_errno(struct proc* p, const char* va, int max)
+struct file* file_open(const char* path, int oflag, int mode)
 {
-       void* kva = user_strdup(p,va,max);
-       if(IS_ERR(kva))
+       struct file* f = NULL;
+       // although path is a kernel pointer, it may be below KERNBASE.
+       // fix that if so.
+       char* malloced = NULL;
+       if((uintptr_t)path < KERNBASE)
        {
-               set_errno(current_tf,-PTR_ERR(kva));
-               return NULL;
+               size_t len = strlen(path)+1;
+               malloced = kmalloc(len,0);
+               if(!malloced)
+                       goto out;
+               path = memcpy(malloced,path,len);
        }
-       return kva;
-}
 
-int memcpy_to_user_errno(struct proc* p, void* dst, const void* src,
-                                int len)
-{
-       if(memcpy_to_user(p,dst,src,len))
+       if(!(f = kmem_cache_alloc(struct_file_cache,0)))
+               goto out;
+
+       f->fd = frontend_syscall(0,APPSERVER_SYSCALL_open,PADDR(path),
+                                oflag,mode,0,NULL);
+       if(f->fd == -1)
        {
-               set_errno(current_tf,EINVAL);
-               return -1;
+               kmem_cache_free(struct_file_cache,f);
+               f = NULL;
+               goto out;
        }
-       return 0;
-}
+       spinlock_init(&f->lock);
+       f->refcnt = 1;
 
-void* kmalloc_errno(int len)
-{
-       void* kva = NULL;
-       if(len < 0 || (kva = kmalloc(len,0)) == NULL)
-               set_errno(current_tf,ENOMEM);
-       return kva;
+out:
+       if(malloced)
+               kfree(malloced);
+       return f;
 }
 
-error_t read_page(struct proc* p, int fd, physaddr_t pa, int pgoff)
+void file_incref(struct file* f)
 {
-       int errno;
-       int ret = frontend_syscall(p->pid,APPSERVER_SYSCALL_pread,fd,
-                               pa,PGSIZE,pgoff*PGSIZE,&errno);
-
-       if(ret >= 0)
-               memset(KADDR(pa)+ret,0,PGSIZE-ret);
-       return ret;
+       spin_lock(&f->lock);
+       f->refcnt++;
+       spin_unlock(&f->lock);
 }
 
-error_t open_file(struct proc* p, const char* path, int oflag, int mode)
+void file_decref(struct file* f)
 {
-       int errno;
-       return frontend_syscall(p->pid,APPSERVER_SYSCALL_open,PADDR(path),
-                               oflag,mode,0,&errno);
-}
-
-error_t close_file(struct proc* p, int fd)
-{
-       int errno;
-       return frontend_syscall(p->pid,APPSERVER_SYSCALL_close,fd,0,0,0,&errno);
+       // if you decref too many times, you'll clobber memory :(
+       spin_lock(&f->lock);
+       if(--f->refcnt == 0)
+       {
+               int ret = frontend_syscall(0,APPSERVER_SYSCALL_close,f->fd,0,0,0,NULL);
+               assert(ret == 0);
+               kmem_cache_free(struct_file_cache,f);
+       }
+       else
+               spin_unlock(&f->lock);
 }
 
-int user_frontend_syscall(struct proc* p, int n, int a0, int a1, int a2, int a3)
+int frontend_syscall_errno(struct proc* p, int n, int a0, int a1, int a2, int a3)
 {
        int errno, ret = frontend_syscall(p->pid,n,a0,a1,a2,a3,&errno);
        if(errno && p)
-               set_errno(current_tf,errno);
+               set_errno(errno);
        return ret;
 }
 
@@ -160,13 +144,26 @@ int32_t frontend_syscall(pid_t pid, int32_t syscall_num,
                          uint32_t arg0, uint32_t arg1, 
                          uint32_t arg2, uint32_t arg3, int32_t* errno)
 {
+#ifndef CONFIG_APPSERVER
+       warn("No appserver support, requested syscall %d for proc %d", syscall_num,
+            pid);
+       if(errno)
+               *errno = ENOSYS;
+       return -1;
+#endif
+
+#ifdef CONFIG_X86
+       if (!irq_is_enabled())
+               warn("IRQ is disabled in frontend_syscall %d for proc %d\n", syscall_num, pid);
+#endif
+
        static spinlock_t lock = SPINLOCK_INITIALIZER;
        int32_t ret;
 
        // only one frontend request at a time.
        // interrupts could try to do frontend requests,
        // which would deadlock, so disable them
-       spin_lock_irqsave(&lock);
+       spin_lock(&lock);
 
        // write syscall into magic memory
        magic_mem[7] = 0;
@@ -183,59 +180,29 @@ int32_t frontend_syscall(pid_t pid, int32_t syscall_num,
                ;
 
        ret = magic_mem[1];
-       *errno = magic_mem[2];
-
-       spin_unlock_irqsave(&lock);
-
-       return ret;
-}
+       if(errno)
+               *errno = magic_mem[2];
 
-int32_t frontend_nbputch(char ch)
-{
-       static spinlock_t putch_lock = SPINLOCK_INITIALIZER;
-       spin_lock_irqsave(&putch_lock);
-
-       int ret = -1;
-       if(magic_mem[8] == 0)
-       {
-               magic_mem[8] = (unsigned int)(unsigned char)ch;
-               ret = 0;
-       }
+       spin_unlock(&lock);
 
-       spin_unlock_irqsave(&putch_lock);
        return ret;
 }
 
-int32_t frontend_nbgetch()
-{
-       static spinlock_t getch_lock = SPINLOCK_INITIALIZER;
-       spin_lock_irqsave(&getch_lock);
-
-       int result = -1;
-       if(magic_mem[9]) 
-       {
-               result = magic_mem[9];
-               magic_mem[9] = 0;
-       }
-
-       spin_unlock_irqsave(&getch_lock);
-       return result;
-}
-
-void __diediedie(trapframe_t* tf, uint32_t srcid, uint32_t code, uint32_t a1, uint32_t a2)
+void __diediedie(uint32_t srcid, uint32_t code, uint32_t a1, uint32_t a2)
 {
        int32_t errno;
        frontend_syscall(0,APPSERVER_SYSCALL_exit,(int)code,0,0,0,&errno);
        while(1);
 }
 
-void appserver_die(int code)
+void appserver_die(uintptr_t code)
 {
        int i;
        for(i = 0; i < num_cpus; i++)
                if(i != core_id())
-                       while(send_active_message(i,(amr_t)&__diediedie,(void*)code,0,0));
+                       while(send_kernel_message(i, (amr_t)&__diediedie, code, 0, 0,
+                                                 KMSG_IMMEDIATE));
 
        // just in case.
-       __diediedie(0,0,code,0,0);
+       __diediedie(0, code, 0, 0);
 }