- System time in BB

From: Douglas G. Danforth <"Douglas>
Date: Thu, 21 Apr 2005 14:19:16 -0400

----boundary-LibPST-iamunique-1421877144_-_-
Content-type: text/plain

skulski{([at]})nowhere.xy
> Chris:
>
> I am using Services.Ticks now, but it is not ideal for me because it
> returns the time in milliseconds since BB was started. I.e., the
> "Ticks = 0" is the time when I double-clicked on the BB icon.
> I need an absolute day time for data logging, with the resolution of 1 ms.
Wojtek,
I found the following on the web which may give you 1-2 millisecond
accuracy.
-Doug

Results of some quick research on timing in Win32
by Ryan Geiss
8/16/2002

You might be thinking to yourself: this is a pretty simple thing
to be posting; what's the big deal? The deal is that somehow,
good timing code has eluded me for years. Finally, frustrated,
I dug in and did some formal experiments on a few different computers,
testing the timing precision they could offer, using various win32
functions. I was fairly surprised by the results!

I tested on three computers; here are their specs:

     Gemini: 933 mhz desktop, win2k
     Vaio: 333 mhz laptop, win98
     HP: 733 mhz laptop, win2k

Also, abbreviations to be used hereafter:

     ms: milliseconds, or 1/1,000 of a second
     us: microseconds, or 1/1,000,000 of a second


timeGetTime - what they don't tell you

First, I tried to determine the precision of timeGetTime().
In order to do this, I simply ran a loop, constantly polling
timeGetTime() until the time changed, and then printing the
delta (between the prev. time and the new time). I then looked
at the output, and for each computer, took the minimum of all
the delta's that occured. (Usually, the minimum was very solid,
occuring about 90% of the time.) The results:

               Resolution of timeGetTime()
     Gemini: 10 ms
     Vaio: 1 ms
     HP: 10 ms

For now, I am assuming that it was the OS kernel that made the
difference: win2k offers a max. precision of 10 ms for timeGetTime(),
while win98 is much better, at 1 ms. I assume that WinXP would also
have a precision of 10 ms, and that Win95 would be ~1 ms, like Win98.
(If anyone tests this out, please let me know either way!)

(Note that using timeGetTime() unfortunately requires linking to
winmm.lib, which slightly increases your file size. You could use
GetTickCount() instead, which doesn't require linking to winmm.lib,
but it tends to not have as good of a timer resolution... so I would
recommend sticking with timeGetTime().

Next, I tested Sleep(). A while back I noticed that when you call
Sleep(1), it doesn't really sleep for 1 ms; it usually sleeps for longer
than that. I verified this by calling Sleep(1) ten times in a row,
and taking the difference in timeGetTime() readings from the beginning
to the end. Whatever delta there was for these ten sleeps, I just divided
it by 10 to get the average duration of Sleep(1). This turned out to be:

               Average duration of Sleep(1)
     Gemini: 10 ms (10 calls to Sleep(1) took exactly 100 ms)
     Vaio: ~4 ms (10 calls to Sleep(1) took 35-45 ms)
     HP: 10 ms (10 calls to Sleep(1) took exactly 100 ms)

Now, this was disturbing, because it meant that if you call Sleep(1)
and Sleep(9) on a win2k machine, there is no difference - it still
sleeps for 10 ms! "So *this* is the reason all my timing code sucks,"
I sighed to myself.

Given that, I decided to give up on Sleep() and timeGetTime(). The
application I was working on required really good fps limiting, and
10ms Sleeps were not precise enough to do a good job. So I looked
elsewhere.



timeBeginPeriod / timeEndPeriod

HOWEVER, I should not have given up so fast! It turns out that there
is a win32 command, timeBeginPeriod(), which solves our problem:
it lowers the granularity of Sleep() to whatever parameter you give it.
So if you're on windows 2000 and you call timeBeginPeriod(1) and then
Sleep(1), it will truly sleep for just 1 millisecond, rather than the
default 10!

timeBeginPeriod() only affects the granularity of Sleep() for the
application
that calls it, so don't worry about messing up the system with it. Also,
be sure you call timeEndPeriod() when your program exits, with the same
parameter you fed into timeBeginPeriod() when your program started
(presumably
1). Both of these functions are in winmm.lib, so you'll have to link to it
if you want to lower your Sleep() granularity down to 1 ms.

How reliable is it? I have yet to find a system for which
timeBeginPeriod(1)
does not drop the granularity of Sleep(1) to 1 or, at most, 2 milliseconds.
If anyone out there does, please let me know
(e-mail: );
I'd like to hear about it, and I will post a warning here.

Note also that calling timeBeginPeriod() also affects the granularity of
some
other timing calls, such as CreateWaitableTimer() and
WaitForSingleObject();
however, some functions are still unaffected, such as _ftime(). (Special
thanks to Mark Epstein for pointing this out to me!)


some convenient test code

The following code will tell you:
     1. what the granularity, or minimum resolution, of calls to
timeGetTime() are,
on your system. In other words, if you sit in a tight loop and call
timeGetTime(),
only noting when the value returned changes, what value do you get? This
granularity tells you, more or less, what kind of potential error to
expect in
the result when calling timeGetTime().
     2. it also tests how long your machine really sleeps when you call
Sleep(1).
Often this is actually 2 or more milliseconds, so be careful!

NOTE that these tests are performed after calling timeBeginPeriod(1), so if
you forget to call timeBeginPeriod(1) in your own init code, you might
not get
as good of granularity as you see from this test!


         #include <stdio.h>
         #include "windows.h"

         int main(int argc, char **argv)
         {
             const int count = 64;

             timeBeginPeriod(1);

             printf("1. testing granularity of timeGetTime()...\n");
             int its = 0;
             long cur = 0, last = timeGetTime();
             while (its < count) {
                 cur = timeGetTime();
                 if (cur != last) {
                     printf("%ld ", cur-last);
                     last = cur;
                     its++;
                 }
             }

             printf("\n\n2. testing granularity of Sleep(1)...\n ");
             long first = timeGetTime();
             cur = first;
             last = first;
             for (int n=0; n<count; n++) {
                 Sleep(1);
                 cur = timeGetTime();
                 printf("%d ", cur-last);
                 last = cur;
             }
             printf("\n");

             return 0;
         }





RDTSC: Eh, no thanks

On the web, I found several references to the "RDTSC" Pentium instruction,
which stands for "Read Time Stamp Counter." This assembly instruction
returns
an unsigned 64-bit integer reading on the processor's internal
high-precision
timer. In order to get the frequency of the timer (how much the timer
return
value will increment in 1 second), you can read the registry for the
machine's
speed (in MHz - millions of cycles per second), like this:

         // WARNING: YOU DON'T REALLY WANT TO USE THIS FUNCTION
         bool GetPentiumClockEstimateFromRegistry(unsigned __int64
*frequency)
         {
             HKEY hKey;
             DWORD cbBuffer;
             LONG rc;

             *frequency = 0;

             rc = RegOpenKeyEx(
                      HKEY_LOCAL_MACHINE,
                      "Hardware\\Description\\System\\CentralProcessor\\0",
                      0,
                      KEY_READ,
                      &hKey
                  );

             if (rc == ERROR_SUCCESS)
             {
                 cbBuffer = sizeof (DWORD);
                 DWORD freq_mhz;
                 rc = RegQueryValueEx
                      (
                        hKey,
                        "~MHz",
                        NULL,
                        NULL,
                        (LPBYTE)(&freq_mhz),
                        &cbBuffer
                      );
                 if (rc == ERROR_SUCCESS)
                     *frequency = freq_mhz*1024*1024;
                 RegCloseKey (hKey);
             }

             return (*frequency > 0);
         }


               Result of GetPentiumClockEstimateFromRegistry()
     Gemini: 975,175,680 Hz
     Vaio: FAILED.
     HP: 573,571,072 Hz <-- strange...

               Empirical tests: RDTSC delta after Sleep(1000)
     Gemini: 931,440,000 Hz
     Vaio: 331,500,000 Hz
     HP: 13,401,287 Hz


However, as you can see, this failed on Vaio (the win98 laptop).
Worse yet, however, is that on the HP, the value in the registry
does not match the MHz rating of the machine (733). That would
be okay if the value was actually the rate at which the timer
ticked; but, after doing some empirical testing, it turns out that
the HP's timer frequency is really 13 MHz. Trusting the
registry reading on the HP would be a big, big mistake!

So, one conclusion is: don't try to read the registry to get the
timer frequency; you're asking for trouble. Instead, do it yourself.

Just call Sleep(1000) to allow 1 second (plus or minus ~1%) to pass,
calling GetPentiumTimeRaw() (below) at the beginning and end, and then
simply subtract the two unsigned __int64's, and voila, you now know
the frequency of the timer that feeds RDTSC on the current system.
(*watch out for timer wraps during that 1 second, though...)

Note that you could easily do this in the background, though, using
timeGetTime() instead of Sleep(), so there wouldn't be a 1-second pause
when your program starts.

         int GetPentiumTimeRaw(unsigned __int64 *ret)
         {
             // returns 0 on failure, 1 on success
             // warning: watch out for wraparound!

             // get high-precision time:
             __try
             {
                 unsigned __int64 *dest = (unsigned __int64 *)ret;
                 __asm
                 {
                     _emit 0xf // these two bytes form the
'rdtsc' asm instruction,
                     _emit 0x31 // available on Pentium I and later.
                     mov esi, dest
                     mov [esi ], eax // lower 32 bits of tsc
                     mov [esi+4], edx // upper 32 bits of tsc
                 }
                 return 1;
             }
             __except(EXCEPTION_EXECUTE_HANDLER)
             {
                 return 0;
             }

             return 0;
         }

Once you figure out the frequency, using this 1-second test, you can now
translate readings from the cpu's timestamp counter directly into a real
'time' reading, in seconds:

         double GetPentiumTimeAsDouble(unsigned __int64 frequency)
         {
             // returns < 0 on failure; otherwise, returns current cpu
time, in seconds.
             // warning: watch out for wraparound!

             if (frequency==0)
                 return -1.0;

             // get high-precision time:
             __try
             {
                 unsigned __int64 high_perf_time;
                 unsigned __int64 *dest = &high_perf_time;
                 __asm
                 {
                     _emit 0xf // these two bytes form the
'rdtsc' asm instruction,
                     _emit 0x31 // available on Pentium I and later.
                     mov esi, dest
                     mov [esi ], eax // lower 32 bits of tsc
                     mov [esi+4], edx // upper 32 bits of tsc
                 }
                 __int64 time_s = (__int64)(high_perf_time /
frequency); // unsigned->sign conversion should be safe here
                 __int64 time_fract = (__int64)(high_perf_time %
frequency); // unsigned->sign conversion should be safe here
                 // note: here, we wrap the timer more frequently (once
per week)
                 // than it otherwise would (VERY RARELY - once every
585 years on
                 // a 1 GHz), to alleviate floating-point precision
errors that start
                 // to occur when you get to very high counter values.
                 double ret = (time_s % (60*60*24*7)) +
(double)time_fract/(double)((__int64)frequency);
                 return ret;
             }
             __except(EXCEPTION_EXECUTE_HANDLER)
             {
                 return -1.0;
             }

             return -1.0;
         }

This works pretty well, works on ALL Pentium I and later processors, and
offers
AMAZING precision. However, it can be messy, especially working that
1-second
test in there with all your other code, so that it runs in the background.


QueryPerformanceFrequency & QueryPerformanceCounter: Nice

There is one more item in our bag of tricks. It is simple, elegant, and
as far
as I can tell, extremely accurate and reliable. It is a pair of win32
functions:
QueryPerformanceFrequency and QueryPerformanceCounter.

