Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / wasm / richards.c
1 // $ emcc -o richards.html -O2 -s TOTAL_MEMORY=83886080 -g1 -s "EXPORTED_FUNCTIONS=[_setup, _getHoldcount, _scheduleIter, _getQpktcount, _main]" ./richards.c
2
3 #include <emscripten.h>
4
5 /*  C version of the systems programming language benchmark 
6 **  Author:  M. J. Jordan  Cambridge Computer Laboratory. 
7 **  
8 **  Modified by:  M. Richards, Nov 1996
9 **    to be ANSI C and runnable on 64 bit machines + other minor changes
10 **  Modified by:  M. Richards, 20 Oct 1998
11 **    made minor corrections to improve ANSI compliance (suggested
12 **    by David Levine)
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #if 1
19 #define                Count           10000*100
20 #define                Qpktcountval    2326410
21 #define                Holdcountval     930563
22 #endif
23
24 #define                TRUE            1
25 #define                FALSE           0
26 #define                MAXINT          32767
27
28 #define                BUFSIZE         3
29 #define                I_IDLE          1
30 #define                I_WORK          2
31 #define                I_HANDLERA      3
32 #define                I_HANDLERB      4
33 #define                I_DEVA          5
34 #define                I_DEVB          6
35 #define                PKTBIT          1
36 #define                WAITBIT         2
37 #define                HOLDBIT         4
38 #define                NOTPKTBIT       !1
39 #define                NOTWAITBIT      !2
40 #define                NOTHOLDBIT      0XFFFB
41
42 #define                S_RUN           0
43 #define                S_RUNPKT        1
44 #define                S_WAIT          2
45 #define                S_WAITPKT       3
46 #define                S_HOLD          4
47 #define                S_HOLDPKT       5
48 #define                S_HOLDWAIT      6
49 #define                S_HOLDWAITPKT   7
50
51 #define                K_DEV           1000
52 #define                K_WORK          1001
53
54 struct packet
55 {
56     struct packet  *p_link;
57     int             p_id;
58     int             p_kind;
59     int             p_a1;
60     char            p_a2[BUFSIZE+1];
61 };
62
63 struct task
64 {
65     struct task    *t_link;
66     int             t_id;
67     int             t_pri;
68     struct packet  *t_wkq;
69     int             t_state;
70     struct task    *(*t_fn)(struct packet *);
71     long            t_v1;
72     long            t_v2;
73 };
74
75 char  alphabet[28] = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
76 struct task *tasktab[11]  =  {(struct task *)10,0,0,0,0,0,0,0,0,0,0};
77 struct task *tasklist    =  0;
78 struct task *tcb;
79 long    taskid;
80 long    v1;
81 long    v2;
82 int     qpktcount    =  0;
83 int     holdcount    =  0;
84 int     tracing      =  0;
85 int     layout       =  0;
86
87 void append(struct packet *pkt, struct packet *ptr);
88
89 void createtask(int id,
90                 int pri,
91                 struct packet *wkq,
92                 int state,
93                 struct task *(*fn)(struct packet *),
94                 long v1,
95                 long v2)
96 {
97     struct task *t = (struct task *)malloc(sizeof(struct task));
98
99     tasktab[id] = t;
100     t->t_link   = tasklist;
101     t->t_id     = id;
102     t->t_pri    = pri;
103     t->t_wkq    = wkq;
104     t->t_state  = state;
105     t->t_fn     = fn;
106     t->t_v1     = v1;
107     t->t_v2     = v2;
108     tasklist    = t;
109 }
110
111 struct packet *pkt(struct packet *link, int id, int kind)
112 {
113     int i;
114     struct packet *p = (struct packet *)malloc(sizeof(struct packet));
115
116     for (i=0; i<=BUFSIZE; i++)
117         p->p_a2[i] = 0;
118
119     p->p_link = link;
120     p->p_id = id;
121     p->p_kind = kind;
122     p->p_a1 = 0;
123
124     return (p);
125 }
126
127 void trace(char a)
128 {
129    if ( --layout <= 0 )
130    {
131         layout = 50;
132     }
133
134 }
135
136 int scheduleIter()
137 {
138     if (tcb == 0)
139         return 0;
140
141     {
142         struct packet *pkt;
143         struct task *newtcb;
144
145         pkt=0;
146
147         switch ( tcb->t_state )
148         {
149             case S_WAITPKT:
150                 pkt = tcb->t_wkq;
151                 tcb->t_wkq = pkt->p_link;
152                 tcb->t_state = tcb->t_wkq == 0 ? S_RUN : S_RUNPKT;
153
154             case S_RUN:
155             case S_RUNPKT:
156                 taskid = tcb->t_id;
157                 v1 = tcb->t_v1;
158                 v2 = tcb->t_v2;
159                 if (tracing) {
160                     trace(taskid+'0');
161                 }
162                 newtcb = (*(tcb->t_fn))(pkt);
163                 tcb->t_v1 = v1;
164                 tcb->t_v2 = v2;
165                 tcb = newtcb;
166                 break;
167
168             case S_WAIT:
169             case S_HOLD:
170             case S_HOLDPKT:
171             case S_HOLDWAIT:
172             case S_HOLDWAITPKT:
173                 tcb = tcb->t_link;
174                 break;
175
176             default:
177                 return 0;
178         }
179     }
180
181     return 1;
182 }
183
184 struct task *wait(void)
185 {
186     tcb->t_state |= WAITBIT;
187     return (tcb);
188 }
189
190 struct task *holdself(void)
191 {
192     ++holdcount;
193     tcb->t_state |= HOLDBIT;
194     return (tcb->t_link) ;
195 }
196
197 struct task *findtcb(int id)
198 {
199     struct task *t = 0;
200
201     if (1<=id && id<=(long)tasktab[0])
202     t = tasktab[id];
203     return(t);
204 }
205
206 struct task *release(int id)
207 {
208     struct task *t;
209
210     t = findtcb(id);
211     if ( t==0 ) return (0);
212
213     t->t_state &= NOTHOLDBIT;
214     if ( t->t_pri > tcb->t_pri ) return (t);
215
216     return (tcb) ;
217 }
218
219
220 struct task *qpkt(struct packet *pkt)
221 {
222     struct task *t;
223
224     t = findtcb(pkt->p_id);
225     if (t==0) return (t);
226
227     qpktcount++;
228
229     pkt->p_link = 0;
230     pkt->p_id = taskid;
231
232    if (t->t_wkq==0)
233     {
234         t->t_wkq = pkt;
235         t->t_state |= PKTBIT;
236         if (t->t_pri > tcb->t_pri) return (t);
237     }
238     else
239     {
240         append(pkt, (struct packet *)&(t->t_wkq));
241     }
242
243     return (tcb);
244 }
245
246 struct task *idlefn(struct packet *pkt)
247 {
248     if ( --v2==0 ) return ( holdself() );
249
250     if ( (v1&1) == 0 )
251     {
252         v1 = ( v1>>1) & MAXINT;
253         return ( release(I_DEVA) );
254     }
255     else
256     {
257         v1 = ( (v1>>1) & MAXINT) ^ 0XD008;
258         return ( release(I_DEVB) );
259     }
260 }
261
262 struct task *workfn(struct packet *pkt)
263 {
264     if ( pkt==0 ) return ( wait() );
265     else
266     {
267         int i;
268
269         v1 = I_HANDLERA + I_HANDLERB - v1;
270         pkt->p_id = v1;
271
272         pkt->p_a1 = 0;
273         for (i=0; i<=BUFSIZE; i++)
274         {
275             v2++;
276             if ( v2 > 26 ) v2 = 1;
277             (pkt->p_a2)[i] = alphabet[v2];
278         }
279         return ( qpkt(pkt) );
280     }
281 }
282
283 struct task *handlerfn(struct packet *pkt)
284 {
285   if ( pkt!=0) {
286     append(pkt, (struct packet *)(pkt->p_kind==K_WORK ? &v1 : &v2));
287   }
288
289   if ( v1!=0 ) {
290     int count;
291     struct packet *workpkt = (struct packet *)v1;
292     count = workpkt->p_a1;
293
294     if ( count > BUFSIZE ) {
295       v1 = (long)(((struct packet *)v1)->p_link);
296       return ( qpkt(workpkt) );
297     }
298
299     if ( v2!=0 ) {
300       struct packet *devpkt;
301
302       devpkt = (struct packet *)v2;
303       v2 = (long)(((struct packet *)v2)->p_link);
304       devpkt->p_a1 = workpkt->p_a2[count];
305       workpkt->p_a1 = count+1;
306       return( qpkt(devpkt) );
307     }
308   }
309   return wait();
310 }
311
312 struct task *devfn(struct packet *pkt)
313 {
314     if ( pkt==0 )
315     {
316         if ( v1==0 ) return ( wait() );
317         pkt = (struct packet *)v1;
318         v1 = 0;
319         return ( qpkt(pkt) );
320     }
321     else
322     {
323         v1 = (long)pkt;
324         if (tracing) trace(pkt->p_a1);
325         return ( holdself() );
326     }
327 }
328
329 void append(struct packet *pkt, struct packet *ptr)
330 {
331     pkt->p_link = 0;
332
333     while ( ptr->p_link ) ptr = ptr->p_link;
334
335     ptr->p_link = pkt;
336 }
337
338 void setup()
339 {
340     struct packet *wkq = 0;
341
342     createtask(I_IDLE, 0, wkq, S_RUN, idlefn, 1, Count);
343
344     wkq = pkt(0, 0, K_WORK);
345     wkq = pkt(wkq, 0, K_WORK);
346
347     createtask(I_WORK, 1000, wkq, S_WAITPKT, workfn, I_HANDLERA, 0);
348
349     wkq = pkt(0, I_DEVA, K_DEV);
350     wkq = pkt(wkq, I_DEVA, K_DEV);
351     wkq = pkt(wkq, I_DEVA, K_DEV);
352
353     createtask(I_HANDLERA, 2000, wkq, S_WAITPKT, handlerfn, 0, 0);
354
355     wkq = pkt(0, I_DEVB, K_DEV);
356     wkq = pkt(wkq, I_DEVB, K_DEV);
357     wkq = pkt(wkq, I_DEVB, K_DEV);
358
359     createtask(I_HANDLERB, 3000, wkq, S_WAITPKT, handlerfn, 0, 0);
360
361     wkq = 0;
362     createtask(I_DEVA, 4000, wkq, S_WAIT, devfn, 0, 0);
363     createtask(I_DEVB, 5000, wkq, S_WAIT, devfn, 0, 0);
364
365     tcb = tasklist;
366
367     qpktcount = holdcount = 0;
368
369     tracing = FALSE;
370     layout = 0;
371 }
372
373 int getQpktcount()
374 {
375     return  qpktcount;
376 }
377
378 int getHoldcount()
379 {
380     return holdcount;
381 }
382
383 int main()
384 {
385     EM_ASM( runRichards() );
386
387     return 0;
388 }
389