1    /*
2     * Some or all of this work - Copyright (c) 2006 - 2021, Intel Corp.
3     * All rights reserved.
4     *
5     * Redistribution and use in source and binary forms, with or without modification,
6     * are permitted provided that the following conditions are met:
7     *
8     * Redistributions of source code must retain the above copyright notice,
9     * this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright notice,
11     * this list of conditions and the following disclaimer in the documentation
12     * and/or other materials provided with the distribution.
13     * Neither the name of Intel Corporation nor the names of its contributors
14     * may be used to endorse or promote products derived from this software
15     * without specific prior written permission.
16     *
17     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27     */
28    /*
29     * SEE:
30     * ??????????? Multi-threading common definitions
31     * see: see structure and the name of this file also later !!!!!!!!!!!!!!
32     * ??????????????????????????????????????????????????????????????????????
33     *
34     *
35     * NOTIONS and NOTATIONS:
36     *
37     * ID and Index of thread:
38     *
39     *   each thread is identified by its ID (delivered from the underlying system)
40     *   and its calculated unique index between all the threads participating in
41     *   the test.
42     *
43     * Control Thread - the thread with index equal to 0
44     * Worker Threads  - all other threads with the non-zero index
45     *
46     * Number of threads (total) -
47     *    the value passed to AcpiExec Threads command
48     *    as a number of threads parameter.
49     *
50     * Number of threads actually in work -
51     *    number of threads actually participating the relevant test.
52     *    Note: this value includes the Control Thread too.
53     */
54    Name (Z147, 0x93)
55    /*
56     * Common data of threads
57     *
58     * Usage:
59     *
60     *   command line: Threads 6 1 MAIN
61     *     6 - number of threads, it can be greater or less than 6
62     *
63     *   redm      - set it to zero to reduce the run time
64     *   vb00-vb06 - use them to suppress the output
65     *
66     *   FLG1      - the _TCI-based Initialization of multithreading interconnection
67     *               (run command TCI_CMD_GET_ID_OF_THREADS to determine indexes of threads)
68     */
69    /*
70     * Flags
71     */
72    Name (CTL0, 0x00) /* the Control thread is ready */
73    Name (REDM, 0x01) /* run tests in reduced mode */
74    Name (GLDI, 0x00) /* global data initialized */
75    /*
76     * Simple switch of the verbal mode
77     *
78     * 0 - silent
79     * otherwise - allow
80     *
81     * s-flags (defaults are given in comment (0/1))
82     */
83    Name (VB00, 0x00) /* (0) common messages */
84    Name (VB02, 0x01) /* (1) trace Control thread */
85    Name (VB03, 0x00) /* (0) trace Worker threads */
86    Name (VB04, 0x01) /* (1) report statistics */
87    Name (VB05, 0x00) /* (0) report warnings by worker-threads */
88    Name (VB06, 0x01) /* (1) report errors by worker-threads */
89    /*
90     * Multi-conditional switches of the verbal mode
91     *
92     * 0 - silent
93     * 1 - allow only for Control Thread to report
94     * 2 - allow only for Worker Threads to report
95     * 3 - allow for all threads to report
96     *
97     * mc-flags
98     */
99    Name (VB01, 0x01) /* header of test */
100    /* Sleep mode */
101
102    Name (SL00, 0x32) /* Default milliseconds to sleep for Control thread */
103    Name (SL01, 0x32) /* Default milliseconds to sleep for Worker threads */
104    /*
105     * Default milliseconds to sleep for Control thread
106     * before to check hang status of worker threads on
107     * operations.
108     */
109    Name (SL02, 0x01F4)
110    /* How many times maximum to repeat sl02 sleeping */
111
112    Name (SL03, 0x01)
113    Name (SLM0, 0x00)   /* Sleeping mode for worker threads */
114    /* Milliseconds to sleep for non-zero slm0 */
115
116    Name (I100, 0x32)
117    Name (I101, 0x64)
118    Name (I102, 0xC8)
119    Name (I103, 0x0190)
120    Name (I104, 0x01F4)
121    Name (I105, 0x4B)
122    Name (I106, 0x96)
123    Name (I107, 0xFA)
124    Name (I108, 0x012C)
125    /* Commands for workers */
126
127    Name (C100, 0xF0) /* Idle thread */
128    Name (C101, 0xF1) /* Exit the infinite loop */
129    Name (C102, 0xF2) /* Sleep for the specified number of Milliseconds */
130    Name (C103, 0xF3) /* Acquire/Sleep/Release */
131    Name (C104, 0xF4) /* <Acquire/Sleep>(0-15 levels)/Release(15-0 levels) */
132    Name (C105, 0xF5) /* Example 0 */
133    Name (C106, 0xF6) /* Acquire specified set of mutexes */
134    Name (C107, 0xF7) /* Release specified set of mutexes */
135    Name (C108, 0xF8) /* Terminate thread */
136    Name (C109, 0xF9) /* Invoke Serialized method */
137    Name (C10A, 0xFA) /* Invoke non-Serialized method, use Mutex for exclusive access to critical section */
138    Name (C10B, 0xFB) /* Non-serialized method is grabbed simultaneously */
139    /* Responds of worker threads (not intersect with 'Commands for workers') */
140
141    Name (RS00, 0x97) /* "I see zero do00" */
142    /* Common use strategies provided by the Control thread */
143
144    Name (CM01, 0x01) /* all workers to exit the infinite loop */
145    Name (CM02, 0x02) /* all workers to sleep for the specified period */
146    /*
147     * This buffer is to be filled by the control thread.
148     * It is filed with the commands to be fulfilled by the
149     * worker threads.
150     *
151     * The thread of i-th index takes the command from the
152     * i-th element of Buffer.
153     *
154     * It is read-only for worker threads.
155     */
156    Name (BS00, Buffer (0x01)
157    {
158         0x00                                             // .
159    })
160    /*
161     * This buffer is zeroed by the control thread and then to be
162     * filled by the worker threads with the commands they have been
163     * fulfilled.
164     */
165    Name (BS01, Buffer (0x01)
166    {
167         0x00                                             // .
168    })
169    /*
170     * This buffer is zeroed by the control thread and then to be
171     * filled by the worker threads when they see that do00 is zero.
172     *
173     * The control thread uses it to check that all the worker threads
174     * saw zero do00 (are idle) before to start the next command.
175     */
176    Name (BS02, Buffer (0x01)
177    {
178         0x00                                             // .
179    })
180    /*
181     * This buffer is zeroed by the control thread and then to
182     * be filled by the idle worker threads.
183     */
184    Name (BS03, Buffer (0x01)
185    {
186         0x00                                             // .
187    })
188    /*
189     * This buffer is zeroed by the control thread and then to be
190     * set up by the worker threads when they complete.
191     */
192    Name (BS04, Buffer (0x01)
193    {
194         0x00                                             // .
195    })
196    /*
197     * p10X - statistics
198     */
199    /*
200     * These package are zeroed by the control thread,
201     * the worker threads accumulate there:
202     * - errors
203     * - number of errors
204     * - warnings
205     * - number of warnings
206     */
207    Name (P100, Package (0x01)
208    {
209        0x00
210    }) /* scale of errors */
211    Name (P101, Package (0x01)
212    {
213        0x00
214    }) /* number of errors */
215    Name (P102, Package (0x01)
216    {
217        0x00
218    }) /* scale of warnings */
219    Name (P103, Package (0x01)
220    {
221        0x00
222    }) /* number of warnings */
223    /* Command statistics */
224
225    Name (P104, Package (0x01)
226    {
227        0x00
228    }) /* number of Sleep */
229    Name (P105, Package (0x01)
230    {
231        0x00
232    }) /* number of Acquire */
233    Name (P106, Package (0x01)
234    {
235        0x00
236    }) /* number of Release */
237    /*
238     * To be filled by the control thread,
239     * non-zero enables to fulfill the commands specified by bs00.
240     */
241    Name (DO00, 0x00)
242    /* Opcodes of errors reported by worker threads */
243
244    Name (ER00, 0x01) /* Acquire failed */
245    Name (ER01, 0x02) /* Flag of mutex is already non-zero (set up by some thread(s)) */
246    Name (ER02, 0x04) /* Invalid flag of mutex (changed by other thread while this one owned that mutex) */
247    Name (ER03, 0x08) /* Unexpected exception */
248    Name (ER04, 0x10) /* Improper exception (no exception, or unexpected opcode, or more than one exception) */
249    Name (ER05, 0x20) /* Invalid command */
250    Name (ER06, 0x40) /* Invalid Index of current thread */
251    Name (ER07, 0x80) /* Too big Index of current thread */
252    Name (ER08, 0x0100) /* Invalid counter of mutex owning */
253    Name (ER09, 0x0200) /* Acquire returned zero but FAIL expected */
254    Name (ER10, 0x0400) /* Serialized method doesn't provide exclusive call */
255    Name (ER11, 0x0800) /* Serialized method doesn't provide exclusive call */
256    Name (ER12, 0x1000) /* Non-serialized method thr-1 didn't get into method */
257    Name (ER13, 0x2000) /* Non-serialized method thr-N didn't get into method */
258    /* Opcodes of warnings reported by worker threads */
259
260    Name (WN00, 0x01) /* Acquire repeatedly the same mutex by thread which already owns it */
261    /*
262     * These packages are to be filled by the control thread.
263     * They are filed with the arguments of commands specified
264     * for the worker threads.
265     *
266     * The thread of i-th index takes the arguments from the
267     * i-th elements of Packages.
268     *
269     * These are read-only for worker threads.
270     *
271     * For Acquire/Release:
272     *
273     * p200 - starting level of mutex
274     * p201 - number of Levels of mutexes
275     * p202 - starting index of mutex (on the specified level)
276     * p203 - number of mutexes of the same level
277     * p204 - exceptional conditions
278     * p205 - opcode of TimeOutValue (see comment to ma00)
279     */
280    Name (P200, Package (0x01)
281    {
282        0x00
283    })
284    Name (P201, Package (0x01)
285    {
286        0x00
287    })
288    Name (P202, Package (0x01)
289    {
290        0x00
291    })
292    Name (P203, Package (0x01)
293    {
294        0x00
295    })
296    Name (P204, Package (0x01)
297    {
298        0x00
299    })
300    Name (P205, Package (0x01)
301    {
302        0x00
303    })
304    /* Exceptions total number */
305
306    Name (EX10, 0x00)
307    /*
308     * p30X - Current state
309     */
310    Name (P300, Package (0x01)
311    {
312        0x00
313    }) /* scale of errors */
314    Name (P301, Package (0x01)
315    {
316        0x00
317    }) /* scale of warnings */
318    /*
319     * Non-zero means to check absence of exception
320     * before and after each operation additionally
321     * to the checking (if any) specified per-operation.
322     */
323    Name (FLG0, 0x00)
324    /*
325     * Handle exceptions
326     *
327     * Exceptional condition flag:
328     *
329     * EX0D      - FAIL expected
330     * EX0E      - check for "no exception"
331     * otherwise - opcode of exception expected
332     */
333    /*
334     * The _TCI-based Initialization of multithreading interconnection
335     * (run command TCI_CMD_GET_ID_OF_THREADS to determine indexes of threads).
336     *
337     * Note: now when arguments (arg0, arg1, arg2) are determined
338     *       by Threads command of AcpiExec and passed to test, it
339     *       is unnecessary to do "The _TCI-based Initialization of
340     *       multithreading interconnection" below. Used temporary.
341     */
342    Name (FLG1, 0x00)
343    /*
344     * Variables used by particular tests
345     *
346     * FLG2,
347     * FLG3
348     *   1) To show that Serialized method is grabbed exclusively
349     *   2) To show that non-Serialized method is grabbed by two threads simultaneously
350     */
351    Name (FLG2, 0x00)
352    Name (FLG3, 0x00)
353    /*
354     * The Control Thread manages and controls the specified testing strategy
355     * to be fulfilled by the Worker Threads.
356     *
357     * arg0 - number of threads
358     * arg1 - ID of current thread (0, can be used for control only)
359     * arg2 - Index of current thread
360     * arg3 - cammand - index of the test strategy to be
361     *        managed and controlled by the Control Thread
362     *        and fulfilled by the Worker Threads (Workers).
363     *
364     * Arguments of the command arg3:
365     *
366     * arg4
367     * arg5
368     * arg6
369     */
370    Method (M100, 7, Serialized)
371    {
372        /* Prohibits activity of all the worker threads */
373
374        Switch (Arg3)
375        {
376            Case (0x01)
377            {
378                /* CM01: All workers to exit the infinite loop */
379
380                M10C (Arg0)
381            }
382            Case (0x02)
383            {
384                /* CM02: All workers to sleep for the specified period */
385
386                M10D (Arg0)
387            }
388
389        }
390    }
391
392    /*
393     * Open testing - init interaction data
394     *
395     * arg0 - number of threads
396     */
397    Method (M102, 1, Serialized)
398    {
399        Name (B000, Buffer (Arg0){})
400        Name (P000, Package (Arg0){})
401        Name (LPN0, 0x00)
402        Name (LPC0, 0x00)
403        DO00 = 0x00
404        CopyObject (B000, BS00) /* \BS00 */
405        CopyObject (B000, BS01) /* \BS01 */
406        CopyObject (B000, BS02) /* \BS02 */
407        CopyObject (B000, BS03) /* \BS03 */
408        CopyObject (P000, P200) /* \P200 */
409        CopyObject (P000, P201) /* \P201 */
410        CopyObject (P000, P202) /* \P202 */
411        CopyObject (P000, P203) /* \P203 */
412        CopyObject (P000, P204) /* \P204 */
413        CopyObject (P000, P205) /* \P205 */
414        CopyObject (P000, P300) /* \P300 */
415        CopyObject (P000, P301) /* \P301 */
416        LPN0 = Arg0
417        LPC0 = 0x00
418        While (LPN0)
419        {
420            P300 [LPC0] = 0x00
421            P301 [LPC0] = 0x00
422            LPN0--
423            LPC0++
424        }
425
426        /*
427         * Initialization to be done once
428         */
429        If (!GLDI)
430        {
431            /* Statistics */
432
433            CopyObject (P000, P100) /* \P100 */
434            CopyObject (P000, P101) /* \P101 */
435            CopyObject (P000, P102) /* \P102 */
436            CopyObject (P000, P103) /* \P103 */
437            CopyObject (P000, P104) /* \P104 */
438            CopyObject (P000, P105) /* \P105 */
439            CopyObject (P000, P106) /* \P106 */
440            CopyObject (B000, BS04) /* \BS04 */
441            LPN0 = Arg0
442            LPC0 = 0x00
443            While (LPN0)
444            {
445                P100 [LPC0] = 0x00
446                P101 [LPC0] = 0x00
447                P102 [LPC0] = 0x00
448                P103 [LPC0] = 0x00
449                P104 [LPC0] = 0x00
450                P105 [LPC0] = 0x00
451                P106 [LPC0] = 0x00
452                LPN0--
453                LPC0++
454            }
455        }
456
457        /* Init fl01 */
458
459        M339 ()
460        /*
461         * Reset all counters (cnt0) and flags (fl00)
462         * corresponding to all Mutexes.
463         */
464        M330 ()
465        /* Report that the Control thread is ready */
466
467        CTL0 = 0x01
468        GLDI = 0x01
469    }
470
471    /*
472     * Control thread waits for all the worker threads to
473     * fulfill the specified for them buffer of commands.
474     *
475     * arg0 - number of threads
476     */
477    Method (M103, 1, Serialized)
478    {
479        /* Wait for all Worker threads and check their statuses */
480
481        Name (B000, Buffer (Arg0){})
482        Name (B001, Buffer (Arg0){})
483        Name (B002, Buffer (Arg0){})
484        CopyObject (BS00, B000) /* \M103.B000 */
485        M110 (Arg0, B000, B001, B002)
486    }
487
488    /*
489     * The _TCI-based initialization of multithreading interconnection
490     *
491     * In result each thread knows its ID and calculated its index
492     * between all threads participating in the test.
493     *
494     * arg0 - number of threads
495     *
496     * Return:
497     *   success   - II-Package
498     *   otherwise - 0
499     */
500    Method (M104, 1, NotSerialized)
501    {
502        /*
503         * Local0 - array of thread IDs
504         * Local1 - auxiliary
505         * Local2 - auxiliary
506         * Local7 - II-Package
507         */
508        If (VB00)
509        {
510            Debug = "Checking for the Test Command Interface with the ACPICA (_TCI) support"
511        }
512
513        If (!M3A5 ())
514        {
515            Debug = "The Test Command Interface with the ACPICA (_TCI) is not supported"
516            Return (0x00)
517        }
518
519        If (VB00)
520        {
521            Debug = "Getting array of thread IDs"
522        }
523
524        Local0 = M163 (Arg0)
525        Local1 = ObjectType (Local0)
526        If ((Local1 != C00C))
527        {
528            Debug = "Failed to get array of thread indexes"
529            Return (0x00)
530        }
531
532        If (VB00)
533        {
534            Debug = "Calculating index of thread"
535        }
536
537        Local7 = M105 (Local0, Arg0)
538        Local2 = ObjectType (Local7)
539        If ((Local2 != C00C))
540        {
541            Debug = "Invalid contents of Package of threads"
542            Return (0x00)
543        }
544
545        Return (Local7)
546    }
547
548    /*
549     * Calculate and return II-Package with Index of current thread between
550     * all threads participating in the test and ID of that thread.
551     *
552     * arg0 - the Package of thread IDs returned by m163 which
553     *        executes the command TCI_CMD_GET_ID_OF_THREADS.
554     * arg1 - number of threads
555     *
556     * Return:
557     * II-Package in success:
558     *	0-th element - ID of that current thread
559     *	1-th element - Index of current thread between all threads participating in test
560     * Integer otherwise:
561     *    0
562     */
563    Method (M105, 2, NotSerialized)
564    {
565        /*
566         * Local0 - auxiliary
567         * Local1 - auxiliary
568         * Local2 - lpN0
569         * Local3 - lpC0
570         * Local4 - TCI_PACKAGE_THR_NUM
571         * Local5 - TCI_PACKAGE_THR_NUM_REAL
572         * Local6 - TCI_PACKAGE_THR_ID (ID of thread)
573         * Local7 - Index of thread
574         */
575        Local7 = FF32 /* \FF32 */
576        /* Store(arg0, Debug) */
577
578        Local4 = DerefOf (Arg0 [C22C]) /* TCI_PACKAGE_THR_NUM */
579        If (!Local4)
580        {
581            Debug = "TCI_PACKAGE_THR_NUM is zero"
582            Return (0x00)
583        }
584
585        Local5 = DerefOf (Arg0 [C22D]) /* TCI_PACKAGE_THR_NUM_REAL */
586        If (!Local5)
587        {
588            Debug = "TCI_PACKAGE_THR_NUM_REAL is zero"
589            Return (0x00)
590        }
591
592        Local6 = DerefOf (Arg0 [C22E]) /* TCI_PACKAGE_THR_ID */
593        If (!Local6)
594        {
595            Debug = "TCI_PACKAGE_THR_ID is zero"
596            Return (0x00)
597        }
598
599        If ((Local4 != Local5))
600        {
601            Debug = "TCI_PACKAGE_THR_NUM != TCI_PACKAGE_THR_NUM_REAL"
602            Debug = Local4
603            Debug = Local5
604            Return (0x00)
605        }
606
607        If ((Local4 != Arg1))
608        {
609            Debug = "TCI_PACKAGE_THR_NUM != Number of threads"
610            Debug = Local4
611            Debug = Arg1
612            Return (0x00)
613        }
614
615        /* Calculate index of thread */
616
617        Local2 = Arg1
618        Local3 = 0x00
619        Local0 = C22F /* \C22F */
620        While (Local2)
621        {
622            Local1 = DerefOf (Arg0 [Local0])
623            If (!Local1)
624            {
625                Debug = "thread ID is zero"
626                Return (0x00)
627            }
628            ElseIf ((Local1 == Local6))
629            {
630                If ((Local7 != FF32))
631                {
632                    Debug = "thread ID encountered twice"
633                    Return (0x00)
634                }
635
636                Local7 = Local3
637            }
638
639            Local0++
640            Local2--
641            Local3++
642        }
643
644        /* Return Package: Index of current thread, ID of current thread */
645
646        Local0 = Package (0x02){}
647        Local0 [0x00] = Local6
648        Local0 [0x01] = Local7
649        Return (Local0)
650    }
651
652    /*
653     * Report errors detected by the worker threads
654     *
655     * arg0 - name of test
656     * arg1 - number of threads
657     */
658    Method (M106, 2, Serialized)
659    {
660        Name (LPN0, 0x00)
661        Name (LPC0, 0x00)
662        LPN0 = Arg1
663        LPC0 = 0x00
664        While (LPN0)
665        {
666            Local0 = DerefOf (P300 [LPC0])
667            If (Local0)
668            {
669                /*
670                 * Reports:
671                 * lpC0   - Index of thread
672                 * Local0 - the scale of its errors
673                 */
674                ERR (Arg0, Z147, __LINE__, 0x00, 0x00, LPC0, Local0)
675            }
676
677            LPN0--
678            LPC0++
679        }
680    }
681
682    /*
683     * Initialization of multithreading interconnection
684     *
685     * Note: now when arguments (arg0, arg1, arg2) are determined
686     *       by Threads command of AcpiExec and passed to test, it
687     *       is unnecessary to do "The _TCI-based Initialization of
688     *       multithreading interconnection" below. Used temporary.
689     *
690     * arg0 - number of threads
691     * arg1 - ID of current thread
692     * arg2 - Index of current thread
693     * arg3 - minimal number of threads needed for test
694     */
695    Method (M107, 4, NotSerialized)
696    {
697        /* Set the multi-threading mode flag */
698
699        SET3 (0x01)
700        /*
701         * Local0 - auxiliary
702         * Local1 - auxiliary
703         * Local6 - ID of thread
704         * Local7 - Index of thread
705         */
706        /* The _TCI-based Initialization of multithreading interconnection */
707        If (FLG1)
708        {
709            Local0 = M104 (Arg0)
710            Local1 = ObjectType (Local0)
711            If ((Local1 != C00C))
712            {
713                ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local1, C00C)
714                Return (0x00)
715            }
716
717            /* Get ID and Index of current thread */
718
719            Local6 = DerefOf (Local0 [0x00])
720            Local7 = DerefOf (Local0 [0x01])
721            If ((Local6 != Arg1))
722            {
723                ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local6, Arg1)
724                Return (0x00)
725            }
726
727            If ((Local7 != Arg2))
728            {
729                ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local7, Arg2)
730                Return (0x00)
731            }
732        }
733
734        If (((Arg0 < 0x02) || (Arg0 < Arg3)))
735        {
736            Debug = "Insufficient number of threads for Test!"
737            Return (0x00)
738        }
739
740        Return (0x01)
741    }
742
743    /*
744     * Close testing
745     *
746     * arg0 - name of test
747     * arg1 - number of threads
748     * arg2 - ID of current thread
749     * arg3 - Index of current thread
750     */
751    Method (M108, 4, NotSerialized)
752    {
753        /* all workers to exit the infinite loop */
754
755        M100 (Arg1, Arg2, Arg3, CM01, 0x00, 0x00, 0x00)
756        /* Report errors detected by the worker threads */
757
758        M106 (Arg0, Arg1)
759    }
760
761    /*
762     * CM01: all workers to exit the infinite loop
763     *
764     * arg0 - number of threads
765     */
766    Method (M10C, 1, Serialized)
767    {
768        /* All workers to exit the infinite loop */
769
770        M200 (BS00, Arg0, C101) /* cmd: Exit the infinite loop */
771        M114 (Arg0)
772        /* Wait for all Worker threads */
773
774        Name (B000, Buffer (Arg0){})
775        Name (B001, Buffer (Arg0){})
776        Name (B002, Buffer (Arg0){})
777        CopyObject (BS00, B000) /* \M10C.B000 */
778        M110 (Arg0, B000, B001, B002)
779    }
780
781    /*
782     * CM02: all workers to sleep for the specified period
783     *
784     * arg0 - number of threads
785     */
786    Method (M10D, 1, NotSerialized)
787    {
788        /* All workers to sleep for the specified period */
789
790        M200 (BS00, Arg0, C102) /* cmd: Sleep for the specified number of Milliseconds */
791        M114 (Arg0)
792        /* Wait for all Worker threads */
793
794        M103 (Arg0)
795    }
796
797    /*
798     * Control thread checks that the specified set of worker threads
799     * hang on the specified operations or completed the operations.
800     *
801     * arg0 - number of threads
802     * arg1 - buffer of arg0 length
803     *        1 - check completion of operation
804     *        2 - check hang
805     *
806     * Return:
807     *   These mean unexpected behaviour:
808     *     0x01 - some threads has not completed operation
809     *     0x02 - some threads are not hang on operation
810     *   These report the contents of buffer:
811     *     0x10 - has checkings of completed operation
812     *     0x20 - has checkings of hang on operation
813     */
814    Method (M10E, 2, Serialized)
815    {
816        Name (LPN0, 0x00)
817        Name (LPC0, 0x00)
818        Name (RVAL, 0x00)
819        LPN0 = Arg0
820        LPC0 = 0x00
821        While (LPN0)
822        {
823            /* For not a Control thread only */
824
825            If ((LPC0 != 0x00))
826            {
827                Local0 = DerefOf (Arg1 [LPC0])
828                Local1 = DerefOf (BS01 [LPC0])
829                If ((Local0 == 0x01))
830                {
831                    /* check completion of operation */
832
833                    RVAL |= 0x10
834                    If (!Local1)
835                    {
836                        RVAL |= 0x01
837                    }
838                }
839                ElseIf ((Local0 == 0x02))
840                {
841                    /* check hang */
842
843                    RVAL |= 0x20
844                    If (Local1)
845                    {
846                        RVAL |= 0x02
847                    }
848                }
849            }
850
851            LPN0--
852            LPC0++
853        }
854
855        Return (RVAL) /* \M10E.RVAL */
856    }
857
858    /*
859     * Run and analyze result of m10e()
860     *
861     * arg0,
862     * arg1 - see m10e
863     */
864    Method (M10F, 2, Serialized)
865    {
866        Name (LPN0, 0x00)
867        Name (LPC0, 0x00)
868        Name (RVAL, 0x00)
869        LPN0 = SL03 /* \SL03 */
870        LPC0 = 0x00
871        While (LPN0)
872        {
873            Sleep (SL02)
874            RVAL = M10E (Arg0, Arg1)
875            If (!(RVAL & 0x20))
876            {
877                /* doesn't have checkings of hang */
878
879                If (!(RVAL & 0x01))
880                {
881                    /* all examined have completed */
882
883                    Break
884                }
885            }
886
887            LPN0--
888            LPC0++
889        }
890
891        Return (RVAL) /* \M10F.RVAL */
892    }
893
894    /*
895     * Control thread waits for all the worker threads to
896     * fulfill the specified for them buffer of commands.
897     *
898     * arg0 - number of threads (total)
899     * arg1 - the per-thread expectations of completion status mapping buffer
900     * arg2 - the per-thread expectations of hang       status mapping buffer
901     * arg3 - the per-thread expectations of idle       status mapping buffer
902     */
903    Method (M110, 4, Serialized)
904    {
905        Name (LPN0, 0x00)
906        Name (LPC0, 0x00)
907        Name (FIND, 0x00)
908        Name (SL80, 0x00)
909        Name (SL81, 0x00)
910        Name (CMD0, 0x00)
911        Name (HNG0, 0x00)
912        Name (IDL0, 0x00)
913        Name (QUIT, 0x00)
914        /*
915         * Check that all the worker threads saw my
916         * non-zero do00 and fulfilled the proper command.
917         */
918        While (0x01)
919        {
920            FIND = 0x00
921            LPN0 = Arg0
922            LPC0 = 0x00
923            While (LPN0)
924            {
925                /* For not a Control thread only */
926
927                If ((LPC0 != 0x00))
928                {
929                    CMD0 = DerefOf (Arg1 [LPC0])
930                    HNG0 = DerefOf (Arg2 [LPC0])
931                    IDL0 = DerefOf (Arg3 [LPC0])
932                    Local0 = DerefOf (BS00 [LPC0])
933                    Local1 = DerefOf (BS01 [LPC0])
934                    Local2 = DerefOf (BS03 [LPC0])
935                    Local3 = DerefOf (BS04 [LPC0]) /* terminated threads */
936                    If (Local3){                    /* Thread already completed by c108 */
937                    }
938                    ElseIf (CMD0)
939                    {
940                        If ((Local0 != CMD0))
941                        {
942                            ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0)
943                            Debug = LPC0 /* \M110.LPC0 */
944                        }
945
946                        If (!Local1)
947                        {
948                            /* Not completed yet */
949
950                            FIND = 0x01
951                            Break
952                        }
953                        ElseIf ((Local1 != Local0))
954                        {
955                            /* Has executed unexpected command */
956
957                            ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local1, Local0)
958                            Debug = LPC0 /* \M110.LPC0 */
959                        }
960                    }
961                    ElseIf (HNG0)
962                    {
963                        SL81 = 0x01
964                        If ((SL80 < SL03))
965                        {
966                            /*
967                             * Delay here is some pure attempt to be objective -
968                             * it can look like hang now but go just after this
969                             * checking.
970                             */
971                            SL80++
972                            Sleep (SL02)
973                        }
974
975                        Local4 = DerefOf (BS01 [LPC0])
976                        If (Local4)
977                        {
978                            /* Doesn't hang */
979
980                            If ((Local4 != Local0))
981                            {
982                                /* Has executed unexpected command */
983
984                                ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local1, Local0)
985                                Debug = LPC0 /* \M110.LPC0 */
986                            }
987
988                            ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, Local4)
989                            Debug = LPC0 /* \M110.LPC0 */
990                        }
991                    }
992                    ElseIf (IDL0)
993                    {
994                        If ((Local0 != C100))
995                        {
996                            ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0)
997                            Debug = LPC0 /* \M110.LPC0 */
998                        }
999
1000                        If (!Local2)
1001                        {
1002                            /* Not completed yet */
1003
1004                            FIND = 0x01
1005                            Break
1006                        }
1007                        ElseIf ((Local2 != C100))
1008                        {
1009                            /* Has executed unexpected command */
1010
1011                            ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0)
1012                            Debug = LPC0 /* \M110.LPC0 */
1013                        }
1014                    }
1015                    Else
1016                    {
1017                        ERR ("m110", Z147, __LINE__, 0x00, 0x00, LPC0, Local0)
1018                        Debug = LPC0 /* \M110.LPC0 */
1019                    }
1020                }
1021
1022                LPN0--
1023                LPC0++
1024            }
1025
1026            QUIT = 0x00
1027            If (!FIND)
1028            {
1029                QUIT = 0x01
1030                /*
1031                 * All threads except those being checked for hang status
1032                 * have completed their commands.
1033                 */
1034                If (SL81)
1035                {
1036                    /* Has threads to check hang status */
1037
1038                    If ((SL80 < SL03))
1039                    {
1040                        /* Not completed yet the specified delay */
1041
1042                        QUIT = 0x00
1043                    }
1044                }
1045            }
1046
1047            If (QUIT)
1048            {
1049                Break
1050            }
1051
1052            /*
1053             * Don't report about Control thread sleeping -
1054             * don't use m206(0, sl00).
1055             */
1056            Sleep (SL00)
1057        }
1058
1059        /*
1060         * Set do00 to zero and check that all the worker threads
1061         * saw my zero do00 (if only it is not the EXIT command).
1062         */
1063        M200 (BS02, Arg0, 0x00)
1064        DO00 = 0x00
1065        While (0x01)
1066        {
1067            FIND = 0x00
1068            LPN0 = Arg0
1069            LPC0 = 0x00
1070            While (LPN0)
1071            {
1072                /* For not a Control thread only */
1073
1074                If ((LPC0 != 0x00))
1075                {
1076                    /*
1077                     * Reset the specified command for each thread
1078                     * which in fact doesn't hang.
1079                     */
1080                    Local0 = DerefOf (BS02 [LPC0])
1081                    If (Local0)
1082                    {
1083                        /* Alive, doesn't hang, so reset its command */
1084
1085                        BS00 [LPC0] = C100 /* \C100 */
1086                        BS01 [LPC0] = 0x00
1087                    }
1088
1089                    /*
1090                     * For all threads except those being checked for
1091                     * hang status and completed already.
1092                     */
1093                    HNG0 = DerefOf (Arg2 [LPC0])
1094                    Local0 = DerefOf (BS04 [LPC0])
1095                    If ((!HNG0 && !Local0))
1096                    {
1097                        Local0 = DerefOf (BS02 [LPC0])
1098                        If (!Local0)
1099                        {
1100                            FIND = 0x01
1101                            Break
1102                        }
1103                    }
1104                }
1105
1106                LPN0--
1107                LPC0++
1108            }
1109
1110            /*
1111             * All threads except those being checked for hang status
1112             * have zeroed do00.
1113             */
1114            If (!FIND)
1115            {
1116                Break
1117            }
1118
1119            /*
1120             * Don't report about Control thread sleeping -
1121             * don't use m206(0, sl00).
1122             */
1123            Sleep (SL00)
1124        }
1125        /* All the worker threads are ready for any next command */
1126    }
1127
1128    /*
1129     * Check absence of exception
1130     *
1131     * arg0 - ID of current thread
1132     * arg1 - Index of current thread
1133     * arg2 - exceptional condition flag
1134     * arg3 - the name of operation
1135     *
1136     * Return opcode of exception to be generated or zero
1137     */
1138    Method (M111, 4, Serialized)
1139    {
1140        If ((FLG0 || Arg2))
1141        {
1142            Local0 = CH08 ("m111", Arg0, Z147, 0x0C, 0x00, 0x00)
1143            If (Local0)
1144            {
1145                SE00 (Arg1, ER03, "Error er03")
1146            }
1147        }
1148
1149        /* Analyze opcode of exception to be generated */
1150
1151        Switch (Arg2)
1152        {
1153            Case (0x00)
1154            {
1155                Local0 = 0x00
1156            }
1157            Case (0xFE)
1158            {
1159                /* EX0E - check "no exception" */
1160
1161                Local0 = 0x00
1162            }
1163            Case (0xFD)
1164            {
1165                /* EX0D - FAIL expected */
1166
1167                Local0 = Arg2
1168                Concatenate (Arg3, ", generating FAIL condition ", Local1)
1169                M201 (Arg1, VB03, Local1)
1170            }
1171            Default
1172            {
1173                Local0 = Arg2
1174                Concatenate (Arg3, ", generating exceptional condition ", Local1)
1175                Concatenate (Local1, Local0, Local1)
1176                M201 (Arg1, VB03, Local1)
1177            }
1178
1179        }
1180
1181        Return (Local0)
1182    }
1183
1184    /*
1185     * Check exception
1186     *
1187     * arg0 - ID of current thread
1188     * arg1 - Index of current thread
1189     * arg2 - exceptional condition flag
1190     * arg3 - return code of operation
1191     */
1192    Method (M112, 4, NotSerialized)
1193    {
1194        Local2 = 0x00
1195        If ((Arg2 == EX0E))
1196        {
1197            /* check "no exception" */
1198
1199            Local0 = CH08 ("m112", Arg0, Z147, 0x0D, 0x00, 0x00)
1200            If (Local0)
1201            {
1202                SE00 (Arg1, ER03, "Error er03")
1203            }
1204        }
1205        ElseIf ((Arg2 == EX0D))
1206        {
1207            /* FAIL of operation expected */
1208
1209            If (!Arg3)
1210            {
1211                ERR ("m112", Z147, __LINE__, 0x00, 0x00, Arg3, 0x01)
1212            }
1213        }
1214        ElseIf (Arg2)
1215        {
1216            /* check presence of particular exception */
1217
1218            Local0 = CH09 (0x00, Arg0, Arg2, Z147, 0x0F, RefOf (Local2))
1219            If (Local0)
1220            {
1221                SE00 (Arg1, ER04, "Error er04")
1222            }
1223        }
1224
1225        If (FLG0)
1226        {
1227            Local0 = CH08 ("m112", Arg0, Z147, 0x10, 0x00, 0x00)
1228            If (Local0)
1229            {
1230                SE00 (Arg1, ER03, "Error er03")
1231            }
1232        }
1233    }
1234
1235    /*
1236     * Control thread initiates execution of commands by the worker threads
1237     *
1238     * arg0 - number of threads (total)
1239     */
1240    Method (M114, 1, NotSerialized)
1241    {
1242        M200 (BS01, Arg0, 0x00)
1243        M200 (BS03, Arg0, 0x00)
1244        DO00 = 0x01
1245    }
1246
1247    /*
1248     * Return index of the greatest alive non-terminated yet thread
1249     *
1250     * arg0 - number of threads
1251     */
1252    Method (M115, 1, Serialized)
1253    {
1254        Name (LPN0, 0x00)
1255        Name (LPC0, 0x00)
1256        /* Means 'not found' */
1257
1258        Local7 = Arg0
1259        /* Inverse order, excluding a Control thread */
1260
1261        LPN0 = (Arg0 - 0x01)
1262        LPC0 = (Arg0 - 0x01)
1263        While (LPN0)
1264        {
1265            Local0 = DerefOf (BS04 [LPC0])
1266            If (!Local0)
1267            {
1268                Local7 = LPC0 /* \M115.LPC0 */
1269                Break
1270            }
1271
1272            LPN0--
1273            LPC0--
1274        }
1275
1276        Return (Local7)
1277    }
1278
1279    /*
1280     * Add error-bit relative to arg0-th thread
1281     *
1282     * arg0 - Index of thread
1283     * arg1 - error-bit
1284     * arg2 - message
1285     */
1286    Method (SE00, 3, NotSerialized)
1287    {
1288        Local0 = DerefOf (P300 [Arg0])
1289        Local1 = (Arg1 | Local0)
1290        P300 [Arg0] = Local1
1291        If (VB04)
1292        {
1293            /* Add scale of Errors */
1294
1295            Local0 = DerefOf (P100 [Arg0])
1296            Local1 = (Arg1 | Local0)
1297            P100 [Arg0] = Local1
1298            /* Increment statistics of Errors (number) */
1299
1300            M212 (RefOf (P101), Arg0)
1301        }
1302
1303        If (VB06)
1304        {
1305            Concatenate ("ERROR: ", Arg2, Local0)
1306            M201 (Arg0, 0x01, Local0)
1307        }
1308    }
1309
1310    /*
1311     * Add warning-bit relative to arg0-th thread
1312     *
1313     * arg0 - Index of thread
1314     * arg1 - warning-bit
1315     * arg2 - message
1316     */
1317    Method (WRN0, 3, NotSerialized)
1318    {
1319        Local0 = DerefOf (P301 [Arg0])
1320        Local1 = (Arg1 | Local0)
1321        P301 [Arg0] = Local1
1322        If (VB04)
1323        {
1324            /* Add scale of Warnings */
1325
1326            Local0 = DerefOf (P102 [Arg0])
1327            Local1 = (Arg1 | Local0)
1328            P102 [Arg0] = Local1
1329            /* Increment statistics of Warnings (number) */
1330
1331            M212 (RefOf (P103), Arg0)
1332        }
1333
1334        If (VB05)
1335        {
1336            Concatenate ("WARNING: ", Arg2, Local0)
1337            M201 (Arg0, 0x01, Local0)
1338        }
1339    }
1340