Use rendez for sleep/wakeup/etc
[akaros.git] / kern / src / net / loopbackmedium.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum
17 {
18         Maxtu=  16*1024,
19 };
20
21 typedef struct LB LB;
22 struct LB
23 {
24         struct proc     *readp;
25         struct queue    *q;
26         struct Fs       *f;
27 };
28
29 static void loopbackread(void *a);
30
31 static void
32 loopbackbind(struct Ipifc *ifc, int unused_int, char **unused_char_pp_t)
33 {
34         LB *lb;
35
36         lb = kzmalloc(sizeof(*lb), 0);
37         lb->f = ifc->conv->p->f;
38         /* TO DO: make queue size a function of kernel memory */
39         lb->q = qopen(128*1024, Qmsg, NULL, NULL);
40         ifc->arg = lb;
41         ifc->mbps = 1000;
42
43         kproc("loopbackread", loopbackread, ifc, 0);
44
45 }
46
47 static void
48 loopbackunbind(struct Ipifc *ifc)
49 {
50         LB *lb = ifc->arg;
51
52         printk("%s is messed up, shouldn't track procs\n", __FUNCTION__);
53
54         /*if(lb->readp)
55           postnote(lb->readp, 1, "unbind", 0);
56         */
57
58         /* wait for reader to die */
59         while(lb->readp != 0)
60                 udelay_sched(300 * 1000);
61
62         /* clean up */
63         qfree(lb->q);
64         kfree(lb);
65 }
66
67 static void
68 loopbackbwrite(struct Ipifc *ifc, struct block *bp, int unused_int, uint8_t *unused_uint8_p_t)
69 {
70         LB *lb;
71
72         lb = ifc->arg;
73         if(qpass(lb->q, bp) < 0)
74                 ifc->outerr++;
75         ifc->out++;
76 }
77
78 static void
79 loopbackread(void *a)
80 {
81         ERRSTACK(2);
82         struct Ipifc *ifc;
83         struct block *bp;
84         LB *lb;
85
86         ifc = a;
87         lb = ifc->arg;
88         lb->readp = current;    /* hide identity under a rock for unbind */
89         if(waserror()){
90                 lb->readp = 0;
91                 /* kill the proc. */
92 #warning "pexit"
93 //              pexit("hangup", 1);
94         }
95         for(;;){
96                 bp = qbread(lb->q, Maxtu);
97                 if(bp == NULL)
98                         continue;
99                 ifc->in++;
100                 if(!canrlock(&ifc->rwlock)){
101                         freeb(bp);
102                         continue;
103                 }
104                 if(waserror()){
105                         runlock(&ifc->rwlock);
106                         nexterror();
107                 }
108                 if(ifc->lifc == NULL)
109                         freeb(bp);
110                 else
111                         ipiput4(lb->f, ifc, bp);
112                 runlock(&ifc->rwlock);
113                 poperror();
114         }
115 }
116
117 struct medium loopbackmedium =
118 {
119 .hsize=         0,
120 .mintu=         0,
121 .maxtu=         Maxtu,
122 .maclen=        0,
123 .name=          "loopback",
124 .bind=          loopbackbind,
125 .unbind=        loopbackunbind,
126 .bwrite=        loopbackbwrite,
127 };
128
129 void
130 loopbackmediumlink(void)
131 {
132         addipmedium(&loopbackmedium);
133 }