Merged gcell-wip -r8159:8202 into trunk. This includes the following
[debian/gnuradio] / gcell / src / lib / runtime / qa_job_manager.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "qa_job_manager.h"
23 #include <cppunit/TestAssert.h>
24 #include "gc_job_manager.h"
25 #include <stdexcept>
26 #include <stdio.h>
27 #include <time.h>
28 #include <errno.h>
29
30 #include <malloc.h>
31
32 // handle to embedded SPU executable w/ QA routines
33 extern spe_program_handle_t gcell_runtime_qa;
34
35 #if 0
36 static void
37 gc_msleep(unsigned long millisecs)
38 {
39   int r;
40   struct timespec tv;
41   tv.tv_sec = millisecs / 1000;
42   tv.tv_nsec = (millisecs - (tv.tv_sec * 1000)) * 1000000;
43   
44   while (1){
45     r = nanosleep(&tv, &tv);
46     if (r == 0)
47       return;
48     if (r == -1 && errno == EINTR)
49       continue;
50     perror("nanosleep");
51     return;
52   }
53 }
54 #endif
55
56 void
57 qa_job_manager::leak_check(test_t t, const std::string &name)
58 {
59   struct mallinfo before, after;
60
61   before = mallinfo();
62   (this->*t)();
63   after = mallinfo();
64
65   size_t delta = after.uordblks - before.uordblks;
66   if (delta != 0){
67     std::cout << name << " leaked memory\n";
68     printf("  before.uordblks = %6d\n", before.uordblks);
69     printf("  after.uordblks  = %6d\n",  after.uordblks);
70     printf("  delta = %d\n", after.uordblks - before.uordblks);
71   }
72 }
73
74 void
75 qa_job_manager::t0()
76 {
77   //leak_check(&qa_job_manager::t1_body, "t1-0");
78 }
79
80 void
81 qa_job_manager::t1()
82 {
83   t1_body();            // leaks 800 bytes first time, could be one-time inits
84   leak_check(&qa_job_manager::t1_body, "t1");
85 }
86
87 void
88 qa_job_manager::t2()
89 {
90   leak_check(&qa_job_manager::t2_body, "t2");
91 }
92
93 void
94 qa_job_manager::t3()
95 {
96   t3_body();            // leaks first time only, could be cppunit
97   leak_check(&qa_job_manager::t3_body, "t3");
98 }
99
100 void
101 qa_job_manager::t4()
102 {
103   leak_check(&qa_job_manager::t4_body, "t4");
104 }
105
106 void
107 qa_job_manager::t5()
108 {
109   leak_check(&qa_job_manager::t5_body, "t5");
110 }
111
112 void
113 qa_job_manager::t6()
114 {
115   leak_check(&qa_job_manager::t6_body, "t6");
116 }
117
118 void
119 qa_job_manager::t7()
120 {
121   leak_check(&qa_job_manager::t7_body, "t7");
122 }
123
124 void
125 qa_job_manager::t8()
126 {
127   leak_check(&qa_job_manager::t8_body, "t8");
128 }
129
130 void
131 qa_job_manager::t9()
132 {
133   leak_check(&qa_job_manager::t9_body, "t9");
134 }
135
136 void
137 qa_job_manager::t10()
138 {
139   leak_check(&qa_job_manager::t10_body, "t10");
140 }
141
142 void
143 qa_job_manager::t11()
144 {
145   leak_check(&qa_job_manager::t11_body, "t11");
146 }
147
148 void
149 qa_job_manager::t12()
150 {
151   leak_check(&qa_job_manager::t12_body, "t12");
152 }
153
154 void
155 qa_job_manager::t13()
156 {
157   leak_check(&qa_job_manager::t13_body, "t13");
158 }
159
160 void
161 qa_job_manager::t14()
162 {
163   leak_check(&qa_job_manager::t14_body, "t14");
164 }
165
166 void
167 qa_job_manager::t15()
168 {
169   leak_check(&qa_job_manager::t15_body, "t15");
170 }
171
172 // ----------------------------------------------------------------
173
174 void
175 qa_job_manager::t1_body()
176 {
177   gc_job_manager_sptr mgr;
178   gc_jm_options opts;
179   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
180   mgr = gc_make_job_manager(&opts);
181 }
182
183 void
184 qa_job_manager::t2_body()
185 {
186   gc_job_manager_sptr mgr;
187   gc_jm_options opts;
188   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
189   opts.nspes = 100;
190   opts.gang_schedule = false;
191   mgr = gc_make_job_manager(&opts);
192 }
193
194 void
195 qa_job_manager::t3_body()
196 {
197   // This leaks memory the first time it's invoked, but I'm not sure
198   // if it's us or the underlying exception handling mechanism, or
199   // cppunit.  cppunit is the prime suspect.
200
201 #if 0
202   gc_job_manager_sptr mgr;
203   gc_jm_options opts;
204   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
205   opts.nspes = 100;
206   opts.gang_schedule = true;
207   CPPUNIT_ASSERT_THROW(mgr = gc_make_job_manager(&opts), std::out_of_range);
208 #endif
209 }
210
211 static void
212 init_jd(gc_job_desc *jd, gc_proc_id_t proc_id)
213 {
214   jd->proc_id = proc_id;
215   jd->input.nargs = 0;
216   jd->output.nargs = 0;
217   jd->eaa.nargs = 0;
218 }
219
220 void
221 qa_job_manager::t4_body()
222 {
223   gc_job_manager_sptr mgr;
224   gc_jm_options opts;
225   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
226   opts.nspes = 1;
227   mgr = gc_make_job_manager(&opts);
228   //mgr->set_debug(-1);
229   static const int NJOBS = 32;
230   gc_job_desc *jds[NJOBS];
231   bool done[NJOBS];
232
233   gc_proc_id_t gcp_no_such;
234   CPPUNIT_ASSERT_THROW(gcp_no_such = mgr->lookup_proc("--no-such-proc-name--"), gc_unknown_proc);
235
236   gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
237   CPPUNIT_ASSERT(gcp_qa_nop != GCP_UNKNOWN_PROC);
238
239   for (int i = 0; i < NJOBS; i++){
240     jds[i] = mgr->alloc_job_desc();
241     init_jd(jds[i], gcp_qa_nop);
242   }
243
244   for (int i = 0; i < NJOBS; i++){
245     if (!mgr->submit_job(jds[i])){
246       printf("%d: submit_job(jds[%d]) failed, status = %d\n",
247              __LINE__, i, jds[i]->status);
248     }
249   }
250
251   int n = mgr->wait_jobs(NJOBS, jds, done, GC_WAIT_ALL);
252   CPPUNIT_ASSERT_EQUAL(NJOBS, n);
253
254   for (int i = 0; i < NJOBS; i++){
255     mgr->free_job_desc(jds[i]);
256   }
257 }
258
259 void
260 qa_job_manager::t5_body()
261 {
262   gc_job_manager_sptr mgr;
263   gc_jm_options opts;
264   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
265   opts.nspes = 0;       // use them all
266   mgr = gc_make_job_manager(&opts);
267   //mgr->set_debug(-1);
268   static const int NJOBS = 32;
269   gc_job_desc *jds[NJOBS];
270   bool done[NJOBS];
271
272   gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
273
274   for (int i = 0; i < NJOBS; i++){
275     jds[i] = mgr->alloc_job_desc();
276     init_jd(jds[i], gcp_qa_nop);
277   }
278
279   for (int i = 0; i < NJOBS; i++){
280     if (!mgr->submit_job(jds[i])){
281       printf("%d: submit_job(jds[%d]) failed, status = %d\n",
282              __LINE__, i, jds[i]->status);
283     }
284   }
285
286   int n = mgr->wait_jobs(NJOBS, jds, done, GC_WAIT_ALL);
287   CPPUNIT_ASSERT_EQUAL(NJOBS, n);
288
289   for (int i = 0; i < NJOBS; i++){
290     mgr->free_job_desc(jds[i]);
291   }
292 }
293
294 void
295 qa_job_manager::t6_body()
296 {
297   gc_job_manager_sptr mgr;
298   gc_jm_options opts;
299   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
300   opts.nspes = 1;       
301   mgr = gc_make_job_manager(&opts);
302   gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
303   gc_job_desc *jd = mgr->alloc_job_desc();
304
305   
306   // test for success with gcp_qa_nop procedure
307   init_jd(jd, gcp_qa_nop);
308   if (!mgr->submit_job(jd)){
309     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
310   }
311   else {
312     mgr->wait_job(jd);
313     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
314   }
315
316   // test for JS_UNKNOWN_PROC with bogus procedure
317   init_jd(jd, -2);
318   if (!mgr->submit_job(jd)){
319     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
320   }
321   else {
322     mgr->wait_job(jd);
323     CPPUNIT_ASSERT_EQUAL(JS_UNKNOWN_PROC, jd->status);
324   }
325
326   mgr->free_job_desc(jd);
327 }
328
329 static int
330 sum_shorts(short *p, int nshorts)
331 {
332   int total = 0;
333   for (int i = 0; i < nshorts; i++)
334     total += p[i];
335
336   return total;
337 }
338
339 static void
340 test_sum_shorts(gc_job_manager_sptr mgr, short *buf, int nshorts)
341 {
342   gc_job_desc *jd = mgr->alloc_job_desc();
343   gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
344
345   init_jd(jd, gcp_qa_sum_shorts);
346   jd->eaa.nargs = 1;
347   jd->eaa.arg[0].ea_addr = ptr_to_ea(buf);
348   jd->eaa.arg[0].direction = GCJD_DMA_GET;
349   jd->eaa.arg[0].get_size = nshorts * sizeof(short);
350   
351
352   if (!mgr->submit_job(jd)){
353     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
354   }
355   else {
356     mgr->wait_job(jd);
357     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
358     int expected = sum_shorts(buf, nshorts);
359     int actual = jd->output.arg[0].s32;
360     CPPUNIT_ASSERT_EQUAL(expected, actual);
361   }
362
363   mgr->free_job_desc(jd);
364 }
365
366 static const int NS = 32768;
367 static short short_buf[NS] _AL128;      // for known alignment
368
369 //
370 // test all "get" alignments and sizes
371 //
372 void
373 qa_job_manager::t7_body()
374 {
375   gc_job_manager_sptr mgr;
376   gc_jm_options opts;
377   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
378   opts.nspes = 1;
379   mgr = gc_make_job_manager(&opts);
380
381   int ea_args_maxsize = mgr->ea_args_maxsize();
382
383   for (int i = 0; i < NS; i++)  // init buffer with known qty
384     short_buf[i] = 0x1234 + i;
385   
386   for (int offset = 0; offset <= 128; offset++){
387     for (int len = 0; len <= 128; len++){
388       test_sum_shorts(mgr, &short_buf[offset], len);
389     }
390   }
391
392   // confirm maximum length
393   for (int offset = 0; offset <= 64; offset++){
394     test_sum_shorts(mgr, &short_buf[offset], ea_args_maxsize/sizeof(short));
395   }
396 }
397
398 //
399 // test "get" args too long
400 //
401 void
402 qa_job_manager::t8_body()
403 {
404   gc_job_manager_sptr mgr;
405   gc_jm_options opts;
406   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
407   opts.nspes = 1;
408   mgr = gc_make_job_manager(&opts);
409   gc_job_desc *jd = mgr->alloc_job_desc();
410   gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
411
412   init_jd(jd, gcp_qa_sum_shorts);
413   jd->eaa.nargs = 1;
414   jd->eaa.arg[0].ea_addr = 0;
415   jd->eaa.arg[0].direction = GCJD_DMA_GET;
416   jd->eaa.arg[0].get_size = 1 << 20;
417
418   if (!mgr->submit_job(jd)){
419     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
420   }
421   else {
422     mgr->wait_job(jd);
423     CPPUNIT_ASSERT_EQUAL(JS_ARGS_TOO_LONG, jd->status);
424   }
425
426   mgr->free_job_desc(jd);
427 }
428
429 //
430 // test MAX_ARGS_EA "get" case
431 //
432 void
433 qa_job_manager::t9_body()
434 {
435   static const int N = 127;
436   static const int M = 201;
437   gc_job_manager_sptr mgr;
438   gc_jm_options opts;
439   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
440   opts.nspes = 1;
441   mgr = gc_make_job_manager(&opts);
442   gc_job_desc *jd = mgr->alloc_job_desc();
443   gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
444
445   init_jd(jd, gcp_qa_sum_shorts);
446   jd->eaa.nargs = MAX_ARGS_EA;
447   for (int i = 0; i < MAX_ARGS_EA; i++){
448     jd->eaa.arg[i].direction = GCJD_DMA_GET;
449     jd->eaa.arg[i].ea_addr = ptr_to_ea(&short_buf[i * M]);
450     jd->eaa.arg[i].get_size = N * sizeof(short);
451   }
452
453   if (!mgr->submit_job(jd)){
454     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
455   }
456   else {
457     mgr->wait_job(jd);
458     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
459     for (int i = 0; i < MAX_ARGS_EA; i++){
460       int expected = sum_shorts(&short_buf[i * M], N);
461       int actual = jd->output.arg[i].s32;
462       CPPUNIT_ASSERT_EQUAL(expected, actual);
463     }
464   }
465
466   mgr->free_job_desc(jd);
467 }
468
469 static bool
470 confirm_const(const unsigned char *buf, size_t len, unsigned char v)
471 {
472   bool ok = true;
473
474   for (size_t i = 0; i < len; i++){
475     if (buf[i] != v){
476       ok = false;
477       printf("confirm_const: buf[%6d] = 0x%02x, expected = 0x%02x\n",
478              i, buf[i], v);
479     }
480   }
481
482   return ok;
483 }
484
485 static bool
486 confirm_seq(const unsigned char *buf, size_t len, unsigned char v)
487 {
488   bool ok = true;
489
490   for (size_t i = 0; i < len; i++, v++){
491     if (buf[i] != v){
492       ok = false;
493       printf("confirm_seq: buf[%6d] = 0x%02x, expected = 0x%02x\n",
494              i, buf[i], v);
495     }
496   }
497
498   return ok;
499 }
500
501 static void
502 test_put_seq(gc_job_manager_sptr mgr, int offset, int len, int starting_val)
503 {
504   gc_job_desc *jd = mgr->alloc_job_desc();
505   gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
506
507   unsigned char *buf = (unsigned char *) short_buf;
508   size_t buf_len = sizeof(short_buf);
509   memset(buf, 0xff, buf_len);
510
511   // two cache lines into the buffer, so we can check before and after
512   int fixed_offset = 256;
513
514   init_jd(jd, gcp_qa_put_seq);
515   jd->input.nargs = 1;
516   jd->input.arg[0].s32 = starting_val;
517   jd->eaa.nargs = 1;
518   jd->eaa.arg[0].ea_addr = ptr_to_ea(buf + fixed_offset + offset);
519   jd->eaa.arg[0].direction = GCJD_DMA_PUT;
520   jd->eaa.arg[0].put_size = len;
521
522   if (!mgr->submit_job(jd)){
523     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
524   }
525   else {
526     mgr->wait_job(jd);
527     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
528     
529     // check before
530     CPPUNIT_ASSERT(confirm_const(&buf[0], fixed_offset + offset, 0xff)); 
531
532     // check sequence
533     CPPUNIT_ASSERT(confirm_seq(&buf[fixed_offset + offset], len, starting_val));
534
535     // check after
536     CPPUNIT_ASSERT(confirm_const(&buf[fixed_offset + offset + len],
537                                  buf_len - fixed_offset - offset - len, 0xff));
538   }
539   mgr->free_job_desc(jd);
540 }
541
542 //
543 // Test all "put" alignments and sizes
544 //
545 void
546 qa_job_manager::t10_body()
547 {
548   gc_job_manager_sptr mgr;
549   gc_jm_options opts;
550   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
551   opts.nspes = 1;
552   mgr = gc_make_job_manager(&opts);
553
554   int starting_val = 13;
555
556   for (int offset = 0; offset <= 128; offset++){
557     for (int len = 0; len <= 128; len++){
558       test_put_seq(mgr, offset, len, starting_val++);
559     }
560   }
561
562   int ea_args_maxsize = mgr->ea_args_maxsize();
563
564   // confirm maximum length
565   for (int offset = 0; offset <= 64; offset++){
566     test_put_seq(mgr, offset, ea_args_maxsize, starting_val++);
567   }
568 }
569
570 //
571 // test "put" args too long
572 //
573 void
574 qa_job_manager::t11_body()
575 {
576   gc_job_manager_sptr mgr;
577   gc_jm_options opts;
578   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
579   opts.nspes = 1;
580   mgr = gc_make_job_manager(&opts);
581   gc_job_desc *jd = mgr->alloc_job_desc();
582   gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
583
584   init_jd(jd, gcp_qa_put_seq);
585   jd->input.nargs = 1;
586   jd->input.arg[0].s32 = 0;
587   jd->eaa.nargs = 1;
588   jd->eaa.arg[0].ea_addr = 0;
589   jd->eaa.arg[0].direction = GCJD_DMA_PUT;
590   jd->eaa.arg[0].put_size = 1 << 20;
591
592   if (!mgr->submit_job(jd)){
593     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
594   }
595   else {
596     mgr->wait_job(jd);
597     CPPUNIT_ASSERT_EQUAL(JS_ARGS_TOO_LONG, jd->status);
598   }
599
600   mgr->free_job_desc(jd);
601 }
602
603 //
604 // test MAX_ARGS_EA "put" case
605 //
606 void
607 qa_job_manager::t12_body()
608 {
609   static const int N = 127;
610   static const int M = 201;
611   gc_job_manager_sptr mgr;
612   gc_jm_options opts;
613   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
614   opts.nspes = 1;
615   mgr = gc_make_job_manager(&opts);
616   gc_job_desc *jd = mgr->alloc_job_desc();
617   gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
618
619   unsigned char *buf = (unsigned char *) short_buf;
620   size_t buf_len = sizeof(short_buf);
621   memset(buf, 0xff, buf_len);
622
623   // two cache lines into the buffer, so we can check before and after
624   int fixed_offset = 256;
625
626   int starting_val = 13;
627
628   init_jd(jd, gcp_qa_put_seq);
629   jd->input.nargs = 1;
630   jd->input.arg[0].s32 = starting_val;
631   jd->eaa.nargs = MAX_ARGS_EA;
632   for (int i = 0; i < MAX_ARGS_EA; i++){
633     jd->eaa.arg[i].direction = GCJD_DMA_PUT;
634     jd->eaa.arg[i].ea_addr = ptr_to_ea(&buf[i * M + fixed_offset]);
635     jd->eaa.arg[i].put_size = N;
636   }
637
638   if (!mgr->submit_job(jd)){
639     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
640   }
641   else {
642     mgr->wait_job(jd);
643     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
644     for (int i = 0; i < MAX_ARGS_EA; i++){
645       CPPUNIT_ASSERT(confirm_seq(&buf[i * M + fixed_offset], N, starting_val));
646       starting_val += N;
647     }
648   }
649
650   mgr->free_job_desc(jd);
651 }
652
653 //
654 // test qa_copy primitive
655 //
656 void
657 qa_job_manager::t13_body()
658 {
659   gc_job_manager_sptr mgr;
660   gc_jm_options opts;
661   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
662   opts.nspes = 1;
663   mgr = gc_make_job_manager(&opts);
664
665   memset(short_buf, 0, sizeof(short_buf));
666   for (int i = 0; i < NS/2; i++)        // init buffer with known qty
667     short_buf[i] = 0x1234 + i;
668
669   int nshorts = NS/2;
670
671   gc_job_desc *jd = mgr->alloc_job_desc();
672   gc_proc_id_t gcp_qa_copy = mgr->lookup_proc("qa_copy");
673
674 #if 0
675   printf("gcq_qa_copy = %d\n", gcp_qa_copy);
676   std::vector<std::string> procs = mgr->proc_names();
677   for (unsigned int i = 0; i < procs.size(); ++i)
678     std::cout << procs[i] << std::endl;
679 #endif
680
681   init_jd(jd, gcp_qa_copy);
682   jd->eaa.nargs = 2;
683   jd->eaa.arg[0].ea_addr = ptr_to_ea(&short_buf[nshorts]);
684   jd->eaa.arg[0].direction = GCJD_DMA_PUT;
685   jd->eaa.arg[0].put_size = nshorts * sizeof(short);
686   
687   jd->eaa.arg[1].ea_addr = ptr_to_ea(&short_buf[0]);
688   jd->eaa.arg[1].direction = GCJD_DMA_GET;
689   jd->eaa.arg[1].get_size = nshorts * sizeof(short);
690   
691
692   if (!mgr->submit_job(jd)){
693     printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
694   }
695   else {
696     mgr->wait_job(jd);
697     CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
698     CPPUNIT_ASSERT_EQUAL(0, jd->output.arg[0].s32);
699
700     bool ok = true;
701     for (int i = 0; i < nshorts; i++){
702       if (short_buf[i] != short_buf[i + nshorts])
703         ok = false;
704     }
705     CPPUNIT_ASSERT(ok);
706   }
707   mgr->free_job_desc(jd);
708 }
709
710 /*
711  * Parallel submission of NJOBS "put" jobs will test double buffered puts.
712  */
713 void
714 qa_job_manager::t14_body()
715 {
716   //return;
717
718   //static const int NJOBS = 64;
719   static const int NJOBS = 128;
720   static const int LEN_PER_JOB = 1021;
721   unsigned char    buf[NJOBS * LEN_PER_JOB];
722   gc_job_desc_t   *jd[NJOBS];
723   bool             done[NJOBS];
724
725   static const int STARTING_VAL = 13;
726
727   memset(buf, 0xff, LEN_PER_JOB * NJOBS);
728
729   gc_job_manager_sptr mgr;
730   gc_jm_options opts;
731   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
732   opts.nspes = 1;
733   mgr = gc_make_job_manager(&opts);
734
735
736   gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
737
738   // do all the initialization up front
739
740   for (int i = 0, val = STARTING_VAL; i < NJOBS; i++, val += 3){
741     jd[i] = mgr->alloc_job_desc();
742     init_jd(jd[i], gcp_qa_put_seq);
743     jd[i]->input.nargs = 1;
744     jd[i]->input.arg[0].s32 = val;
745     jd[i]->eaa.nargs = 1;
746     jd[i]->eaa.arg[0].ea_addr = ptr_to_ea(&buf[i * LEN_PER_JOB]);
747     jd[i]->eaa.arg[0].direction = GCJD_DMA_PUT;
748     jd[i]->eaa.arg[0].put_size = LEN_PER_JOB;
749   }
750
751   // submit them all
752
753   for (int i = 0; i < NJOBS; i++){
754     if (!mgr->submit_job(jd[i])){
755       printf("%d: submit_job(jd[%2d]) failed, status = %d\n", __LINE__, i, jd[i]->status);
756     }
757   }
758
759   // wait for them all
760
761   int n = mgr->wait_jobs(NJOBS, jd, done, GC_WAIT_ALL);
762   CPPUNIT_ASSERT_EQUAL(NJOBS, n);
763
764   // check results
765
766   for (int i = 0, val = STARTING_VAL; i < NJOBS; i++, val += 3){
767     CPPUNIT_ASSERT_EQUAL(JS_OK, jd[i]->status);
768     CPPUNIT_ASSERT(confirm_seq(&buf[i * LEN_PER_JOB], LEN_PER_JOB, val));
769   }
770   
771   // cleanup
772   for (int i = 0; i < NJOBS; i++)
773     mgr->free_job_desc(jd[i]);
774 }
775
776 void
777 qa_job_manager::t15_body()
778 {
779   gc_jm_options opts;
780   opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa);
781   opts.nspes = 1;
782   gc_job_manager_sptr mgr = gc_make_job_manager(&opts);
783
784   gc_job_manager::set_singleton(mgr);
785
786   CPPUNIT_ASSERT(gc_job_manager::singleton());
787   mgr.reset();
788   CPPUNIT_ASSERT_THROW(gc_job_manager::singleton(), boost::bad_weak_ptr);
789 }