]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/agg.c
upas/*: cleanup mkfiles (thanks amavect)
[plan9front.git] / sys / src / libdtracy / agg.c
1 #include <u.h>
2 #include <libc.h>
3 #include <dtracy.h>
4
5 int
6 dtaunpackid(DTAgg *a)
7 {
8         a->type = a->id >> 28 & 15;
9         a->keysize = a->id >> 13 & 0x7ff8;
10         switch(a->type){
11         case AGGCNT:
12         case AGGSUM:
13         case AGGMIN:
14         case AGGMAX:
15                 a->recsize = 8 + a->keysize + 8;
16                 return 0;
17         case AGGAVG:
18                 a->recsize = 8 + a->keysize + 16;
19                 return 0;
20         case AGGSTD:
21                 a->recsize = 8 + a->keysize + 32;
22                 return 0;
23         default:
24                 return -1;
25         }
26 }
27
28 static u64int
29 hash(uchar *s, int n, int m)
30 {
31         u64int h;
32         int i;
33         
34         h = 0xcbf29ce484222325ULL;
35         for(i = 0; i < n; i++){
36                 h ^= s[i];
37                 h *= 0x100000001b3ULL;
38         }
39         for(; i < m; i++)
40                 h *= 0x100000001b3ULL;
41         return h;
42 }
43
44 static int
45 keyeq(uchar *a, uchar *b, int n, int m)
46 {
47         int i;
48         
49         for(i = 0; i < n; i++)
50                 if(a[i] != b[i])
51                         return 0;
52         for(; i < m; i++)
53                 if(a[i] != 0)
54                         return 0;
55         return 1;
56 }
57
58 /* calculate v*v with 128 bits precision and add it to the 128-bit word at q */
59 static void
60 addsquare(u64int *q, s64int v)
61 {
62         u32int v0;
63         s32int v1;
64         s64int s0, s1, s2;
65         u64int r;
66         
67         v0 = v;
68         v1 = v>>32;
69         s0 = (s64int)v0 * (s64int)v0;
70         s1 = (s64int)v0 * (s64int)v1;
71         s2 = (s64int)v1 * (s64int)v1;
72         r = s0 + (s1<<33);
73         if(r < (u64int)s0) q[1]++;
74         q[0] += r;
75         if(q[0] < r) q[1]++;
76         q[1] += s2 + (s1>>31);
77 }
78
79 static void
80 updaterecord(int type, u64int *q, s64int val)
81 {
82         switch(type){
83         case AGGCNT: q[0] += 1; break;
84         case AGGSUM: q[0] += val; break;
85         case AGGAVG: q[0] += val; q[1]++; break;
86         case AGGMIN: if(val < q[0]) q[0] = val; break;
87         case AGGMAX: if(val > q[0]) q[0] = val; break;
88         case AGGSTD: q[0] += val; q[1]++; addsquare(&q[2], val); break;
89         }
90 }
91
92 static void
93 createrecord(int type, u64int *q, s64int val)
94 {
95         switch(type){
96         case AGGCNT: q[0] = 1; break;
97         case AGGSUM: case AGGMIN: case AGGMAX: q[0] = val; break;
98         case AGGAVG: q[0] = val; q[1] = 1; break;
99         case AGGSTD: q[0] = val; q[1] = 1; q[2] = 0; q[3] = 0; addsquare(&q[2], val); break;
100         }
101 }
102
103 /* runs in probe context */
104 void
105 dtarecord(DTChan *ch, int mach, DTAgg *a, uchar *key, int nkey, s64int val)
106 {
107         u64int h;
108         u32int *p, *q;
109         DTBuf *c;
110         
111         c = ch->aggwrbufs[mach];
112         h = hash(key, nkey, a->keysize);
113         p = (u32int*)(c->data + DTABUCKETS + (h % DTANUMBUCKETS) * 4);
114         while(*p != DTANIL){
115                 assert((uint)*p < DTABUCKETS);
116                 q = (u32int*)(c->data + *p);
117                 if(q[1] == a->id && keyeq((uchar*)(q + 2), key, nkey, a->keysize) == 0){
118                         updaterecord(a->type, (u64int*)(q + 2 + a->keysize / 4), val);
119                         return;
120                 }
121                 p = q;
122         }
123         if(c->wr + a->recsize > DTABUCKETS)
124                 return;
125         *p = c->wr;
126         q = (u32int*)(c->data + c->wr);
127         q[0] = DTANIL;
128         q[1] = a->id;
129         if(nkey == a->keysize)
130                 memmove(&q[2], key, nkey);
131         else if(nkey > a->keysize){
132                 memmove(&q[2], key, nkey);
133                 memset((uchar*)q + 8 + nkey, 0, a->keysize - nkey);
134         }else
135                 memmove(&q[2], key, a->keysize);
136         createrecord(a->type, (u64int*)(q + 2 + a->keysize / 4), val);
137         c->wr += a->recsize;
138 }