Bring back the ARSC functionality that was removed earlier.
[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 <arsc_server.h>
21
22
23
24 struct proc_list arsc_proc_list = TAILQ_HEAD_INITIALIZER(arsc_proc_list);
25 spinlock_t arsc_proc_lock = SPINLOCK_INITIALIZER;
26
27 intreg_t syscall_async(struct proc *p, syscall_req_t *call)
28 {
29         return syscall(p, call->num, call->args[0], call->args[1],
30                        call->args[2], call->args[3], call->args[4]);
31 }
32
33 intreg_t sys_init_arsc(struct proc* p)
34 {
35         spin_lock_irqsave(&arsc_proc_lock);
36         TAILQ_INSERT_TAIL(&arsc_proc_list, p, proc_arsc_link);
37         spin_unlock_irqsave(&arsc_proc_lock);
38         return ESUCCESS;
39 }
40
41
42 void arsc_server(trapframe_t *tf)
43 {
44         struct proc *p = NULL;
45         TAILQ_INIT(&arsc_proc_list);
46         while (true)
47         {
48                 while (TAILQ_EMPTY(&arsc_proc_list))
49                         cpu_relax();
50
51                 printd ("detected process\n");
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         // looking at a process not initialized to perform arsc. 
66         if (sysbr == NULL) 
67                 return count;
68
69         /* make sure the proc is still alive, and keep it from dying from under us
70          * incref will return ESUCCESS on success.  This might need some thought
71          * regarding when the incref should have happened (like by whoever passed us
72          * the *p). */
73         // TODO: ought to be unnecessary, if you called this right, kept here for
74         // now in case anyone actually uses the ARSCs.
75         kref_get(&p->kref, 1);
76
77         // max is the most we'll process.  max = 0 means do as many as possible
78         // TODO: check for initialization of the ring. 
79         while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
80                 printd ("start processing req %d\n", count);
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                 rsp.retval = syscall_async(p, req);
99                 // write response into the slot it came from
100                 memcpy(req, &rsp, sizeof(syscall_rsp_t));
101                 // update our counter for what we've produced (assumes we went in order!)
102                 (sysbr->rsp_prod_pvt)++;
103                 RING_PUSH_RESPONSES(sysbr);
104                 //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",
105                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
106         }
107         // load sane page tables (and don't rely on decref to do it for you).
108         lcr3(boot_cr3);
109         kref_put(&p->kref);
110         return (intreg_t)count;
111 }
112