QueryPerformanceFrequency returns the amount that the counter will
increment over
1 second; QueryPerformanceCounter returns a LARGE_INTEGER (a 64-bit
*signed* integer)
that is the current value of the counter.

Perhaps I am lucky, but it works flawlessly on my 3 machines. The MSDN
library
says that it should work on Windows 95 and later.

Here are some results:

               Return value of QueryPerformanceFrequency
     Gemini: 3,579,545 Hz
     Vaio: 1,193,000 Hz
     HP: 3,579,545 Hz

               Maximum # of unique readings I could get in 1 second
     Gemini: 658,000 (-> 1.52 us resolution!)
     Vaio: 174,300 (-> 5.73 us resolution!)
     HP: 617,000 (-> 1.62 us resolution!)

I was pretty excited to see timing resolutions in the low-microsecond
range. Note that for the latter test, I avoided printing any text
during the 1-second interval, as it would drastically affect the outcome.

Now, here is my question to you: do these two functions work for you?
What OS does the computer run, what is the MHz rating, and is it a laptop
or desktop? What was the result of QueryPerformanceFrequency?
What was the max. # of unique readings you could get in 1 second?
Can you find any computers that it doesn't work on? Let me know
(e-mail: ), and
I'll collect & publish everyone's results here.

So, until I find some computers that QueryPerformanceFrequency &
QueryPerformanceCounter don't work on, I'm sticking with them. If they
fail,
I've got backup code that will kick in, which uses timeGetTime(); I didn't
bother to use RDTSC because of the calibration issue, and I'm hopeful that
these two functions are highly reliable. I suppose only feedback from
readers like you will tell... =)


Accurate FPS Limiting / High-precision 'Sleeps'

So now, when I need to do FPS limiting (limiting the framerate to some
maximum), I don't just naively call Sleep() anymore. Instead, I use
QueryPerformanceCounter in a loop that runs Sleep(0). Sleep(0) simply
gives up your thread's current timeslice to another waiting thread; it
doesn't really sleep at all. So, if you just keep calling Sleep(0)
in a loop until QueryPerformanceCounter() says you've hit the right time,
you'll get ultra-accurate FPS readings.

There is one problem with this kind of fps limiting: it will use up
100% of the CPU. Even though the computer WILL remain
quite responsive, because the app sucking up the idle time is being very
"nice", this will still look very bad on the CPU meter (which will stay
at 100%) and, much worse, it will drain the battery quite quickly on
laptops.

To get around this, I use a hybrid algorithm that uses Sleep() to do the
bulk of the waiting, and QueryPerformanceCounter() to do the finishing
touches, making it accurate to ~10 microseconds, but still wasting very
little processor.

My code for accurate FPS limiting looks something like this, and runs
at the end of each frame, immediately after the page flip:


         // note: BE SURE YOU CALL timeBeginPeriod(1) at program startup!!!
         // note: BE SURE YOU CALL timeEndPeriod(1) at program exit!!!
         // note: that will require linking to winmm.lib
         // note: never use static initializers (like this) with Winamp
plug-ins!
         static LARGE_INTEGER m_prev_end_of_frame = 0;
         int max_fps = 60;

         LARGE_INTEGER t;
         QueryPerformanceCounter(&t);

         if (m_prev_end_of_frame.QuadPart != 0)
         {
             int ticks_to_wait = (int)m_high_perf_timer_freq.QuadPart /
max_fps;
             int done = 0;
             do
             {
                 QueryPerformanceCounter(&t);

                 int ticks_passed = (int)((__int64)t.QuadPart -
(__int64)m_prev_end_of_frame.QuadPart);
                 int ticks_left = ticks_to_wait - ticks_passed;

                 if (t.QuadPart < m_prev_end_of_frame.QuadPart) //
time wrap
                     done = 1;
                 if (ticks_passed >= ticks_to_wait)
                     done = 1;

                 if (!done)
                 {
                     // if > 0.002s left, do Sleep(1), which will
actually sleep some
                     // steady amount, probably 1-2 ms,
                     // and do so in a nice way (cpu meter drops;
laptop battery spared).
                     // otherwise, do a few Sleep(0)'s, which just give
up the timeslice,
                     // but don't really save cpu or battery, but do
pass a tiny
                     // amount of time.
                     if (ticks_left >
(int)m_high_perf_timer_freq.QuadPart*2/1000)
                         Sleep(1);
                     else
                         for (int i=0; i<10; i++)
                             Sleep(0); // causes thread to give up its
timeslice
                 }
             }
             while (!done);
         }

         m_prev_end_of_frame = t;

...which is trivial to convert this into a high-precision Sleep() function.


Conclusions & Summary

Using regular old timeGetTime() to do timing is not reliable on many
Windows-based
operating systems because the granularity of the system timer can be as
high as 10-15
milliseconds, meaning that timeGetTime() is only accurate to 10-15
milliseconds.
[Note that the high granularities occur on NT-based operation systems
like Windows NT,
2000, and XP. Windows 95 and 98 tend to have much better granularity,
around 1-5 ms.]

However, if you call timeBeginPeriod(1) at the beginning of your program
(and
timeEndPeriod(1) at the end), timeGetTime() will usually become accurate
to 1-2
milliseconds, and will provide you with extremely accurate timing
information.

Sleep() behaves similarly; the length of time that Sleep() actually
sleeps for
goes hand-in-hand with the granularity of timeGetTime(), so after calling
timeBeginPeriod(1) once, Sleep(1) will actually sleep for 1-2
milliseconds, Sleep(2)
for 2-3, and so on (instead of sleeping in increments as high as 10-15 ms).

For higher precision timing (sub-millisecond accuracy), you'll probably
want to avoid
using the assembly mnemonic RDTSC because it is hard to calibrate;
instead, use
QueryPerformanceFrequency and QueryPerformanceCounter, which are
accurate to less
than 10 microseconds (0.00001 seconds).

For simple timing, both timeGetTime and QueryPerformanceCounter work
well, and
QueryPerformanceCounter is obviously more accurate. However, if you
need to do
any kind of "timed pauses" (such as those necessary for framerate
limiting), you
need to be careful of sitting in a loop calling QueryPerformanceCounter,
waiting
for it to reach a certain value; this will eat up 100% of your
processor. Instead,
consider a hybrid scheme, where you call Sleep(1) (don't forget
timeBeginPeriod(1)
first!) whenever you need to pass more than 1 ms of time, and then only
enter the
QueryPerformanceCounter 100%-busy loop to finish off the last < 1/1000th
of a
second of the delay you need. This will give you ultra-accurate delays
(accurate
to 10 microseconds), with very minimal CPU usage. See the code above.



UPDATE: a few people have written e-mail pointing me to this Microsoft
Knowledge
Base article which outlines some cases in which the QueryPerformanceCounter
function can unexpectedly jump forward by a few seconds.

UPDATE: Ross Bencina was kind enough to point out to me that rdtsc "is a
per-cpu
operation, so on multiprocessor systems you have to be careful that
multiple calls
to rdtsc are actually executing on the same cpu." Thanks Ross!




This document copyright (c)2002+ Ryan M. Geiss.

Return to faq page

--- BlackBox
--- send subject HELP or UNSUBSCRIBE to blackbox{([at]})nowhere.xy



----boundary-LibPST-iamunique-1421877144_-_-
Content-type: application/rtf
Content-transfer-encoding: base64
Content-Disposition: attachment; filename="rtf-body.rtf"

