From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1382EC32789 for ; Fri, 2 Nov 2018 16:18:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A26D72081B for ; Fri, 2 Nov 2018 16:18:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A26D72081B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rowland.harvard.edu Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727668AbeKCB0Z (ORCPT ); Fri, 2 Nov 2018 21:26:25 -0400 Received: from iolanthe.rowland.org ([192.131.102.54]:37440 "HELO iolanthe.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1726707AbeKCB0Y (ORCPT ); Fri, 2 Nov 2018 21:26:24 -0400 Received: (qmail 3249 invoked by uid 2102); 2 Nov 2018 12:18:45 -0400 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 2 Nov 2018 12:18:45 -0400 Date: Fri, 2 Nov 2018 12:18:45 -0400 (EDT) From: Alan Stern X-X-Sender: stern@iolanthe.rowland.org To: Laurent Pinchart cc: Felipe Balbi , Paul Elder , Bin Liu , , , , , Subject: Re: [PATCH 4/6] usb: gadget: add functions to signal udc driver to delay status stage In-Reply-To: <1864168.qYyPzk9PJV@avalon> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, 2 Nov 2018, Laurent Pinchart wrote: > Hi Felipe, > > On Friday, 2 November 2018 15:17:20 EET Felipe Balbi wrote: > > Laurent Pinchart writes: > > >>>>> +void usb_ep_delay_status(struct usb_ep *ep) > > >>>>> > > >>>>> +{ > > >>>>> + ep->delayed_status = true; > > >>>>> +} > > >>>>> +EXPORT_SYMBOL_GPL(usb_ep_delay_status); > > >>>> > > >>>> Is usb_ep_set_delay_status() better? I thought it implies get/return > > >>>> action if a verb is missing in the function name. > > >>> > > >>> For what it's worth, I understand the function name as "delay the > > >>> status stage", with "delay" being a verb. Maybe the short description > > >>> could be updated accordingly. > > >>> > > >>> Is there a reason for adding a new function for this? This is exactly > > >>> what the USB_GADGET_DELAYED_STATUS return value from the setup callback > > >>> is meant for (and it is already used by some gadget drivers). > > >> > > >> In theory, we might be able to use USB_GADGET_DELAYED_STATUS for this. > > >> However, there are a few ambiguities that prevent us from doing so. > > >> > > >> First of all, we want to delay only the status stage for control OUT > > >> requests; according to composite.h, USB_GADGET_DELAYED_STATUS is for > > >> delaying the "data/status stages". Does this mean that it delays the > > >> status stage only or does it delay both stages? If the slash means > > >> "and", then we cannot use USB_GADGET_DELAYED_STATUS. The comment in composite.h is wrong; it should refer only to the status stage. In fact, it should refer only to the status stage for control-OUT transfers; there's no reason ever to delay the status stage of a control-IN transfer (the driver should instead delay the data stage if it needs to). > > >> Furthermore, we have found that USB_GADGET_DELAYED_STATUS is racey, > > >> which has already been observed in the UVC gadget driver previously [0]. > > >> The raceiness stems from the fact that things can happen in between > > >> returning USB_GADGET_DELAYED_STATUS and the composite layer reacting to > > >> it - especially if usb_composite_setup_continue is called within that > > >> window it causes a WARN. In any case, the fact that the mechanism itself > > >> is racey suggests that it needs improvement, and using it wouldn't be a > > >> good solution in this case. I don't understand this at all. The composite layer reacts to USB_GADGET_DELAYED_STATUS as soon as it receives the return value. Can Paul or Laurent give a more explicit example of this race? Assuming you are correct, wouldn't it make sense to fix or eliminate the race by changing composite.c? > > >>> Is it a question of when the gadget driver learns that it will need to > > >>> delay the status stage? If that's the case, > > >> > > >> Not really. > > >> > > >>> why not always return > > >>> USB_GADGET_DELAYED_STATUS from the setup callback? Then instead of > > >>> calling usb_ep_delay_status() when a delay is needed, you could queue > > >>> the status request when a delay isn't needed. > > >> > > >> Theoretically this might work, but see the problems mentioned above. > > >> > > >>> As a more general solution, Felipe has said that a UDC driver should > > >>> _never_ carry out the status stage transaction until the gadget driver > > >>> has told it to do so. Then there would be no need for any sort of > > >>> delay indicator. > > >> > > >> Yeah, but, > > >> > > >>> (But implementing this would require significant > > >>> changes to a bunch of different drivers...) > > >> > > >> exactly :/ > > > > add a flag to gadget structure. Something like > > "supports_explicit_status_stage" and add a new return value > > USB_EXPLICIT_STATUS_STAGE. > > > > Then, take uvc for example, implement the new setup: > > > > if (supports_explicit_status_stage) > > return USB_EXPLICIT_STATUS_STAGE; > > > > then on dwc3 you would: > > > > switch (ret) { > > case USB_EXPLICIT_STATUS_STAGE: > > case USB_GADGET_DELAYED_STATUS: > > wait_for_status_request_queue(); > > break; > > default: > > start_status_stage(); > > } > > > > If this works with dwc3 + uvc, then we have a good recipe on how to > > implement for the other drivers. > > Given that we need to delay the status stage and not the data stage, we can't > explicitly request the status stage through a usb request queue. Why not? The status stage for a control-OUT transfer is simply a zero-length IN transaction. It's easy to queue a request for such a transaction. Is the issue that there's no way to specify the direction of the request (hence no direct way to tell whether a zero-length request is for the data stage or the status stage)? Admittedly, it might be nice to provide a library routine in the UDC core to queue such requests, since it involves a bunch of uninteresting boilerplate operations. > Would a new > explicit function call work for you for that purpose ? It would be okay, but I question whether one is really needed. > > > Alan, Felipe, how do we move forward with this ? There are several issues > > > with the existing control request handling mechanism in the USB gadget > > > stack, and while Paul could work on improving the mechanism, we need to > > > provide clear guidance regarding the direction we want to take. > > > > > > For reference, the issues I know about for the USB_GADGET_DELAYED_STATUS > > > mechanism are > > > > > > - The mechanism is inherently racy. It relies on signaling the delay at > > > the very end of the processing in the setup handler, which by definition > > > occurs after the work to process the control request is queued (in the > > > generic sense, regardless of whether this involves a kernel workqueue or > > > passing the work to userspace). There is thus a race window after queuing > > > the work and before signaling the delay during which the work handler > > > could signal completion. I'm not at all sure what you're talking about here. Do you mean this code near the end of composite_setup()? check_value: /* respond with data transfer before status phase? */ if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { req->length = value; req->context = cdev; req->zero = value < w_length; value = composite_ep0_queue(cdev, req, GFP_ATOMIC); Plainly the code checks for USB_GADGET_DELAYED_STATUS _before_ queuing req, not after. So where's the race? > > We won't fix this until all functions and UDCs are converted over, but > > it's doable. > > It could be fixed by signaling the delay through an explicit function call > before queueing the work instead of through a return value though, but I agree > that long term requesting the status stage explicitly would likely be cleaner. Yes, I agree that relying on an implicit status stage is not a good idea for the long term. > > > - The mechanism is poorly documented. As Paul mentioned, comments in the > > > code state that USB_GADGET_DELAYED_STATUS delay the "data/status stages". > > > This is very unclear, and the only three UDCs that implement the > > > mechanism seem to do so in different ways: We can fix comments and documentation pretty easily. :-) > > > - The mtu driver states in a comment that it will "handle the delay > > > STATUS phase till receive ep_queue on ep0". > > > > > > - The bdc driver states in a comment that "The ep0 state will remain > > > WAIT_FOR_DATA_START till we received ep_queue on ep0". > > > > > > - The dwc3 driver seems to handle USB_GADGET_DELAYED_STATUS for the > > > SET_CONFIG request only. > > > > that's the only one that has needed it so far. I'm all for making status > > stage ALWAYS explicit, that will, in the long run, simplify UDC > > drivers and make the API easier to understand. > > > > > - The mechanism relies on queueing a request to the UDC to signal that it > > > should continue with the status stage. That request can be queued either > > > by the USB gadget function driver directly, or by the composite layer in > > > usb_composite_setup_continue() (the latter is restricted to requests that > > > carry no data as it sets the request length to 0). This is problematic if > > > we want to delay the status phase after completing the data phase, in > > > order to validate the setup phase data and the data phase data (for a > > > control OUT request) together. > > > > It shouldn't cause problems, actually. Most of the issues come from the > > fact that sometimes gadget driver just returns a success and expects UDC > > to initiate status stage and sometimes gadget driver wants to handle > > status stage explicitly. > > Requesting the status stage explicitly requires an API to do so (quite > obviously). Your proposal is to use the usb request queue as a signal to > continue to the next stage. My point is that this can't work for control OUT > requests, where we may want to delay the status stage after the data is > received by the UDC, and thus after the request is queued. We need a different > API for that. Why so? Consider the following logic for ep0 in the UDC: A SETUP packet is received, for an OUT transfer. If setup.wLength > 0 then the next request queued for ep0 is the data stage, so it is an OUT request. Otherwise (i.e., if setup.wLength == 0 or for the second request queued after the SETUP is received), the next request is the status stage, so it must be a 0-length IN request. This requires the UDC to specifically keep track of the direction of the current transfer and whether or not a data-stage transfer has already been queued. That shouldn't be hard. (But it does involve a race in cases where the host gets tired of waiting and issues another SETUP packet before the processing of the first transfer is finished.) The corresponding logic for IN transfers is simpler, since IN transfers are not allowed to have zero length. The first request following the SETUP packet is the data stage and the second is the status stage. > For control IN, we may want to delay the data stage if we can't respond > directly, or proceed with the data stage immediately. In both cases this can > be signaled by a request being queued. There is no need to delay the status > stage as it's initiated by the host. Yes. > For control OUT, we may want to delay the data stage if we need to validate > the setup stage data asynchronously. Proceeding to the data stage can be > signaled by queueing a request. We may also want to delay the status stage if > we need to validate the data stage data asynchronously. This can't be signaled > by queueing a request. It can be, if we use the logic outlined above. > I wonder if there's really a use case for delaying the data stage of control > OUT requests, as it seems to me that we can perform the asynchronous > validation of the setup and data stages together, in which case we would > always proceed to the data stage, and only potentially delay the status stage. > However, if we switch to an explicit API where the transition from the setup > to the data stage is triggered by queueing a request, and given that such a > transition may need to be delayed for the control IN case, delaying the data > stage for control OUT would essentially come for free. > > In any case we need an API to delay the status stage of a control OUT request. > There are two options here. We can consider that the status stage shouldn't be > delayed by default and add a new function to be called from the data stage > completion handler to request a status stage delay (using the return value of > the completion handler isn't a good idea as it would be racy as explained > above). A second function would be needed to request the status stage (which, > as explained above too, can't be done by queueing a request). A second option > is to consider that the status stage is delayed by default until explcitly > required. In both cases the same new function is needed to request the status > stage. > > Note that delaying the data stage and delaying the status stage are two > different problems, and don't necessarily need to be solved together. However, > if I understand things correctly, we currently delay the data stage of a few > control OUT requests (they all have a 0 bytes data stage) as a mean to > completion of the request. I believe that this use case could be implemented > by delaying the status stage instead, so the two are still related in a way. > > If we end up moving to explicit state handling, with the data stage being > entered by queueing a request, and the status stage being entered by calling a > new function, control OUT requests with 0 bytes of data that can be handled > synchronously in the setup handler would require function drivers to both > queue a zero-length request and call the status function. This would make the > function code more complex, and I wonder whether a shortcut would be a good > idea, perhaps in the form of a flag in the request that tells the UDC to > automatically proceed to the status stage immediately after the data stage. Or > we could make that behaviour the default when the request doesn't have a > completion handler (as moving explicitly to the status stage should be done at > the earliest from the data stage completion handler). > > > > For those reasons I think a new mechanism is needed. It should either > > > signal the status phase delay through an explicit function call instead > > > of a return value (to solve the race mentioned above), or by requiring > > > all requests to be explicitly completed (but that will require changing > > > all USB function drivers). Furthermore, the mechanism need to support > > > delaying the status phase after queuing the request for the data phase, > > > so we need an explicit way to signal that the UDC should proceed with the > > > status phase, other than queueing the request. > > > > > > Thoughts ? Preferences ? > > > > how about making status stage always explicit? > > If we implement a proof of concept, could you help us converting drivers over > to the new API ? I'll assume we'll have to address all UDCs first, and then > the function drivers. I'll certainly help for the drivers I'm familiar with. Alan Stern From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [4/6] usb: gadget: add functions to signal udc driver to delay status stage From: Alan Stern Message-Id: Date: Fri, 2 Nov 2018 12:18:45 -0400 (EDT) To: Laurent Pinchart Cc: Felipe Balbi , Paul Elder , Bin Liu , kieran.bingham@ideasonboard.com, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, rogerq@ti.com List-ID: T24gRnJpLCAyIE5vdiAyMDE4LCBMYXVyZW50IFBpbmNoYXJ0IHdyb3RlOgoKPiBIaSBGZWxpcGUs Cj4gCj4gT24gRnJpZGF5LCAyIE5vdmVtYmVyIDIwMTggMTU6MTc6MjAgRUVUIEZlbGlwZSBCYWxi aSB3cm90ZToKPiA+IExhdXJlbnQgUGluY2hhcnQgd3JpdGVzOgo+ID4gPj4+Pj4gK3ZvaWQgdXNi X2VwX2RlbGF5X3N0YXR1cyhzdHJ1Y3QgdXNiX2VwICplcCkKPiA+ID4+Pj4+IAo+ID4gPj4+Pj4g K3sKPiA+ID4+Pj4+ICsJZXAtPmRlbGF5ZWRfc3RhdHVzID0gdHJ1ZTsKPiA+ID4+Pj4+ICt9Cj4g PiA+Pj4+PiArRVhQT1JUX1NZTUJPTF9HUEwodXNiX2VwX2RlbGF5X3N0YXR1cyk7Cj4gPiA+Pj4+ IAo+ID4gPj4+PiBJcyB1c2JfZXBfc2V0X2RlbGF5X3N0YXR1cygpIGJldHRlcj8gSSB0aG91Z2h0 IGl0IGltcGxpZXMgZ2V0L3JldHVybgo+ID4gPj4+PiBhY3Rpb24gaWYgYSB2ZXJiIGlzIG1pc3Np bmcgaW4gdGhlIGZ1bmN0aW9uIG5hbWUuCj4gPiA+Pj4gCj4gPiA+Pj4gRm9yIHdoYXQgaXQncyB3 b3J0aCwgSSB1bmRlcnN0YW5kIHRoZSBmdW5jdGlvbiBuYW1lIGFzICJkZWxheSB0aGUKPiA+ID4+ PiBzdGF0dXMgc3RhZ2UiLCB3aXRoICJkZWxheSIgYmVpbmcgYSB2ZXJiLiBNYXliZSB0aGUgc2hv cnQgZGVzY3JpcHRpb24KPiA+ID4+PiBjb3VsZCBiZSB1cGRhdGVkIGFjY29yZGluZ2x5Lgo+ID4g Pj4+IAo+ID4gPj4+IElzIHRoZXJlIGEgcmVhc29uIGZvciBhZGRpbmcgYSBuZXcgZnVuY3Rpb24g Zm9yIHRoaXM/ICBUaGlzIGlzIGV4YWN0bHkKPiA+ID4+PiB3aGF0IHRoZSBVU0JfR0FER0VUX0RF TEFZRURfU1RBVFVTIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBzZXR1cCBjYWxsYmFjawo+ID4gPj4+ IGlzIG1lYW50IGZvciAoYW5kIGl0IGlzIGFscmVhZHkgdXNlZCBieSBzb21lIGdhZGdldCBkcml2 ZXJzKS4KPiA+ID4+IAo+ID4gPj4gSW4gdGhlb3J5LCB3ZSBtaWdodCBiZSBhYmxlIHRvIHVzZSBV U0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIGZvciB0aGlzLgo+ID4gPj4gSG93ZXZlciwgdGhlcmUg YXJlIGEgZmV3IGFtYmlndWl0aWVzIHRoYXQgcHJldmVudCB1cyBmcm9tIGRvaW5nIHNvLgo+ID4g Pj4gCj4gPiA+PiBGaXJzdCBvZiBhbGwsIHdlIHdhbnQgdG8gZGVsYXkgb25seSB0aGUgc3RhdHVz IHN0YWdlIGZvciBjb250cm9sIE9VVAo+ID4gPj4gcmVxdWVzdHM7IGFjY29yZGluZyB0byBjb21w b3NpdGUuaCwgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBpcyBmb3IKPiA+ID4+IGRlbGF5aW5n IHRoZSAiZGF0YS9zdGF0dXMgc3RhZ2VzIi4gRG9lcyB0aGlzIG1lYW4gdGhhdCBpdCBkZWxheXMg dGhlCj4gPiA+PiBzdGF0dXMgc3RhZ2Ugb25seSBvciBkb2VzIGl0IGRlbGF5IGJvdGggc3RhZ2Vz PyBJZiB0aGUgc2xhc2ggbWVhbnMKPiA+ID4+ICJhbmQiLCB0aGVuIHdlIGNhbm5vdCB1c2UgVVNC X0dBREdFVF9ERUxBWUVEX1NUQVRVUy4KClRoZSBjb21tZW50IGluIGNvbXBvc2l0ZS5oIGlzIHdy b25nOyBpdCBzaG91bGQgcmVmZXIgb25seSB0byB0aGUgc3RhdHVzCnN0YWdlLiAgSW4gZmFjdCwg aXQgc2hvdWxkIHJlZmVyIG9ubHkgdG8gdGhlIHN0YXR1cyBzdGFnZSBmb3IKY29udHJvbC1PVVQg dHJhbnNmZXJzOyB0aGVyZSdzIG5vIHJlYXNvbiBldmVyIHRvIGRlbGF5IHRoZSBzdGF0dXMgc3Rh Z2UKb2YgYSBjb250cm9sLUlOIHRyYW5zZmVyICh0aGUgZHJpdmVyIHNob3VsZCBpbnN0ZWFkIGRl bGF5IHRoZSBkYXRhCnN0YWdlIGlmIGl0IG5lZWRzIHRvKS4KCj4gPiA+PiBGdXJ0aGVybW9yZSwg d2UgaGF2ZSBmb3VuZCB0aGF0IFVTQl9HQURHRVRfREVMQVlFRF9TVEFUVVMgaXMgcmFjZXksCj4g PiA+PiB3aGljaCBoYXMgYWxyZWFkeSBiZWVuIG9ic2VydmVkIGluIHRoZSBVVkMgZ2FkZ2V0IGRy aXZlciBwcmV2aW91c2x5IFswXS4KPiA+ID4+IFRoZSByYWNlaW5lc3Mgc3RlbXMgZnJvbSB0aGUg ZmFjdCB0aGF0IHRoaW5ncyBjYW4gaGFwcGVuIGluIGJldHdlZW4KPiA+ID4+IHJldHVybmluZyBV U0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIGFuZCB0aGUgY29tcG9zaXRlIGxheWVyIHJlYWN0aW5n IHRvCj4gPiA+PiBpdCAtIGVzcGVjaWFsbHkgaWYgdXNiX2NvbXBvc2l0ZV9zZXR1cF9jb250aW51 ZSBpcyBjYWxsZWQgd2l0aGluIHRoYXQKPiA+ID4+IHdpbmRvdyBpdCBjYXVzZXMgYSBXQVJOLiBJ biBhbnkgY2FzZSwgdGhlIGZhY3QgdGhhdCB0aGUgbWVjaGFuaXNtIGl0c2VsZgo+ID4gPj4gaXMg cmFjZXkgc3VnZ2VzdHMgdGhhdCBpdCBuZWVkcyBpbXByb3ZlbWVudCwgYW5kIHVzaW5nIGl0IHdv dWxkbid0IGJlIGEKPiA+ID4+IGdvb2Qgc29sdXRpb24gaW4gdGhpcyBjYXNlLgoKSSBkb24ndCB1 bmRlcnN0YW5kIHRoaXMgYXQgYWxsLiAgVGhlIGNvbXBvc2l0ZSBsYXllciByZWFjdHMgdG8gClVT Ql9HQURHRVRfREVMQVlFRF9TVEFUVVMgYXMgc29vbiBhcyBpdCByZWNlaXZlcyB0aGUgcmV0dXJu IHZhbHVlLiAgQ2FuIApQYXVsIG9yIExhdXJlbnQgZ2l2ZSBhIG1vcmUgZXhwbGljaXQgZXhhbXBs ZSBvZiB0aGlzIHJhY2U/CgpBc3N1bWluZyB5b3UgYXJlIGNvcnJlY3QsIHdvdWxkbid0IGl0IG1h a2Ugc2Vuc2UgdG8gZml4IG9yIGVsaW1pbmF0ZSAKdGhlIHJhY2UgYnkgY2hhbmdpbmcgY29tcG9z aXRlLmM/Cgo+ID4gPj4+IElzIGl0IGEgcXVlc3Rpb24gb2Ygd2hlbiB0aGUgZ2FkZ2V0IGRyaXZl ciBsZWFybnMgdGhhdCBpdCB3aWxsIG5lZWQgdG8KPiA+ID4+PiBkZWxheSB0aGUgc3RhdHVzIHN0 YWdlPyAgSWYgdGhhdCdzIHRoZSBjYXNlLAo+ID4gPj4gCj4gPiA+PiBOb3QgcmVhbGx5Lgo+ID4g Pj4gCj4gPiA+Pj4gd2h5IG5vdCBhbHdheXMgcmV0dXJuCj4gPiA+Pj4gVVNCX0dBREdFVF9ERUxB WUVEX1NUQVRVUyBmcm9tIHRoZSBzZXR1cCBjYWxsYmFjaz8gIFRoZW4gaW5zdGVhZCBvZgo+ID4g Pj4+IGNhbGxpbmcgdXNiX2VwX2RlbGF5X3N0YXR1cygpIHdoZW4gYSBkZWxheSBpcyBuZWVkZWQs IHlvdSBjb3VsZCBxdWV1ZQo+ID4gPj4+IHRoZSBzdGF0dXMgcmVxdWVzdCB3aGVuIGEgZGVsYXkg aXNuJ3QgbmVlZGVkLgo+ID4gPj4gCj4gPiA+PiBUaGVvcmV0aWNhbGx5IHRoaXMgbWlnaHQgd29y aywgYnV0IHNlZSB0aGUgcHJvYmxlbXMgbWVudGlvbmVkIGFib3ZlLgo+ID4gPj4gCj4gPiA+Pj4g QXMgYSBtb3JlIGdlbmVyYWwgc29sdXRpb24sIEZlbGlwZSBoYXMgc2FpZCB0aGF0IGEgVURDIGRy aXZlciBzaG91bGQKPiA+ID4+PiBfbmV2ZXJfIGNhcnJ5IG91dCB0aGUgc3RhdHVzIHN0YWdlIHRy YW5zYWN0aW9uIHVudGlsIHRoZSBnYWRnZXQgZHJpdmVyCj4gPiA+Pj4gaGFzIHRvbGQgaXQgdG8g ZG8gc28uICBUaGVuIHRoZXJlIHdvdWxkIGJlIG5vIG5lZWQgZm9yIGFueSBzb3J0IG9mCj4gPiA+ Pj4gZGVsYXkgaW5kaWNhdG9yLgo+ID4gPj4gCj4gPiA+PiBZZWFoLCBidXQsCj4gPiA+PiAKPiA+ ID4+PiAoQnV0IGltcGxlbWVudGluZyB0aGlzIHdvdWxkIHJlcXVpcmUgc2lnbmlmaWNhbnQKPiA+ ID4+PiBjaGFuZ2VzIHRvIGEgYnVuY2ggb2YgZGlmZmVyZW50IGRyaXZlcnMuLi4pCj4gPiA+PiAK PiA+ID4+IGV4YWN0bHkgOi8KPiA+IAo+ID4gYWRkIGEgZmxhZyB0byBnYWRnZXQgc3RydWN0dXJl LiBTb21ldGhpbmcgbGlrZQo+ID4gInN1cHBvcnRzX2V4cGxpY2l0X3N0YXR1c19zdGFnZSIgYW5k IGFkZCBhIG5ldyByZXR1cm4gdmFsdWUKPiA+IFVTQl9FWFBMSUNJVF9TVEFUVVNfU1RBR0UuCj4g PiAKPiA+IFRoZW4sIHRha2UgdXZjIGZvciBleGFtcGxlLCBpbXBsZW1lbnQgdGhlIG5ldyBzZXR1 cDoKPiA+IAo+ID4gaWYgKHN1cHBvcnRzX2V4cGxpY2l0X3N0YXR1c19zdGFnZSkKPiA+IAlyZXR1 cm4gVVNCX0VYUExJQ0lUX1NUQVRVU19TVEFHRTsKPiA+IAo+ID4gdGhlbiBvbiBkd2MzIHlvdSB3 b3VsZDoKPiA+IAo+ID4gc3dpdGNoIChyZXQpIHsKPiA+IGNhc2UgVVNCX0VYUExJQ0lUX1NUQVRV U19TVEFHRToKPiA+IGNhc2UgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUzoKPiA+IAl3YWl0X2Zv cl9zdGF0dXNfcmVxdWVzdF9xdWV1ZSgpOwo+ID4gICAgICAgICBicmVhazsKPiA+IGRlZmF1bHQ6 Cj4gPiAJc3RhcnRfc3RhdHVzX3N0YWdlKCk7Cj4gPiB9Cj4gPiAKPiA+IElmIHRoaXMgd29ya3Mg d2l0aCBkd2MzICsgdXZjLCB0aGVuIHdlIGhhdmUgYSBnb29kIHJlY2lwZSBvbiBob3cgdG8KPiA+ IGltcGxlbWVudCBmb3IgdGhlIG90aGVyIGRyaXZlcnMuCj4gCj4gR2l2ZW4gdGhhdCB3ZSBuZWVk IHRvIGRlbGF5IHRoZSBzdGF0dXMgc3RhZ2UgYW5kIG5vdCB0aGUgZGF0YSBzdGFnZSwgd2UgY2Fu J3QgCj4gZXhwbGljaXRseSByZXF1ZXN0IHRoZSBzdGF0dXMgc3RhZ2UgdGhyb3VnaCBhIHVzYiBy ZXF1ZXN0IHF1ZXVlLgoKV2h5IG5vdD8gIFRoZSBzdGF0dXMgc3RhZ2UgZm9yIGEgY29udHJvbC1P VVQgdHJhbnNmZXIgaXMgc2ltcGx5IGEKemVyby1sZW5ndGggSU4gdHJhbnNhY3Rpb24uICBJdCdz IGVhc3kgdG8gcXVldWUgYSByZXF1ZXN0IGZvciBzdWNoIGEKdHJhbnNhY3Rpb24uICBJcyB0aGUg aXNzdWUgdGhhdCB0aGVyZSdzIG5vIHdheSB0byBzcGVjaWZ5IHRoZSBkaXJlY3Rpb24Kb2YgdGhl IHJlcXVlc3QgKGhlbmNlIG5vIGRpcmVjdCB3YXkgdG8gdGVsbCB3aGV0aGVyIGEgemVyby1sZW5n dGgKcmVxdWVzdCBpcyBmb3IgdGhlIGRhdGEgc3RhZ2Ugb3IgdGhlIHN0YXR1cyBzdGFnZSk/CgpB ZG1pdHRlZGx5LCBpdCBtaWdodCBiZSBuaWNlIHRvIHByb3ZpZGUgYSBsaWJyYXJ5IHJvdXRpbmUg aW4gdGhlIFVEQwpjb3JlIHRvIHF1ZXVlIHN1Y2ggcmVxdWVzdHMsIHNpbmNlIGl0IGludm9sdmVz IGEgYnVuY2ggb2YgdW5pbnRlcmVzdGluZwpib2lsZXJwbGF0ZSBvcGVyYXRpb25zLgoKPiBXb3Vs ZCBhIG5ldyAKPiBleHBsaWNpdCBmdW5jdGlvbiBjYWxsIHdvcmsgZm9yIHlvdSBmb3IgdGhhdCBw dXJwb3NlID8KCkl0IHdvdWxkIGJlIG9rYXksIGJ1dCBJIHF1ZXN0aW9uIHdoZXRoZXIgb25lIGlz IHJlYWxseSBuZWVkZWQuCgo+ID4gPiBBbGFuLCBGZWxpcGUsIGhvdyBkbyB3ZSBtb3ZlIGZvcndh cmQgd2l0aCB0aGlzID8gVGhlcmUgYXJlIHNldmVyYWwgaXNzdWVzCj4gPiA+IHdpdGggdGhlIGV4 aXN0aW5nIGNvbnRyb2wgcmVxdWVzdCBoYW5kbGluZyBtZWNoYW5pc20gaW4gdGhlIFVTQiBnYWRn ZXQKPiA+ID4gc3RhY2ssIGFuZCB3aGlsZSBQYXVsIGNvdWxkIHdvcmsgb24gaW1wcm92aW5nIHRo ZSBtZWNoYW5pc20sIHdlIG5lZWQgdG8KPiA+ID4gcHJvdmlkZSBjbGVhciBndWlkYW5jZSByZWdh cmRpbmcgdGhlIGRpcmVjdGlvbiB3ZSB3YW50IHRvIHRha2UuCj4gPiA+IAo+ID4gPiBGb3IgcmVm ZXJlbmNlLCB0aGUgaXNzdWVzIEkga25vdyBhYm91dCBmb3IgdGhlIFVTQl9HQURHRVRfREVMQVlF RF9TVEFUVVMKPiA+ID4gbWVjaGFuaXNtIGFyZQo+ID4gPiAKPiA+ID4gLSBUaGUgbWVjaGFuaXNt IGlzIGluaGVyZW50bHkgcmFjeS4gSXQgcmVsaWVzIG9uIHNpZ25hbGluZyB0aGUgZGVsYXkgYXQK PiA+ID4gdGhlIHZlcnkgZW5kIG9mIHRoZSBwcm9jZXNzaW5nIGluIHRoZSBzZXR1cCBoYW5kbGVy LCB3aGljaCBieSBkZWZpbml0aW9uCj4gPiA+IG9jY3VycyBhZnRlciB0aGUgd29yayB0byBwcm9j ZXNzIHRoZSBjb250cm9sIHJlcXVlc3QgaXMgcXVldWVkIChpbiB0aGUKPiA+ID4gZ2VuZXJpYyBz ZW5zZSwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoaXMgaW52b2x2ZXMgYSBrZXJuZWwgd29ya3F1 ZXVlIG9yCj4gPiA+IHBhc3NpbmcgdGhlIHdvcmsgdG8gdXNlcnNwYWNlKS4gVGhlcmUgaXMgdGh1 cyBhIHJhY2Ugd2luZG93IGFmdGVyIHF1ZXVpbmcKPiA+ID4gdGhlIHdvcmsgYW5kIGJlZm9yZSBz aWduYWxpbmcgdGhlIGRlbGF5IGR1cmluZyB3aGljaCB0aGUgd29yayBoYW5kbGVyCj4gPiA+IGNv dWxkIHNpZ25hbCBjb21wbGV0aW9uLgoKSSdtIG5vdCBhdCBhbGwgc3VyZSB3aGF0IHlvdSdyZSB0 YWxraW5nIGFib3V0IGhlcmUuICBEbyB5b3UgbWVhbiB0aGlzIApjb2RlIG5lYXIgdGhlIGVuZCBv ZiBjb21wb3NpdGVfc2V0dXAoKT8KCmNoZWNrX3ZhbHVlOgoJLyogcmVzcG9uZCB3aXRoIGRhdGEg dHJhbnNmZXIgYmVmb3JlIHN0YXR1cyBwaGFzZT8gKi8KCWlmICh2YWx1ZSA+PSAwICYmIHZhbHVl ICE9IFVTQl9HQURHRVRfREVMQVlFRF9TVEFUVVMpIHsKCQlyZXEtPmxlbmd0aCA9IHZhbHVlOwoJ CXJlcS0+Y29udGV4dCA9IGNkZXY7CgkJcmVxLT56ZXJvID0gdmFsdWUgPCB3X2xlbmd0aDsKCQl2 YWx1ZSA9IGNvbXBvc2l0ZV9lcDBfcXVldWUoY2RldiwgcmVxLCBHRlBfQVRPTUlDKTsKClBsYWlu bHkgdGhlIGNvZGUgY2hlY2tzIGZvciBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIF9iZWZvcmVf IHF1ZXVpbmcgCnJlcSwgbm90IGFmdGVyLiAgU28gd2hlcmUncyB0aGUgcmFjZT8KCj4gPiBXZSB3 b24ndCBmaXggdGhpcyB1bnRpbCBhbGwgZnVuY3Rpb25zIGFuZCBVRENzIGFyZSBjb252ZXJ0ZWQg b3ZlciwgYnV0Cj4gPiBpdCdzIGRvYWJsZS4KPiAKPiBJdCBjb3VsZCBiZSBmaXhlZCBieSBzaWdu YWxpbmcgdGhlIGRlbGF5IHRocm91Z2ggYW4gZXhwbGljaXQgZnVuY3Rpb24gY2FsbCAKPiBiZWZv cmUgcXVldWVpbmcgdGhlIHdvcmsgaW5zdGVhZCBvZiB0aHJvdWdoIGEgcmV0dXJuIHZhbHVlIHRo b3VnaCwgYnV0IEkgYWdyZWUgCj4gdGhhdCBsb25nIHRlcm0gcmVxdWVzdGluZyB0aGUgc3RhdHVz IHN0YWdlIGV4cGxpY2l0bHkgd291bGQgbGlrZWx5IGJlIGNsZWFuZXIuCgpZZXMsIEkgYWdyZWUg dGhhdCByZWx5aW5nIG9uIGFuIGltcGxpY2l0IHN0YXR1cyBzdGFnZSBpcyBub3QgYSBnb29kIApp ZGVhIGZvciB0aGUgbG9uZyB0ZXJtLgoKPiA+ID4gLSBUaGUgbWVjaGFuaXNtIGlzIHBvb3JseSBk b2N1bWVudGVkLiBBcyBQYXVsIG1lbnRpb25lZCwgY29tbWVudHMgaW4gdGhlCj4gPiA+IGNvZGUg c3RhdGUgdGhhdCBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIGRlbGF5IHRoZSAiZGF0YS9zdGF0 dXMgc3RhZ2VzIi4KPiA+ID4gVGhpcyBpcyB2ZXJ5IHVuY2xlYXIsIGFuZCB0aGUgb25seSB0aHJl ZSBVRENzIHRoYXQgaW1wbGVtZW50IHRoZQo+ID4gPiBtZWNoYW5pc20gc2VlbSB0byBkbyBzbyBp biBkaWZmZXJlbnQgd2F5czoKCldlIGNhbiBmaXggY29tbWVudHMgYW5kIGRvY3VtZW50YXRpb24g cHJldHR5IGVhc2lseS4gIDotKQoKPiA+ID4gICAtIFRoZSBtdHUgZHJpdmVyIHN0YXRlcyBpbiBh IGNvbW1lbnQgdGhhdCBpdCB3aWxsICJoYW5kbGUgdGhlIGRlbGF5Cj4gPiA+ICAgU1RBVFVTIHBo YXNlIHRpbGwgcmVjZWl2ZSBlcF9xdWV1ZSBvbiBlcDAiLgo+ID4gPiAKPiA+ID4gICAtIFRoZSBi ZGMgZHJpdmVyIHN0YXRlcyBpbiBhIGNvbW1lbnQgdGhhdCAiVGhlIGVwMCBzdGF0ZSB3aWxsIHJl bWFpbgo+ID4gPiAgIFdBSVRfRk9SX0RBVEFfU1RBUlQgdGlsbCB3ZSByZWNlaXZlZCBlcF9xdWV1 ZSBvbiBlcDAiLgo+ID4gPiAKPiA+ID4gICAtIFRoZSBkd2MzIGRyaXZlciBzZWVtcyB0byBoYW5k bGUgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBmb3IgdGhlCj4gPiA+ICAgU0VUX0NPTkZJRyBy ZXF1ZXN0IG9ubHkuCj4gPiAKPiA+IHRoYXQncyB0aGUgb25seSBvbmUgdGhhdCBoYXMgbmVlZGVk IGl0IHNvIGZhci4gSSdtIGFsbCBmb3IgbWFraW5nIHN0YXR1cwo+ID4gc3RhZ2UgQUxXQVlTIGV4 cGxpY2l0LCB0aGF0IHdpbGwsIGluIHRoZSBsb25nIHJ1biwgc2ltcGxpZnkgVURDCj4gPiBkcml2 ZXJzIGFuZCBtYWtlIHRoZSBBUEkgZWFzaWVyIHRvIHVuZGVyc3RhbmQuCj4gPiAKPiA+ID4gLSBU aGUgbWVjaGFuaXNtIHJlbGllcyBvbiBxdWV1ZWluZyBhIHJlcXVlc3QgdG8gdGhlIFVEQyB0byBz aWduYWwgdGhhdCBpdAo+ID4gPiBzaG91bGQgY29udGludWUgd2l0aCB0aGUgc3RhdHVzIHN0YWdl LiBUaGF0IHJlcXVlc3QgY2FuIGJlIHF1ZXVlZCBlaXRoZXIKPiA+ID4gYnkgdGhlIFVTQiBnYWRn ZXQgZnVuY3Rpb24gZHJpdmVyIGRpcmVjdGx5LCBvciBieSB0aGUgY29tcG9zaXRlIGxheWVyIGlu Cj4gPiA+IHVzYl9jb21wb3NpdGVfc2V0dXBfY29udGludWUoKSAodGhlIGxhdHRlciBpcyByZXN0 cmljdGVkIHRvIHJlcXVlc3RzIHRoYXQKPiA+ID4gY2Fycnkgbm8gZGF0YSBhcyBpdCBzZXRzIHRo ZSByZXF1ZXN0IGxlbmd0aCB0byAwKS4gVGhpcyBpcyBwcm9ibGVtYXRpYyBpZgo+ID4gPiB3ZSB3 YW50IHRvIGRlbGF5IHRoZSBzdGF0dXMgcGhhc2UgYWZ0ZXIgY29tcGxldGluZyB0aGUgZGF0YSBw aGFzZSwgaW4KPiA+ID4gb3JkZXIgdG8gdmFsaWRhdGUgdGhlIHNldHVwIHBoYXNlIGRhdGEgYW5k IHRoZSBkYXRhIHBoYXNlIGRhdGEgKGZvciBhCj4gPiA+IGNvbnRyb2wgT1VUIHJlcXVlc3QpIHRv Z2V0aGVyLgo+ID4gCj4gPiBJdCBzaG91bGRuJ3QgY2F1c2UgcHJvYmxlbXMsIGFjdHVhbGx5LiBN b3N0IG9mIHRoZSBpc3N1ZXMgY29tZSBmcm9tIHRoZQo+ID4gZmFjdCB0aGF0IHNvbWV0aW1lcyBn YWRnZXQgZHJpdmVyIGp1c3QgcmV0dXJucyBhIHN1Y2Nlc3MgYW5kIGV4cGVjdHMgVURDCj4gPiB0 byBpbml0aWF0ZSBzdGF0dXMgc3RhZ2UgYW5kIHNvbWV0aW1lcyBnYWRnZXQgZHJpdmVyIHdhbnRz IHRvIGhhbmRsZQo+ID4gc3RhdHVzIHN0YWdlIGV4cGxpY2l0bHkuCj4gCj4gUmVxdWVzdGluZyB0 aGUgc3RhdHVzIHN0YWdlIGV4cGxpY2l0bHkgcmVxdWlyZXMgYW4gQVBJIHRvIGRvIHNvIChxdWl0 ZSAKPiBvYnZpb3VzbHkpLiBZb3VyIHByb3Bvc2FsIGlzIHRvIHVzZSB0aGUgdXNiIHJlcXVlc3Qg cXVldWUgYXMgYSBzaWduYWwgdG8gCj4gY29udGludWUgdG8gdGhlIG5leHQgc3RhZ2UuIE15IHBv aW50IGlzIHRoYXQgdGhpcyBjYW4ndCB3b3JrIGZvciBjb250cm9sIE9VVCAKPiByZXF1ZXN0cywg d2hlcmUgd2UgbWF5IHdhbnQgdG8gZGVsYXkgdGhlIHN0YXR1cyBzdGFnZSBhZnRlciB0aGUgZGF0 YSBpcyAKPiByZWNlaXZlZCBieSB0aGUgVURDLCBhbmQgdGh1cyBhZnRlciB0aGUgcmVxdWVzdCBp cyBxdWV1ZWQuIFdlIG5lZWQgYSBkaWZmZXJlbnQgCj4gQVBJIGZvciB0aGF0LgoKV2h5IHNvPyAg Q29uc2lkZXIgdGhlIGZvbGxvd2luZyBsb2dpYyBmb3IgZXAwIGluIHRoZSBVREM6CgoJQSBTRVRV UCBwYWNrZXQgaXMgcmVjZWl2ZWQsIGZvciBhbiBPVVQgdHJhbnNmZXIuCgoJSWYgc2V0dXAud0xl bmd0aCA+IDAgdGhlbiB0aGUgbmV4dCByZXF1ZXN0IHF1ZXVlZCBmb3IgZXAwIGlzCgl0aGUgZGF0 YSBzdGFnZSwgc28gaXQgaXMgYW4gT1VUIHJlcXVlc3QuCgoJT3RoZXJ3aXNlIChpLmUuLCBpZiBz ZXR1cC53TGVuZ3RoID09IDAgb3IgZm9yIHRoZSBzZWNvbmQKCXJlcXVlc3QgcXVldWVkIGFmdGVy IHRoZSBTRVRVUCBpcyByZWNlaXZlZCksIHRoZSBuZXh0IHJlcXVlc3QKCWlzIHRoZSBzdGF0dXMg c3RhZ2UsIHNvIGl0IG11c3QgYmUgYSAwLWxlbmd0aCBJTiByZXF1ZXN0LgoKVGhpcyByZXF1aXJl cyB0aGUgVURDIHRvIHNwZWNpZmljYWxseSBrZWVwIHRyYWNrIG9mIHRoZSBkaXJlY3Rpb24gb2YK dGhlIGN1cnJlbnQgdHJhbnNmZXIgYW5kIHdoZXRoZXIgb3Igbm90IGEgZGF0YS1zdGFnZSB0cmFu c2ZlciBoYXMKYWxyZWFkeSBiZWVuIHF1ZXVlZC4gIFRoYXQgc2hvdWxkbid0IGJlIGhhcmQuICAo QnV0IGl0IGRvZXMgaW52b2x2ZSBhCnJhY2UgaW4gY2FzZXMgd2hlcmUgdGhlIGhvc3QgZ2V0cyB0 aXJlZCBvZiB3YWl0aW5nIGFuZCBpc3N1ZXMgYW5vdGhlcgpTRVRVUCBwYWNrZXQgYmVmb3JlIHRo ZSBwcm9jZXNzaW5nIG9mIHRoZSBmaXJzdCB0cmFuc2ZlciBpcyBmaW5pc2hlZC4pCgpUaGUgY29y cmVzcG9uZGluZyBsb2dpYyBmb3IgSU4gdHJhbnNmZXJzIGlzIHNpbXBsZXIsIHNpbmNlIElOIHRy YW5zZmVycyAKYXJlIG5vdCBhbGxvd2VkIHRvIGhhdmUgemVybyBsZW5ndGguICBUaGUgZmlyc3Qg cmVxdWVzdCBmb2xsb3dpbmcgdGhlIApTRVRVUCBwYWNrZXQgaXMgdGhlIGRhdGEgc3RhZ2UgYW5k IHRoZSBzZWNvbmQgaXMgdGhlIHN0YXR1cyBzdGFnZS4KCj4gRm9yIGNvbnRyb2wgSU4sIHdlIG1h eSB3YW50IHRvIGRlbGF5IHRoZSBkYXRhIHN0YWdlIGlmIHdlIGNhbid0IHJlc3BvbmQgCj4gZGly ZWN0bHksIG9yIHByb2NlZWQgd2l0aCB0aGUgZGF0YSBzdGFnZSBpbW1lZGlhdGVseS4gSW4gYm90 aCBjYXNlcyB0aGlzIGNhbiAKPiBiZSBzaWduYWxlZCBieSBhIHJlcXVlc3QgYmVpbmcgcXVldWVk LiBUaGVyZSBpcyBubyBuZWVkIHRvIGRlbGF5IHRoZSBzdGF0dXMgCj4gc3RhZ2UgYXMgaXQncyBp bml0aWF0ZWQgYnkgdGhlIGhvc3QuCgpZZXMuCgo+IEZvciBjb250cm9sIE9VVCwgd2UgbWF5IHdh bnQgdG8gZGVsYXkgdGhlIGRhdGEgc3RhZ2UgaWYgd2UgbmVlZCB0byB2YWxpZGF0ZSAKPiB0aGUg c2V0dXAgc3RhZ2UgZGF0YSBhc3luY2hyb25vdXNseS4gUHJvY2VlZGluZyB0byB0aGUgZGF0YSBz dGFnZSBjYW4gYmUgCj4gc2lnbmFsZWQgYnkgcXVldWVpbmcgYSByZXF1ZXN0LiBXZSBtYXkgYWxz byB3YW50IHRvIGRlbGF5IHRoZSBzdGF0dXMgc3RhZ2UgaWYgCj4gd2UgbmVlZCB0byB2YWxpZGF0 ZSB0aGUgZGF0YSBzdGFnZSBkYXRhIGFzeW5jaHJvbm91c2x5LiBUaGlzIGNhbid0IGJlIHNpZ25h bGVkIAo+IGJ5IHF1ZXVlaW5nIGEgcmVxdWVzdC4KCkl0IGNhbiBiZSwgaWYgd2UgdXNlIHRoZSBs b2dpYyBvdXRsaW5lZCBhYm92ZS4KCj4gSSB3b25kZXIgaWYgdGhlcmUncyByZWFsbHkgYSB1c2Ug Y2FzZSBmb3IgZGVsYXlpbmcgdGhlIGRhdGEgc3RhZ2Ugb2YgY29udHJvbCAKPiBPVVQgcmVxdWVz dHMsIGFzIGl0IHNlZW1zIHRvIG1lIHRoYXQgd2UgY2FuIHBlcmZvcm0gdGhlIGFzeW5jaHJvbm91 cyAKPiB2YWxpZGF0aW9uIG9mIHRoZSBzZXR1cCBhbmQgZGF0YSBzdGFnZXMgdG9nZXRoZXIsIGlu IHdoaWNoIGNhc2Ugd2Ugd291bGQgCj4gYWx3YXlzIHByb2NlZWQgdG8gdGhlIGRhdGEgc3RhZ2Us IGFuZCBvbmx5IHBvdGVudGlhbGx5IGRlbGF5IHRoZSBzdGF0dXMgc3RhZ2UuIAo+IEhvd2V2ZXIs IGlmIHdlIHN3aXRjaCB0byBhbiBleHBsaWNpdCBBUEkgd2hlcmUgdGhlIHRyYW5zaXRpb24gZnJv bSB0aGUgc2V0dXAgCj4gdG8gdGhlIGRhdGEgc3RhZ2UgaXMgdHJpZ2dlcmVkIGJ5IHF1ZXVlaW5n IGEgcmVxdWVzdCwgYW5kIGdpdmVuIHRoYXQgc3VjaCBhIAo+IHRyYW5zaXRpb24gbWF5IG5lZWQg dG8gYmUgZGVsYXllZCBmb3IgdGhlIGNvbnRyb2wgSU4gY2FzZSwgZGVsYXlpbmcgdGhlIGRhdGEg Cj4gc3RhZ2UgZm9yIGNvbnRyb2wgT1VUIHdvdWxkIGVzc2VudGlhbGx5IGNvbWUgZm9yIGZyZWUu Cj4gCj4gSW4gYW55IGNhc2Ugd2UgbmVlZCBhbiBBUEkgdG8gZGVsYXkgdGhlIHN0YXR1cyBzdGFn ZSBvZiBhIGNvbnRyb2wgT1VUIHJlcXVlc3QuIAo+IFRoZXJlIGFyZSB0d28gb3B0aW9ucyBoZXJl LiBXZSBjYW4gY29uc2lkZXIgdGhhdCB0aGUgc3RhdHVzIHN0YWdlIHNob3VsZG4ndCBiZSAKPiBk ZWxheWVkIGJ5IGRlZmF1bHQgYW5kIGFkZCBhIG5ldyBmdW5jdGlvbiB0byBiZSBjYWxsZWQgZnJv bSB0aGUgZGF0YSBzdGFnZSAKPiBjb21wbGV0aW9uIGhhbmRsZXIgdG8gcmVxdWVzdCBhIHN0YXR1 cyBzdGFnZSBkZWxheSAodXNpbmcgdGhlIHJldHVybiB2YWx1ZSBvZiAKPiB0aGUgY29tcGxldGlv biBoYW5kbGVyIGlzbid0IGEgZ29vZCBpZGVhIGFzIGl0IHdvdWxkIGJlIHJhY3kgYXMgZXhwbGFp bmVkIAo+IGFib3ZlKS4gQSBzZWNvbmQgZnVuY3Rpb24gd291bGQgYmUgbmVlZGVkIHRvIHJlcXVl c3QgdGhlIHN0YXR1cyBzdGFnZSAod2hpY2gsIAo+IGFzIGV4cGxhaW5lZCBhYm92ZSB0b28sIGNh bid0IGJlIGRvbmUgYnkgcXVldWVpbmcgYSByZXF1ZXN0KS4gQSBzZWNvbmQgb3B0aW9uIAo+IGlz IHRvIGNvbnNpZGVyIHRoYXQgdGhlIHN0YXR1cyBzdGFnZSBpcyBkZWxheWVkIGJ5IGRlZmF1bHQg dW50aWwgZXhwbGNpdGx5IAo+IHJlcXVpcmVkLiBJbiBib3RoIGNhc2VzIHRoZSBzYW1lIG5ldyBm dW5jdGlvbiBpcyBuZWVkZWQgdG8gcmVxdWVzdCB0aGUgc3RhdHVzIAo+IHN0YWdlLgo+IAo+IE5v dGUgdGhhdCBkZWxheWluZyB0aGUgZGF0YSBzdGFnZSBhbmQgZGVsYXlpbmcgdGhlIHN0YXR1cyBz dGFnZSBhcmUgdHdvIAo+IGRpZmZlcmVudCBwcm9ibGVtcywgYW5kIGRvbid0IG5lY2Vzc2FyaWx5 IG5lZWQgdG8gYmUgc29sdmVkIHRvZ2V0aGVyLiBIb3dldmVyLCAKPiBpZiBJIHVuZGVyc3RhbmQg dGhpbmdzIGNvcnJlY3RseSwgd2UgY3VycmVudGx5IGRlbGF5IHRoZSBkYXRhIHN0YWdlIG9mIGEg ZmV3IAo+IGNvbnRyb2wgT1VUIHJlcXVlc3RzICh0aGV5IGFsbCBoYXZlIGEgMCBieXRlcyBkYXRh IHN0YWdlKSBhcyBhIG1lYW4gdG8gCj4gY29tcGxldGlvbiBvZiB0aGUgcmVxdWVzdC4gSSBiZWxp ZXZlIHRoYXQgdGhpcyB1c2UgY2FzZSBjb3VsZCBiZSBpbXBsZW1lbnRlZCAKPiBieSBkZWxheWlu ZyB0aGUgc3RhdHVzIHN0YWdlIGluc3RlYWQsIHNvIHRoZSB0d28gYXJlIHN0aWxsIHJlbGF0ZWQg aW4gYSB3YXkuCj4gCj4gSWYgd2UgZW5kIHVwIG1vdmluZyB0byBleHBsaWNpdCBzdGF0ZSBoYW5k bGluZywgd2l0aCB0aGUgZGF0YSBzdGFnZSBiZWluZyAKPiBlbnRlcmVkIGJ5IHF1ZXVlaW5nIGEg cmVxdWVzdCwgYW5kIHRoZSBzdGF0dXMgc3RhZ2UgYmVpbmcgZW50ZXJlZCBieSBjYWxsaW5nIGEg Cj4gbmV3IGZ1bmN0aW9uLCBjb250cm9sIE9VVCByZXF1ZXN0cyB3aXRoIDAgYnl0ZXMgb2YgZGF0 YSB0aGF0IGNhbiBiZSBoYW5kbGVkIAo+IHN5bmNocm9ub3VzbHkgaW4gdGhlIHNldHVwIGhhbmRs ZXIgd291bGQgcmVxdWlyZSBmdW5jdGlvbiBkcml2ZXJzIHRvIGJvdGggCj4gcXVldWUgYSB6ZXJv LWxlbmd0aCByZXF1ZXN0IGFuZCBjYWxsIHRoZSBzdGF0dXMgZnVuY3Rpb24uIFRoaXMgd291bGQg bWFrZSB0aGUgCj4gZnVuY3Rpb24gY29kZSBtb3JlIGNvbXBsZXgsIGFuZCBJIHdvbmRlciB3aGV0 aGVyIGEgc2hvcnRjdXQgd291bGQgYmUgYSBnb29kIAo+IGlkZWEsIHBlcmhhcHMgaW4gdGhlIGZv cm0gb2YgYSBmbGFnIGluIHRoZSByZXF1ZXN0IHRoYXQgdGVsbHMgdGhlIFVEQyB0byAKPiBhdXRv bWF0aWNhbGx5IHByb2NlZWQgdG8gdGhlIHN0YXR1cyBzdGFnZSBpbW1lZGlhdGVseSBhZnRlciB0 aGUgZGF0YSBzdGFnZS4gT3IgCj4gd2UgY291bGQgbWFrZSB0aGF0IGJlaGF2aW91ciB0aGUgZGVm YXVsdCB3aGVuIHRoZSByZXF1ZXN0IGRvZXNuJ3QgaGF2ZSBhIAo+IGNvbXBsZXRpb24gaGFuZGxl ciAoYXMgbW92aW5nIGV4cGxpY2l0bHkgdG8gdGhlIHN0YXR1cyBzdGFnZSBzaG91bGQgYmUgZG9u ZSBhdCAKPiB0aGUgZWFybGllc3QgZnJvbSB0aGUgZGF0YSBzdGFnZSBjb21wbGV0aW9uIGhhbmRs ZXIpLgo+IAo+ID4gPiBGb3IgdGhvc2UgcmVhc29ucyBJIHRoaW5rIGEgbmV3IG1lY2hhbmlzbSBp cyBuZWVkZWQuIEl0IHNob3VsZCBlaXRoZXIKPiA+ID4gc2lnbmFsIHRoZSBzdGF0dXMgcGhhc2Ug ZGVsYXkgdGhyb3VnaCBhbiBleHBsaWNpdCBmdW5jdGlvbiBjYWxsIGluc3RlYWQKPiA+ID4gb2Yg YSByZXR1cm4gdmFsdWUgKHRvIHNvbHZlIHRoZSByYWNlIG1lbnRpb25lZCBhYm92ZSksIG9yIGJ5 IHJlcXVpcmluZwo+ID4gPiBhbGwgcmVxdWVzdHMgdG8gYmUgZXhwbGljaXRseSBjb21wbGV0ZWQg KGJ1dCB0aGF0IHdpbGwgcmVxdWlyZSBjaGFuZ2luZwo+ID4gPiBhbGwgVVNCIGZ1bmN0aW9uIGRy aXZlcnMpLiBGdXJ0aGVybW9yZSwgdGhlIG1lY2hhbmlzbSBuZWVkIHRvIHN1cHBvcnQKPiA+ID4g ZGVsYXlpbmcgdGhlIHN0YXR1cyBwaGFzZSBhZnRlciBxdWV1aW5nIHRoZSByZXF1ZXN0IGZvciB0 aGUgZGF0YSBwaGFzZSwKPiA+ID4gc28gd2UgbmVlZCBhbiBleHBsaWNpdCB3YXkgdG8gc2lnbmFs IHRoYXQgdGhlIFVEQyBzaG91bGQgcHJvY2VlZCB3aXRoIHRoZQo+ID4gPiBzdGF0dXMgcGhhc2Us IG90aGVyIHRoYW4gcXVldWVpbmcgdGhlIHJlcXVlc3QuCj4gPiA+IAo+ID4gPiBUaG91Z2h0cyA/ IFByZWZlcmVuY2VzID8KPiA+IAo+ID4gaG93IGFib3V0IG1ha2luZyBzdGF0dXMgc3RhZ2UgYWx3 YXlzIGV4cGxpY2l0Pwo+IAo+IElmIHdlIGltcGxlbWVudCBhIHByb29mIG9mIGNvbmNlcHQsIGNv dWxkIHlvdSBoZWxwIHVzIGNvbnZlcnRpbmcgZHJpdmVycyBvdmVyIAo+IHRvIHRoZSBuZXcgQVBJ ID8gSSdsbCBhc3N1bWUgd2UnbGwgaGF2ZSB0byBhZGRyZXNzIGFsbCBVRENzIGZpcnN0LCBhbmQg dGhlbiAKPiB0aGUgZnVuY3Rpb24gZHJpdmVycy4KCkknbGwgY2VydGFpbmx5IGhlbHAgZm9yIHRo ZSBkcml2ZXJzIEknbSBmYW1pbGlhciB3aXRoLgoKQWxhbiBTdGVybgo=