27e37adffa033e56e041f76b9268f22428ab5a36
[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
23
24
25 struct proc_list arsc_proc_list = TAILQ_HEAD_INITIALIZER(arsc_proc_list);
26 spinlock_t arsc_proc_lock = SPINLOCK_INITIALIZER;
27
28 intreg_t inline syscall_async(struct proc *p, syscall_req_t *call)
29 {
30         return syscall(p, call->num, call->args[0], call->args[1],
31                        call->args[2], call->args[3], call->args[4]);
32 }
33
34 intreg_t sys_init_arsc(struct proc* p)
35 {
36         spin_lock_irqsave(&arsc_proc_lock);
37         TAILQ_INSERT_TAIL(&arsc_proc_list, p, proc_arsc_link);
38         spin_unlock_irqsave(&arsc_proc_lock);
39         return ESUCCESS;
40 }
41
42
43 void arsc_server(trapframe_t *tf)
44 {
45         struct proc *p = NULL;
46         TAILQ_INIT(&arsc_proc_list);
47         while (true)
48         {
49                 while (TAILQ_EMPTY(&arsc_proc_list))
50                         cpu_relax();
51
52                 TAILQ_FOREACH(p, &arsc_proc_list, proc_link)
53                 {
54                         // TODO: we may need an atomic swap to inc ref count
55                         if (p->state != PROC_DYING)
56                                 process_generic_syscalls (p, MAX_ASRC_BATCH); 
57                 }
58         }
59 }
60
61 static intreg_t process_generic_syscalls(struct proc *p, size_t max)
62 {
63         size_t count = 0;
64         syscall_back_ring_t* sysbr = &p->syscallbackring;
65         struct per_cpu_info* coreinfo = &per_cpu_info[core_id()];
66         // looking at a process not initialized to perform arsc. 
67         if (sysbr == NULL) 
68                 return count;
69
70         /* make sure the proc is still alive, and keep it from dying from under us
71          * incref will return ESUCCESS on success.  This might need some thought
72          * regarding when the incref should have happened (like by whoever passed us
73          * the *p). */
74         // TODO: ought to be unnecessary, if you called this right, kept here for
75         // now in case anyone actually uses the ARSCs.
76         kref_get(&p->kref, 1);
77
78         // max is the most we'll process.  max = 0 means do as many as possible
79         // TODO: check for initialization of the ring. 
80         while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
81                 if (!count) {
82                         // ASSUME: one queue per process
83                         // only switch cr3 for the very first request for this queue
84                         // need to switch to the right context, so we can handle the user pointer
85                         // that points to a data payload of the syscall
86                         lcr3(p->env_cr3);
87                 }
88                 count++;
89                 //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",
90                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
91                 // might want to think about 0-ing this out, if we aren't
92                 // going to explicitly fill in all fields
93                 syscall_rsp_t rsp;
94                 // this assumes we get our answer immediately for the syscall.
95                 syscall_req_t* req = RING_GET_REQUEST(sysbr, ++(sysbr->req_cons));
96                 // print req
97                 printd("req no %d, req arg %c\n", req->num, *((char*)req->args[0]));
98                 
99                 coreinfo->cur_ret.returnloc = &(rsp.retval);
100                 coreinfo->cur_ret.errno_loc = &(rsp.syserr);
101                 
102                 rsp.retval = syscall_async(p, req);
103                 // write response into the slot it came from
104                 memcpy(req, &rsp, sizeof(syscall_rsp_t));
105                 // update our counter for what we've produced (assumes we went in order!)
106                 (sysbr->rsp_prod_pvt)++;
107                 RING_PUSH_RESPONSES(sysbr);
108                 //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",
109                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
110         }
111         // load sane page tables (and don't rely on decref to do it for you).
112         lcr3(boot_cr3);
113         kref_put(&p->kref);
114         return (intreg_t)count;
115 }
116