Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: distributor.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)distributor.fth 1.11 02/03/12 | |
43 | purpose: | |
44 | copyright: Copyright 1997-2000, 2002 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | : end-of-line ( first-transfer -- last-transfer ) | |
48 | begin | |
49 | dup next-transfer le-l@ | |
50 | while | |
51 | next-transfer le-l@ dev>virt | |
52 | repeat | |
53 | ; | |
54 | ||
55 | : add-to-line ( transfer-d last-transfer -- ) | |
56 | swap virt>dev swap next-transfer le-l! | |
57 | ; | |
58 | ||
59 | \ Put on done q in the same order as they show up on the controller done-q. | |
60 | \ Stored on the endpoint done-q's as dev addresses, little endian, because | |
61 | \ we reuse next-transfer to tie the q together, just as the other q's. | |
62 | \ Could change to use a different field and virt addresses. | |
63 | \ Don't need to sync this because the controller never accesses this field. | |
64 | : t>end-done ( transfer-d -- ) | |
65 | 0 over next-transfer l! \ at least for now, this will be the last one | |
66 | \ "should" be le-l!, but the result is the same | |
67 | dup my-endpoint @ | |
68 | dup ping-done-q | |
69 | swap for-controller @ + ( transfer-d endp-q-pointer ) | |
70 | dup @ if \ go to the end of the line | |
71 | @ end-of-line add-to-line | |
72 | else ! | |
73 | then | |
74 | ; | |
75 | ||
76 | : distribute-replies ( dev-done-head -- ) | |
77 | begin | |
78 | dev>virt dup sync-transfer | |
79 | dup next-transfer le-l@ swap ( dev-next curr-transfer-d ) | |
80 | t>end-done ( dev-next ) | |
81 | ?dup 0= \ 0 marks end of q | |
82 | until | |
83 | ; | |
84 | ||
85 | variable done-mutex \ must be global | |
86 | ||
87 | \ This mutex code is a little cleverer, it will release the mutex if | |
88 | \ the caller is the current owner. | |
89 | \ Stolen from the keyboard code. | |
90 | \ XXX may not need this cleverness. | |
91 | \ XXX heavily dependent on 32 bit execution tokens, as it gets something | |
92 | \ from the return stack and saves it in a 32 bit variable. | |
93 | ||
94 | \ XXX doesn't look like it really works here. mutex-enter is only called by take-done-q, | |
95 | \ so the done-owner is always the same (once the open is done). open always unlocks | |
96 | \ the mutex, so how does this protect the distributor? | |
97 | ||
98 | \ variable done-owner \ XXX global? | |
99 | ||
100 | \ : mutex-enter ( -- locked? ) | |
101 | \ done-mutex dup @ swap on ( locked? ) | |
102 | \ r@ done-owner rot if ( req var ) | |
103 | \ 2dup @ <> if ( req var ) | |
104 | \ 2drop true exit ( true ) | |
105 | \ then ( var req ) | |
106 | \ then ( req var ) | |
107 | \ ! false ( false ) | |
108 | \ ; | |
109 | ||
110 | \ : mutex-exit ( -- ) done-mutex off ; | |
111 | ||
112 | \ Used by done-waiting? | |
113 | : take-done-q ( -- ) | |
114 | new-done? if | |
115 | sync-hcca | |
116 | hcca done-head le-l@ | |
117 | \ toss interrupt-on bit which un-aligns the done-head: | |
118 | 1 invert and | |
119 | clear-done-head | |
120 | distribute-replies | |
121 | then | |
122 | ; | |
123 | ||
124 | \ Really should take off the alarm list when quit level runs, then put back on alarm | |
125 | \ list. Redman says that triggers an alarm list bug, so can't do it now. | |
126 | ||
127 | : alarm-take-done-q ( -- ) \ use on alarm level with 10 ms tick timer | |
128 | done-mutex @ 0= if \ XXX diff from use in mutex-enter, -exit | |
129 | take-done-q | |
130 | then | |
131 | ; | |
132 | ||
133 | : quit-take-done-q ( -- ) \ use on quit loop level | |
134 | true done-mutex ! \ XXX diff from use in mutex-enter, -exit | |
135 | take-done-q | |
136 | 0 done-mutex ! | |
137 | ; | |
138 | ||
139 | \ Replies are distributed by children, but the distributor is protected by | |
140 | \ the mutex so that replies go in order. | |
141 | ||
142 | \ XXX Check this code to make sure it's re-entrant. | |
143 | \ XXX Check this code to make sure it has no race conditions with the code | |
144 | \ running at the normal level which is editing the q's to install new stuff | |
145 | \ or disable-int-transactions. | |
146 | ||
147 | \ XXX Problem: 10 ms timer ticking for the keyboard and disk being booted | |
148 | \ from. each can see the other's transfer descriptors on the done q. | |
149 | \ Keep old done-q's until descriptors are all claimed? Or timed out somehow? | |
150 | \ **attach a done-q to each endpoint descriptor and distribute them from the | |
151 | \ chip's done-q? | |
152 | ||
153 | \ Still a problem if the keyboard is looking at 10ms timer intervals, | |
154 | \ essentially interrupting, while the boot device is looking at the regular | |
155 | \ execution intervals. There's a race condition over who looks at the | |
156 | \ done q of the chip to distribute the transfer descriptors. | |
157 | ||
158 | \ In practice there will be 1 set of transactions running off the 10ms timer | |
159 | \ for the keyboard and 1 running as usual for a boot device. There may be | |
160 | \ more instances of usb devices open, but only these will be running. | |
161 | \ Even if there is a usb output device that runs interrupt transfers, that | |
162 | \ will probably be run as a normal device, rather than hung off the 10 ms | |
163 | \ timer. | |
164 | ||
165 | \ The normal code looks to see if there are transfers to distribute. There | |
166 | \ are. Just then, the interrupt code runs, finds and distributes the | |
167 | \ transfers. It finishes, and the normal code thinks there are transfers | |
168 | \ to distribute, so it tries to do so -- but they have already been | |
169 | \ distributed before the normal code could grab the done q. | |
170 | ||
171 | \ One possible solution: | |
172 | \ Put the done-q transfer distribution code at the 10 ms interrupt as well. | |
173 | ||
174 | \ Another one: | |
175 | \ The normal instance looks again after grabbing the done q to find out if | |
176 | \ there are really any transfers to distribute (by looking at the bit in the | |
177 | \ register?). If there are it distributes them, because it really has the | |
178 | \ done q now, having set the control. If the ones that were there before | |
179 | \ have already been distributed, but new ones arrived (so the bit is true), | |
180 | \ that's ok. Just go ahead and distribute them. | |
181 | ||
182 | \ **Better variation: | |
183 | \ Grab the done q before finding out whether there are any entries. Then | |
184 | \ look at the done q and distribute. Then give up the q, and look at the | |
185 | \ endpoint done q. | |
186 | ||
187 | \ Is there another race condition? The normal code looks at its endpoint | |
188 | \ done q, and while fiddling with it, a new transfer is distributed to it | |
189 | \ by the 10ms timer instance. What happens? Does grabbing the done q | |
190 | \ extend to grabbing all the done q's at once? | |
191 | ||
192 | \ Note, once the chip done-q is turned over to the software, the chip | |
193 | \ essentially stalls until it is returned to the chip. The chip doesn't | |
194 | \ re-use the old done-q, but rather starts a new one. So all the transfers | |
195 | \ on the done-q must be distributed before the done-q is lost track of. So | |
196 | \ can't have the situation where the normal code grabbed its own done q and | |
197 | \ locked out the 10 ms timer code from distributing a transfer onto the normal | |
198 | \ done q, as the 10 ms timer code has a problem knowing what to do with the | |
199 | \ leftover transfers, and can't sit waiting for the normal code to release | |
200 | \ its done q. | |
201 | ||
202 | \ **use two endpoint done q's. one being emptied by the code, one being filled | |
203 | \ by the distributor. while the code is emptying one, it does not touch the | |
204 | \ other. also, the distributor only puts them on the other and does not touch | |
205 | \ the one being emptied. when 1st is empty, code switches to the other. | |
206 | \ switch is ok, as if distributor puts some more on just as code is switching, | |
207 | \ that's ok. | |
208 | ||
209 | \ what about a pipe between the distributor and the code? don't see it. | |
210 | ||
211 | \ could also use a ring of transfer addresses without links. could work, | |
212 | \ but it seems more cumbersome than just ping-ponging the q's. | |
213 | ||
214 | \ must be the kind of thing that the normal code doesn't need to lock, since | |
215 | \ the distributor code can't block, since it might be running as part of | |
216 | \ the 10ms timer instance. |