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/*
30 * Multi access to different type data
31 *
32 * Types:
33 * - Buffer
34 * - Package
35 *
36 * Notations:
37 *
38 * Leading thread - the worker thread #1 which plays in the relevant test
39 *                  some control role.
40 */
41
42
43/* Leading thread (thread #1) put there commands for other threads */
44Name(b900, Buffer(){0,0,0,0,0,0,0,0})
45
46/*
47 * This buffer is zeroed by the leading thread and then to
48 * be filled by other worker threads, some non-zero respond to
49 * the leading thread.
50 */
51Name(b901, Buffer(){0,0,0,0,0,0,0,0})
52
53/*
54 * This buffer is zeroed by the leading thread and then to be
55 * filled by other worker threads when they see that i900 is zero.
56 *
57 * The leading thread uses it to check that all the worker threads
58 * saw zero i900 before to start the next command.
59 */
60Name(b902, Buffer(){0,0,0,0,0,0,0,0})
61
62Name(i900, 0)    // signal start fulfilling command
63Name(i901, 0x30) // to do command 0x30 once only
64Name(c900, 0x31) //
65
66/*
67 * Test #.
68 *
69 * Leading thread (thread #1) is a controlling thread other are worker threads here.
70 *
71 * arg0 - number of threads
72 * arg1 - ID of current thread
73 * arg2 - Index of current thread
74 */
75Method(m900, 1)
76{
77	if (LGreater(arg0, 8)) {
78		se00(arg2, er06)
79		return
80	}
81	if (LGreaterEqual(arg2, arg0)) {
82		se00(arg2, er06)
83	}
84
85	if (LEqual(arg2, 1)) {
86
87		/* Leading thread */
88
89		While (1) {
90
91			if (i901) {
92				Store(0, i901)
93				m200(b900, arg0, 0x30)
94				m200(b901, arg0, 0)
95				Store(1, i900)
96			}
97
98			m206(arg2, sl01)
99		}
100	} else {
101		While (1) {
102
103			/* Determine the command for particular thread */
104
105			Store(c900, Local0)
106
107			/* Control thread allows for worker threads to fulfill their commands */
108			if (i900) {
109				Store(DerefOf(Index(b901, arg2)), Local1)
110				/* This thread doesn't yet fulfill its command */
111				if (LNot(Local1)) {
112					/* Command to be fulfilled */
113					Store(DerefOf(Index(b900, arg2)), Local0)
114				}
115				/* Unnecessary */
116				if (LNot(i900)) {
117					Store(c900, Local0)
118				}
119			}
120
121			if (LNot(i900)) {
122				Store(DerefOf(Index(b902, arg2)), Local0)
123				if (LNot(Local0)) {
124					/* Any non-zero value */
125					Store(rs00, Index(b902, arg2))
126				}
127			}
128			m206(arg2, sl01)
129		}
130	}
131}
132
133/*
134 * Thread 1 waits for all the worker threads to
135 * fulfill the specified for them the buffer of commands.
136 *
137 * arg0 - number of threads
138 * arg1 - flag if to check that all the worker threads saw my zero do00
139 */
140Method(m9ff, 2)
141{
142	Name(lpN0, 0)
143	Name(lpC0, 0)
144	Name(find, 0)
145
146	/*
147	 * Check that all the worker threads saw my
148	 * non-zero do00 and fulfilled the proper command.
149	 */
150	While (1) {
151		Store(0, find)
152		Store(arg0, lpN0)
153		Store(0, lpC0)
154		While (lpN0) {
155
156			/* For not a Control thread only */
157			if (LNotEqual(lpC0, 0)) {
158				Store(DerefOf(Index(b900, lpC0)), Local0)
159				Store(DerefOf(Index(b901, lpC0)), Local1)
160				if (LNotEqual(Local0, Local1)) {
161					Store(1, find)
162					break
163				}
164			}
165
166			Decrement(lpN0)
167			Increment(lpC0)
168		}
169
170		if (LNot(find)) {
171			break
172		}
173
174		/*
175		 * Don't report about Control thread sleeping -
176		 * don't use m206(0, sl00).
177		 */
178		Sleep(sl00)
179	}
180
181	/*
182	 * Check that all the worker threads saw my zero do00
183	 * (if only it is not the EXIT command).
184	 * Note: assumed that EXIT command is specified for all
185	 *       the threads simultaneously, so only.
186	 */
187	if (arg1) {
188		if (fl01) {
189			m109()
190		} else {
191			m200(b902, arg0, 0)
192		}
193		Store(0, do00)
194		While (1) {
195			Store(0, find)
196			if (fl01) {
197				Store(m10a(), find)
198			} else {
199				Store(arg0, lpN0)
200				Store(0, lpC0)
201				While (lpN0) {
202
203					/* For not a Control thread only */
204					if (LNotEqual(lpC0, 0)) {
205						Store(DerefOf(Index(b902, lpC0)), Local0)
206						if (LNot(Local0)) {
207							Store(1, find)
208							break
209						}
210					}
211
212					Decrement(lpN0)
213					Increment(lpC0)
214				}
215			}
216
217			if (LNot(find)) {
218				break
219			}
220
221			/*
222			 * Don't report about Control thread sleeping -
223			 * don't use m206(0, sl00).
224			 */
225			Sleep(sl00)
226		}
227
228		/* All the worker threads are ready for any next command */
229	}
230}
231