Fix kref references that are no longer there.
[akaros.git] / kern / src / arsc.c
1 /* See COPYRIGHT for copyright information. */
2
3 #ifdef __SHARC__
4 #pragma nosharc
5 #endif
6
7
8 #include <ros/common.h>
9 #include <ros/ring_syscall.h>
10 #include <arch/types.h>
11 #include <arch/arch.h>
12 #include <arch/mmu.h>
13 #include <error.h>
14
15 #include <syscall.h>
16 #include <kmalloc.h>
17 #include <pmap.h>
18 #include <stdio.h>
19 #include <hashtable.h>
20 #include <smp.h>
21 #include <arsc_server.h>
22 #include <kref.h>
23
24
25
26 struct proc_list arsc_proc_list = TAILQ_HEAD_INITIALIZER(arsc_proc_list);
27 spinlock_t arsc_proc_lock = SPINLOCK_INITIALIZER;
28
29 intreg_t inline syscall_async(struct proc *p, syscall_req_t *call)
30 {
31         struct syscall* sc = call->sc;
32         return syscall(p, sc->num, sc->arg0, sc->arg1,
33                        sc->arg2, sc->arg3, sc->arg4, sc->arg5);
34 }
35
36 syscall_sring_t* sys_init_arsc(struct proc *p)
37 {
38         kref_get(&p->p_kref, 1);                /* we're storing an external ref here */
39         syscall_sring_t* sring;
40         void * va;
41         // TODO: need to pin this page in the future when swapping happens
42         va = do_mmap(p,MMAP_LOWEST_VA, SYSCALLRINGSIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_POPULATE, NULL, 0);
43         pte_t *pte = pgdir_walk(p->env_pgdir, (void*)va, 0);
44         assert(pte);
45         sring = (syscall_sring_t*) (ppn2kva(PTE2PPN(*pte)));
46         /*make sure we are able to allocate the shared ring */
47         assert(sring != NULL);
48         p->procdata->syscallring = sring;
49         /* Initialize the generic syscall ring buffer */
50         SHARED_RING_INIT(sring);
51
52         BACK_RING_INIT(&p->syscallbackring,
53                        sring,
54                        SYSCALLRINGSIZE);
55
56         spin_lock_irqsave(&arsc_proc_lock);
57         TAILQ_INSERT_TAIL(&arsc_proc_list, p, proc_arsc_link);
58         spin_unlock_irqsave(&arsc_proc_lock);
59         return (syscall_sring_t*)va;
60 }
61
62 void arsc_server(struct trapframe *tf)
63 {
64         struct proc *p = NULL;
65         TAILQ_INIT(&arsc_proc_list);
66         while (1) {
67                 while (TAILQ_EMPTY(&arsc_proc_list))
68                         cpu_relax();
69                 
70                 TAILQ_FOREACH(p, &arsc_proc_list, proc_link) {
71                         /* Probably want to try to process a dying process's syscalls.  If
72                          * not, just move it to an else case */
73                         process_generic_syscalls (p, MAX_ASRC_BATCH); 
74                         if (p->state == PROC_DYING) {
75                                 TAILQ_REMOVE(&arsc_proc_list, p, proc_arsc_link);
76                                 proc_decref(p);
77                                 /* Need to break out, so the TAILQ_FOREACH doesn't flip out.
78                                  * It's not fair, but we're not dealing with that yet anyway */
79                                 break;
80                         }
81                 }
82         }
83 }
84
85 static intreg_t process_generic_syscalls(struct proc *p, size_t max)
86 {
87         size_t count = 0;
88         syscall_back_ring_t* sysbr = &p->syscallbackring;
89         struct per_cpu_info* pcpui = &per_cpu_info[core_id()];
90         // looking at a process not initialized to perform arsc. 
91         if (sysbr == NULL) 
92                 return count;
93         
94         // max is the most we'll process.  max = 0 means do as many as possible
95         // TODO: check for initialization of the ring. 
96         while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
97                 if (!count) {
98                         // ASSUME: one queue per process
99                         // only switch cr3 for the very first request for this queue
100                         // need to switch to the right context, so we can handle the user pointer
101                         // that points to a data payload of the syscall
102                         lcr3(p->env_cr3);
103                         pcpui->cur_proc = p;
104                 }
105                 count++;
106                 //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",
107                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
108                 // might want to think about 0-ing this out, if we aren't
109                 // going to explicitly fill in all fields
110                 syscall_rsp_t rsp;
111                 // this assumes we get our answer immediately for the syscall.
112                 syscall_req_t* req = RING_GET_REQUEST(sysbr, ++sysbr->req_cons);
113                 // print req
114                 printd("req no %d, req arg %c\n", req->num, *((char*)req->args[0]));
115                 
116                 pcpui->cur_sysc = req->sc;
117                 run_local_syscall(req->sc); // TODO: blocking call will block arcs as well.
118                 
119                 // need to keep the slot in the ring buffer if it is blocked
120                 (sysbr->rsp_prod_pvt)++;
121                 req->status = RES_ready;
122                 RING_PUSH_RESPONSES(sysbr);
123
124                 //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",
125                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
126         }
127         // load sane page tables (and don't rely on decref to do it for you).
128         lcr3(boot_cr3);
129         return (intreg_t)count;
130 }
131