e1xydGYxXGFuc2lcYW5zaWNwZzEyNTJcZnJvbXRleHQgXGRlZmYwe1xmb250dGJsDQp7XGYwXGZz
d2lzcyBBcmlhbDt9DQp7XGYxXGZtb2Rlcm4gQ291cmllciBOZXc7fQ0Ke1xmMlxmbmlsXGZjaGFy
c2V0MiBTeW1ib2w7fQ0Ke1xmM1xmbW9kZXJuXGZjaGFyc2V0MCBDb3VyaWVyIE5ldzt9fQ0Ke1xj
b2xvcnRibFxyZWQwXGdyZWVuMFxibHVlMDtccmVkMFxncmVlbjBcYmx1ZTI1NTt9DQpcdWMxXHBh
cmRccGxhaW5cZGVmdGFiMzYwIFxmMFxmczIwIHNrdWxza2lAcGFzLnJvY2hlc3Rlci5lZHUgd3Jv
dGU6XHBhcg0KPiBDaHJpczpccGFyDQo+IFxwYXINCj4gSSBhbSB1c2luZyBTZXJ2aWNlcy5UaWNr
cyBub3csIGJ1dCBpdCBpcyBub3QgaWRlYWwgZm9yIG1lIGJlY2F1c2UgaXRccGFyDQo+IHJldHVy
bnMgdGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHNpbmNlIEJCIHdhcyBzdGFydGVkLiBJLmUuLCB0
aGVccGFyDQo+ICJUaWNrcyA9IDAiIGlzIHRoZSB0aW1lIHdoZW4gSSBkb3VibGUtY2xpY2tlZCBv
biB0aGUgQkIgaWNvbi5ccGFyDQo+IEkgbmVlZCBhbiBhYnNvbHV0ZSBkYXkgdGltZSBmb3IgZGF0
YSBsb2dnaW5nLCB3aXRoIHRoZSByZXNvbHV0aW9uIG9mIDEgbXMuXHBhcg0KV29qdGVrLFxwYXIN
CkkgZm91bmQgdGhlIGZvbGxvd2luZyBvbiB0aGUgd2ViIHdoaWNoIG1heSBnaXZlIHlvdSAxLTIg
bWlsbGlzZWNvbmQgXHBhcg0KYWNjdXJhY3kuXHBhcg0KLURvdWdccGFyDQpccGFyDQpSZXN1bHRz
IG9mIHNvbWUgcXVpY2sgcmVzZWFyY2ggb24gdGltaW5nIGluIFdpbjMyXHBhcg0KYnkgUnlhbiBH
ZWlzc1xwYXINCjgvMTYvMjAwMlxwYXINClxwYXINCllvdSBtaWdodCBiZSB0aGlua2luZyB0byB5
b3Vyc2VsZjogdGhpcyBpcyBhIHByZXR0eSBzaW1wbGUgdGhpbmdccGFyDQp0byBiZSBwb3N0aW5n
OyB3aGF0J3MgdGhlIGJpZyBkZWFsPyAgVGhlIGRlYWwgaXMgdGhhdCBzb21laG93LFxwYXINCmdv
b2QgdGltaW5nIGNvZGUgaGFzIGVsdWRlZCBtZSBmb3IgeWVhcnMuICBGaW5hbGx5LCBmcnVzdHJh
dGVkLFxwYXINCkkgZHVnIGluIGFuZCBkaWQgc29tZSBmb3JtYWwgZXhwZXJpbWVudHMgb24gYSBm
ZXcgZGlmZmVyZW50IGNvbXB1dGVycyxccGFyDQp0ZXN0aW5nIHRoZSB0aW1pbmcgcHJlY2lzaW9u
IHRoZXkgY291bGQgb2ZmZXIsIHVzaW5nIHZhcmlvdXMgd2luMzJccGFyDQpmdW5jdGlvbnMuICBJ
IHdhcyBmYWlybHkgc3VycHJpc2VkIGJ5IHRoZSByZXN1bHRzIVxwYXINClxwYXINCkkgdGVzdGVk
IG9uIHRocmVlIGNvbXB1dGVyczsgaGVyZSBhcmUgdGhlaXIgc3BlY3M6XHBhcg0KXHBhcg0KICAg
ICBHZW1pbmk6ICAgOTMzIG1oeiBkZXNrdG9wLCB3aW4ya1xwYXINCiAgICAgVmFpbzogICAgIDMz
MyBtaHogbGFwdG9wLCAgd2luOThccGFyDQogICAgIEhQOiAgICAgICA3MzMgbWh6IGxhcHRvcCwg
IHdpbjJrXHBhcg0KXHBhcg0KQWxzbywgYWJicmV2aWF0aW9ucyB0byBiZSB1c2VkIGhlcmVhZnRl
cjpccGFyDQpccGFyDQogICAgIG1zOiBtaWxsaXNlY29uZHMsIG9yIDEvMSwwMDAgb2YgYSBzZWNv
bmRccGFyDQogICAgIHVzOiBtaWNyb3NlY29uZHMsIG9yIDEvMSwwMDAsMDAwIG9mIGEgc2Vjb25k
XHBhcg0KXHBhcg0KXHBhcg0KdGltZUdldFRpbWUgLSB3aGF0IHRoZXkgZG9uJ3QgdGVsbCB5b3Vc
cGFyDQpccGFyDQpGaXJzdCwgSSB0cmllZCB0byBkZXRlcm1pbmUgdGhlIHByZWNpc2lvbiBvZiB0
aW1lR2V0VGltZSgpLlxwYXINCkluIG9yZGVyIHRvIGRvIHRoaXMsIEkgc2ltcGx5IHJhbiBhIGxv
b3AsIGNvbnN0YW50bHkgcG9sbGluZ1xwYXINCnRpbWVHZXRUaW1lKCkgdW50aWwgdGhlIHRpbWUg
Y2hhbmdlZCwgYW5kIHRoZW4gcHJpbnRpbmcgdGhlXHBhcg0KZGVsdGEgKGJldHdlZW4gdGhlIHBy
ZXYuIHRpbWUgYW5kIHRoZSBuZXcgdGltZSkuICBJIHRoZW4gbG9va2VkXHBhcg0KYXQgdGhlIG91
dHB1dCwgYW5kIGZvciBlYWNoIGNvbXB1dGVyLCB0b29rIHRoZSBtaW5pbXVtIG9mIGFsbFxwYXIN
CnRoZSBkZWx0YSdzIHRoYXQgb2NjdXJlZC4gIChVc3VhbGx5LCB0aGUgbWluaW11bSB3YXMgdmVy
eSBzb2xpZCxccGFyDQpvY2N1cmluZyBhYm91dCA5MCUgb2YgdGhlIHRpbWUuKSAgVGhlIHJlc3Vs
dHM6XHBhcg0KXHBhcg0KICAgICAgICAgICAgICAgUmVzb2x1dGlvbiBvZiB0aW1lR2V0VGltZSgp
XHBhcg0KICAgICBHZW1pbmk6ICAgMTAgbXNccGFyDQogICAgIFZhaW86ICAgICAxIG1zXHBhcg0K
ICAgICBIUDogICAgICAgMTAgbXNccGFyDQpccGFyDQpGb3Igbm93LCBJIGFtIGFzc3VtaW5nIHRo
YXQgaXQgd2FzIHRoZSBPUyBrZXJuZWwgdGhhdCBtYWRlIHRoZVxwYXINCmRpZmZlcmVuY2U6IHdp
bjJrIG9mZmVycyBhIG1heC4gcHJlY2lzaW9uIG9mIDEwIG1zIGZvciB0aW1lR2V0VGltZSgpLFxw
YXINCndoaWxlIHdpbjk4IGlzIG11Y2ggYmV0dGVyLCBhdCAxIG1zLiAgSSBhc3N1bWUgdGhhdCBX
aW5YUCB3b3VsZCBhbHNvXHBhcg0KaGF2ZSBhIHByZWNpc2lvbiBvZiAxMCBtcywgYW5kIHRoYXQg
V2luOTUgd291bGQgYmUgfjEgbXMsIGxpa2UgV2luOTguXHBhcg0KKElmIGFueW9uZSB0ZXN0cyB0
aGlzIG91dCwgcGxlYXNlIGxldCBtZSBrbm93IGVpdGhlciB3YXkhKVxwYXINClxwYXINCihOb3Rl
IHRoYXQgdXNpbmcgdGltZUdldFRpbWUoKSB1bmZvcnR1bmF0ZWx5IHJlcXVpcmVzIGxpbmtpbmcg
dG9ccGFyDQp3aW5tbS5saWIsIHdoaWNoIHNsaWdodGx5IGluY3JlYXNlcyB5b3VyIGZpbGUgc2l6
ZS4gIFlvdSBjb3VsZCB1c2VccGFyDQpHZXRUaWNrQ291bnQoKSBpbnN0ZWFkLCB3aGljaCBkb2Vz
bid0IHJlcXVpcmUgbGlua2luZyB0byB3aW5tbS5saWIsXHBhcg0KYnV0IGl0IHRlbmRzIHRvIG5v
dCBoYXZlIGFzIGdvb2Qgb2YgYSB0aW1lciByZXNvbHV0aW9uLi4uIHNvIEkgd291bGRccGFyDQpy
ZWNvbW1lbmQgc3RpY2tpbmcgd2l0aCB0aW1lR2V0VGltZSgpLlxwYXINClxwYXINCk5leHQsIEkg
dGVzdGVkIFNsZWVwKCkuICBBIHdoaWxlIGJhY2sgSSBub3RpY2VkIHRoYXQgd2hlbiB5b3UgY2Fs
bFxwYXINClNsZWVwKDEpLCBpdCBkb2Vzbid0IHJlYWxseSBzbGVlcCBmb3IgMSBtczsgaXQgdXN1
YWxseSBzbGVlcHMgZm9yIGxvbmdlclxwYXINCnRoYW4gdGhhdC4gIEkgdmVyaWZpZWQgdGhpcyBi
eSBjYWxsaW5nIFNsZWVwKDEpIHRlbiB0aW1lcyBpbiBhIHJvdyxccGFyDQphbmQgdGFraW5nIHRo
ZSBkaWZmZXJlbmNlIGluIHRpbWVHZXRUaW1lKCkgcmVhZGluZ3MgZnJvbSB0aGUgYmVnaW5uaW5n
XHBhcg0KdG8gdGhlIGVuZC4gIFdoYXRldmVyIGRlbHRhIHRoZXJlIHdhcyBmb3IgdGhlc2UgdGVu
IHNsZWVwcywgSSBqdXN0IGRpdmlkZWRccGFyDQppdCBieSAxMCB0byBnZXQgdGhlIGF2ZXJhZ2Ug
ZHVyYXRpb24gb2YgU2xlZXAoMSkuICBUaGlzIHR1cm5lZCBvdXQgdG8gYmU6XHBhcg0KXHBhcg0K
ICAgICAgICAgICAgICAgQXZlcmFnZSBkdXJhdGlvbiBvZiBTbGVlcCgxKVxwYXINCiAgICAgR2Vt
aW5pOiAgIDEwIG1zICAoMTAgY2FsbHMgdG8gU2xlZXAoMSkgdG9vayBleGFjdGx5IDEwMCBtcylc
cGFyDQogICAgIFZhaW86ICAgICB+NCBtcyAgKDEwIGNhbGxzIHRvIFNsZWVwKDEpIHRvb2sgMzUt
NDUgbXMpXHBhcg0KICAgICBIUDogICAgICAgMTAgbXMgICgxMCBjYWxscyB0byBTbGVlcCgxKSB0
b29rIGV4YWN0bHkgMTAwIG1zKVxwYXINClxwYXINCk5vdywgdGhpcyB3YXMgZGlzdHVyYmluZywg
YmVjYXVzZSBpdCBtZWFudCB0aGF0IGlmIHlvdSBjYWxsIFNsZWVwKDEpXHBhcg0KYW5kIFNsZWVw
KDkpIG9uIGEgd2luMmsgbWFjaGluZSwgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSAtIGl0IHN0aWxs
XHBhcg0Kc2xlZXBzIGZvciAxMCBtcyEgICJTbyAqdGhpcyogaXMgdGhlIHJlYXNvbiBhbGwgbXkg
dGltaW5nIGNvZGUgc3Vja3MsIlxwYXINCkkgc2lnaGVkIHRvIG15c2VsZi5ccGFyDQpccGFyDQpH
aXZlbiB0aGF0LCBJIGRlY2lkZWQgdG8gZ2l2ZSB1cCBvbiBTbGVlcCgpIGFuZCB0aW1lR2V0VGlt
ZSgpLiAgVGhlXHBhcg0KYXBwbGljYXRpb24gSSB3YXMgd29ya2luZyBvbiByZXF1aXJlZCByZWFs
bHkgZ29vZCBmcHMgbGltaXRpbmcsIGFuZFxwYXINCjEwbXMgU2xlZXBzIHdlcmUgbm90IHByZWNp
c2UgZW5vdWdoIHRvIGRvIGEgZ29vZCBqb2IuICBTbyBJIGxvb2tlZFxwYXINCmVsc2V3aGVyZS5c
cGFyDQpccGFyDQpccGFyDQpccGFyDQp0aW1lQmVnaW5QZXJpb2QgLyB0aW1lRW5kUGVyaW9kXHBh
cg0KXHBhcg0KSE9XRVZFUiwgSSBzaG91bGQgbm90IGhhdmUgZ2l2ZW4gdXAgc28gZmFzdCEgIEl0
IHR1cm5zIG91dCB0aGF0IHRoZXJlXHBhcg0KaXMgYSB3aW4zMiBjb21tYW5kLCB0aW1lQmVnaW5Q
ZXJpb2QoKSwgd2hpY2ggc29sdmVzIG91ciBwcm9ibGVtOlxwYXINCml0IGxvd2VycyB0aGUgZ3Jh
bnVsYXJpdHkgb2YgU2xlZXAoKSB0byB3aGF0ZXZlciBwYXJhbWV0ZXIgeW91IGdpdmUgaXQuXHBh
cg0KU28gaWYgeW91J3JlIG9uIHdpbmRvd3MgMjAwMCBhbmQgeW91IGNhbGwgdGltZUJlZ2luUGVy
aW9kKDEpIGFuZCB0aGVuXHBhcg0KU2xlZXAoMSksIGl0IHdpbGwgdHJ1bHkgc2xlZXAgZm9yIGp1
c3QgMSBtaWxsaXNlY29uZCwgcmF0aGVyIHRoYW4gdGhlXHBhcg0KZGVmYXVsdCAxMCFccGFyDQpc
cGFyDQp0aW1lQmVnaW5QZXJpb2QoKSBvbmx5IGFmZmVjdHMgdGhlIGdyYW51bGFyaXR5IG9mIFNs
ZWVwKCkgZm9yIHRoZSBccGFyDQphcHBsaWNhdGlvblxwYXINCnRoYXQgY2FsbHMgaXQsIHNvIGRv
bid0IHdvcnJ5IGFib3V0IG1lc3NpbmcgdXAgdGhlIHN5c3RlbSB3aXRoIGl0LiAgQWxzbyxccGFy
DQpiZSBzdXJlIHlvdSBjYWxsIHRpbWVFbmRQZXJpb2QoKSB3aGVuIHlvdXIgcHJvZ3JhbSBleGl0
cywgd2l0aCB0aGUgc2FtZVxwYXINCnBhcmFtZXRlciB5b3UgZmVkIGludG8gdGltZUJlZ2luUGVy
aW9kKCkgd2hlbiB5b3VyIHByb2dyYW0gc3RhcnRlZCBccGFyDQoocHJlc3VtYWJseVxwYXINCjEp
LiAgQm90aCBvZiB0aGVzZSBmdW5jdGlvbnMgYXJlIGluIHdpbm1tLmxpYiwgc28geW91J2xsIGhh
dmUgdG8gbGluayB0byBpdFxwYXINCmlmIHlvdSB3YW50IHRvIGxvd2VyIHlvdXIgU2xlZXAoKSBn
cmFudWxhcml0eSBkb3duIHRvIDEgbXMuXHBhcg0KXHBhcg0KSG93IHJlbGlhYmxlIGlzIGl0PyAg
SSBoYXZlIHlldCB0byBmaW5kIGEgc3lzdGVtIGZvciB3aGljaCBccGFyDQp0aW1lQmVnaW5QZXJp
b2QoMSlccGFyDQpkb2VzIG5vdCBkcm9wIHRoZSBncmFudWxhcml0eSBvZiBTbGVlcCgxKSB0byAx
IG9yLCBhdCBtb3N0LCAyIG1pbGxpc2Vjb25kcy5ccGFyDQpJZiBhbnlvbmUgb3V0IHRoZXJlIGRv
ZXMsIHBsZWFzZSBsZXQgbWUga25vd1xwYXINCihlLW1haWw6ICk7XHBhcg0KSSdkIGxpa2UgdG8g
aGVhciBhYm91dCBpdCwgYW5kIEkgd2lsbCBwb3N0IGEgd2FybmluZyBoZXJlLlxwYXINClxwYXIN
Ck5vdGUgYWxzbyB0aGF0IGNhbGxpbmcgdGltZUJlZ2luUGVyaW9kKCkgYWxzbyBhZmZlY3RzIHRo
ZSBncmFudWxhcml0eSBvZiBccGFyDQpzb21lXHBhcg0Kb3RoZXIgdGltaW5nIGNhbGxzLCBzdWNo
IGFzIENyZWF0ZVdhaXRhYmxlVGltZXIoKSBhbmQgXHBhcg0KV2FpdEZvclNpbmdsZU9iamVjdCgp
O1xwYXINCmhvd2V2ZXIsIHNvbWUgZnVuY3Rpb25zIGFyZSBzdGlsbCB1bmFmZmVjdGVkLCBzdWNo
IGFzIF9mdGltZSgpLiAgKFNwZWNpYWxccGFyDQp0aGFua3MgdG8gTWFyayBFcHN0ZWluIGZvciBw
b2ludGluZyB0aGlzIG91dCB0byBtZSEpXHBhcg0KXHBhcg0KXHBhcg0Kc29tZSBjb252ZW5pZW50
IHRlc3QgY29kZVxwYXINClxwYXINClRoZSBmb2xsb3dpbmcgY29kZSB3aWxsIHRlbGwgeW91Olxw
YXINCiAgICAgMS4gd2hhdCB0aGUgZ3JhbnVsYXJpdHksIG9yIG1pbmltdW0gcmVzb2x1dGlvbiwg
b2YgY2FsbHMgdG8gXHBhcg0KdGltZUdldFRpbWUoKSBhcmUsXHBhcg0Kb24geW91ciBzeXN0ZW0u
ICBJbiBvdGhlciB3b3JkcywgaWYgeW91IHNpdCBpbiBhIHRpZ2h0IGxvb3AgYW5kIGNhbGwgXHBh
cg0KdGltZUdldFRpbWUoKSxccGFyDQpvbmx5IG5vdGluZyB3aGVuIHRoZSB2YWx1ZSByZXR1cm5l
ZCBjaGFuZ2VzLCB3aGF0IHZhbHVlIGRvIHlvdSBnZXQ/ICBUaGlzXHBhcg0KZ3JhbnVsYXJpdHkg
dGVsbHMgeW91LCBtb3JlIG9yIGxlc3MsIHdoYXQga2luZCBvZiBwb3RlbnRpYWwgZXJyb3IgdG8g
XHBhcg0KZXhwZWN0IGluXHBhcg0KdGhlIHJlc3VsdCB3aGVuIGNhbGxpbmcgdGltZUdldFRpbWUo
KS5ccGFyDQogICAgIDIuIGl0IGFsc28gdGVzdHMgaG93IGxvbmcgeW91ciBtYWNoaW5lIHJlYWxs
eSBzbGVlcHMgd2hlbiB5b3UgY2FsbCBccGFyDQpTbGVlcCgxKS5ccGFyDQpPZnRlbiB0aGlzIGlz
IGFjdHVhbGx5IDIgb3IgbW9yZSBtaWxsaXNlY29uZHMsIHNvIGJlIGNhcmVmdWwhXHBhcg0KXHBh
cg0KTk9URSB0aGF0IHRoZXNlIHRlc3RzIGFyZSBwZXJmb3JtZWQgYWZ0ZXIgY2FsbGluZyB0aW1l
QmVnaW5QZXJpb2QoMSksIHNvIGlmXHBhcg0KeW91IGZvcmdldCB0byBjYWxsIHRpbWVCZWdpblBl
cmlvZCgxKSBpbiB5b3VyIG93biBpbml0IGNvZGUsIHlvdSBtaWdodCBccGFyDQpub3QgZ2V0XHBh
cg0KYXMgZ29vZCBvZiBncmFudWxhcml0eSBhcyB5b3Ugc2VlIGZyb20gdGhpcyB0ZXN0IVxwYXIN
ClxwYXINClxwYXINCiAgICAgICAgICNpbmNsdWRlICAgICAgICA8c3RkaW8uaD5ccGFyDQogICAg
ICAgICAjaW5jbHVkZSAgICAgICAgIndpbmRvd3MuaCJccGFyDQpccGFyDQogICAgICAgICBpbnQg
bWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpXHBhcg0KICAgICAgICAgXHtccGFyDQogICAgICAg
ICAgICAgY29uc3QgaW50IGNvdW50ID0gNjQ7XHBhcg0KXHBhcg0KICAgICAgICAgICAgIHRpbWVC
ZWdpblBlcmlvZCgxKTtccGFyDQpccGFyDQogICAgICAgICAgICAgcHJpbnRmKCIxLiB0ZXN0aW5n
IGdyYW51bGFyaXR5IG9mIHRpbWVHZXRUaW1lKCkuLi5cXG4iKTtccGFyDQogICAgICAgICAgICAg
aW50IGl0cyA9IDA7XHBhcg0KICAgICAgICAgICAgIGxvbmcgY3VyID0gMCwgbGFzdCA9IHRpbWVH
ZXRUaW1lKCk7XHBhcg0KICAgICAgICAgICAgIHdoaWxlIChpdHMgPCBjb3VudCkgXHtccGFyDQog
ICAgICAgICAgICAgICAgIGN1ciA9IHRpbWVHZXRUaW1lKCk7XHBhcg0KICAgICAgICAgICAgICAg
ICBpZiAoY3VyICE9IGxhc3QpIFx7XHBhcg0KICAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCIl
bGQgIiwgY3VyLWxhc3QpO1xwYXINCiAgICAgICAgICAgICAgICAgICAgIGxhc3QgPSBjdXI7XHBh
cg0KICAgICAgICAgICAgICAgICAgICAgaXRzKys7XHBhcg0KICAgICAgICAgICAgICAgICBcfVxw
YXINCiAgICAgICAgICAgICBcfVxwYXINClxwYXINCiAgICAgICAgICAgICBwcmludGYoIlxcblxc
bjIuIHRlc3RpbmcgZ3JhbnVsYXJpdHkgb2YgU2xlZXAoMSkuLi5cXG4gICIpO1xwYXINCiAgICAg
ICAgICAgICBsb25nIGZpcnN0ID0gdGltZUdldFRpbWUoKTtccGFyDQogICAgICAgICAgICAgY3Vy
ID0gZmlyc3Q7XHBhcg0KICAgICAgICAgICAgIGxhc3QgPSBmaXJzdDtccGFyDQogICAgICAgICAg
ICAgZm9yIChpbnQgbj0wOyBuPGNvdW50OyBuKyspIFx7XHBhcg0KICAgICAgICAgICAgICAgICBT
bGVlcCgxKTtccGFyDQogICAgICAgICAgICAgICAgIGN1ciA9IHRpbWVHZXRUaW1lKCk7XHBhcg0K
ICAgICAgICAgICAgICAgICBwcmludGYoIiVkICIsIGN1ci1sYXN0KTtccGFyDQogICAgICAgICAg
ICAgICAgIGxhc3QgPSBjdXI7XHBhcg0KICAgICAgICAgICAgIFx9XHBhcg0KICAgICAgICAgICAg
IHByaW50ZigiXFxuIik7XHBhcg0KXHBhcg0KICAgICAgICAgICAgIHJldHVybiAwO1xwYXINCiAg
ICAgICAgIFx9XHBhcg0KXHBhcg0KXHBhcg0KXHBhcg0KXHBhcg0KXHBhcg0KUkRUU0M6IEVoLCBu
byB0aGFua3NccGFyDQpccGFyDQpPbiB0aGUgd2ViLCBJIGZvdW5kIHNldmVyYWwgcmVmZXJlbmNl
cyB0byB0aGUgIlJEVFNDIiBQZW50aXVtIGluc3RydWN0aW9uLFxwYXINCndoaWNoIHN0YW5kcyBm
b3IgIlJlYWQgVGltZSBTdGFtcCBDb3VudGVyLiIgIFRoaXMgYXNzZW1ibHkgaW5zdHJ1Y3Rpb24g
XHBhcg0KcmV0dXJuc1xwYXINCmFuIHVuc2lnbmVkIDY0LWJpdCBpbnRlZ2VyIHJlYWRpbmcgb24g
dGhlIHByb2Nlc3NvcidzIGludGVybmFsIFxwYXINCmhpZ2gtcHJlY2lzaW9uXHBhcg0KdGltZXIu
ICBJbiBvcmRlciB0byBnZXQgdGhlIGZyZXF1ZW5jeSBvZiB0aGUgdGltZXIgKGhvdyBtdWNoIHRo
ZSB0aW1lciBccGFyDQpyZXR1cm5ccGFyDQp2YWx1ZSB3aWxsIGluY3JlbWVudCBpbiAxIHNlY29u
ZCksIHlvdSBjYW4gcmVhZCB0aGUgcmVnaXN0cnkgZm9yIHRoZSBccGFyDQptYWNoaW5lJ3NccGFy
DQpzcGVlZCAoaW4gTUh6IC0gbWlsbGlvbnMgb2YgY3ljbGVzIHBlciBzZWNvbmQpLCBsaWtlIHRo
aXM6XHBhcg0KXHBhcg0KICAgICAgICAgLy8gV0FSTklORzogWU9VIERPTidUIFJFQUxMWSBXQU5U
IFRPIFVTRSBUSElTIEZVTkNUSU9OXHBhcg0KICAgICAgICAgYm9vbCBHZXRQZW50aXVtQ2xvY2tF
c3RpbWF0ZUZyb21SZWdpc3RyeSh1bnNpZ25lZCBfX2ludDY0IFxwYXINCipmcmVxdWVuY3kpXHBh
cg0KICAgICAgICAgXHtccGFyDQogICAgICAgICAgICAgSEtFWSAgICAgICAgICAgICAgICAgICAg
ICAgIGhLZXk7XHBhcg0KICAgICAgICAgICAgIERXT1JEICAgICAgICAgICAgICAgICAgICAgICBj
YkJ1ZmZlcjtccGFyDQogICAgICAgICAgICAgTE9ORyAgICAgICAgICAgICAgICAgICAgICAgIHJj
O1xwYXINClxwYXINCiAgICAgICAgICAgICAqZnJlcXVlbmN5ID0gMDtccGFyDQpccGFyDQogICAg
ICAgICAgICAgcmMgPSBSZWdPcGVuS2V5RXgoXHBhcg0KICAgICAgICAgICAgICAgICAgICAgIEhL
RVlfTE9DQUxfTUFDSElORSxccGFyDQogICAgICAgICAgICAgICAgICAgICAgIkhhcmR3YXJlXFxc
XERlc2NyaXB0aW9uXFxcXFN5c3RlbVxcXFxDZW50cmFsUHJvY2Vzc29yXFxcXDAiLFxwYXINCiAg
ICAgICAgICAgICAgICAgICAgICAwLFxwYXINCiAgICAgICAgICAgICAgICAgICAgICBLRVlfUkVB
RCxccGFyDQogICAgICAgICAgICAgICAgICAgICAgJmhLZXlccGFyDQogICAgICAgICAgICAgICAg
ICApO1xwYXINClxwYXINCiAgICAgICAgICAgICBpZiAocmMgPT0gRVJST1JfU1VDQ0VTUylccGFy
DQogICAgICAgICAgICAgXHtccGFyDQogICAgICAgICAgICAgICAgIGNiQnVmZmVyID0gc2l6ZW9m
IChEV09SRCk7XHBhcg0KICAgICAgICAgICAgICAgICBEV09SRCBmcmVxX21oejtccGFyDQogICAg
ICAgICAgICAgICAgIHJjID0gUmVnUXVlcnlWYWx1ZUV4XHBhcg0KICAgICAgICAgICAgICAgICAg
ICAgIChccGFyDQogICAgICAgICAgICAgICAgICAgICAgICBoS2V5LFxwYXINCiAgICAgICAgICAg
ICAgICAgICAgICAgICJ+TUh6IixccGFyDQogICAgICAgICAgICAgICAgICAgICAgICBOVUxMLFxw
YXINCiAgICAgICAgICAgICAgICAgICAgICAgIE5VTEwsXHBhcg0KICAgICAgICAgICAgICAgICAg
ICAgICAgKExQQllURSkoJmZyZXFfbWh6KSxccGFyDQogICAgICAgICAgICAgICAgICAgICAgICAm
Y2JCdWZmZXJccGFyDQogICAgICAgICAgICAgICAgICAgICAgKTtccGFyDQogICAgICAgICAgICAg
ICAgIGlmIChyYyA9PSBFUlJPUl9TVUNDRVNTKVxwYXINCiAgICAgICAgICAgICAgICAgICAgICpm
cmVxdWVuY3kgPSBmcmVxX21oeioxMDI0KjEwMjQ7XHBhcg0KICAgICAgICAgICAgICAgICBSZWdD
bG9zZUtleSAoaEtleSk7XHBhcg0KICAgICAgICAgICAgIFx9XHBhcg0KXHBhcg0KICAgICAgICAg
ICAgIHJldHVybiAoKmZyZXF1ZW5jeSA+IDApO1xwYXINCiAgICAgICAgIFx9XHBhcg0KXHBhcg0K
XHBhcg0KICAgICAgICAgICAgICAgUmVzdWx0IG9mIEdldFBlbnRpdW1DbG9ja0VzdGltYXRlRnJv
bVJlZ2lzdHJ5KClccGFyDQogICAgIEdlbWluaTogICA5NzUsMTc1LDY4MCBIelxwYXINCiAgICAg
VmFpbzogICAgIEZBSUxFRC5ccGFyDQogICAgIEhQOiAgICAgICA1NzMsNTcxLDA3MiBIeiAgIDwt
LSBzdHJhbmdlLi4uXHBhcg0KXHBhcg0KICAgICAgICAgICAgICAgRW1waXJpY2FsIHRlc3RzOiBS
RFRTQyBkZWx0YSBhZnRlciBTbGVlcCgxMDAwKVxwYXINCiAgICAgR2VtaW5pOiAgIDkzMSw0NDAs
MDAwIEh6XHBhcg0KICAgICBWYWlvOiAgICAgMzMxLDUwMCwwMDAgSHpccGFyDQogICAgIEhQOiAg
ICAgICAgMTMsNDAxLDI4NyBIelxwYXINClxwYXINClxwYXINCkhvd2V2ZXIsIGFzIHlvdSBjYW4g
c2VlLCB0aGlzIGZhaWxlZCBvbiBWYWlvICh0aGUgd2luOTggbGFwdG9wKS5ccGFyDQpXb3JzZSB5
ZXQsIGhvd2V2ZXIsIGlzIHRoYXQgb24gdGhlIEhQLCB0aGUgdmFsdWUgaW4gdGhlIHJlZ2lzdHJ5
XHBhcg0KZG9lcyBub3QgbWF0Y2ggdGhlIE1IeiByYXRpbmcgb2YgdGhlIG1hY2hpbmUgKDczMyku
ICBUaGF0IHdvdWxkXHBhcg0KYmUgb2theSBpZiB0aGUgdmFsdWUgd2FzIGFjdHVhbGx5IHRoZSBy
YXRlIGF0IHdoaWNoIHRoZSB0aW1lclxwYXINCnRpY2tlZDsgYnV0LCBhZnRlciBkb2luZyBzb21l
IGVtcGlyaWNhbCB0ZXN0aW5nLCBpdCB0dXJucyBvdXQgdGhhdFxwYXINCnRoZSBIUCdzIHRpbWVy
IGZyZXF1ZW5jeSBpcyByZWFsbHkgMTMgTUh6LiAgVHJ1c3RpbmcgdGhlXHBhcg0KcmVnaXN0cnkg
cmVhZGluZyBvbiB0aGUgSFAgd291bGQgYmUgYSBiaWcsIGJpZyBtaXN0YWtlIVxwYXINClxwYXIN
ClNvLCBvbmUgY29uY2x1c2lvbiBpczogZG9uJ3QgdHJ5IHRvIHJlYWQgdGhlIHJlZ2lzdHJ5IHRv
IGdldCB0aGVccGFyDQp0aW1lciBmcmVxdWVuY3k7IHlvdSdyZSBhc2tpbmcgZm9yIHRyb3VibGUu
ICBJbnN0ZWFkLCBkbyBpdCB5b3Vyc2VsZi5ccGFyDQpccGFyDQpKdXN0IGNhbGwgU2xlZXAoMTAw
MCkgdG8gYWxsb3cgMSBzZWNvbmQgKHBsdXMgb3IgbWludXMgfjElKSB0byBwYXNzLFxwYXINCmNh
bGxpbmcgR2V0UGVudGl1bVRpbWVSYXcoKSAoYmVsb3cpIGF0IHRoZSBiZWdpbm5pbmcgYW5kIGVu
ZCwgYW5kIHRoZW5ccGFyDQpzaW1wbHkgc3VidHJhY3QgdGhlIHR3byB1bnNpZ25lZCBfX2ludDY0
J3MsIGFuZCB2b2lsYSwgeW91IG5vdyBrbm93XHBhcg0KdGhlIGZyZXF1ZW5jeSBvZiB0aGUgdGlt
ZXIgdGhhdCBmZWVkcyBSRFRTQyBvbiB0aGUgY3VycmVudCBzeXN0ZW0uXHBhcg0KKCp3YXRjaCBv
dXQgZm9yIHRpbWVyIHdyYXBzIGR1cmluZyB0aGF0IDEgc2Vjb25kLCB0aG91Z2guLi4pXHBhcg0K
XHBhcg0KTm90ZSB0aGF0IHlvdSBjb3VsZCBlYXNpbHkgZG8gdGhpcyBpbiB0aGUgYmFja2dyb3Vu
ZCwgdGhvdWdoLCB1c2luZ1xwYXINCnRpbWVHZXRUaW1lKCkgaW5zdGVhZCBvZiBTbGVlcCgpLCBz
byB0aGVyZSB3b3VsZG4ndCBiZSBhIDEtc2Vjb25kIHBhdXNlXHBhcg0Kd2hlbiB5b3VyIHByb2dy
YW0gc3RhcnRzLlxwYXINClxwYXINCiAgICAgICAgIGludCBHZXRQZW50aXVtVGltZVJhdyh1bnNp
Z25lZCBfX2ludDY0ICpyZXQpXHBhcg0KICAgICAgICAgXHtccGFyDQogICAgICAgICAgICAgLy8g
cmV0dXJucyAwIG9uIGZhaWx1cmUsIDEgb24gc3VjY2Vzc1xwYXINCiAgICAgICAgICAgICAvLyB3
YXJuaW5nOiB3YXRjaCBvdXQgZm9yIHdyYXBhcm91bmQhXHBhcg0KXHBhcg0KICAgICAgICAgICAg
IC8vIGdldCBoaWdoLXByZWNpc2lvbiB0aW1lOlxwYXINCiAgICAgICAgICAgICBfX3RyeVxwYXIN
CiAgICAgICAgICAgICBce1xwYXINCiAgICAgICAgICAgICAgICAgdW5zaWduZWQgX19pbnQ2NCAq
ZGVzdCA9ICh1bnNpZ25lZCBfX2ludDY0ICopcmV0O1xwYXINCiAgICAgICAgICAgICAgICAgX19h
c21ccGFyDQogICAgICAgICAgICAgICAgIFx7XHBhcg0KICAgICAgICAgICAgICAgICAgICAgX2Vt
aXQgMHhmICAgICAgICAvLyB0aGVzZSB0d28gYnl0ZXMgZm9ybSB0aGUgXHBhcg0KJ3JkdHNjJyBh
c20gaW5zdHJ1Y3Rpb24sXHBhcg0KICAgICAgICAgICAgICAgICAgICAgX2VtaXQgMHgzMSAgICAg
ICAvLyAgYXZhaWxhYmxlIG9uIFBlbnRpdW0gSSBhbmQgbGF0ZXIuXHBhcg0KICAgICAgICAgICAg
ICAgICAgICAgbW92IGVzaSwgZGVzdFxwYXINCiAgICAgICAgICAgICAgICAgICAgIG1vdiBbZXNp
ICBdLCBlYXggICAgLy8gbG93ZXIgMzIgYml0cyBvZiB0c2NccGFyDQogICAgICAgICAgICAgICAg
ICAgICBtb3YgW2VzaSs0XSwgZWR4ICAgIC8vIHVwcGVyIDMyIGJpdHMgb2YgdHNjXHBhcg0KICAg
ICAgICAgICAgICAgICBcfVxwYXINCiAgICAgICAgICAgICAgICAgcmV0dXJuIDE7XHBhcg0KICAg
ICAgICAgICAgIFx9XHBhcg0KICAgICAgICAgICAgIF9fZXhjZXB0KEVYQ0VQVElPTl9FWEVDVVRF
X0hBTkRMRVIpXHBhcg0KICAgICAgICAgICAgIFx7XHBhcg0KICAgICAgICAgICAgICAgICByZXR1
cm4gMDtccGFyDQogICAgICAgICAgICAgXH1ccGFyDQpccGFyDQogICAgICAgICAgICAgcmV0dXJu
IDA7XHBhcg0KICAgICAgICAgXH1ccGFyDQpccGFyDQpPbmNlIHlvdSBmaWd1cmUgb3V0IHRoZSBm
cmVxdWVuY3ksIHVzaW5nIHRoaXMgMS1zZWNvbmQgdGVzdCwgeW91IGNhbiBub3dccGFyDQp0cmFu
c2xhdGUgcmVhZGluZ3MgZnJvbSB0aGUgY3B1J3MgdGltZXN0YW1wIGNvdW50ZXIgZGlyZWN0bHkg
aW50byBhIHJlYWxccGFyDQondGltZScgcmVhZGluZywgaW4gc2Vjb25kczpccGFyDQpccGFyDQog
ICAgICAgICBkb3VibGUgR2V0UGVudGl1bVRpbWVBc0RvdWJsZSh1bnNpZ25lZCBfX2ludDY0IGZy
ZXF1ZW5jeSlccGFyDQogICAgICAgICBce1xwYXINCiAgICAgICAgICAgICAvLyByZXR1cm5zIDwg
MCBvbiBmYWlsdXJlOyBvdGhlcndpc2UsIHJldHVybnMgY3VycmVudCBjcHUgXHBhcg0KdGltZSwg
aW4gc2Vjb25kcy5ccGFyDQogICAgICAgICAgICAgLy8gd2FybmluZzogd2F0Y2ggb3V0IGZvciB3
cmFwYXJvdW5kIVxwYXINClxwYXINCiAgICAgICAgICAgICBpZiAoZnJlcXVlbmN5PT0wKVxwYXIN
CiAgICAgICAgICAgICAgICAgcmV0dXJuIC0xLjA7XHBhcg0KXHBhcg0KICAgICAgICAgICAgIC8v
IGdldCBoaWdoLXByZWNpc2lvbiB0aW1lOlxwYXINCiAgICAgICAgICAgICBfX3RyeVxwYXINCiAg
ICAgICAgICAgICBce1xwYXINCiAgICAgICAgICAgICAgICAgdW5zaWduZWQgX19pbnQ2NCBoaWdo
X3BlcmZfdGltZTtccGFyDQogICAgICAgICAgICAgICAgIHVuc2lnbmVkIF9faW50NjQgKmRlc3Qg
PSAmaGlnaF9wZXJmX3RpbWU7XHBhcg0KICAgICAgICAgICAgICAgICBfX2FzbVxwYXINCiAgICAg
ICAgICAgICAgICAgXHtccGFyDQogICAgICAgICAgICAgICAgICAgICBfZW1pdCAweGYgICAgICAg
IC8vIHRoZXNlIHR3byBieXRlcyBmb3JtIHRoZSBccGFyDQoncmR0c2MnIGFzbSBpbnN0cnVjdGlv
bixccGFyDQogICAgICAgICAgICAgICAgICAgICBfZW1pdCAweDMxICAgICAgIC8vICBhdmFpbGFi
bGUgb24gUGVudGl1bSBJIGFuZCBsYXRlci5ccGFyDQogICAgICAgICAgICAgICAgICAgICBtb3Yg
ZXNpLCBkZXN0XHBhcg0KICAgICAgICAgICAgICAgICAgICAgbW92IFtlc2kgIF0sIGVheCAgICAv
LyBsb3dlciAzMiBiaXRzIG9mIHRzY1xwYXINCiAgICAgICAgICAgICAgICAgICAgIG1vdiBbZXNp
KzRdLCBlZHggICAgLy8gdXBwZXIgMzIgYml0cyBvZiB0c2NccGFyDQogICAgICAgICAgICAgICAg
IFx9XHBhcg0KICAgICAgICAgICAgICAgICBfX2ludDY0IHRpbWVfcyAgICAgPSAoX19pbnQ2NCko
aGlnaF9wZXJmX3RpbWUgLyBccGFyDQpmcmVxdWVuY3kpOyAgLy8gdW5zaWduZWQtPnNpZ24gY29u
dmVyc2lvbiBzaG91bGQgYmUgc2FmZSBoZXJlXHBhcg0KICAgICAgICAgICAgICAgICBfX2ludDY0
IHRpbWVfZnJhY3QgPSAoX19pbnQ2NCkoaGlnaF9wZXJmX3RpbWUgJSBccGFyDQpmcmVxdWVuY3kp
OyAgLy8gdW5zaWduZWQtPnNpZ24gY29udmVyc2lvbiBzaG91bGQgYmUgc2FmZSBoZXJlXHBhcg0K
ICAgICAgICAgICAgICAgICAvLyBub3RlOiBoZXJlLCB3ZSB3cmFwIHRoZSB0aW1lciBtb3JlIGZy
ZXF1ZW50bHkgKG9uY2UgXHBhcg0KcGVyIHdlZWspXHBhcg0KICAgICAgICAgICAgICAgICAvLyB0
aGFuIGl0IG90aGVyd2lzZSB3b3VsZCAoVkVSWSBSQVJFTFkgLSBvbmNlIGV2ZXJ5IFxwYXINCjU4
NSB5ZWFycyBvblxwYXINCiAgICAgICAgICAgICAgICAgLy8gYSAxIEdIeiksIHRvIGFsbGV2aWF0
ZSBmbG9hdGluZy1wb2ludCBwcmVjaXNpb24gXHBhcg0KZXJyb3JzIHRoYXQgc3RhcnRccGFyDQog
ICAgICAgICAgICAgICAgIC8vIHRvIG9jY3VyIHdoZW4geW91IGdldCB0byB2ZXJ5IGhpZ2ggY291
bnRlciB2YWx1ZXMuXHBhcg0KICAgICAgICAgICAgICAgICBkb3VibGUgcmV0ID0gKHRpbWVfcyAl
ICg2MCo2MCoyNCo3KSkgKyBccGFyDQooZG91YmxlKXRpbWVfZnJhY3QvKGRvdWJsZSkoKF9faW50
NjQpZnJlcXVlbmN5KTtccGFyDQogICAgICAgICAgICAgICAgIHJldHVybiByZXQ7XHBhcg0KICAg
ICAgICAgICAgIFx9XHBhcg0KICAgICAgICAgICAgIF9fZXhjZXB0KEVYQ0VQVElPTl9FWEVDVVRF
X0hBTkRMRVIpXHBhcg0KICAgICAgICAgICAgIFx7XHBhcg0KICAgICAgICAgICAgICAgICByZXR1
cm4gLTEuMDtccGFyDQogICAgICAgICAgICAgXH1ccGFyDQpccGFyDQogICAgICAgICAgICAgcmV0
dXJuIC0xLjA7XHBhcg0KICAgICAgICAgXH1ccGFyDQpccGFyDQpUaGlzIHdvcmtzIHByZXR0eSB3
ZWxsLCB3b3JrcyBvbiBBTEwgUGVudGl1bSBJIGFuZCBsYXRlciBwcm9jZXNzb3JzLCBhbmQgXHBh
cg0Kb2ZmZXJzXHBhcg0KQU1BWklORyBwcmVjaXNpb24uICBIb3dldmVyLCBpdCBjYW4gYmUgbWVz
c3ksIGVzcGVjaWFsbHkgd29ya2luZyB0aGF0IFxwYXINCjEtc2Vjb25kXHBhcg0KdGVzdCBpbiB0
aGVyZSB3aXRoIGFsbCB5b3VyIG90aGVyIGNvZGUsIHNvIHRoYXQgaXQgcnVucyBpbiB0aGUgYmFj
a2dyb3VuZC5ccGFyDQpccGFyDQpccGFyDQpRdWVyeVBlcmZvcm1hbmNlRnJlcXVlbmN5ICYgUXVl
cnlQZXJmb3JtYW5jZUNvdW50ZXI6IE5pY2VccGFyDQpccGFyDQpUaGVyZSBpcyBvbmUgbW9yZSBp
dGVtIGluIG91ciBiYWcgb2YgdHJpY2tzLiAgSXQgaXMgc2ltcGxlLCBlbGVnYW50LCBhbmQgXHBh
cg0KYXMgZmFyXHBhcg0KYXMgSSBjYW4gdGVsbCwgZXh0cmVtZWx5IGFjY3VyYXRlIGFuZCByZWxp
YWJsZS4gIEl0IGlzIGEgcGFpciBvZiB3aW4zMiBccGFyDQpmdW5jdGlvbnM6XHBhcg0KUXVlcnlQ
ZXJmb3JtYW5jZUZyZXF1ZW5jeSBhbmQgUXVlcnlQZXJmb3JtYW5jZUNvdW50ZXIuXHBhcg0KXHBh
cg0KUXVlcnlQZXJmb3JtYW5jZUZyZXF1ZW5jeSByZXR1cm5zIHRoZSBhbW91bnQgdGhhdCB0aGUg
Y291bnRlciB3aWxsIFxwYXINCmluY3JlbWVudCBvdmVyXHBhcg0KMSBzZWNvbmQ7IFF1ZXJ5UGVy
Zm9ybWFuY2VDb3VudGVyIHJldHVybnMgYSBMQVJHRV9JTlRFR0VSIChhIDY0LWJpdCBccGFyDQoq
c2lnbmVkKiBpbnRlZ2VyKVxwYXINCnRoYXQgaXMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGNv
dW50ZXIuXHBhcg0KXHBhcg0KUGVyaGFwcyBJIGFtIGx1Y2t5LCBidXQgaXQgd29ya3MgZmxhd2xl
c3NseSBvbiBteSAzIG1hY2hpbmVzLiAgVGhlIE1TRE4gXHBhcg0KbGlicmFyeVxwYXINCnNheXMg
dGhhdCBpdCBzaG91bGQgd29yayBvbiBXaW5kb3dzIDk1IGFuZCBsYXRlci5ccGFyDQpccGFyDQpI
ZXJlIGFyZSBzb21lIHJlc3VsdHM6XHBhcg0KXHBhcg0KICAgICAgICAgICAgICAgUmV0dXJuIHZh
bHVlIG9mIFF1ZXJ5UGVyZm9ybWFuY2VGcmVxdWVuY3lccGFyDQogICAgIEdlbWluaTogICAzLDU3
OSw1NDUgSHpccGFyDQogICAgIFZhaW86ICAgICAxLDE5MywwMDAgSHpccGFyDQogICAgIEhQOiAg
ICAgICAzLDU3OSw1NDUgSHpccGFyDQpccGFyDQogICAgICAgICAgICAgICBNYXhpbXVtICMgb2Yg
dW5pcXVlIHJlYWRpbmdzIEkgY291bGQgZ2V0IGluIDEgc2Vjb25kXHBhcg0KICAgICBHZW1pbmk6
ICAgNjU4LDAwMCAgKC0+IDEuNTIgdXMgcmVzb2x1dGlvbiEpXHBhcg0KICAgICBWYWlvOiAgICAg
MTc0LDMwMCAgKC0+IDUuNzMgdXMgcmVzb2x1dGlvbiEpXHBhcg0KICAgICBIUDogICAgICAgNjE3
LDAwMCAgKC0+IDEuNjIgdXMgcmVzb2x1dGlvbiEpXHBhcg0KXHBhcg0KSSB3YXMgcHJldHR5IGV4
Y2l0ZWQgdG8gc2VlIHRpbWluZyByZXNvbHV0aW9ucyBpbiB0aGUgbG93LW1pY3Jvc2Vjb25kXHBh
cg0KcmFuZ2UuICBOb3RlIHRoYXQgZm9yIHRoZSBsYXR0ZXIgdGVzdCwgSSBhdm9pZGVkIHByaW50
aW5nIGFueSB0ZXh0XHBhcg0KZHVyaW5nIHRoZSAxLXNlY29uZCBpbnRlcnZhbCwgYXMgaXQgd291
bGQgZHJhc3RpY2FsbHkgYWZmZWN0IHRoZSBvdXRjb21lLlxwYXINClxwYXINCk5vdywgaGVyZSBp
cyBteSBxdWVzdGlvbiB0byB5b3U6IGRvIHRoZXNlIHR3byBmdW5jdGlvbnMgd29yayBmb3IgeW91
P1xwYXINCldoYXQgT1MgZG9lcyB0aGUgY29tcHV0ZXIgcnVuLCB3aGF0IGlzIHRoZSBNSHogcmF0
aW5nLCBhbmQgaXMgaXQgYSBsYXB0b3BccGFyDQpvciBkZXNrdG9wPyAgV2hhdCB3YXMgdGhlIHJl
c3VsdCBvZiBRdWVyeVBlcmZvcm1hbmNlRnJlcXVlbmN5P1xwYXINCldoYXQgd2FzIHRoZSBtYXgu
ICMgb2YgdW5pcXVlIHJlYWRpbmdzIHlvdSBjb3VsZCBnZXQgaW4gMSBzZWNvbmQ/XHBhcg0KQ2Fu
IHlvdSBmaW5kIGFueSBjb21wdXRlcnMgdGhhdCBpdCBkb2Vzbid0IHdvcmsgb24/ICBMZXQgbWUg
a25vdyBccGFyDQooZS1tYWlsOiApLCBhbmRccGFyDQpJJ2xsIGNvbGxlY3QgJiBwdWJsaXNoIGV2
ZXJ5b25lJ3MgcmVzdWx0cyBoZXJlLlxwYXINClxwYXINClNvLCB1bnRpbCBJIGZpbmQgc29tZSBj
b21wdXRlcnMgdGhhdCBRdWVyeVBlcmZvcm1hbmNlRnJlcXVlbmN5ICZccGFyDQpRdWVyeVBlcmZv
cm1hbmNlQ291bnRlciBkb24ndCB3b3JrIG9uLCBJJ20gc3RpY2tpbmcgd2l0aCB0aGVtLiAgSWYg
dGhleSBccGFyDQpmYWlsLFxwYXINCkkndmUgZ290IGJhY2t1cCBjb2RlIHRoYXQgd2lsbCBraWNr
IGluLCB3aGljaCB1c2VzIHRpbWVHZXRUaW1lKCk7IEkgZGlkbid0XHBhcg0KYm90aGVyIHRvIHVz
ZSBSRFRTQyBiZWNhdXNlIG9mIHRoZSBjYWxpYnJhdGlvbiBpc3N1ZSwgYW5kIEknbSBob3BlZnVs
IHRoYXRccGFyDQp0aGVzZSB0d28gZnVuY3Rpb25zIGFyZSBoaWdobHkgcmVsaWFibGUuICBJIHN1
cHBvc2Ugb25seSBmZWVkYmFjayBmcm9tXHBhcg0KcmVhZGVycyBsaWtlIHlvdSB3aWxsIHRlbGwu
Li4gPSlccGFyDQpccGFyDQpccGFyDQpBY2N1cmF0ZSBGUFMgTGltaXRpbmcgLyBIaWdoLXByZWNp
c2lvbiAnU2xlZXBzJ1xwYXINClxwYXINClNvIG5vdywgd2hlbiBJIG5lZWQgdG8gZG8gRlBTIGxp
bWl0aW5nIChsaW1pdGluZyB0aGUgZnJhbWVyYXRlIHRvIHNvbWVccGFyDQptYXhpbXVtKSwgSSBk
b24ndCBqdXN0IG5haXZlbHkgY2FsbCBTbGVlcCgpIGFueW1vcmUuICBJbnN0ZWFkLCBJIHVzZVxw
YXINClF1ZXJ5UGVyZm9ybWFuY2VDb3VudGVyIGluIGEgbG9vcCB0aGF0IHJ1bnMgU2xlZXAoMCku
ICBTbGVlcCgwKSBzaW1wbHlccGFyDQpnaXZlcyB1cCB5b3VyIHRocmVhZCdzIGN1cnJlbnQgdGlt
ZXNsaWNlIHRvIGFub3RoZXIgd2FpdGluZyB0aHJlYWQ7IGl0XHBhcg0KZG9lc24ndCByZWFsbHkg
c2xlZXAgYXQgYWxsLiAgU28sIGlmIHlvdSBqdXN0IGtlZXAgY2FsbGluZyBTbGVlcCgwKVxwYXIN
CmluIGEgbG9vcCB1bnRpbCBRdWVyeVBlcmZvcm1hbmNlQ291bnRlcigpIHNheXMgeW91J3ZlIGhp
dCB0aGUgcmlnaHQgdGltZSxccGFyDQp5b3UnbGwgZ2V0IHVsdHJhLWFjY3VyYXRlIEZQUyByZWFk
aW5ncy5ccGFyDQpccGFyDQpUaGVyZSBpcyBvbmUgcHJvYmxlbSB3aXRoIHRoaXMga2luZCBvZiBm
cHMgbGltaXRpbmc6IGl0IHdpbGwgdXNlIHVwXHBhcg0KMTAwJSBvZiB0aGUgQ1BVLiAgRXZlbiB0
aG91Z2ggdGhlIGNvbXB1dGVyIFdJTEwgcmVtYWluXHBhcg0KcXVpdGUgcmVzcG9uc2l2ZSwgYmVj
YXVzZSB0aGUgYXBwIHN1Y2tpbmcgdXAgdGhlIGlkbGUgdGltZSBpcyBiZWluZyB2ZXJ5XHBhcg0K
Im5pY2UiLCB0aGlzIHdpbGwgc3RpbGwgbG9vayB2ZXJ5IGJhZCBvbiB0aGUgQ1BVIG1ldGVyICh3
aGljaCB3aWxsIHN0YXlccGFyDQphdCAxMDAlKSBhbmQsIG11Y2ggd29yc2UsIGl0IHdpbGwgZHJh
aW4gdGhlIGJhdHRlcnkgcXVpdGUgcXVpY2tseSBvblxwYXINCmxhcHRvcHMuXHBhcg0KXHBhcg0K
VG8gZ2V0IGFyb3VuZCB0aGlzLCBJIHVzZSBhIGh5YnJpZCBhbGdvcml0aG0gdGhhdCB1c2VzIFNs
ZWVwKCkgdG8gZG8gdGhlXHBhcg0KYnVsayBvZiB0aGUgd2FpdGluZywgYW5kIFF1ZXJ5UGVyZm9y
bWFuY2VDb3VudGVyKCkgdG8gZG8gdGhlIGZpbmlzaGluZ1xwYXINCnRvdWNoZXMsIG1ha2luZyBp
dCBhY2N1cmF0ZSB0byB+MTAgbWljcm9zZWNvbmRzLCBidXQgc3RpbGwgd2FzdGluZyB2ZXJ5XHBh
cg0KbGl0dGxlIHByb2Nlc3Nvci5ccGFyDQpccGFyDQpNeSBjb2RlIGZvciBhY2N1cmF0ZSBGUFMg
bGltaXRpbmcgbG9va3Mgc29tZXRoaW5nIGxpa2UgdGhpcywgYW5kIHJ1bnNccGFyDQphdCB0aGUg
ZW5kIG9mIGVhY2ggZnJhbWUsIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBwYWdlIGZsaXA6XHBhcg0K
XHBhcg0KXHBhcg0KICAgICAgICAgLy8gbm90ZTogQkUgU1VSRSBZT1UgQ0FMTCB0aW1lQmVnaW5Q
ZXJpb2QoMSkgYXQgcHJvZ3JhbSBzdGFydHVwISEhXHBhcg0KICAgICAgICAgLy8gbm90ZTogQkUg
U1VSRSBZT1UgQ0FMTCB0aW1lRW5kUGVyaW9kKDEpIGF0IHByb2dyYW0gZXhpdCEhIVxwYXINCiAg
ICAgICAgIC8vIG5vdGU6IHRoYXQgd2lsbCByZXF1aXJlIGxpbmtpbmcgdG8gd2lubW0ubGliXHBh
cg0KICAgICAgICAgLy8gbm90ZTogbmV2ZXIgdXNlIHN0YXRpYyBpbml0aWFsaXplcnMgKGxpa2Ug
dGhpcykgd2l0aCBXaW5hbXAgXHBhcg0KcGx1Zy1pbnMhXHBhcg0KICAgICAgICAgc3RhdGljIExB
UkdFX0lOVEVHRVIgbV9wcmV2X2VuZF9vZl9mcmFtZSA9IDA7XHBhcg0KICAgICAgICAgaW50IG1h
eF9mcHMgPSA2MDtccGFyDQpccGFyDQogICAgICAgICBMQVJHRV9JTlRFR0VSIHQ7XHBhcg0KICAg
ICAgICAgUXVlcnlQZXJmb3JtYW5jZUNvdW50ZXIoJnQpO1xwYXINClxwYXINCiAgICAgICAgIGlm
IChtX3ByZXZfZW5kX29mX2ZyYW1lLlF1YWRQYXJ0ICE9IDApXHBhcg0KICAgICAgICAgXHtccGFy
DQogICAgICAgICAgICAgaW50IHRpY2tzX3RvX3dhaXQgPSAoaW50KW1faGlnaF9wZXJmX3RpbWVy
X2ZyZXEuUXVhZFBhcnQgLyBccGFyDQptYXhfZnBzO1xwYXINCiAgICAgICAgICAgICBpbnQgZG9u
ZSA9IDA7XHBhcg0KICAgICAgICAgICAgIGRvXHBhcg0KICAgICAgICAgICAgIFx7XHBhcg0KICAg
ICAgICAgICAgICAgICBRdWVyeVBlcmZvcm1hbmNlQ291bnRlcigmdCk7XHBhcg0KXHBhcg0KICAg
ICAgICAgICAgICAgICBpbnQgdGlja3NfcGFzc2VkID0gKGludCkoKF9faW50NjQpdC5RdWFkUGFy
dCAtIFxwYXINCihfX2ludDY0KW1fcHJldl9lbmRfb2ZfZnJhbWUuUXVhZFBhcnQpO1xwYXINCiAg
ICAgICAgICAgICAgICAgaW50IHRpY2tzX2xlZnQgPSB0aWNrc190b193YWl0IC0gdGlja3NfcGFz
c2VkO1xwYXINClxwYXINCiAgICAgICAgICAgICAgICAgaWYgKHQuUXVhZFBhcnQgPCBtX3ByZXZf
ZW5kX29mX2ZyYW1lLlF1YWRQYXJ0KSAgICAvLyBccGFyDQp0aW1lIHdyYXBccGFyDQogICAgICAg
ICAgICAgICAgICAgICBkb25lID0gMTtccGFyDQogICAgICAgICAgICAgICAgIGlmICh0aWNrc19w
YXNzZWQgPj0gdGlja3NfdG9fd2FpdClccGFyDQogICAgICAgICAgICAgICAgICAgICBkb25lID0g
MTtccGFyDQpccGFyDQogICAgICAgICAgICAgICAgIGlmICghZG9uZSlccGFyDQogICAgICAgICAg
ICAgICAgIFx7XHBhcg0KICAgICAgICAgICAgICAgICAgICAgLy8gaWYgPiAwLjAwMnMgbGVmdCwg
ZG8gU2xlZXAoMSksIHdoaWNoIHdpbGwgXHBhcg0KYWN0dWFsbHkgc2xlZXAgc29tZVxwYXINCiAg
ICAgICAgICAgICAgICAgICAgIC8vICAgc3RlYWR5IGFtb3VudCwgcHJvYmFibHkgMS0yIG1zLFxw
YXINCiAgICAgICAgICAgICAgICAgICAgIC8vICAgYW5kIGRvIHNvIGluIGEgbmljZSB3YXkgKGNw
dSBtZXRlciBkcm9wczsgXHBhcg0KbGFwdG9wIGJhdHRlcnkgc3BhcmVkKS5ccGFyDQogICAgICAg
ICAgICAgICAgICAgICAvLyBvdGhlcndpc2UsIGRvIGEgZmV3IFNsZWVwKDApJ3MsIHdoaWNoIGp1
c3QgZ2l2ZSBccGFyDQp1cCB0aGUgdGltZXNsaWNlLFxwYXINCiAgICAgICAgICAgICAgICAgICAg
IC8vICAgYnV0IGRvbid0IHJlYWxseSBzYXZlIGNwdSBvciBiYXR0ZXJ5LCBidXQgZG8gXHBhcg0K
cGFzcyBhIHRpbnlccGFyDQogICAgICAgICAgICAgICAgICAgICAvLyAgIGFtb3VudCBvZiB0aW1l
LlxwYXINCiAgICAgICAgICAgICAgICAgICAgIGlmICh0aWNrc19sZWZ0ID4gXHBhcg0KKGludClt
X2hpZ2hfcGVyZl90aW1lcl9mcmVxLlF1YWRQYXJ0KjIvMTAwMClccGFyDQogICAgICAgICAgICAg
ICAgICAgICAgICAgU2xlZXAoMSk7XHBhcg0KICAgICAgICAgICAgICAgICAgICAgZWxzZVxwYXIN
CiAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpPTA7IGk8MTA7IGkrKylccGFyDQog
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNsZWVwKDApOyAgLy8gY2F1c2VzIHRocmVhZCB0
byBnaXZlIHVwIGl0cyBccGFyDQp0aW1lc2xpY2VccGFyDQogICAgICAgICAgICAgICAgIFx9XHBh
cg0KICAgICAgICAgICAgIFx9XHBhcg0KICAgICAgICAgICAgIHdoaWxlICghZG9uZSk7XHBhcg0K
ICAgICAgICAgXH1ccGFyDQpccGFyDQogICAgICAgICBtX3ByZXZfZW5kX29mX2ZyYW1lID0gdDtc
cGFyDQpccGFyDQouLi53aGljaCBpcyB0cml2aWFsIHRvIGNvbnZlcnQgdGhpcyBpbnRvIGEgaGln
aC1wcmVjaXNpb24gU2xlZXAoKSBmdW5jdGlvbi5ccGFyDQpccGFyDQpccGFyDQpDb25jbHVzaW9u
cyAmIFN1bW1hcnlccGFyDQpccGFyDQpVc2luZyByZWd1bGFyIG9sZCB0aW1lR2V0VGltZSgpIHRv
IGRvIHRpbWluZyBpcyBub3QgcmVsaWFibGUgb24gbWFueSBccGFyDQpXaW5kb3dzLWJhc2VkXHBh
cg0Kb3BlcmF0aW5nIHN5c3RlbXMgYmVjYXVzZSB0aGUgZ3JhbnVsYXJpdHkgb2YgdGhlIHN5c3Rl
bSB0aW1lciBjYW4gYmUgYXMgXHBhcg0KaGlnaCBhcyAxMC0xNVxwYXINCm1pbGxpc2Vjb25kcywg
bWVhbmluZyB0aGF0IHRpbWVHZXRUaW1lKCkgaXMgb25seSBhY2N1cmF0ZSB0byAxMC0xNSBccGFy
DQptaWxsaXNlY29uZHMuXHBhcg0KW05vdGUgdGhhdCB0aGUgaGlnaCBncmFudWxhcml0aWVzIG9j
Y3VyIG9uIE5ULWJhc2VkIG9wZXJhdGlvbiBzeXN0ZW1zIFxwYXINCmxpa2UgV2luZG93cyBOVCxc
cGFyDQoyMDAwLCBhbmQgWFAuICBXaW5kb3dzIDk1IGFuZCA5OCB0ZW5kIHRvIGhhdmUgbXVjaCBi
ZXR0ZXIgZ3JhbnVsYXJpdHksIFxwYXINCmFyb3VuZCAxLTUgbXMuXVxwYXINClxwYXINCkhvd2V2
ZXIsIGlmIHlvdSBjYWxsIHRpbWVCZWdpblBlcmlvZCgxKSBhdCB0aGUgYmVnaW5uaW5nIG9mIHlv
dXIgcHJvZ3JhbSBccGFyDQooYW5kXHBhcg0KdGltZUVuZFBlcmlvZCgxKSBhdCB0aGUgZW5kKSwg
dGltZUdldFRpbWUoKSB3aWxsIHVzdWFsbHkgYmVjb21lIGFjY3VyYXRlIFxwYXINCnRvIDEtMlxw
YXINCm1pbGxpc2Vjb25kcywgYW5kIHdpbGwgcHJvdmlkZSB5b3Ugd2l0aCBleHRyZW1lbHkgYWNj
dXJhdGUgdGltaW5nIFxwYXINCmluZm9ybWF0aW9uLlxwYXINClxwYXINClNsZWVwKCkgYmVoYXZl
cyBzaW1pbGFybHk7IHRoZSBsZW5ndGggb2YgdGltZSB0aGF0IFNsZWVwKCkgYWN0dWFsbHkgXHBh
cg0Kc2xlZXBzIGZvclxwYXINCmdvZXMgaGFuZC1pbi1oYW5kIHdpdGggdGhlIGdyYW51bGFyaXR5
IG9mIHRpbWVHZXRUaW1lKCksIHNvIGFmdGVyIGNhbGxpbmdccGFyDQp0aW1lQmVnaW5QZXJpb2Qo
MSkgb25jZSwgU2xlZXAoMSkgd2lsbCBhY3R1YWxseSBzbGVlcCBmb3IgMS0yIFxwYXINCm1pbGxp
c2Vjb25kcywgU2xlZXAoMilccGFyDQpmb3IgMi0zLCBhbmQgc28gb24gKGluc3RlYWQgb2Ygc2xl
ZXBpbmcgaW4gaW5jcmVtZW50cyBhcyBoaWdoIGFzIDEwLTE1IG1zKS5ccGFyDQpccGFyDQpGb3Ig
aGlnaGVyIHByZWNpc2lvbiB0aW1pbmcgKHN1Yi1taWxsaXNlY29uZCBhY2N1cmFjeSksIHlvdSds
bCBwcm9iYWJseSBccGFyDQp3YW50IHRvIGF2b2lkXHBhcg0KdXNpbmcgdGhlIGFzc2VtYmx5IG1u
ZW1vbmljIFJEVFNDIGJlY2F1c2UgaXQgaXMgaGFyZCB0byBjYWxpYnJhdGU7IFxwYXINCmluc3Rl
YWQsIHVzZVxwYXINClF1ZXJ5UGVyZm9ybWFuY2VGcmVxdWVuY3kgYW5kIFF1ZXJ5UGVyZm9ybWFu
Y2VDb3VudGVyLCB3aGljaCBhcmUgXHBhcg0KYWNjdXJhdGUgdG8gbGVzc1xwYXINCnRoYW4gMTAg
bWljcm9zZWNvbmRzICgwLjAwMDAxIHNlY29uZHMpLlxwYXINClxwYXINCkZvciBzaW1wbGUgdGlt
aW5nLCBib3RoIHRpbWVHZXRUaW1lIGFuZCBRdWVyeVBlcmZvcm1hbmNlQ291bnRlciB3b3JrIFxw
YXINCndlbGwsIGFuZFxwYXINClF1ZXJ5UGVyZm9ybWFuY2VDb3VudGVyIGlzIG9idmlvdXNseSBt
b3JlIGFjY3VyYXRlLiAgSG93ZXZlciwgaWYgeW91IFxwYXINCm5lZWQgdG8gZG9ccGFyDQphbnkg
a2luZCBvZiAidGltZWQgcGF1c2VzIiAoc3VjaCBhcyB0aG9zZSBuZWNlc3NhcnkgZm9yIGZyYW1l
cmF0ZSBccGFyDQpsaW1pdGluZyksIHlvdVxwYXINCm5lZWQgdG8gYmUgY2FyZWZ1bCBvZiBzaXR0
aW5nIGluIGEgbG9vcCBjYWxsaW5nIFF1ZXJ5UGVyZm9ybWFuY2VDb3VudGVyLCBccGFyDQp3YWl0
aW5nXHBhcg0KZm9yIGl0IHRvIHJlYWNoIGEgY2VydGFpbiB2YWx1ZTsgdGhpcyB3aWxsIGVhdCB1
cCAxMDAlIG9mIHlvdXIgXHBhcg0KcHJvY2Vzc29yLiAgSW5zdGVhZCxccGFyDQpjb25zaWRlciBh
IGh5YnJpZCBzY2hlbWUsIHdoZXJlIHlvdSBjYWxsIFNsZWVwKDEpIChkb24ndCBmb3JnZXQgXHBh
cg0KdGltZUJlZ2luUGVyaW9kKDEpXHBhcg0KZmlyc3QhKSB3aGVuZXZlciB5b3UgbmVlZCB0byBw
YXNzIG1vcmUgdGhhbiAxIG1zIG9mIHRpbWUsIGFuZCB0aGVuIG9ubHkgXHBhcg0KZW50ZXIgdGhl
XHBhcg0KUXVlcnlQZXJmb3JtYW5jZUNvdW50ZXIgMTAwJS1idXN5IGxvb3AgdG8gZmluaXNoIG9m
ZiB0aGUgbGFzdCA8IDEvMTAwMHRoIFxwYXINCm9mIGFccGFyDQpzZWNvbmQgb2YgdGhlIGRlbGF5
IHlvdSBuZWVkLiAgVGhpcyB3aWxsIGdpdmUgeW91IHVsdHJhLWFjY3VyYXRlIGRlbGF5cyBccGFy
DQooYWNjdXJhdGVccGFyDQp0byAxMCBtaWNyb3NlY29uZHMpLCB3aXRoIHZlcnkgbWluaW1hbCBD
UFUgdXNhZ2UuICBTZWUgdGhlIGNvZGUgYWJvdmUuXHBhcg0KXHBhcg0KXHBhcg0KXHBhcg0KVVBE
QVRFOiBhIGZldyBwZW9wbGUgaGF2ZSB3cml0dGVuIGUtbWFpbCBwb2ludGluZyBtZSB0byB0aGlz
IE1pY3Jvc29mdCBccGFyDQpLbm93bGVkZ2VccGFyDQpCYXNlIGFydGljbGUgd2hpY2ggb3V0bGlu
ZXMgc29tZSBjYXNlcyBpbiB3aGljaCB0aGUgUXVlcnlQZXJmb3JtYW5jZUNvdW50ZXJccGFyDQpm
dW5jdGlvbiBjYW4gdW5leHBlY3RlZGx5IGp1bXAgZm9yd2FyZCBieSBhIGZldyBzZWNvbmRzLlxw
YXINClxwYXINClVQREFURTogUm9zcyBCZW5jaW5hIHdhcyBraW5kIGVub3VnaCB0byBwb2ludCBv
dXQgdG8gbWUgdGhhdCByZHRzYyAiaXMgYSBccGFyDQpwZXItY3B1XHBhcg0Kb3BlcmF0aW9uLCBz
byBvbiBtdWx0aXByb2Nlc3NvciBzeXN0ZW1zIHlvdSBoYXZlIHRvIGJlIGNhcmVmdWwgdGhhdCBc
cGFyDQptdWx0aXBsZSBjYWxsc1xwYXINCnRvIHJkdHNjIGFyZSBhY3R1YWxseSBleGVjdXRpbmcg
b24gdGhlIHNhbWUgY3B1LiIgIFRoYW5rcyBSb3NzIVxwYXINClxwYXINClxwYXINClxwYXINClxw
YXINClRoaXMgZG9jdW1lbnQgY29weXJpZ2h0IChjKTIwMDIrIFJ5YW4gTS4gR2Vpc3MuXHBhcg0K
XHBhcg0KUmV0dXJuIHRvIGZhcSBwYWdlXHBhcg0KXHBhcg0KLS0tIEJsYWNrQm94XHBhcg0KLS0t
IHNlbmQgc3ViamVjdCBIRUxQIG9yIFVOU1VCU0NSSUJFIHRvIGJsYWNrYm94QG9iZXJvbi5jaH19
ACAgIGlmICh0aWM=


----boundary-LibPST-iamunique-1421877144_-_---
Received on Thu Apr 21 2005 - 20:19:16 UTC

This archive was generated by hypermail 2.3.0 : Thu Sep 26 2013 - 06:28:17 UTC