library(xts)
library(zoo)

1. Introduction to eXtensible Time Series, using xts and zoo for time series

Introducing xts and zoo objects - Video

What is an xts object?

There are many different types of objects in R. With a variety of different features, each has a unique purpose. Some classes inherit behavior from their parents, allowing for custom extensions to existing and well-understood R objects. This makes it easy to adapt existing code to new functionality.

It is for this reason that xts extends the popular zoo class. Knowing this, and what you have seen so far, which of these statements is true?

Possible Answers

  • xts objects are matrix objects internally.
  • xts objects are indexed by a formal time object.
  • Most zoo methods work for xts.
  • All of the above. (Correct)

More than a matrix

It is best to think of xts objects as normal R matrices, but with special powers. These powers let you manipulate your data as a function of time, as your data is now self-aware of when it exists in time. Before we can start to exploit these powers, it will be helpful to see how xts objects relate to their base-R relatives.

In this exercise, you will get a feel for xts and how it behaves like a matrix object. The xts object ex_matrix and matrix object core have been pre-loaded for you.

Instructions - Load the xts package using the library() function. - Look at the structure of the sample xts called ex_matrix using str(). - Given that ex_matrix is a matrix, extract the 3rd row and 2nd column. - Now take the matrix core and extract the 3rd row and 2nd column. Notice the difference.

# Load xts
library(xts)

# View the structure of ex_matrix
str(ex_matrix)

# Extract the 3rd observation of the 2nd column of ex_matrix
ex_matrix[3, 2]

# Extract the 3rd observation of the 2nd column of core 
core[3, 2]

Your first xts object

xts objects are simple. Think of them as a matrix of observations combined with an index of corresponding dates and times.

xts = matrix + times The main xts constructor takes a number of arguments, but the two most important are x for the data and order.by for the index. x must be a vector or matrix. order.by is a vector which must be the same length or number of rows as x, be a proper time or date object (very important!), and be in increasing order.

xts also allows you to bind arbitrary key-value attributes to your data. This lets you keep metadata about your object inside your object. To add these at creation, you simply pass additional name = value arguments to the xts() function.

Since we are focusing here on the mechanics, we’ll use random numbers as our data so we can focus on creating the object rather than worry about its contents.

Instructions - Create an object called data that contains five random numbers using rnorm(). - Create a Date class index from “2016-01-01” of length five called dates. - Use the xts constructor to create an object called smith using data and dates as the index. - Create an object called bday which contains a POSIXct date object containing the date - “1899-05-08”. - Create an xts object called hayek using data, dates, and a new attribute called born, which should contain the birthday object you just created.

# Create the object data using 5 random numbers
data <- rnorm(5)

# Create dates as a Date class object starting from 2016-01-01
dates <- seq(as.Date("2016-01-01"), length = 5, by = "days")

# Use xts() to create smith
smith <- xts(x = data, order.by = dates)

# Create bday (1899-05-08) using a POSIXct date class object
bday <- as.POSIXct("1899-05-08")

# Create hayek and add a new attribute called born
hayek <- xts(x = data, order.by = dates, born = bday)

Deconstructing xts

Now that you can create xts objects, your next task is to examine an xts object from the inside.

At the core of both xts and zoo is a simple R matrix with a few additional attributes. The most important of these attributes is the index. The index holds all the information we need for xts to treat our data as a time series.

When working with time series, it will sometimes be necessary to separate your time series into its core data and index attributes for additional analysis and manipulation. The core data is the matrix portion of xts. You can separate this from the xts object using coredata(). The index portion of the xts object is available using the index() function. Note that both of these functions are methods from the zoo class, which xts extends.

In this exercise you will use these built-in functions to extract both the internal matrix data and internal index from your sample xts object. You will use the hayek time series you created in the last exercise to practice these new functions.

Instructions - Extract the core data of hayek using coredata() and call this hayek_core. - View the class of hayek_core using the class() function. - Extract the date index of hayek using index() and call this hayek_index. - View the class of hayek_index.

# Extract the core data of hayek
hayek_core <- coredata(hayek)

# View the class of hayek_core
class(hayek_core)

# Extract the index of hayek
hayek_index <- index(hayek)

# View the class of hayek_index
class(hayek_index)

Time based indices

xts objects get their power from the index attribute that holds the time dimension. One major difference between xts and most other time series objects in R is the ability to use any one of various classes that are used to represent time. Whether POSIXct, Date, or some other class, xts will convert this into an internal form to make subsetting as natural to the user as possible.

a <- xts(x = 1:2, as.Date(“2012-01-01”) + 0:1) a[index(a)] We’ll get into more detail on subsetting xts objects in a later chapter. For now you can simply use date objects to index appropriate rows from your time series. You can think of this as effectively matching the rownames you see in the object. This works as anticipated for time objects because the rownames are really dates!

For this exercise you’ll create two time series using two different time classes. You will then subset each object using the other object’s index.

Instructions - Create an object of 5 dates called dates starting at “2016-01-01”. - Create a time series ts_a using the numbers 1 through 5 as your data, and dates as your - order.by index. - Create a time series ts_b using the numbers 1 through 5 as your data, and the same dates, but - as POSIXct objects. - Use the index from ts_b to extract the dates from ts_a. - Now do the reverse, indexing ts_b using the times from ts_a.

# Create dates
dates <- as.Date("2016-01-01") + 0:4

# Create ts_a
ts_a <- xts(x = 1:5, order.by = dates)

# Create ts_b
ts_b <- xts(x = 1:5, order.by = as.POSIXct(dates))

# Extract the rows of ts_a using the index of ts_b
ts_a[index(ts_a)]

# Extract the rows of ts_b using the index of ts_a
ts_a[index(ts_b)]

Importing, exporting and converting time series - Video

Converting xts objects

It is often necessary to convert between classes when working with time series data in R. Conversion can be required for many reasons, but typically you’ll be looking to use a function that may not be time series aware or you may want to use a particular aspect of xts with something that doesn’t necessarily need to be a full time series.

Luckily, it is quite easy to convert back and forth using the standard as.* style functionality provided in R (for example, as.POSIXct() or as.matrix()).

xts provides methods to convert all of the major objects you are likely to come across. Suitable native R types like matrix, data.frame, and ts are supported, as well as contributed ones such as timeSeries, fts and of course zoo. as.xts() is the workhorse function to do the conversions to xts, and similar functions will provide the reverse behavior.

To get a feel for moving data between classes, let’s try a few examples using the Australian population ts object from R named austres.

Instructions Convert the ts class austres data set to an xts and call it au. Then convert the new au xts object into a matrix, am. Inspect the first few entries of this new matrix by using the head() function. Convert the original austres directly into a matrix called am2. Now inspect the first few entries of this new matrix by using the same function. Notice how this time, the conversion didn’t preserve the time information?

# Convert austres to an xts object called au
au <- as.xts(austres)

# Then convert your xts object (au) into a matrix am
am <- as.matrix(au)

# Inspect the head of am
head(am)

# Convert the original austres into a matrix am2
am2 <- as.matrix(austres)

# Inspect the head of am2
head(am2)
> austres
        Qtr1    Qtr2    Qtr3    Qtr4
1971         13067.3 13130.5 13198.4
1972 13254.2 13303.7 13353.9 13409.3
1973 13459.2 13504.5 13552.6 13614.3
1974 13669.5 13722.6 13772.1 13832.0
1975 13862.6 13893.0 13926.8 13968.9
1976 14004.7 14033.1 14066.0 14110.1
1977 14155.6 14192.2 14231.7 14281.5
1978 14330.3 14359.3 14396.6 14430.8
1979 14478.4 14515.7 14554.9 14602.5
1980 14646.4 14695.4 14746.6 14807.4
1981 14874.4 14923.3 14988.7 15054.1
1982 15121.7 15184.2 15239.3 15288.9
1983 15346.2 15393.5 15439.0 15483.5
1984 15531.5 15579.4 15628.5 15677.3
1985 15736.7 15788.3 15839.7 15900.6
1986 15961.5 16018.3 16076.9 16139.0
1987 16203.0 16263.3 16327.9 16398.9
1988 16478.3 16538.2 16621.6 16697.0
1989 16777.2 16833.1 16891.6 16956.8
1990 17026.3 17085.4 17106.9 17169.4
1991 17239.4 17292.0 17354.2 17414.2
1992 17447.3 17482.6 17526.0 17568.7
1993 17627.1 17661.5

austres <- read.delim("clipboard")
# austres <- as.ts(austres)
austres

Importing data

You can now convert data to xts using as.xts(). However, in most real world applications you will often need to read raw data from files on disk or the web. This can be challenging without knowing the right commands.

In the first part of this exercise, you will start by reading a csv file from disk using the base-R read.csv. After you read the data, the next step is to convert it to xts. Here you will be required to use the xts() constructor as well as deal with converting non-standard dates into something that xts understands.

In part two of this exercise, you will read the same data into a zoo object using read.zoo and then convert the zoo object into an xts object.

The data in this exercise are quite simple, but will require some effort to properly import and clean. The full name of the file you will be working with has been saved as the value of tmp_file. On disk, the data look like:

a,b 1/02/2015, 1, 3 2/03/2015, 2, 4

Instructions

  • Read the data located at the value of tmp_file using read.csv() to a new variable called dat.
  • Convert dat into an xts object using the xts() constructor. Use as.Date() with rownames(dat) - as the first argument.
  • Create dat_zoo by using read.zoo() to read in the same tmp_file, and set the argument format - equal to “%m/%d/%Y”.
  • Create dat_xts by converting dat_zoo to xts by using as.xts().
tmp_file <- "http://s3.amazonaws.com/assets.datacamp.com/production/course_1127/datasets/tmp_file.csv"
# Create dat by reading tmp_file
dat <- read.csv(tmp_file)

# Convert dat into xts
xts(dat, order.by = as.Date(rownames(dat), "%m/%d/%Y"))

# Read tmp_file using read.zoo
dat_zoo <- read.zoo(tmp_file, index.column = 0, sep = ",", format = "%m/%d/%Y")

# Convert dat_zoo to xts
dat_xts <- as.xts(dat_zoo)

Exporting xts objects

Now that you can read raw data into xts and zoo objects, it is only natural that you learn how to reverse the process.

There are two main use cases for exporting xts objects. First, you may require an object to persist across sessions for use in later analysis. In this case, it is almost always best to use saveRDS() and readRDS() to serialize single R objects.

Alternatively, you may find yourself needing to share the results of your analysis with others, often expecting the data to be consumed by processes unaware of both R and xts. Most of us would prefer not to think of this horrible fate for our data, but the real world mandates that we at least understand how this works.

One of the best ways to write an xts object from R is to use the zoo function write.zoo(). In this exercise you’ll take your temporary data and write it to disk using write.zoo().

Instructions Convert sunspots to xts and save it as sunspots_xts. The temporary file name will be loaded for you. Using write.zoo(), save the sunspots_xts data to the tmp file. Read the tmp file back into R using read.zoo(). Call this sun. Convert sun to xts using the as.xts() function. Call this sun_xts.

data(sunspots)
class(sunspots)
# Convert sunspots to xts using as.xts().
sunspots_xts <- as.xts(sunspots)

# Get the temporary file name
tmp <- tempfile()

# Write the xts object using zoo to tmp 
write.zoo(sunspots_xts, sep = ",", file = tmp)

# Read the tmp file. FUN = as.yearmon converts strings such as Jan 1749 into a proper time class
sun <- read.zoo(tmp, sep = ",", FUN = as.yearmon)

# Convert sun into xts. Save this as sun_xts
sun_xts <- as.xts(sun)

2. First Order of Business - Basic Manipulations

Introducing time based queries - Video

The ISO-8601 standard

The ISO-8601 standard is the internationally recognized and accepted way to represent dates and times. The standard allows for a common format to not only describe dates, but also to represent ranges and repeating intervals.

xts makes use of this standard for all extract and replace operations. This makes code both easy to write and easy to maintain. It also makes for very concise expression of date ranges and intervals.

For xts to work correctly, it is very important to follow the standard exactly. Details can be found in xts subset and .parseISO8601 documentation.

Which is a valid ISO-8601 string acceptable by xts?

Possible Answers

  • “2005-01-02”
  • “200501”
  • “2010/02/22”
    1. and (2) only (Correct)
  • all of the above

Querying for dates

One of the most powerful aspects of working with time series in xts is the ability to quickly and efficiently specify dates and time ranges for subsetting.

Date ranges can be extracted from xts objects by simply specifying the period(s) you want using special character strings in your subset.

A[“20090825”] ## Aug 25, 2009 A[“201203/201212”] ## Mar to Dec 2012 A[“/201601”] ## Up to and including January 2016 For this exercise you will create a simple but very common query. Extract a range of dates using the ISO-8601 feature of xts. After successfully extracting a full year, you will then create a subset of your new object with specific start and end dates using this same notation.

Let’s find some time!

Instructions - Using xts-style time subsetting, select only the year 2016 from the x time series, and call - this x_2016. - Using an explicit start and end date string, get all data from January 1, 2016 through March - 22, 2016. Call this jan_march. - To ensure that you subset all 82 rows, use the length function.

# Select all of 2016 from x
x_2016 <- x["2016"]

# Select January 1, 2016 to March 22, 2016
jan_march <- x["20160101/20160322"]

# Verify that jan_march contains 82 rows
82 == length(jan_march)

Extracting recurring intraday intervals

The most common time series data “in the wild” is daily. On occasion, you may find yourself working with intraday data, which contains both dates and times. In this case it is sometimes necessary to view only a subset of time for each day over multiple days. Using xts, you can slice days easily by using special notation in the i = argument to the single bracket extraction (i.e. [i, j]).

As you learned in the previous exercise, the trick to this is to not specify explicit dates, but rather to use the special T/T notation designed for intraday repeating intervals.

Intraday times for all days NYSE[“T09:30/T16:00”]

In this exercise, you will extract recurring morning hours from the time series irreg, which holds irregular data from the month of January 2010. Remember, you can always use the R console to experiment with irreg or to view the help pages with ?xts.

Instructions Using the irregular time series irreg, assign all observations between 8AM and 10AM to morn_2010. Using morn_2010, extract only those observations from the morning of January 13th, 2010.

# Extract all data from irreg between 8AM and 10AM
morn_2010 <- irreg["T08:00/T10:00"]

# Extract the observations in morn_2010 for January 13th, 2010
morn_2010["20100113"]

Alternative extraction techniques - Video

Row selection with time objects

Often you may need to subset an existing time series with a set of Dates, or time-based objects. These might be from as.Date(), as.POSIXct(), or a variety of other classes. In this exercise you’ll explore how, given an xts object x, it is possible to extract relevant observations using a vector of dates in brackets.

The objects x and dates have been pre-loaded in your workspace.

Instructions - Use the vector dates to subset the object x. - Subset x using dates that are first converted to POSIXct.

# Subset x using the vector dates
x[dates]

# Subset x using dates as POSIXct
x[as.POSIXct(dates)]

Update and replace elements

Replacing values in xts objects is just as easy as extracting them. You can use either ISO-8601 strings, date objects, logicals, or integers to locate the rows you want to replace. One reason you may want to do this would be to replace known intervals or observations with NA, say due to a malfunctioning sensor on a particular day or a set of outliers given a holiday.

For individual observations located sporadically throughout your data dates, integers or logical vectors are a great choice. For continuous blocks of time, ISO-8601 is the preferred method.

In this exercise, you’ll continue using the vector dates from the previous exercise to modify your x object. Both are already loaded in your workspace.

Instructions - Use the vector dates to replace values in x with NA values. - Replace all values in x for dates (not referring to the vector) from June 9, 2016 onward with - 0. Use ISO-8601 style replacement. - Use the console to look at the value for June 11, 2016 to show that your hard work has paid off!

# Replace the values in x contained in the dates vector with NA
x[dates] <- NA

# Replace all values in x for dates starting June 9, 2016 with 0
x["2016-06-09/"] <- 0

# Verify that the value in x for June 11, 2016 is now indeed 0
x["20160611"]

Additional Methods To Find Periods in Your Data - Video

Find the first or last period of time

Sometimes you need to locate data by relative time. Something that is easier said than put into code. This is equivalent to requesting the head or tail of a series, but instead of using an absolute offset, you describe a relative position in time. A simple example would be something like the last 3 weeks of a series, or the first day of current month.

Without a time aware object, this gets quite complicated very quickly. Luckily, xts has the necessary prerequisites built in for you to use with very little learning required. Using the first() and last() functions it is actually quite easy!

For this exercise, you’ll extract relative observations from a data set called temps, a time series of summer temperature data from Chicago, IL, USA.

Instructions - Create a new variable lastweek by extracting the last 1 week from temps. - Using your newly created data, extract the last 2 observations without respect to time. - Now extract every day from lastweek except the first two days (this is tricky!).

# Create lastweek using the last 1 week of temps
lastweek <- last(temps, "1 week")

# Print the last 2 observations in lastweek
last(lastweek, 2)

# Extract all but the first two days of lastweek
first(lastweek, "-2 days")

Combining first and last

Now that you have seen how to extract the first or last chunk of a time series using natural looking language, it is only a matter of time before you need to get a bit more complex.

In this exercise, you’ll extract a very specific subset of observations by linking together multiple calls to first() and last().

# Last 3 days of first week
last(first(Temps, '1 week'), '3 days') 

You will reconfigure the example above using the temps data from the previous exercise. The trick to using such a complex command is to work from the inside function, out.

Instructions - Find the first three days of the second week of the temps data set. Use combinations of first() and last() to do this.

# Extract the first three days of the second week of temps
first(last(first(temps, "2 weeks"), "1 week"), "3 days")

Math operations in xts - Video

Matrix arithmetic - add, subtract, multiply, and divide in time!

xts objects respect time. By design when you perform any binary operation using two xts objects, these objects are first aligned using the intersection of the indexes. This may be surprising when first encountered.

The reason for this is that you want to preserve the point-in-time aspect of your data, assuring that you don’t introduce accidental look ahead (or look behind!) bias into your calculations.

What this means in practice is that you will sometimes be tasked with handling this behavior if you want to preserve the dimensions of your data.

Your options include:

Use coredata() or as.numeric() (drop one to a matrix or vector). Manually shift index values - i.e. use lag(). Reindex your data (before or after the calculation). In this exercise, you’ll look at the normal behavior, as well as an example using the first option. For now you will use two small objects a and b. Examine these objects in the console before you start.

Instructions Add a and b. Notice the behavior of the dates, which ones remain? Add a with the numeric value of b. b will need to be converted to a numeric for this to work.

# Add a and b
a+b

# Add a with the numeric value of b
a + as.numeric(b)

Math with non-overlapping indexes

The previous exercise illustrated the ins and outs of doing basic math with xts objects. At this point you are aware that xts respects time and will only return the intersection of times when doing various mathematical operations.

We alluded to another way to handle this behavior in the last exercise. Namely, re-indexing your data before an operation. This makes it possible to preserve the dimensions of your data by leveraging the same mechanism that xts uses internally in its own Ops method (the code dispatched when you call + or similar).

The third way involves modifying the two series you want by assuring you have some union of dates - the dates you require in your final output. To do this you will need a few functions that won’t be dealt with in depth until Chapter 3, but are very useful here.

merge(b, index(a)) Don’t worry if you aren’t yet familiar with merge(). This exercise may be easier if you just follow along with the instructions.

Instructions Using a and b from the previous exercise, get the value of a + b for each date in a. If no b is available on a given date, the answer should be a on that date. Now add a to b, but this time make sure all values of a are added to the last known value of b in time.

# Add a to b, and fill all missing rows of b with 0
a + merge(b, index(a), fill = 0)

# Add a to b and fill NAs with the last observation
a + merge(b, index(a), fill = na.locf)

3. Merging and modifying time series

Merging and modifying time series - Video

Combining xts by column with merge

xts makes it easy to join data by column and row using a few different functions. All results will be correctly ordered in time, regardless of original frequencies or date class. One of the most important functions to accomplish this is merge(). It takes one or more series and joins them by column. It’s also possible to combine a series with a vector of dates. This is especially useful for normalizing observations to a fixed calendar.

merge() takes three key arguments which we will emphasize here. First is the …, which lets you pass in an arbitrary number of objects to combine. The second argument is join, which specifies how to join the series - accepting arguments such as inner or left. This is similar to a relational database join, only here, the index is what we join on. The final argument for this exercise is fill. This keyword specifies what to do with the new values in a series if there is missingness introduced as a result of the merge.

# Basic argument use
merge(a, b, join = "right", fill = 9999)

For this exercise, you will explore some of the different join types to get a feel for using merge(). The objects a and b have been pre-loaded into your workspace.

Instructions - Merge a and b using merge() (or cbind()), with the argument join set to “inner”. - Perform a left-join of a and b. Use merge() and set the argument join to the correct value. Fill all missing values with zero (use the fill argument).

# Perform an inner join of a and b
merge(a, b, join = "inner")

# Perform a left-join of a and b, fill missing values with 0
merge(a, b, join = "left", fill = 0)

Merging xts objects by column comes in handy when preparing data for time series analysis.

Combining xts by row with rbind

Now that you have merged data by column, you will be happy to know it’s just as easy to add new rows to your data.

xts provides its own S3 method to the base rbind() generic function. The xts rbind function is much simpler than merge(). The only argument that matters is …, which takes an arbitrary number of objects to bind. What is different is that rbind requires a time series, since we need to have timestamps for R to know where to insert new data.

For this exercise you will update your temps data with three new observations. One will be before the series started and two will be after. Pay attention to your function call, does order matter?

In your workspace, the objects temps, temps_june30, temps_july17 and temps_july18 are already loaded.

Instructions - Bind the row from June 30th (temps_june30) to temps, and call this temps2. - Bind the rows from July 17th and 18th to temps2. Call this temps3.

# Row bind temps_june30 to temps, assign this to temps2
temps2 <- rbind(temps, temps_june30)

# Row bind temps_july17 and temps_july18 to temps2, call this temps3
temps3 <- rbind(temps_july17, temps_july18, temps2)

Because xts objects are ordered by their time index, the order of arguments in xts’s rbind() command is unimportant.

What types of data can be combined using merge?

Although xts is very flexible when it comes to binding new columns to existing objects, there are still some exceptions. Which of the following is not able to be successfully merged with the xts object a?

Before you answer, try each possibility in the console to your right to see how they behave. We’ve provided two time series, a and b for you to work with.

Possible Answers - xts objects of identical type (e.g. integer + integer). - data.frames with various column types. (Correct) - POSIXct dates vector. - Atomic vectors of the same type (e.g. numeric). - A single NA.

Handling missingness in your data - Video

Fill missing values using last or previous observation

As you’ve encountered already, it’s not uncommon to find yourself with missing values (i.e. NAs) in your time series. This may be the result of a data omission or some mathematical or merge operation you do on your data.

The xts package leverages the power of zoo for help with this. zoo provides a variety of missing data handling functions which are usable by xts.

In this exercise you will use the most basic of these, na.locf(). This function takes the last observation carried forward approach. In most circumstances this is the correct thing to do. It both preserves the last known value and prevents any look-ahead bias from entering into the data.

You can also apply next observation carried backward by setting fromLast = TRUE.

# Last obs. carried forward
na.locf(x)                

# Next obs. carried backward
na.locf(x, fromLast = TRUE) 

Instructions

  • Using a subset of temps, fill missing NA observations with the last observation known. Store - them in temps_last.
  • Using another subset of temps, backfill missing NA observations with the next observation. - Store them in temps_next.
# Fill missing values in temps using the last observation
temps_last <- na.locf(temps)  

# Fill missing values in temps using the next observation
temps_next <- na.locf(temps, fromLast=TRUE)

NA interpolation using na.approx()

On occasion, a simple carry forward approach to missingness isn’t appropriate. It may be that a series is missing an observation due to a higher frequency sampling than the generating process. You might also encounter an observation that is in error, yet expected to be somewhere between the values of its neighboring observations.

These are scenarios where interpolation is useful. zoo provides a powerful tool to do this. Based on simple linear interpolation between points, implemented with na.approx() the data points are approximated using the distance between the index values. In other words, the estimated value is linear in time.

For this exercise, you’ll use a smaller xts version of the Box and Jenkin’s AirPassengers data set that ships with R. We’ve removed a few months of data to illustrate various fill techniques.

One takeaway, aside from getting a feel for the functions, is to see how various fill techniques impact your data, and especially how it will impact your understanding of it.

Caveat Emptor!

The AirPassengers data set is available in your workspace as AirPass.

Instructions - Fill in missing months in AirPass with linear interpolation using na.approx().

# Interpolate NAs using linear approximation
na.approx(AirPass)

Linear interpolation is a straightforward way to account for missingness, although it is up to you to determine its applicability.

Lag operators and difference operations

Combine a leading and lagging time series

Another common modification for time series is the ability to lag a series. Also known as a backshift operation, it’s typically shown in literature using LkLk notation, indicating a transformation in time LkX=Xt???kLkX=Xt???k. This lets you see observations like yesterday’s value in the context of today.

Both zoo and xts implement this behavior, and in fact extend it from the ts original in R. There are two major differences between xts and zoo implementations that you need to be aware of. One is the direction of the lag for a given k. The second is how missingness is handled afterwards.

For historical reasons in R, zoo uses a convention for the sign of k in which negative values indicate lags and positive values indicate leads. That is, in zoo lag(x, k = 1) will shift future values one step back in time. This is inconsistent with the vast majority of the time series literature, but is consistent with behavior in base R. xts implements the exact opposite, namely for a positive k, the series will shift the last value in time one period forward; this is consistent with intuition, but quite different than zoo.

In this exercise, you will construct a single xts object with three columns. The first column is data one day ahead, the second column is the original data, and the third column is the one day behind - all using xts. A simple xts object, x, has been loaded into your workspace.

# Your final object
cbind(lead_x, x, lag_x)

Instructions - Create a one period lead of x called lead_x. - Create a one period lag of x called lag_x. - Using the merge() function, combine lead + x + lag into a new object z.

# Create a leading object called lead_x
lead_x <- lag(x, k = -1)

# Create a lagging object called lag_x
lag_x <- lag(x, k = 1)

# Merge your three series together and assign to z
z = cbind(lead_x, x, lag_x)

Generating leads and lags can help you visualize trends in your time series data over time.

Calculate a difference of a series using diff()

Another common operation on time series, typically on those that are non-stationary, is to take a difference of the series. The number of differences to take of a series is an application of recursively calling the difference function n times.

A simple way to view a single (or “first order”) difference is to see it as x(t) - x(t-k) where k is the number of lags to go back. Higher order differences are simply the reapplication of a difference to each prior result.

In R, the difference operator for xts is made available using the diff() command. This function takes two arguments of note. The first is the lag, which is the number of periods, and the second is differences, which is the order of the difference (e.g. how many times diff() is called).

# These are the same
diff(x, differences = 2)
diff(diff(x))

In this exercise, you will reuse the AirPass data from earlier in this chapter, though this time you will use the full series from 1948 to 1960.

Instructions

  • Construct a first order difference of AirPass by hand, using lag() and subtraction. Save this - as diff_by_hand.
  • To verify that your result is identical to using diff(AirPass), combine and inspect the first - few rows of both in your console. Use merge() and head() for this.
  • Get the first order 12 month difference of series AirPass. Be sure to specify both the lag and differences arguments in diff().
# Calculate the first difference of AirPass and assign to diff_by_hand
diff_by_hand <- AirPass - lag(AirPass, k=1)

# Use merge to compare the first parts of diff_by_hand and diff(AirPass)
merge(head(diff_by_hand), head(diff(AirPass)))

# Calculate the first order 12 month difference of AirPass
diff(AirPass, lag = 12, differences = 1)

As you can see, differencing your series is only one step more complex than generating lags and leads.

What is the key difference in lag between xts and zoo

As you’ve seen, generating lags and leads are an important tool in your arsenal for handling time series data in R. However, because xts employs slightly different procedures for generating lags and leads compared with zoo of base-R, you have to be very precise in your calls to lag().

Which of the following is FALSE?

Possible Answers - The NA observations in xts resulting from lag() are preserved. - The NA observations in zoo resulting from lag() are dropped. - The k argument in zoo uses positive values for shifting past observations forward. (Correct) - The k argument in xts uses positive values for shifting past observations forward.

xts follows the literature, while zoo continues with the norms of base-R.

4. Apply and aggregate by time

Apply by Time - Video

temps Temp.Max Temp.Mean Temp.Min 2016-07-01 74 69 60 2016-07-02 78 66 56 2016-07-03 79 68 59 2016-07-04 80 76 69 2016-07-05 90 79 68 2016-07-06 89 79 70 2016-07-07 87 78 72 2016-07-08 89 80 72 2016-07-09 81 73 67 2016-07-10 83 72 64 2016-07-11 93 81 69 2016-07-12 89 82 77 2016-07-13 86 78 68 2016-07-14 89 80 68 2016-07-15 75 72 60 2016-07-16 79 69 60

Find intervals by time in xts

One of the benefits to working with time series objects is how easy it is to apply functions by time.

The main function in xts to facilitate this is endpoints(). It takes a time series (or a vector of times) and returns the locations of the last observations in each interval.

For example, the code below locates the last observation of each year for the AirPass data set.

endpoints(AirPass, on = “years”) [1] 0 12 24 36 48 60 72 84 96 108 120 132 144 The argument on supports a variety of periods, including “years”, “quarters”, “months”, as well as intraday intervals such as “hours”, and “minutes”. What is returned is a vector starting with 0 and ending with the extent (last row) of your data.

In addition to each period, you can find the KthKth period by utilizing the k argument. For example, setting the arguments of your endpoints() call to on = “weeks”, k = 2, would generate the final day of every other week in your data. Note that the last value returned will always be the length of your input data, even if it doesn’t correspond to a skipped interval.

In this exercise you’ll use endpoints() to find two sets of endpoints for the daily temps data.

Instructions - Use endpoints() to locate the end of week in your temps data. - Use endpoints() to locate the end of every second week in your temps data. Remember to use the k argument.

# Locate the weeks
endpoints(temps, on = "weeks")

# Locate every two weeks
endpoints(temps, on = "weeks", k = 2)

As you’ll see in the next exercise, locating endpoints can help speed the process of aggregating time series data.

Apply a function by time period(s)

At this point you know how to locate the end of periods using endpoints(). You may be wondering what it is you do with these values.

In the most simple case you can subset your object to get the last values. In certain cases this may be useful. For example, to identify the last known value of a sensor during the hour or get the value of the USD/JPY exchange rate at the start of the day. For most series, you will want to apply a function to the values between endpoints. In essence, use the base function apply(), but used on a window of time.

To do this easily, xts provides the period.apply() command, which takes a time series, an index of endpoints, and a function.

period.apply(x, INDEX, FUN, …) In this exercise you’ll practice using period.apply() by taking the weekly mean of your temps data. You’ll also look at one of the shortcut functions that does the same thing with slightly different syntax.

Instructions - Calculate the weekly endpoints of the temps series and assign to ep. - Using period.apply(), calculate the weekly mean of the Temp.Mean column of your temps data. Remember that your endpoints were calculated weekly.

# Calculate the weekly endpoints
ep <- endpoints(temps, on = "weeks")

# Now calculate the weekly mean and display the results
period.apply(temps[, "Temp.Mean"], INDEX = ep, FUN = mean)
       Temp.Mean

2016-07-03 67.66667 2016-07-10 76.71429 2016-07-16 77.00000

The period.apply() command allows you to easily calculate complex qualities of your time series data.

Using lapply() and split() to apply functions on intervals

Along the same lines as the previous exercise, xts gives you an additional mechanism to dive into periods of your data. Often it is useful to physically split your data into disjoint chunks by time and perform some calculation on these periods.

For this exercise you’ll make use of the xts split() command to chunk your data by time. The split() function creates a list containing an element for each split. The f argument in split() is a character string describing the period to split by (i.e. “months”, “years”, etc.).

Here you will follow the same process you followed in the previous exercise. However, this time you will manually split your data first, and then apply the mean() function to each chunk. The function lapply() is used for the most efficient calculations. In cases where you don’t want to return a time series, this proves to be very intuitive and effective.

Instructions - Use split() to split your temps data by weeks. Call this temps_weekly - Use lapply() to get the weekly mean of temps_weekly. Call this temps_avg. Print this list.

# Split temps by week
temps_weekly <- split(temps, f = "weeks")

# Create a list of weekly means, temps_avg, and print this list
temps_avg <- lapply(X = temps_weekly, FUN = mean)
temps_avg

As you can see, period.apply() is similar to using a combination of split() and lapply()

Selection by endpoints vs. split-lapply-rbind

By now you have seen that even in xts there is more than one way to accomplish a task. In this exercise we’ll highlight this explicitly by tackling the same challenge using two different methods. When you are on your own, you will likely find situations where one or the other will be more intuitive, but for now you should make sure you are able to do both.

Starting with the same daily series temps, the challenge will be to find the last observation in each week.

Note that these functions will always find the dates that are in the closed interval [start of period, end of period] even if there is no observation at the exact start or end. xts represents irregular time series, so it is perfectly valid to have holes in the data where one might expect an observation.

Using the slides and video examples as a reference, find the last observation for each week in our temps data.

Instructions Use the split()-lapply()-rbind() paradigm, given for you in the script, to find the last observation in each week in temps. It is stored in temps_1. Use endpoints() to find the last days of the week in temps. Store the resulting vector in last_day_of_weeks. Create temps_2 by subsetting temps using last_day_of_weeks.

# Use the proper combination of split, lapply and rbind
temps_1 <- do.call(rbind, lapply(split(temps, "weeks"), function(w) last(w, n = "1 day")))

# Create last_day_of_weeks using endpoints()
last_day_of_weeks <- endpoints(temps, "weeks")

# Subset temps using last_day_of_weeks 
temps_2 <- temps[last_day_of_weeks]

Converting periodicity - Video

Convert univariate series to OHLC data

Aggregating time series can be a frustrating task. For example, in financial series it is common to find Open-High-Low-Close data (or OHLC) calculated over some repeating and regular interval.

Also known as range bars, aggregating a series based on some regular window can make analysis easier amongst series that have varying frequencies. A weekly economic series and a daily stock series can be compared more easily if the daily is converted to weekly.

In this exercise, you’ll convert from a univariate series into OHLC series, and then convert your final OHLC series back into a univariate series using the xts function to.period(). This function takes a time-series, x, and a string for the period (i.e. months, days, etc.), in addition to a number of other optional arguments.

to.period(x, period = “months”, k = 1, indexAt, name=NULL, OHLC = TRUE, …) You will use a new data set for this exercise, usd_eur, a daily USD/EUR exchange rate from 1999 to August 2016, which has been loaded into your workspace.

Instructions - Convert usd_eur into a weekly OHLC series using to.period(). Call this new series usd_eur_weekly. Note that by default OHLC = TRUE. - Convert usd_eur into a monthly OHLC series. Call this series usd_eur_monthly. - Convert usd_eur into a yearly univariate (no OHLC bars) series. Call this series usd_eur_yearly.

# Convert usd_eur to weekly and assign to usd_eur_weekly
usd_eur_weekly <- to.period(usd_eur, period = "weeks")

# Convert usd_eur to monthly and assign to usd_eur_monthly
usd_eur_monthly <- to.period(usd_eur, period = "months")

# Convert usd_eur to yearly univariate and assign to usd_eur_yearly
usd_eur_yearly <- to.period(usd_eur, period = "years", OHLC = FALSE)

Convert a series to a lower frequency

Besides converting univariate time series to OHLC series, to.period() also lets you convert OHLC to lower regularized frequency - something like subsampling your data.

Depending on the chosen frequency, the index class of your data may be coerced to something more appropriate to the new data. For example, when using the shortcut function to.quarterly(), xts will convert your index to the yearqtr class to make periods more obvious.

We can override this behavior by using the indexAt argument. Specifically, using firstof would give you the time from the beginning of the period. In addition, you can change the base name of each column by supplying a string to the argument name.

For this exercise we’ll introduce a new dataset, the edhec hedge fund index data from the PerformanceAnalytics package.

In this exercise you will use the Equity Market Neutral time series from the edhec data, which we’ve assigned to eq_mkt.

Instructions - Convert eq_mkt to quarterly OHLC using the base to.period(). Call this mkt_quarterly. - Convert the original eq_mkt again, this time using to.quarterly() directl y. Change the base name of each OHLC column to edhec_equity and change the index to “firstof”. Call this mkt_quarterly2.

install.packages("PerformanceAnalytics")
library(PerformanceAnalytics)
data(edhec)
dim(edhec)
names(edhec)
eq_mkt <- edhec[, "Equity Market Neutral"]
dim(eq_mkt)
# Convert eq_mkt to quarterly OHLC
mkt_quarterly <- to.period(eq_mkt, period = "quarters")

# Convert eq_mkt to quarterly using shortcut function
mkt_quarterly2 <- to.quarterly(edhec, name = "edhec_quity", indexAt = "firstof")

Rolling functions - apply windowing functions to time series data - Video

Calculate basic rolling value of series by month

One common aggregation you may want to apply involves doing a calculation within the context of a period, but returning the interim results for each observation of the period.

For example, you may want to calculate a running month-to-date cumulative sum of a series. This would be relevant when looking at monthly performance of a mutual fund you are interested in investing in.

For this exercise, you’ll calculate the cumulative annual return using the edhec fund data from the last exercise. To do this, you’ll follow the split()-lapply()-rbind() pattern demonstrated below:

x_split <- split(x, f = “months”) x_list <- lapply(x_split, cummax) x_list_rbind <- do.call(rbind, x_list) Note the last call uses R’s somewhat strange do.call(rbind, …) syntax, which allows you to pass a list to rbind instead of passing each object one at a time. This is a handy shortcut for your R toolkit.

Instructions - Using split(), break up the edhec data into years. Assign this to edhec_years. - Use lapply() to find the cumsum() of the returns per year on edhec_years. Assign this to edhec_ytd. - Use do.call() with rbind to convert your previous list output to a single xts object. Assign this to edhec_xts.

# Split edhec into years
edhec_years <- split(edhec , f = "years")

# Use lapply to calculate the cumsum for each year in edhec_years
edhec_ytd <- lapply(edhec_years, FUN = cumsum)

# Use do.call to rbind the results
edhec_xts <- do.call(rbind, edhec_ytd)

Calculate the rolling standard deviation of a time series

Another common requirement when working with time series data is to apply a function on a rolling window of data. xts provides this facility through the intuitively named zoo function rollapply().

This function takes a time series object x, a window size width, and a function FUN to apply to each rolling period. The width argument can be tricky; a number supplied to the width argument specifies the number of observations in a window. For instance, to take the rolling 10-day max of a series, you would type the following:

rollapply(x, width = 10, FUN = max, na.rm = TRUE) Note that the above would only take the 10-day max of a series with daily observations. If the series had monthly observations, it would take the 10-month max. Also note that you can pass additional arguments (i.e. na.rm to the max function) just like you would with apply().

Instructions - Using rollapply(), calculate the 3-month standard deviation of the eq_mkt series. Note that eq_mkt has monthly observations. Call your 3-month rolling standard deviation eq_sd.

# Use rollapply to calculate the rolling 3 period sd of eq_mkt
eq_sd <- rollapply(eq_mkt, width=3, FUN = sd)

Rolling values are a useful metric in time series data. Now that you are familiar with the core features of the xts package, the final chapter will explore a few more advanced topics using xts.

5. Extra features of xts

Index, Attributes, and Timezones - Video

Time via index() 50xp For this multiple choice question, you will use the pre-loaded temps data to help you find the correct answer.

Which of the following statements is false?

Possible Answers

  • Using the tclass() function on temps returns the same output as does indexClass().
  • indexFormat(temps) <- “%b %d, %Y” changes the index of the first entry of the data to Jul 01, 2016.
  • Typing help(OlsonNames) into the console will provide R documentation for time zones.
  • The time zone of the temps data set is set to “America/New_York”. (Correct)

Class attributes - tclass, tzone, and tformat

xts objects are somewhat tricky when it comes to time. Internally, we have now seen that the index attribute is really a vector of numeric values corresponding to the seconds since the UNIX epoch (1970-01-01).

How these values are displayed on printing and how they are returned to the user when using the index() function is dependent on a few key internal attributes.

The information that controls this behavior can be viewed and even changed through a set of accessor functions detailed here:

The index class using indexClass() (e.g. from Date to chron) The time zone using indexTZ() (e.g. from America/Chicago to Europe/London) The time format to be displayed via indexFormat() (e.g. YYYY-MM-DD) In this exercise, you will practice each of these functions and view the results of your changes. To do so, you’ll once again use the temps data that has been pre-loaded into your workspace.

Instructions View the first three rows of the index in the current temps data. Find the index class of temps using the most relevant command above. Find the time zone of temps, again using the most relevant command above. Change the index format of temps to “%b-%d-%Y”. View the new index format using head().

# View the first three indexes of temps
index(temps)[1:3]

# Get the index class of temps
indexClass(temps)

# Get the timezone of temps
indexTZ(temps)

# Change the format of the time display
indexFormat(temps) <- "%b-%d-%Y"

# View the new format
head(temps)

Time Zones (and why you should care!)

One of the trickiest parts to working with time series in general is dealing with time zones. xts provides a simple way to leverage time zones on a per-series basis. While R provides time zone support in native classes POSIXct and POSIXlt, xts extends this power to the entire object, allowing you to have multiple time zones across various objects.

Some internal operation system functions require a time zone to do date math. If a time zone isn’t explicitly set, one is chosen for you! Be careful to always set a time zone in your environment to prevent errors when working with dates and times.

xts provides the function tzone(), which allows you to extract or set time zones.

tzone(x) <- “Time_Zone” In this exercise you will work with an object called times to practice constructing your own xts objects with custom time zones.

Instructions

  • Construct an xts time series of the numbers 1 through 10 called times_xts, with tzone set to “America/Chicago”, and indexed by the times object.
  • Modify times_xts to show time in “Asia/Hong_Kong”.
  • Extract the current time zone as a string.
# Construct times_xts with tzone set to America/Chicago
times_xts <- xts(1:10, order.by = times, tzone = "America/Chicago")

# Change the time zone of times_xts to Asia/Hong_Kong
tzone(times_xts) <- "Asia/Hong_Kong"
  
# Extract the current time zone of times_xts
indexTZ(times_xts)

Periods, Periodicity and Timestamps - Video

Determining periodicity 100xp The idea of periodicity is pretty simple: With what regularity does your data repeat? For stock market data, you might have hourly prices or maybe daily open-high-low-close bars. For macroeconomic series, it might be monthly or weekly survey numbers.

xts provides a handy tool to discover this regularity in your data by estimating the frequency of the observations - what we are referring to as periodicity - using the periodicity() command

In this exercise, you’ll try this out on a few sample data sets. In real life you might find yourself doing this as a first step to understanding your data before diving in for further analysis.

Instructions Calculate the periodicity of the temps data set. Calculate the periodicity of the edhec data set. Convert the edhec data to yearly periodicity using to.yearly(). Call this edhec_yearly. Calculate the periodicity of edhec_yearly.

# Calculate the periodicity of temps
periodicity(temps)

# Calculate the periodicity of edhec
periodicity(edhec)

# Convert edhec to yearly
edhec_yearly <- to.yearly(edhec)

# Calculate the periodicity of edhec_yearly
periodicity(edhec_yearly)

The periodicity() command combined with the to.period() set of commands gives you a simple way to manipulate your time series data.

Find the number of periods in your data

Often it is handy to know not just the range of your time series index, but also how many discrete irregular periods your time series data covers. You shouldn’t be surprised to learn that xts provides a set of functions to do just that!

If you have a time series, it is now easy to see how many days, weeks or years your data contains. To do so, simply use the function ndays() and its shortcut functions nmonths(), nquarters(), and so forth, making counting irregular periods easy.

Instructions

  • Count the months in edhec.
  • Count the quarters in edhec.
  • Count the years in edhec.
# Count the months
nmonths(edhec)

# Count the quarters
nquarters(edhec)

# Count the years
nyears(edhec)

Secret index tools

xts uses a very special attribute called index to provide time support to your objects. For performance and design reasons, the index is stored in a special way. This means that regardless of the class of your index (e.g. Date or yearmon) everything internally looks the same to xts. The raw index is actually a simple vector of fractional seconds since the UNIX epoch.

Normally you want to access the times you stored. index() does this magically for you by using your indexClass. To get to the raw vector of the index, you can use .index(). Note the critical dot before the function name.

More useful than extracting raw seconds is the ability to extract time components similar to the POSIXlt class, which closely mirrors the underlying POSIX internal compiled structure tm. This functionality is provided by a handful of commands such as .indexday(), .indexmon(), .indexyear(), and more.

In this exercise, you’ll take a look at the weekend weather in our pre-loaded temps data using the .indexwday() command. Note that the values range from 0-6, with Sunday equal to 0. Recall that you can use a logical vector to extract elements of an xts object.

Instructions

  • Practice extracting the underlying units of your index in the temps data. Use .index() to see the number of seconds, and .indexwday() to see the day of the week of your observations.
  • Create index using the which() function to extract weekend observations in temps.
  • Select the indexed values from temps.
# Explore underlying units of temps in two commands: .index() and .indexwday()
.index(temps)
.indexwday(temps)


# Create an index of weekend days using which()
index <- which(.indexwday(temps) == 0 | .indexwday(temps) == 6)

# Select the index
temps[index]

Modifying timestamps

Most time series we’ve seen have been daily or lower frequency. Depending on your field, you might encounter higher frequency data - think intraday trading intervals, or sensor data from medical equipment.

In these situations, there are two functions in xts that are handy to know.

If you find that you have observations with identical timestamps, it might be useful to perturb or remove these times to allow for uniqueness. xts provides the function make.index.unique() for just this purpose. The eps argument, short for epsilon or small change, controls how much identical times should be perturbed, and drop = TRUE lets you just remove duplicate observations entirely.

On other ocassions you might find your timestamps a bit too precise. In these instances it might be better to round up to some fixed interval, for example an observation may occur at any point in an hour, but you want to record the latest as of the beginning of the next hour. For this situation, the align.time() command will do what you need, setting the n argument to the number of seconds you’d like to round to.

make.index.unique(x, eps = 1e-4) # Perturb make.index.unique(x, drop = TRUE) # Drop duplicates align.time(x, n = 60) # Round to the minute In this exercise, you’ll try the three use cases on an xts object called z.

Instructions - Convert the z series times to a unique series using make.index.unique(), where eps = 1e-4. Save this to z_unique. - Remove duplicate times in z. Save this to z_dup. - Align z to the nearest hour using align.time(). Save this to z_round.

# Make z have unique timestamps
z_unique <- make.index.unique(z, eps = 1e-4)

# Remove duplicate times in z
z_dup <- make.index.unique(z, drop = TRUE)

# Round observations in z to the next hour
z_round <- align.time(z, n = 3600)

These final commands should round out your xts knowledge and give you the complete tools to manipulate time series data in R.

LS0tDQp0aXRsZTogIk1hbmlwdWxhdGluZyBUaW1lIFNlcmllcyBEYXRhIGluIFIgd2l0aCB4dHMgJiB6b28iDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMQ0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeSh4dHMpDQpsaWJyYXJ5KHpvbykNCmBgYA0KDQojIDEuIEludHJvZHVjdGlvbiB0byBlWHRlbnNpYmxlIFRpbWUgU2VyaWVzLCB1c2luZyB4dHMgYW5kIHpvbyBmb3IgdGltZSBzZXJpZXMgIA0KDQojIyBJbnRyb2R1Y2luZyB4dHMgYW5kIHpvbyBvYmplY3RzIC0gVmlkZW8NCg0KIyMjIFdoYXQgaXMgYW4geHRzIG9iamVjdD8NCg0KVGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IHR5cGVzIG9mIG9iamVjdHMgaW4gUi4gV2l0aCBhIHZhcmlldHkgb2YgZGlmZmVyZW50IGZlYXR1cmVzLCBlYWNoIGhhcyBhIHVuaXF1ZSBwdXJwb3NlLiBTb21lIGNsYXNzZXMgaW5oZXJpdCBiZWhhdmlvciBmcm9tIHRoZWlyIHBhcmVudHMsIGFsbG93aW5nIGZvciBjdXN0b20gZXh0ZW5zaW9ucyB0byBleGlzdGluZyBhbmQgd2VsbC11bmRlcnN0b29kIFIgb2JqZWN0cy4gVGhpcyBtYWtlcyBpdCBlYXN5IHRvIGFkYXB0IGV4aXN0aW5nIGNvZGUgdG8gbmV3IGZ1bmN0aW9uYWxpdHkuDQoNCkl0IGlzIGZvciB0aGlzIHJlYXNvbiB0aGF0IHh0cyBleHRlbmRzIHRoZSBwb3B1bGFyIHpvbyBjbGFzcy4gS25vd2luZyB0aGlzLCBhbmQgd2hhdCB5b3UgaGF2ZSBzZWVuIHNvIGZhciwgd2hpY2ggb2YgdGhlc2Ugc3RhdGVtZW50cyBpcyB0cnVlPw0KDQpQb3NzaWJsZSBBbnN3ZXJzIA0KDQogLSB4dHMgb2JqZWN0cyBhcmUgbWF0cml4IG9iamVjdHMgaW50ZXJuYWxseS4NCiAtIHh0cyBvYmplY3RzIGFyZSBpbmRleGVkIGJ5IGEgZm9ybWFsIHRpbWUgb2JqZWN0Lg0KIC0gTW9zdCB6b28gbWV0aG9kcyB3b3JrIGZvciB4dHMuDQogLSBBbGwgb2YgdGhlIGFib3ZlLiAoQ29ycmVjdCkNCiANCg0KIyMgTW9yZSB0aGFuIGEgbWF0cml4DQoNCkl0IGlzIGJlc3QgdG8gdGhpbmsgb2YgeHRzIG9iamVjdHMgYXMgbm9ybWFsIFIgbWF0cmljZXMsIGJ1dCB3aXRoIHNwZWNpYWwgcG93ZXJzLiBUaGVzZSBwb3dlcnMgbGV0IHlvdSBtYW5pcHVsYXRlIHlvdXIgZGF0YSBhcyBhIGZ1bmN0aW9uIG9mIHRpbWUsIGFzIHlvdXIgZGF0YSBpcyBub3cgc2VsZi1hd2FyZSBvZiB3aGVuIGl0IGV4aXN0cyBpbiB0aW1lLiBCZWZvcmUgd2UgY2FuIHN0YXJ0IHRvIGV4cGxvaXQgdGhlc2UgcG93ZXJzLCBpdCB3aWxsIGJlIGhlbHBmdWwgdG8gc2VlIGhvdyB4dHMgb2JqZWN0cyByZWxhdGUgdG8gdGhlaXIgYmFzZS1SIHJlbGF0aXZlcy4NCg0KSW4gdGhpcyBleGVyY2lzZSwgeW91IHdpbGwgZ2V0IGEgZmVlbCBmb3IgeHRzIGFuZCBob3cgaXQgYmVoYXZlcyBsaWtlIGEgbWF0cml4IG9iamVjdC4gVGhlIHh0cyBvYmplY3QgZXhfbWF0cml4IGFuZCBtYXRyaXggb2JqZWN0IGNvcmUgaGF2ZSBiZWVuIHByZS1sb2FkZWQgZm9yIHlvdS4NCg0KSW5zdHJ1Y3Rpb25zDQogLSBMb2FkIHRoZSB4dHMgcGFja2FnZSB1c2luZyB0aGUgbGlicmFyeSgpIGZ1bmN0aW9uLg0KIC0gTG9vayBhdCB0aGUgc3RydWN0dXJlIG9mIHRoZSBzYW1wbGUgeHRzIGNhbGxlZCBleF9tYXRyaXggdXNpbmcgc3RyKCkuDQogLSBHaXZlbiB0aGF0IGV4X21hdHJpeCBpcyBhIG1hdHJpeCwgZXh0cmFjdCB0aGUgM3JkIHJvdyBhbmQgMm5kIGNvbHVtbi4NCiAtIE5vdyB0YWtlIHRoZSBtYXRyaXggY29yZSBhbmQgZXh0cmFjdCB0aGUgM3JkIHJvdyBhbmQgMm5kIGNvbHVtbi4gTm90aWNlIHRoZSBkaWZmZXJlbmNlLg0KIA0KYGBge3J9DQojIExvYWQgeHRzDQpsaWJyYXJ5KHh0cykNCg0KIyBWaWV3IHRoZSBzdHJ1Y3R1cmUgb2YgZXhfbWF0cml4DQpzdHIoZXhfbWF0cml4KQ0KDQojIEV4dHJhY3QgdGhlIDNyZCBvYnNlcnZhdGlvbiBvZiB0aGUgMm5kIGNvbHVtbiBvZiBleF9tYXRyaXgNCmV4X21hdHJpeFszLCAyXQ0KDQojIEV4dHJhY3QgdGhlIDNyZCBvYnNlcnZhdGlvbiBvZiB0aGUgMm5kIGNvbHVtbiBvZiBjb3JlIA0KY29yZVszLCAyXQ0KYGBgDQoNCg0KIyMgWW91ciBmaXJzdCB4dHMgb2JqZWN0DQoNCnh0cyBvYmplY3RzIGFyZSBzaW1wbGUuIFRoaW5rIG9mIHRoZW0gYXMgYSBtYXRyaXggb2Ygb2JzZXJ2YXRpb25zIGNvbWJpbmVkIHdpdGggYW4gaW5kZXggb2YgY29ycmVzcG9uZGluZyBkYXRlcyBhbmQgdGltZXMuDQoNCiAgeHRzID0gbWF0cml4ICsgdGltZXMNClRoZSBtYWluIHh0cyBjb25zdHJ1Y3RvciB0YWtlcyBhIG51bWJlciBvZiBhcmd1bWVudHMsIGJ1dCB0aGUgdHdvIG1vc3QgaW1wb3J0YW50IGFyZSB4IGZvciB0aGUgZGF0YSBhbmQgb3JkZXIuYnkgZm9yIHRoZSBpbmRleC4geCBtdXN0IGJlIGEgdmVjdG9yIG9yIG1hdHJpeC4gb3JkZXIuYnkgaXMgYSB2ZWN0b3Igd2hpY2ggbXVzdCBiZSB0aGUgc2FtZSBsZW5ndGggb3IgbnVtYmVyIG9mIHJvd3MgYXMgeCwgYmUgYSBwcm9wZXIgdGltZSBvciBkYXRlIG9iamVjdCAodmVyeSBpbXBvcnRhbnQhKSwgYW5kIGJlIGluIGluY3JlYXNpbmcgb3JkZXIuDQoNCnh0cyBhbHNvIGFsbG93cyB5b3UgdG8gYmluZCBhcmJpdHJhcnkga2V5LXZhbHVlIGF0dHJpYnV0ZXMgdG8geW91ciBkYXRhLiBUaGlzIGxldHMgeW91IGtlZXAgbWV0YWRhdGEgYWJvdXQgeW91ciBvYmplY3QgaW5zaWRlIHlvdXIgb2JqZWN0LiBUbyBhZGQgdGhlc2UgYXQgY3JlYXRpb24sIHlvdSBzaW1wbHkgcGFzcyBhZGRpdGlvbmFsIG5hbWUgPSB2YWx1ZSBhcmd1bWVudHMgdG8gdGhlIHh0cygpIGZ1bmN0aW9uLg0KDQpTaW5jZSB3ZSBhcmUgZm9jdXNpbmcgaGVyZSBvbiB0aGUgbWVjaGFuaWNzLCB3ZSdsbCB1c2UgcmFuZG9tIG51bWJlcnMgYXMgb3VyIGRhdGEgc28gd2UgY2FuIGZvY3VzIG9uIGNyZWF0aW5nIHRoZSBvYmplY3QgcmF0aGVyIHRoYW4gd29ycnkgYWJvdXQgaXRzIGNvbnRlbnRzLg0KDQpJbnN0cnVjdGlvbnMNCiAtIENyZWF0ZSBhbiBvYmplY3QgY2FsbGVkIGRhdGEgdGhhdCBjb250YWlucyBmaXZlIHJhbmRvbSBudW1iZXJzIHVzaW5nIHJub3JtKCkuDQogLSBDcmVhdGUgYSBEYXRlIGNsYXNzIGluZGV4IGZyb20gIjIwMTYtMDEtMDEiIG9mIGxlbmd0aCBmaXZlIGNhbGxlZCBkYXRlcy4NCiAtIFVzZSB0aGUgeHRzIGNvbnN0cnVjdG9yIHRvIGNyZWF0ZSBhbiBvYmplY3QgY2FsbGVkIHNtaXRoIHVzaW5nIGRhdGEgYW5kIGRhdGVzIGFzIHRoZSBpbmRleC4NCiAtIENyZWF0ZSBhbiBvYmplY3QgY2FsbGVkIGJkYXkgd2hpY2ggY29udGFpbnMgYSBQT1NJWGN0IGRhdGUgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGRhdGUgIC0gIjE4OTktMDUtMDgiLg0KIC0gQ3JlYXRlIGFuIHh0cyBvYmplY3QgY2FsbGVkIGhheWVrIHVzaW5nIGRhdGEsIGRhdGVzLCBhbmQgYSBuZXcgYXR0cmlidXRlIGNhbGxlZCBib3JuLCB3aGljaCBzaG91bGQgY29udGFpbiB0aGUgYmlydGhkYXkgb2JqZWN0IHlvdSBqdXN0IGNyZWF0ZWQuDQogDQpgYGB7cn0NCiMgQ3JlYXRlIHRoZSBvYmplY3QgZGF0YSB1c2luZyA1IHJhbmRvbSBudW1iZXJzDQpkYXRhIDwtIHJub3JtKDUpDQoNCiMgQ3JlYXRlIGRhdGVzIGFzIGEgRGF0ZSBjbGFzcyBvYmplY3Qgc3RhcnRpbmcgZnJvbSAyMDE2LTAxLTAxDQpkYXRlcyA8LSBzZXEoYXMuRGF0ZSgiMjAxNi0wMS0wMSIpLCBsZW5ndGggPSA1LCBieSA9ICJkYXlzIikNCg0KIyBVc2UgeHRzKCkgdG8gY3JlYXRlIHNtaXRoDQpzbWl0aCA8LSB4dHMoeCA9IGRhdGEsIG9yZGVyLmJ5ID0gZGF0ZXMpDQoNCiMgQ3JlYXRlIGJkYXkgKDE4OTktMDUtMDgpIHVzaW5nIGEgUE9TSVhjdCBkYXRlIGNsYXNzIG9iamVjdA0KYmRheSA8LSBhcy5QT1NJWGN0KCIxODk5LTA1LTA4IikNCg0KIyBDcmVhdGUgaGF5ZWsgYW5kIGFkZCBhIG5ldyBhdHRyaWJ1dGUgY2FsbGVkIGJvcm4NCmhheWVrIDwtIHh0cyh4ID0gZGF0YSwgb3JkZXIuYnkgPSBkYXRlcywgYm9ybiA9IGJkYXkpDQpgYGANCg0KIyMgRGVjb25zdHJ1Y3RpbmcgeHRzDQoNCk5vdyB0aGF0IHlvdSBjYW4gY3JlYXRlIHh0cyBvYmplY3RzLCB5b3VyIG5leHQgdGFzayBpcyB0byBleGFtaW5lIGFuIHh0cyBvYmplY3QgZnJvbSB0aGUgaW5zaWRlLg0KDQpBdCB0aGUgY29yZSBvZiBib3RoIHh0cyBhbmQgem9vIGlzIGEgc2ltcGxlIFIgbWF0cml4IHdpdGggYSBmZXcgYWRkaXRpb25hbCBhdHRyaWJ1dGVzLiBUaGUgbW9zdCBpbXBvcnRhbnQgb2YgdGhlc2UgYXR0cmlidXRlcyBpcyB0aGUgaW5kZXguIFRoZSBpbmRleCBob2xkcyBhbGwgdGhlIGluZm9ybWF0aW9uIHdlIG5lZWQgZm9yIHh0cyB0byB0cmVhdCBvdXIgZGF0YSBhcyBhIHRpbWUgc2VyaWVzLg0KDQpXaGVuIHdvcmtpbmcgd2l0aCB0aW1lIHNlcmllcywgaXQgd2lsbCBzb21ldGltZXMgYmUgbmVjZXNzYXJ5IHRvIHNlcGFyYXRlIHlvdXIgdGltZSBzZXJpZXMgaW50byBpdHMgY29yZSBkYXRhIGFuZCBpbmRleCBhdHRyaWJ1dGVzIGZvciBhZGRpdGlvbmFsIGFuYWx5c2lzIGFuZCBtYW5pcHVsYXRpb24uIFRoZSBjb3JlIGRhdGEgaXMgdGhlIG1hdHJpeCBwb3J0aW9uIG9mIHh0cy4gWW91IGNhbiBzZXBhcmF0ZSB0aGlzIGZyb20gdGhlIHh0cyBvYmplY3QgdXNpbmcgY29yZWRhdGEoKS4gVGhlIGluZGV4IHBvcnRpb24gb2YgdGhlIHh0cyBvYmplY3QgaXMgYXZhaWxhYmxlIHVzaW5nIHRoZSBpbmRleCgpIGZ1bmN0aW9uLiBOb3RlIHRoYXQgYm90aCBvZiB0aGVzZSBmdW5jdGlvbnMgYXJlIG1ldGhvZHMgZnJvbSB0aGUgem9vIGNsYXNzLCB3aGljaCB4dHMgZXh0ZW5kcy4NCg0KSW4gdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCB1c2UgdGhlc2UgYnVpbHQtaW4gZnVuY3Rpb25zIHRvIGV4dHJhY3QgYm90aCB0aGUgaW50ZXJuYWwgbWF0cml4IGRhdGEgYW5kIGludGVybmFsIGluZGV4IGZyb20geW91ciBzYW1wbGUgeHRzIG9iamVjdC4gWW91IHdpbGwgdXNlIHRoZSBoYXllayB0aW1lIHNlcmllcyB5b3UgY3JlYXRlZCBpbiB0aGUgbGFzdCBleGVyY2lzZSB0byBwcmFjdGljZSB0aGVzZSBuZXcgZnVuY3Rpb25zLg0KDQpJbnN0cnVjdGlvbnMNCiAtIEV4dHJhY3QgdGhlIGNvcmUgZGF0YSBvZiBoYXllayB1c2luZyBjb3JlZGF0YSgpIGFuZCBjYWxsIHRoaXMgaGF5ZWtfY29yZS4NCiAtIFZpZXcgdGhlIGNsYXNzIG9mIGhheWVrX2NvcmUgdXNpbmcgdGhlIGNsYXNzKCkgZnVuY3Rpb24uDQogLSBFeHRyYWN0IHRoZSBkYXRlIGluZGV4IG9mIGhheWVrIHVzaW5nIGluZGV4KCkgYW5kIGNhbGwgdGhpcyBoYXlla19pbmRleC4NCiAtIFZpZXcgdGhlIGNsYXNzIG9mIGhheWVrX2luZGV4Lg0KIA0KIA0KIA0KYGBge3J9DQojIEV4dHJhY3QgdGhlIGNvcmUgZGF0YSBvZiBoYXllaw0KaGF5ZWtfY29yZSA8LSBjb3JlZGF0YShoYXllaykNCg0KIyBWaWV3IHRoZSBjbGFzcyBvZiBoYXlla19jb3JlDQpjbGFzcyhoYXlla19jb3JlKQ0KDQojIEV4dHJhY3QgdGhlIGluZGV4IG9mIGhheWVrDQpoYXlla19pbmRleCA8LSBpbmRleChoYXllaykNCg0KIyBWaWV3IHRoZSBjbGFzcyBvZiBoYXlla19pbmRleA0KY2xhc3MoaGF5ZWtfaW5kZXgpDQpgYGANCg0KIyMgVGltZSBiYXNlZCBpbmRpY2VzDQoNCnh0cyBvYmplY3RzIGdldCB0aGVpciBwb3dlciBmcm9tIHRoZSBpbmRleCBhdHRyaWJ1dGUgdGhhdCBob2xkcyB0aGUgdGltZSBkaW1lbnNpb24uIE9uZSBtYWpvciBkaWZmZXJlbmNlIGJldHdlZW4geHRzIGFuZCBtb3N0IG90aGVyIHRpbWUgc2VyaWVzIG9iamVjdHMgaW4gUiBpcyB0aGUgYWJpbGl0eSB0byB1c2UgYW55IG9uZSBvZiB2YXJpb3VzIGNsYXNzZXMgdGhhdCBhcmUgdXNlZCB0byByZXByZXNlbnQgdGltZS4gV2hldGhlciBQT1NJWGN0LCBEYXRlLCBvciBzb21lIG90aGVyIGNsYXNzLCB4dHMgd2lsbCBjb252ZXJ0IHRoaXMgaW50byBhbiBpbnRlcm5hbCBmb3JtIHRvIG1ha2Ugc3Vic2V0dGluZyBhcyBuYXR1cmFsIHRvIHRoZSB1c2VyIGFzIHBvc3NpYmxlLg0KDQphIDwtIHh0cyh4ID0gMToyLCBhcy5EYXRlKCIyMDEyLTAxLTAxIikgKyAwOjEpDQphW2luZGV4KGEpXQ0KV2UnbGwgZ2V0IGludG8gbW9yZSBkZXRhaWwgb24gc3Vic2V0dGluZyB4dHMgb2JqZWN0cyBpbiBhIGxhdGVyIGNoYXB0ZXIuIEZvciBub3cgeW91IGNhbiBzaW1wbHkgdXNlIGRhdGUgb2JqZWN0cyB0byBpbmRleCBhcHByb3ByaWF0ZSByb3dzIGZyb20geW91ciB0aW1lIHNlcmllcy4gWW91IGNhbiB0aGluayBvZiB0aGlzIGFzIGVmZmVjdGl2ZWx5IG1hdGNoaW5nIHRoZSByb3duYW1lcyB5b3Ugc2VlIGluIHRoZSBvYmplY3QuIFRoaXMgd29ya3MgYXMgYW50aWNpcGF0ZWQgZm9yIHRpbWUgb2JqZWN0cyBiZWNhdXNlIHRoZSByb3duYW1lcyBhcmUgcmVhbGx5IGRhdGVzIQ0KDQpGb3IgdGhpcyBleGVyY2lzZSB5b3UnbGwgY3JlYXRlIHR3byB0aW1lIHNlcmllcyB1c2luZyB0d28gZGlmZmVyZW50IHRpbWUgY2xhc3Nlcy4gWW91IHdpbGwgdGhlbiBzdWJzZXQgZWFjaCBvYmplY3QgdXNpbmcgdGhlIG90aGVyIG9iamVjdCdzIGluZGV4Lg0KDQpJbnN0cnVjdGlvbnMNCiAtIENyZWF0ZSBhbiBvYmplY3Qgb2YgNSBkYXRlcyBjYWxsZWQgZGF0ZXMgc3RhcnRpbmcgYXQgIjIwMTYtMDEtMDEiLg0KIC0gQ3JlYXRlIGEgdGltZSBzZXJpZXMgdHNfYSB1c2luZyB0aGUgbnVtYmVycyAxIHRocm91Z2ggNSBhcyB5b3VyIGRhdGEsIGFuZCBkYXRlcyBhcyB5b3VyICAtIG9yZGVyLmJ5IGluZGV4Lg0KIC0gQ3JlYXRlIGEgdGltZSBzZXJpZXMgdHNfYiB1c2luZyB0aGUgbnVtYmVycyAxIHRocm91Z2ggNSBhcyB5b3VyIGRhdGEsIGFuZCB0aGUgc2FtZSBkYXRlcywgYnV0ICAtIGFzIFBPU0lYY3Qgb2JqZWN0cy4NCiAtIFVzZSB0aGUgaW5kZXggZnJvbSB0c19iIHRvIGV4dHJhY3QgdGhlIGRhdGVzIGZyb20gdHNfYS4NCiAtIE5vdyBkbyB0aGUgcmV2ZXJzZSwgaW5kZXhpbmcgdHNfYiB1c2luZyB0aGUgdGltZXMgZnJvbSB0c19hLg0KDQpgYGB7cn0NCiMgQ3JlYXRlIGRhdGVzDQpkYXRlcyA8LSBhcy5EYXRlKCIyMDE2LTAxLTAxIikgKyAwOjQNCg0KIyBDcmVhdGUgdHNfYQ0KdHNfYSA8LSB4dHMoeCA9IDE6NSwgb3JkZXIuYnkgPSBkYXRlcykNCg0KIyBDcmVhdGUgdHNfYg0KdHNfYiA8LSB4dHMoeCA9IDE6NSwgb3JkZXIuYnkgPSBhcy5QT1NJWGN0KGRhdGVzKSkNCg0KIyBFeHRyYWN0IHRoZSByb3dzIG9mIHRzX2EgdXNpbmcgdGhlIGluZGV4IG9mIHRzX2INCnRzX2FbaW5kZXgodHNfYSldDQoNCiMgRXh0cmFjdCB0aGUgcm93cyBvZiB0c19iIHVzaW5nIHRoZSBpbmRleCBvZiB0c19hDQp0c19hW2luZGV4KHRzX2IpXQ0KYGBgDQoNCiMjIEltcG9ydGluZywgZXhwb3J0aW5nIGFuZCBjb252ZXJ0aW5nIHRpbWUgc2VyaWVzIC0gVmlkZW8NCg0KIyMjIENvbnZlcnRpbmcgeHRzIG9iamVjdHMNCg0KSXQgaXMgb2Z0ZW4gbmVjZXNzYXJ5IHRvIGNvbnZlcnQgYmV0d2VlbiBjbGFzc2VzIHdoZW4gd29ya2luZyB3aXRoIHRpbWUgc2VyaWVzIGRhdGEgaW4gUi4gQ29udmVyc2lvbiBjYW4gYmUgcmVxdWlyZWQgZm9yIG1hbnkgcmVhc29ucywgYnV0IHR5cGljYWxseSB5b3UnbGwgYmUgbG9va2luZyB0byB1c2UgYSBmdW5jdGlvbiB0aGF0IG1heSBub3QgYmUgdGltZSBzZXJpZXMgYXdhcmUgb3IgeW91IG1heSB3YW50IHRvIHVzZSBhIHBhcnRpY3VsYXIgYXNwZWN0IG9mIHh0cyB3aXRoIHNvbWV0aGluZyB0aGF0IGRvZXNuJ3QgbmVjZXNzYXJpbHkgbmVlZCB0byBiZSBhIGZ1bGwgdGltZSBzZXJpZXMuDQoNCkx1Y2tpbHksIGl0IGlzIHF1aXRlIGVhc3kgdG8gY29udmVydCBiYWNrIGFuZCBmb3J0aCB1c2luZyB0aGUgc3RhbmRhcmQgYXMuKiBzdHlsZSBmdW5jdGlvbmFsaXR5IHByb3ZpZGVkIGluIFIgKGZvciBleGFtcGxlLCBhcy5QT1NJWGN0KCkgb3IgYXMubWF0cml4KCkpLg0KDQp4dHMgcHJvdmlkZXMgbWV0aG9kcyB0byBjb252ZXJ0IGFsbCBvZiB0aGUgbWFqb3Igb2JqZWN0cyB5b3UgYXJlIGxpa2VseSB0byBjb21lIGFjcm9zcy4gU3VpdGFibGUgbmF0aXZlIFIgdHlwZXMgbGlrZSBtYXRyaXgsIGRhdGEuZnJhbWUsIGFuZCB0cyBhcmUgc3VwcG9ydGVkLCBhcyB3ZWxsIGFzIGNvbnRyaWJ1dGVkIG9uZXMgc3VjaCBhcyB0aW1lU2VyaWVzLCBmdHMgYW5kIG9mIGNvdXJzZSB6b28uIGFzLnh0cygpIGlzIHRoZSB3b3JraG9yc2UgZnVuY3Rpb24gdG8gZG8gdGhlIGNvbnZlcnNpb25zIHRvIHh0cywgYW5kIHNpbWlsYXIgZnVuY3Rpb25zIHdpbGwgcHJvdmlkZSB0aGUgcmV2ZXJzZSBiZWhhdmlvci4NCg0KVG8gZ2V0IGEgZmVlbCBmb3IgbW92aW5nIGRhdGEgYmV0d2VlbiBjbGFzc2VzLCBsZXQncyB0cnkgYSBmZXcgZXhhbXBsZXMgdXNpbmcgdGhlIEF1c3RyYWxpYW4gcG9wdWxhdGlvbiB0cyBvYmplY3QgZnJvbSBSIG5hbWVkIGF1c3RyZXMuDQoNCkluc3RydWN0aW9ucw0KQ29udmVydCB0aGUgdHMgY2xhc3MgYXVzdHJlcyBkYXRhIHNldCB0byBhbiB4dHMgYW5kIGNhbGwgaXQgYXUuDQpUaGVuIGNvbnZlcnQgdGhlIG5ldyBhdSB4dHMgb2JqZWN0IGludG8gYSBtYXRyaXgsIGFtLg0KSW5zcGVjdCB0aGUgZmlyc3QgZmV3IGVudHJpZXMgb2YgdGhpcyBuZXcgbWF0cml4IGJ5IHVzaW5nIHRoZSBoZWFkKCkgZnVuY3Rpb24uDQpDb252ZXJ0IHRoZSBvcmlnaW5hbCBhdXN0cmVzIGRpcmVjdGx5IGludG8gYSBtYXRyaXggY2FsbGVkIGFtMi4NCk5vdyBpbnNwZWN0IHRoZSBmaXJzdCBmZXcgZW50cmllcyBvZiB0aGlzIG5ldyBtYXRyaXggYnkgdXNpbmcgdGhlIHNhbWUgZnVuY3Rpb24uIE5vdGljZSBob3cgdGhpcyB0aW1lLCB0aGUgY29udmVyc2lvbiBkaWRuJ3QgcHJlc2VydmUgdGhlIHRpbWUgaW5mb3JtYXRpb24/DQoNCmBgYHtyfQ0KIyBDb252ZXJ0IGF1c3RyZXMgdG8gYW4geHRzIG9iamVjdCBjYWxsZWQgYXUNCmF1IDwtIGFzLnh0cyhhdXN0cmVzKQ0KDQojIFRoZW4gY29udmVydCB5b3VyIHh0cyBvYmplY3QgKGF1KSBpbnRvIGEgbWF0cml4IGFtDQphbSA8LSBhcy5tYXRyaXgoYXUpDQoNCiMgSW5zcGVjdCB0aGUgaGVhZCBvZiBhbQ0KaGVhZChhbSkNCg0KIyBDb252ZXJ0IHRoZSBvcmlnaW5hbCBhdXN0cmVzIGludG8gYSBtYXRyaXggYW0yDQphbTIgPC0gYXMubWF0cml4KGF1c3RyZXMpDQoNCiMgSW5zcGVjdCB0aGUgaGVhZCBvZiBhbTINCmhlYWQoYW0yKQ0KYGBgDQoNCmBgYHtyfQ0KPiBhdXN0cmVzDQogICAgICAgIFF0cjEgICAgUXRyMiAgICBRdHIzICAgIFF0cjQNCjE5NzEgICAgICAgICAxMzA2Ny4zIDEzMTMwLjUgMTMxOTguNA0KMTk3MiAxMzI1NC4yIDEzMzAzLjcgMTMzNTMuOSAxMzQwOS4zDQoxOTczIDEzNDU5LjIgMTM1MDQuNSAxMzU1Mi42IDEzNjE0LjMNCjE5NzQgMTM2NjkuNSAxMzcyMi42IDEzNzcyLjEgMTM4MzIuMA0KMTk3NSAxMzg2Mi42IDEzODkzLjAgMTM5MjYuOCAxMzk2OC45DQoxOTc2IDE0MDA0LjcgMTQwMzMuMSAxNDA2Ni4wIDE0MTEwLjENCjE5NzcgMTQxNTUuNiAxNDE5Mi4yIDE0MjMxLjcgMTQyODEuNQ0KMTk3OCAxNDMzMC4zIDE0MzU5LjMgMTQzOTYuNiAxNDQzMC44DQoxOTc5IDE0NDc4LjQgMTQ1MTUuNyAxNDU1NC45IDE0NjAyLjUNCjE5ODAgMTQ2NDYuNCAxNDY5NS40IDE0NzQ2LjYgMTQ4MDcuNA0KMTk4MSAxNDg3NC40IDE0OTIzLjMgMTQ5ODguNyAxNTA1NC4xDQoxOTgyIDE1MTIxLjcgMTUxODQuMiAxNTIzOS4zIDE1Mjg4LjkNCjE5ODMgMTUzNDYuMiAxNTM5My41IDE1NDM5LjAgMTU0ODMuNQ0KMTk4NCAxNTUzMS41IDE1NTc5LjQgMTU2MjguNSAxNTY3Ny4zDQoxOTg1IDE1NzM2LjcgMTU3ODguMyAxNTgzOS43IDE1OTAwLjYNCjE5ODYgMTU5NjEuNSAxNjAxOC4zIDE2MDc2LjkgMTYxMzkuMA0KMTk4NyAxNjIwMy4wIDE2MjYzLjMgMTYzMjcuOSAxNjM5OC45DQoxOTg4IDE2NDc4LjMgMTY1MzguMiAxNjYyMS42IDE2Njk3LjANCjE5ODkgMTY3NzcuMiAxNjgzMy4xIDE2ODkxLjYgMTY5NTYuOA0KMTk5MCAxNzAyNi4zIDE3MDg1LjQgMTcxMDYuOSAxNzE2OS40DQoxOTkxIDE3MjM5LjQgMTcyOTIuMCAxNzM1NC4yIDE3NDE0LjINCjE5OTIgMTc0NDcuMyAxNzQ4Mi42IDE3NTI2LjAgMTc1NjguNw0KMTk5MyAxNzYyNy4xIDE3NjYxLjUNCg0KYXVzdHJlcyA8LSByZWFkLmRlbGltKCJjbGlwYm9hcmQiKQ0KIyBhdXN0cmVzIDwtIGFzLnRzKGF1c3RyZXMpDQphdXN0cmVzDQpgYGANCg0KIyMgSW1wb3J0aW5nIGRhdGENCg0KWW91IGNhbiBub3cgY29udmVydCBkYXRhIHRvIHh0cyB1c2luZyBhcy54dHMoKS4gSG93ZXZlciwgaW4gbW9zdCByZWFsIHdvcmxkIGFwcGxpY2F0aW9ucyB5b3Ugd2lsbCBvZnRlbiBuZWVkIHRvIHJlYWQgcmF3IGRhdGEgZnJvbSBmaWxlcyBvbiBkaXNrIG9yIHRoZSB3ZWIuIFRoaXMgY2FuIGJlIGNoYWxsZW5naW5nIHdpdGhvdXQga25vd2luZyB0aGUgcmlnaHQgY29tbWFuZHMuDQoNCkluIHRoZSBmaXJzdCBwYXJ0IG9mIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIHN0YXJ0IGJ5IHJlYWRpbmcgYSBjc3YgZmlsZSBmcm9tIGRpc2sgdXNpbmcgdGhlIGJhc2UtUiByZWFkLmNzdi4gQWZ0ZXIgeW91IHJlYWQgdGhlIGRhdGEsIHRoZSBuZXh0IHN0ZXAgaXMgdG8gY29udmVydCBpdCB0byB4dHMuIEhlcmUgeW91IHdpbGwgYmUgcmVxdWlyZWQgdG8gdXNlIHRoZSB4dHMoKSBjb25zdHJ1Y3RvciBhcyB3ZWxsIGFzIGRlYWwgd2l0aCBjb252ZXJ0aW5nIG5vbi1zdGFuZGFyZCBkYXRlcyBpbnRvIHNvbWV0aGluZyB0aGF0IHh0cyB1bmRlcnN0YW5kcy4NCg0KSW4gcGFydCB0d28gb2YgdGhpcyBleGVyY2lzZSwgeW91IHdpbGwgcmVhZCB0aGUgc2FtZSBkYXRhIGludG8gYSB6b28gb2JqZWN0IHVzaW5nIHJlYWQuem9vIGFuZCB0aGVuIGNvbnZlcnQgdGhlIHpvbyBvYmplY3QgaW50byBhbiB4dHMgb2JqZWN0Lg0KDQpUaGUgZGF0YSBpbiB0aGlzIGV4ZXJjaXNlIGFyZSBxdWl0ZSBzaW1wbGUsIGJ1dCB3aWxsIHJlcXVpcmUgc29tZSBlZmZvcnQgdG8gcHJvcGVybHkgaW1wb3J0IGFuZCBjbGVhbi4gVGhlIGZ1bGwgbmFtZSBvZiB0aGUgZmlsZSB5b3Ugd2lsbCBiZSB3b3JraW5nIHdpdGggaGFzIGJlZW4gc2F2ZWQgYXMgdGhlIHZhbHVlIG9mIHRtcF9maWxlLiBPbiBkaXNrLCB0aGUgZGF0YSBsb29rIGxpa2U6DQoNCmEsYg0KMS8wMi8yMDE1LCAxLCAzDQoyLzAzLzIwMTUsIDIsIDQNCg0KSW5zdHJ1Y3Rpb25zDQoNCiAtIFJlYWQgdGhlIGRhdGEgbG9jYXRlZCBhdCB0aGUgdmFsdWUgb2YgdG1wX2ZpbGUgdXNpbmcgcmVhZC5jc3YoKSB0byBhIG5ldyB2YXJpYWJsZSBjYWxsZWQgZGF0Lg0KIC0gQ29udmVydCBkYXQgaW50byBhbiB4dHMgb2JqZWN0IHVzaW5nIHRoZSB4dHMoKSBjb25zdHJ1Y3Rvci4gVXNlIGFzLkRhdGUoKSB3aXRoIHJvd25hbWVzKGRhdCkgIC0gYXMgdGhlIGZpcnN0IGFyZ3VtZW50Lg0KIC0gQ3JlYXRlIGRhdF96b28gYnkgdXNpbmcgcmVhZC56b28oKSB0byByZWFkIGluIHRoZSBzYW1lIHRtcF9maWxlLCBhbmQgc2V0IHRoZSBhcmd1bWVudCBmb3JtYXQgIC0gZXF1YWwgdG8gIiVtLyVkLyVZIi4NCiAtIENyZWF0ZSBkYXRfeHRzIGJ5IGNvbnZlcnRpbmcgZGF0X3pvbyB0byB4dHMgYnkgdXNpbmcgYXMueHRzKCkuDQoNCg0KYGBge3J9DQp0bXBfZmlsZSA8LSAiaHR0cDovL3MzLmFtYXpvbmF3cy5jb20vYXNzZXRzLmRhdGFjYW1wLmNvbS9wcm9kdWN0aW9uL2NvdXJzZV8xMTI3L2RhdGFzZXRzL3RtcF9maWxlLmNzdiINCmBgYA0KDQpgYGB7cn0NCiMgQ3JlYXRlIGRhdCBieSByZWFkaW5nIHRtcF9maWxlDQpkYXQgPC0gcmVhZC5jc3YodG1wX2ZpbGUpDQoNCiMgQ29udmVydCBkYXQgaW50byB4dHMNCnh0cyhkYXQsIG9yZGVyLmJ5ID0gYXMuRGF0ZShyb3duYW1lcyhkYXQpLCAiJW0vJWQvJVkiKSkNCg0KIyBSZWFkIHRtcF9maWxlIHVzaW5nIHJlYWQuem9vDQpkYXRfem9vIDwtIHJlYWQuem9vKHRtcF9maWxlLCBpbmRleC5jb2x1bW4gPSAwLCBzZXAgPSAiLCIsIGZvcm1hdCA9ICIlbS8lZC8lWSIpDQoNCiMgQ29udmVydCBkYXRfem9vIHRvIHh0cw0KZGF0X3h0cyA8LSBhcy54dHMoZGF0X3pvbykNCmBgYA0KDQojIyMgRXhwb3J0aW5nIHh0cyBvYmplY3RzDQoNCk5vdyB0aGF0IHlvdSBjYW4gcmVhZCByYXcgZGF0YSBpbnRvIHh0cyBhbmQgem9vIG9iamVjdHMsIGl0IGlzIG9ubHkgbmF0dXJhbCB0aGF0IHlvdSBsZWFybiBob3cgdG8gcmV2ZXJzZSB0aGUgcHJvY2Vzcy4NCg0KVGhlcmUgYXJlIHR3byBtYWluIHVzZSBjYXNlcyBmb3IgZXhwb3J0aW5nIHh0cyBvYmplY3RzLiBGaXJzdCwgeW91IG1heSByZXF1aXJlIGFuIG9iamVjdCB0byBwZXJzaXN0IGFjcm9zcyBzZXNzaW9ucyBmb3IgdXNlIGluIGxhdGVyIGFuYWx5c2lzLiBJbiB0aGlzIGNhc2UsIGl0IGlzIGFsbW9zdCBhbHdheXMgYmVzdCB0byB1c2Ugc2F2ZVJEUygpIGFuZCByZWFkUkRTKCkgdG8gc2VyaWFsaXplIHNpbmdsZSBSIG9iamVjdHMuDQoNCkFsdGVybmF0aXZlbHksIHlvdSBtYXkgZmluZCB5b3Vyc2VsZiBuZWVkaW5nIHRvIHNoYXJlIHRoZSByZXN1bHRzIG9mIHlvdXIgYW5hbHlzaXMgd2l0aCBvdGhlcnMsIG9mdGVuIGV4cGVjdGluZyB0aGUgZGF0YSB0byBiZSBjb25zdW1lZCBieSBwcm9jZXNzZXMgdW5hd2FyZSBvZiBib3RoIFIgYW5kIHh0cy4gTW9zdCBvZiB1cyB3b3VsZCBwcmVmZXIgbm90IHRvIHRoaW5rIG9mIHRoaXMgaG9ycmlibGUgZmF0ZSBmb3Igb3VyIGRhdGEsIGJ1dCB0aGUgcmVhbCB3b3JsZCBtYW5kYXRlcyB0aGF0IHdlIGF0IGxlYXN0IHVuZGVyc3RhbmQgaG93IHRoaXMgd29ya3MuDQoNCk9uZSBvZiB0aGUgYmVzdCB3YXlzIHRvIHdyaXRlIGFuIHh0cyBvYmplY3QgZnJvbSBSIGlzIHRvIHVzZSB0aGUgem9vIGZ1bmN0aW9uIHdyaXRlLnpvbygpLiBJbiB0aGlzIGV4ZXJjaXNlIHlvdSdsbCB0YWtlIHlvdXIgdGVtcG9yYXJ5IGRhdGEgYW5kIHdyaXRlIGl0IHRvIGRpc2sgdXNpbmcgd3JpdGUuem9vKCkuDQoNCkluc3RydWN0aW9ucw0KQ29udmVydCBzdW5zcG90cyB0byB4dHMgYW5kIHNhdmUgaXQgYXMgc3Vuc3BvdHNfeHRzLg0KVGhlIHRlbXBvcmFyeSBmaWxlIG5hbWUgd2lsbCBiZSBsb2FkZWQgZm9yIHlvdS4NClVzaW5nIHdyaXRlLnpvbygpLCBzYXZlIHRoZSBzdW5zcG90c194dHMgZGF0YSB0byB0aGUgdG1wIGZpbGUuDQpSZWFkIHRoZSB0bXAgZmlsZSBiYWNrIGludG8gUiB1c2luZyByZWFkLnpvbygpLiBDYWxsIHRoaXMgc3VuLg0KQ29udmVydCBzdW4gdG8geHRzIHVzaW5nIHRoZSBhcy54dHMoKSBmdW5jdGlvbi4gQ2FsbCB0aGlzIHN1bl94dHMuDQoNCmBgYHtyfQ0KZGF0YShzdW5zcG90cykNCmNsYXNzKHN1bnNwb3RzKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDb252ZXJ0IHN1bnNwb3RzIHRvIHh0cyB1c2luZyBhcy54dHMoKS4NCnN1bnNwb3RzX3h0cyA8LSBhcy54dHMoc3Vuc3BvdHMpDQoNCiMgR2V0IHRoZSB0ZW1wb3JhcnkgZmlsZSBuYW1lDQp0bXAgPC0gdGVtcGZpbGUoKQ0KDQojIFdyaXRlIHRoZSB4dHMgb2JqZWN0IHVzaW5nIHpvbyB0byB0bXAgDQp3cml0ZS56b28oc3Vuc3BvdHNfeHRzLCBzZXAgPSAiLCIsIGZpbGUgPSB0bXApDQoNCiMgUmVhZCB0aGUgdG1wIGZpbGUuIEZVTiA9IGFzLnllYXJtb24gY29udmVydHMgc3RyaW5ncyBzdWNoIGFzIEphbiAxNzQ5IGludG8gYSBwcm9wZXIgdGltZSBjbGFzcw0Kc3VuIDwtIHJlYWQuem9vKHRtcCwgc2VwID0gIiwiLCBGVU4gPSBhcy55ZWFybW9uKQ0KDQojIENvbnZlcnQgc3VuIGludG8geHRzLiBTYXZlIHRoaXMgYXMgc3VuX3h0cw0Kc3VuX3h0cyA8LSBhcy54dHMoc3VuKQ0KDQpgYGANCg0KIzIuIEZpcnN0IE9yZGVyIG9mIEJ1c2luZXNzIC0gQmFzaWMgTWFuaXB1bGF0aW9ucw0KDQojIyBJbnRyb2R1Y2luZyB0aW1lIGJhc2VkIHF1ZXJpZXMgLSBWaWRlbw0KDQojIyMgVGhlIElTTy04NjAxIHN0YW5kYXJkDQoNClRoZSBJU08tODYwMSBzdGFuZGFyZCBpcyB0aGUgaW50ZXJuYXRpb25hbGx5IHJlY29nbml6ZWQgYW5kIGFjY2VwdGVkIHdheSB0byByZXByZXNlbnQgZGF0ZXMgYW5kIHRpbWVzLiBUaGUgc3RhbmRhcmQgYWxsb3dzIGZvciBhIGNvbW1vbiBmb3JtYXQgdG8gbm90IG9ubHkgZGVzY3JpYmUgZGF0ZXMsIGJ1dCBhbHNvIHRvIHJlcHJlc2VudCByYW5nZXMgYW5kIHJlcGVhdGluZyBpbnRlcnZhbHMuDQoNCnh0cyBtYWtlcyB1c2Ugb2YgdGhpcyBzdGFuZGFyZCBmb3IgYWxsIGV4dHJhY3QgYW5kIHJlcGxhY2Ugb3BlcmF0aW9ucy4gVGhpcyBtYWtlcyBjb2RlIGJvdGggZWFzeSB0byB3cml0ZSBhbmQgZWFzeSB0byBtYWludGFpbi4gSXQgYWxzbyBtYWtlcyBmb3IgdmVyeSBjb25jaXNlIGV4cHJlc3Npb24gb2YgZGF0ZSByYW5nZXMgYW5kIGludGVydmFscy4NCg0KRm9yIHh0cyB0byB3b3JrIGNvcnJlY3RseSwgaXQgaXMgdmVyeSBpbXBvcnRhbnQgdG8gZm9sbG93IHRoZSBzdGFuZGFyZCBleGFjdGx5LiBEZXRhaWxzIGNhbiBiZSBmb3VuZCBpbiB4dHMgc3Vic2V0IGFuZCAucGFyc2VJU084NjAxIGRvY3VtZW50YXRpb24uDQoNCldoaWNoIGlzIGEgdmFsaWQgSVNPLTg2MDEgc3RyaW5nIGFjY2VwdGFibGUgYnkgeHRzPw0KDQpQb3NzaWJsZSBBbnN3ZXJzDQoNCiAtICIyMDA1LTAxLTAyIg0KIC0gIjIwMDUwMSINCiAtICIyMDEwLzAyLzIyIg0KIC0gKDEpIGFuZCAoMikgb25seSAoQ29ycmVjdCkNCiAtIGFsbCBvZiB0aGUgYWJvdmUNCiANCiMjIyBRdWVyeWluZyBmb3IgZGF0ZXMNCg0KT25lIG9mIHRoZSBtb3N0IHBvd2VyZnVsIGFzcGVjdHMgb2Ygd29ya2luZyB3aXRoIHRpbWUgc2VyaWVzIGluIHh0cyBpcyB0aGUgYWJpbGl0eSB0byBxdWlja2x5IGFuZCBlZmZpY2llbnRseSBzcGVjaWZ5IGRhdGVzIGFuZCB0aW1lIHJhbmdlcyBmb3Igc3Vic2V0dGluZy4NCg0KRGF0ZSByYW5nZXMgY2FuIGJlIGV4dHJhY3RlZCBmcm9tIHh0cyBvYmplY3RzIGJ5IHNpbXBseSBzcGVjaWZ5aW5nIHRoZSBwZXJpb2QocykgeW91IHdhbnQgdXNpbmcgc3BlY2lhbCBjaGFyYWN0ZXIgc3RyaW5ncyBpbiB5b3VyIHN1YnNldC4NCg0KQVsiMjAwOTA4MjUiXSAgICAgICAjIyBBdWcgMjUsIDIwMDkNCkFbIjIwMTIwMy8yMDEyMTIiXSAgIyMgTWFyIHRvIERlYyAyMDEyDQpBWyIvMjAxNjAxIl0gICAgICAgICMjIFVwIHRvIGFuZCBpbmNsdWRpbmcgSmFudWFyeSAyMDE2DQpGb3IgdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCBjcmVhdGUgYSBzaW1wbGUgYnV0IHZlcnkgY29tbW9uIHF1ZXJ5LiBFeHRyYWN0IGEgcmFuZ2Ugb2YgZGF0ZXMgdXNpbmcgdGhlIElTTy04NjAxIGZlYXR1cmUgb2YgeHRzLiBBZnRlciBzdWNjZXNzZnVsbHkgZXh0cmFjdGluZyBhIGZ1bGwgeWVhciwgeW91IHdpbGwgdGhlbiBjcmVhdGUgYSBzdWJzZXQgb2YgeW91ciBuZXcgb2JqZWN0IHdpdGggc3BlY2lmaWMgc3RhcnQgYW5kIGVuZCBkYXRlcyB1c2luZyB0aGlzIHNhbWUgbm90YXRpb24uDQoNCkxldCdzIGZpbmQgc29tZSB0aW1lIQ0KDQpJbnN0cnVjdGlvbnMNCiAtIFVzaW5nIHh0cy1zdHlsZSB0aW1lIHN1YnNldHRpbmcsIHNlbGVjdCBvbmx5IHRoZSB5ZWFyIDIwMTYgZnJvbSB0aGUgeCB0aW1lIHNlcmllcywgYW5kIGNhbGwgIC0gdGhpcyB4XzIwMTYuDQogLSBVc2luZyBhbiBleHBsaWNpdCBzdGFydCBhbmQgZW5kIGRhdGUgc3RyaW5nLCBnZXQgYWxsIGRhdGEgZnJvbSBKYW51YXJ5IDEsIDIwMTYgdGhyb3VnaCBNYXJjaCAgLSAyMiwgMjAxNi4gQ2FsbCB0aGlzIGphbl9tYXJjaC4NCiAtIFRvIGVuc3VyZSB0aGF0IHlvdSBzdWJzZXQgYWxsIDgyIHJvd3MsIHVzZSB0aGUgbGVuZ3RoIGZ1bmN0aW9uLg0KIA0KIA0KYGBge3J9DQojIFNlbGVjdCBhbGwgb2YgMjAxNiBmcm9tIHgNCnhfMjAxNiA8LSB4WyIyMDE2Il0NCg0KIyBTZWxlY3QgSmFudWFyeSAxLCAyMDE2IHRvIE1hcmNoIDIyLCAyMDE2DQpqYW5fbWFyY2ggPC0geFsiMjAxNjAxMDEvMjAxNjAzMjIiXQ0KDQojIFZlcmlmeSB0aGF0IGphbl9tYXJjaCBjb250YWlucyA4MiByb3dzDQo4MiA9PSBsZW5ndGgoamFuX21hcmNoKQ0KYGBgDQoNCiMjIyBFeHRyYWN0aW5nIHJlY3VycmluZyBpbnRyYWRheSBpbnRlcnZhbHMNCg0KVGhlIG1vc3QgY29tbW9uIHRpbWUgc2VyaWVzIGRhdGEgImluIHRoZSB3aWxkIiBpcyBkYWlseS4gT24gb2NjYXNpb24sIHlvdSBtYXkgZmluZCB5b3Vyc2VsZiB3b3JraW5nIHdpdGggaW50cmFkYXkgZGF0YSwgd2hpY2ggY29udGFpbnMgYm90aCBkYXRlcyBhbmQgdGltZXMuIEluIHRoaXMgY2FzZSBpdCBpcyBzb21ldGltZXMgbmVjZXNzYXJ5IHRvIHZpZXcgb25seSBhIHN1YnNldCBvZiB0aW1lIGZvciBlYWNoIGRheSBvdmVyIG11bHRpcGxlIGRheXMuIFVzaW5nIHh0cywgeW91IGNhbiBzbGljZSBkYXlzIGVhc2lseSBieSB1c2luZyBzcGVjaWFsIG5vdGF0aW9uIGluIHRoZSBpID0gYXJndW1lbnQgdG8gdGhlIHNpbmdsZSBicmFja2V0IGV4dHJhY3Rpb24gKGkuZS4gW2ksIGpdKS4NCg0KQXMgeW91IGxlYXJuZWQgaW4gdGhlIHByZXZpb3VzIGV4ZXJjaXNlLCB0aGUgdHJpY2sgdG8gdGhpcyBpcyB0byBub3Qgc3BlY2lmeSBleHBsaWNpdCBkYXRlcywgYnV0IHJhdGhlciB0byB1c2UgdGhlIHNwZWNpYWwgVC9UIG5vdGF0aW9uIGRlc2lnbmVkIGZvciBpbnRyYWRheSByZXBlYXRpbmcgaW50ZXJ2YWxzLg0KDQpJbnRyYWRheSB0aW1lcyBmb3IgYWxsIGRheXMNCk5ZU0VbIlQwOTozMC9UMTY6MDAiXSANCg0KSW4gdGhpcyBleGVyY2lzZSwgeW91IHdpbGwgZXh0cmFjdCByZWN1cnJpbmcgbW9ybmluZyBob3VycyBmcm9tIHRoZSB0aW1lIHNlcmllcyBpcnJlZywgd2hpY2ggaG9sZHMgaXJyZWd1bGFyIGRhdGEgZnJvbSB0aGUgbW9udGggb2YgSmFudWFyeSAyMDEwLiBSZW1lbWJlciwgeW91IGNhbiBhbHdheXMgdXNlIHRoZSBSIGNvbnNvbGUgdG8gZXhwZXJpbWVudCB3aXRoIGlycmVnIG9yIHRvIHZpZXcgdGhlIGhlbHAgcGFnZXMgd2l0aCA/eHRzLg0KDQpJbnN0cnVjdGlvbnMNClVzaW5nIHRoZSBpcnJlZ3VsYXIgdGltZSBzZXJpZXMgaXJyZWcsIGFzc2lnbiBhbGwgb2JzZXJ2YXRpb25zIGJldHdlZW4gOEFNIGFuZCAxMEFNIHRvIG1vcm5fMjAxMC4NClVzaW5nIG1vcm5fMjAxMCwgZXh0cmFjdCBvbmx5IHRob3NlIG9ic2VydmF0aW9ucyBmcm9tIHRoZSBtb3JuaW5nIG9mIEphbnVhcnkgMTN0aCwgMjAxMC4NCg0KYGBge3J9DQojIEV4dHJhY3QgYWxsIGRhdGEgZnJvbSBpcnJlZyBiZXR3ZWVuIDhBTSBhbmQgMTBBTQ0KbW9ybl8yMDEwIDwtIGlycmVnWyJUMDg6MDAvVDEwOjAwIl0NCg0KIyBFeHRyYWN0IHRoZSBvYnNlcnZhdGlvbnMgaW4gbW9ybl8yMDEwIGZvciBKYW51YXJ5IDEzdGgsIDIwMTANCm1vcm5fMjAxMFsiMjAxMDAxMTMiXQ0KYGBgDQoNCiMjIEFsdGVybmF0aXZlIGV4dHJhY3Rpb24gdGVjaG5pcXVlcyAtIFZpZGVvDQoNCiMjIFJvdyBzZWxlY3Rpb24gd2l0aCB0aW1lIG9iamVjdHMNCg0KT2Z0ZW4geW91IG1heSBuZWVkIHRvIHN1YnNldCBhbiBleGlzdGluZyB0aW1lIHNlcmllcyB3aXRoIGEgc2V0IG9mIERhdGVzLCBvciB0aW1lLWJhc2VkIG9iamVjdHMuIFRoZXNlIG1pZ2h0IGJlIGZyb20gYXMuRGF0ZSgpLCBhcy5QT1NJWGN0KCksIG9yIGEgdmFyaWV0eSBvZiBvdGhlciBjbGFzc2VzLiBJbiB0aGlzIGV4ZXJjaXNlIHlvdSdsbCBleHBsb3JlIGhvdywgZ2l2ZW4gYW4geHRzIG9iamVjdCB4LCBpdCBpcyBwb3NzaWJsZSB0byBleHRyYWN0IHJlbGV2YW50IG9ic2VydmF0aW9ucyB1c2luZyBhIHZlY3RvciBvZiBkYXRlcyBpbiBicmFja2V0cy4NCg0KVGhlIG9iamVjdHMgeCBhbmQgZGF0ZXMgaGF2ZSBiZWVuIHByZS1sb2FkZWQgaW4geW91ciB3b3Jrc3BhY2UuDQoNCkluc3RydWN0aW9ucw0KLSBVc2UgdGhlIHZlY3RvciBkYXRlcyB0byBzdWJzZXQgdGhlIG9iamVjdCB4Lg0KLSBTdWJzZXQgeCB1c2luZyBkYXRlcyB0aGF0IGFyZSBmaXJzdCBjb252ZXJ0ZWQgdG8gUE9TSVhjdC4NCg0KYGBge3J9DQojIFN1YnNldCB4IHVzaW5nIHRoZSB2ZWN0b3IgZGF0ZXMNCnhbZGF0ZXNdDQoNCiMgU3Vic2V0IHggdXNpbmcgZGF0ZXMgYXMgUE9TSVhjdA0KeFthcy5QT1NJWGN0KGRhdGVzKV0NCmBgYA0KDQojIyMgVXBkYXRlIGFuZCByZXBsYWNlIGVsZW1lbnRzDQoNClJlcGxhY2luZyB2YWx1ZXMgaW4geHRzIG9iamVjdHMgaXMganVzdCBhcyBlYXN5IGFzIGV4dHJhY3RpbmcgdGhlbS4gWW91IGNhbiB1c2UgZWl0aGVyIElTTy04NjAxIHN0cmluZ3MsIGRhdGUgb2JqZWN0cywgbG9naWNhbHMsIG9yIGludGVnZXJzIHRvIGxvY2F0ZSB0aGUgcm93cyB5b3Ugd2FudCB0byByZXBsYWNlLiBPbmUgcmVhc29uIHlvdSBtYXkgd2FudCB0byBkbyB0aGlzIHdvdWxkIGJlIHRvIHJlcGxhY2Uga25vd24gaW50ZXJ2YWxzIG9yIG9ic2VydmF0aW9ucyB3aXRoIE5BLCBzYXkgZHVlIHRvIGEgbWFsZnVuY3Rpb25pbmcgc2Vuc29yIG9uIGEgcGFydGljdWxhciBkYXkgb3IgYSBzZXQgb2Ygb3V0bGllcnMgZ2l2ZW4gYSBob2xpZGF5Lg0KDQpGb3IgaW5kaXZpZHVhbCBvYnNlcnZhdGlvbnMgbG9jYXRlZCBzcG9yYWRpY2FsbHkgdGhyb3VnaG91dCB5b3VyIGRhdGEgZGF0ZXMsIGludGVnZXJzIG9yIGxvZ2ljYWwgdmVjdG9ycyBhcmUgYSBncmVhdCBjaG9pY2UuIEZvciBjb250aW51b3VzIGJsb2NrcyBvZiB0aW1lLCBJU08tODYwMSBpcyB0aGUgcHJlZmVycmVkIG1ldGhvZC4NCg0KSW4gdGhpcyBleGVyY2lzZSwgeW91J2xsIGNvbnRpbnVlIHVzaW5nIHRoZSB2ZWN0b3IgZGF0ZXMgZnJvbSB0aGUgcHJldmlvdXMgZXhlcmNpc2UgdG8gbW9kaWZ5IHlvdXIgeCBvYmplY3QuIEJvdGggYXJlIGFscmVhZHkgbG9hZGVkIGluIHlvdXIgd29ya3NwYWNlLg0KDQpJbnN0cnVjdGlvbnMNCiAtIFVzZSB0aGUgdmVjdG9yIGRhdGVzIHRvIHJlcGxhY2UgdmFsdWVzIGluIHggd2l0aCBOQSB2YWx1ZXMuDQogLSBSZXBsYWNlIGFsbCB2YWx1ZXMgaW4geCBmb3IgZGF0ZXMgKG5vdCByZWZlcnJpbmcgdG8gdGhlIHZlY3RvcikgZnJvbSBKdW5lIDksIDIwMTYgb253YXJkIHdpdGggIC0gMC4gVXNlIElTTy04NjAxIHN0eWxlIHJlcGxhY2VtZW50Lg0KIC0gVXNlIHRoZSBjb25zb2xlIHRvIGxvb2sgYXQgdGhlIHZhbHVlIGZvciBKdW5lIDExLCAyMDE2IHRvIHNob3cgdGhhdCB5b3VyIGhhcmQgd29yayBoYXMgcGFpZCBvZmYhDQoNCmBgYHtyfQ0KIyBSZXBsYWNlIHRoZSB2YWx1ZXMgaW4geCBjb250YWluZWQgaW4gdGhlIGRhdGVzIHZlY3RvciB3aXRoIE5BDQp4W2RhdGVzXSA8LSBOQQ0KDQojIFJlcGxhY2UgYWxsIHZhbHVlcyBpbiB4IGZvciBkYXRlcyBzdGFydGluZyBKdW5lIDksIDIwMTYgd2l0aCAwDQp4WyIyMDE2LTA2LTA5LyJdIDwtIDANCg0KIyBWZXJpZnkgdGhhdCB0aGUgdmFsdWUgaW4geCBmb3IgSnVuZSAxMSwgMjAxNiBpcyBub3cgaW5kZWVkIDANCnhbIjIwMTYwNjExIl0NCmBgYA0KDQojIyBBZGRpdGlvbmFsIE1ldGhvZHMgVG8gRmluZCBQZXJpb2RzIGluIFlvdXIgRGF0YSAtIFZpZGVvDQoNCiMjIyBGaW5kIHRoZSBmaXJzdCBvciBsYXN0IHBlcmlvZCBvZiB0aW1lDQoNClNvbWV0aW1lcyB5b3UgbmVlZCB0byBsb2NhdGUgZGF0YSBieSByZWxhdGl2ZSB0aW1lLiBTb21ldGhpbmcgdGhhdCBpcyBlYXNpZXIgc2FpZCB0aGFuIHB1dCBpbnRvIGNvZGUuIFRoaXMgaXMgZXF1aXZhbGVudCB0byByZXF1ZXN0aW5nIHRoZSBoZWFkIG9yIHRhaWwgb2YgYSBzZXJpZXMsIGJ1dCBpbnN0ZWFkIG9mIHVzaW5nIGFuIGFic29sdXRlIG9mZnNldCwgeW91IGRlc2NyaWJlIGEgcmVsYXRpdmUgcG9zaXRpb24gaW4gdGltZS4gQSBzaW1wbGUgZXhhbXBsZSB3b3VsZCBiZSBzb21ldGhpbmcgbGlrZSB0aGUgbGFzdCAzIHdlZWtzIG9mIGEgc2VyaWVzLCBvciB0aGUgZmlyc3QgZGF5IG9mIGN1cnJlbnQgbW9udGguDQoNCldpdGhvdXQgYSB0aW1lIGF3YXJlIG9iamVjdCwgdGhpcyBnZXRzIHF1aXRlIGNvbXBsaWNhdGVkIHZlcnkgcXVpY2tseS4gTHVja2lseSwgeHRzIGhhcyB0aGUgbmVjZXNzYXJ5IHByZXJlcXVpc2l0ZXMgYnVpbHQgaW4gZm9yIHlvdSB0byB1c2Ugd2l0aCB2ZXJ5IGxpdHRsZSBsZWFybmluZyByZXF1aXJlZC4gVXNpbmcgdGhlIGZpcnN0KCkgYW5kIGxhc3QoKSBmdW5jdGlvbnMgaXQgaXMgYWN0dWFsbHkgcXVpdGUgZWFzeSENCg0KRm9yIHRoaXMgZXhlcmNpc2UsIHlvdSdsbCBleHRyYWN0IHJlbGF0aXZlIG9ic2VydmF0aW9ucyBmcm9tIGEgZGF0YSBzZXQgY2FsbGVkIHRlbXBzLCBhIHRpbWUgc2VyaWVzIG9mIHN1bW1lciB0ZW1wZXJhdHVyZSBkYXRhIGZyb20gQ2hpY2FnbywgSUwsIFVTQS4NCg0KSW5zdHJ1Y3Rpb25zDQogLSBDcmVhdGUgYSBuZXcgdmFyaWFibGUgbGFzdHdlZWsgYnkgZXh0cmFjdGluZyB0aGUgbGFzdCAxIHdlZWsgZnJvbSB0ZW1wcy4NCiAtIFVzaW5nIHlvdXIgbmV3bHkgY3JlYXRlZCBkYXRhLCBleHRyYWN0IHRoZSBsYXN0IDIgb2JzZXJ2YXRpb25zIHdpdGhvdXQgcmVzcGVjdCB0byB0aW1lLg0KIC0gTm93IGV4dHJhY3QgZXZlcnkgZGF5IGZyb20gbGFzdHdlZWsgZXhjZXB0IHRoZSBmaXJzdCB0d28gZGF5cyAodGhpcyBpcyB0cmlja3khKS4NCiANCmBgYHtyfQ0KIyBDcmVhdGUgbGFzdHdlZWsgdXNpbmcgdGhlIGxhc3QgMSB3ZWVrIG9mIHRlbXBzDQpsYXN0d2VlayA8LSBsYXN0KHRlbXBzLCAiMSB3ZWVrIikNCg0KIyBQcmludCB0aGUgbGFzdCAyIG9ic2VydmF0aW9ucyBpbiBsYXN0d2Vlaw0KbGFzdChsYXN0d2VlaywgMikNCg0KIyBFeHRyYWN0IGFsbCBidXQgdGhlIGZpcnN0IHR3byBkYXlzIG9mIGxhc3R3ZWVrDQpmaXJzdChsYXN0d2VlaywgIi0yIGRheXMiKQ0KYGBgDQoNCiMjIyBDb21iaW5pbmcgZmlyc3QgYW5kIGxhc3QNCg0KTm93IHRoYXQgeW91IGhhdmUgc2VlbiBob3cgdG8gZXh0cmFjdCB0aGUgZmlyc3Qgb3IgbGFzdCBjaHVuayBvZiBhIHRpbWUgc2VyaWVzIHVzaW5nIG5hdHVyYWwgbG9va2luZyBsYW5ndWFnZSwgaXQgaXMgb25seSBhIG1hdHRlciBvZiB0aW1lIGJlZm9yZSB5b3UgbmVlZCB0byBnZXQgYSBiaXQgbW9yZSBjb21wbGV4Lg0KDQpJbiB0aGlzIGV4ZXJjaXNlLCB5b3UnbGwgZXh0cmFjdCBhIHZlcnkgc3BlY2lmaWMgc3Vic2V0IG9mIG9ic2VydmF0aW9ucyBieSBsaW5raW5nIHRvZ2V0aGVyIG11bHRpcGxlIGNhbGxzIHRvIGZpcnN0KCkgYW5kIGxhc3QoKS4NCg0KYGBge3J9DQojIExhc3QgMyBkYXlzIG9mIGZpcnN0IHdlZWsNCmxhc3QoZmlyc3QoVGVtcHMsICcxIHdlZWsnKSwgJzMgZGF5cycpIA0KYGBgDQoNCllvdSB3aWxsIHJlY29uZmlndXJlIHRoZSBleGFtcGxlIGFib3ZlIHVzaW5nIHRoZSB0ZW1wcyBkYXRhIGZyb20gdGhlIHByZXZpb3VzIGV4ZXJjaXNlLiBUaGUgdHJpY2sgdG8gdXNpbmcgc3VjaCBhIGNvbXBsZXggY29tbWFuZCBpcyB0byB3b3JrIGZyb20gdGhlIGluc2lkZSBmdW5jdGlvbiwgb3V0Lg0KDQpJbnN0cnVjdGlvbnMNCiAtIEZpbmQgdGhlIGZpcnN0IHRocmVlIGRheXMgb2YgdGhlIHNlY29uZCB3ZWVrIG9mIHRoZSB0ZW1wcyBkYXRhIHNldC4gVXNlIGNvbWJpbmF0aW9ucyBvZiBmaXJzdCgpIGFuZCBsYXN0KCkgdG8gZG8gdGhpcy4NCiANCmBgYHtyfQ0KIyBFeHRyYWN0IHRoZSBmaXJzdCB0aHJlZSBkYXlzIG9mIHRoZSBzZWNvbmQgd2VlayBvZiB0ZW1wcw0KZmlyc3QobGFzdChmaXJzdCh0ZW1wcywgIjIgd2Vla3MiKSwgIjEgd2VlayIpLCAiMyBkYXlzIikNCmBgYA0KDQogDQojIyBNYXRoIG9wZXJhdGlvbnMgaW4geHRzIC0gVmlkZW8NCg0KIyMjIE1hdHJpeCBhcml0aG1ldGljIC0gYWRkLCBzdWJ0cmFjdCwgbXVsdGlwbHksIGFuZCBkaXZpZGUgaW4gdGltZSENCg0KeHRzIG9iamVjdHMgcmVzcGVjdCB0aW1lLiBCeSBkZXNpZ24gd2hlbiB5b3UgcGVyZm9ybSBhbnkgYmluYXJ5IG9wZXJhdGlvbiB1c2luZyB0d28geHRzIG9iamVjdHMsIHRoZXNlIG9iamVjdHMgYXJlIGZpcnN0IGFsaWduZWQgdXNpbmcgdGhlIGludGVyc2VjdGlvbiBvZiB0aGUgaW5kZXhlcy4gVGhpcyBtYXkgYmUgc3VycHJpc2luZyB3aGVuIGZpcnN0IGVuY291bnRlcmVkLg0KDQpUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQgeW91IHdhbnQgdG8gcHJlc2VydmUgdGhlIHBvaW50LWluLXRpbWUgYXNwZWN0IG9mIHlvdXIgZGF0YSwgYXNzdXJpbmcgdGhhdCB5b3UgZG9uJ3QgaW50cm9kdWNlIGFjY2lkZW50YWwgbG9vayBhaGVhZCAob3IgbG9vayBiZWhpbmQhKSBiaWFzIGludG8geW91ciBjYWxjdWxhdGlvbnMuDQoNCldoYXQgdGhpcyBtZWFucyBpbiBwcmFjdGljZSBpcyB0aGF0IHlvdSB3aWxsIHNvbWV0aW1lcyBiZSB0YXNrZWQgd2l0aCBoYW5kbGluZyB0aGlzIGJlaGF2aW9yIGlmIHlvdSB3YW50IHRvIHByZXNlcnZlIHRoZSBkaW1lbnNpb25zIG9mIHlvdXIgZGF0YS4NCg0KWW91ciBvcHRpb25zIGluY2x1ZGU6DQoNClVzZSBjb3JlZGF0YSgpIG9yIGFzLm51bWVyaWMoKSAoZHJvcCBvbmUgdG8gYSBtYXRyaXggb3IgdmVjdG9yKS4NCk1hbnVhbGx5IHNoaWZ0IGluZGV4IHZhbHVlcyAtIGkuZS4gdXNlIGxhZygpLg0KUmVpbmRleCB5b3VyIGRhdGEgKGJlZm9yZSBvciBhZnRlciB0aGUgY2FsY3VsYXRpb24pLg0KSW4gdGhpcyBleGVyY2lzZSwgeW91J2xsIGxvb2sgYXQgdGhlIG5vcm1hbCBiZWhhdmlvciwgYXMgd2VsbCBhcyBhbiBleGFtcGxlIHVzaW5nIHRoZSBmaXJzdCBvcHRpb24uIEZvciBub3cgeW91IHdpbGwgdXNlIHR3byBzbWFsbCBvYmplY3RzIGEgYW5kIGIuIEV4YW1pbmUgdGhlc2Ugb2JqZWN0cyBpbiB0aGUgY29uc29sZSBiZWZvcmUgeW91IHN0YXJ0Lg0KDQpJbnN0cnVjdGlvbnMNCkFkZCBhIGFuZCBiLiBOb3RpY2UgdGhlIGJlaGF2aW9yIG9mIHRoZSBkYXRlcywgd2hpY2ggb25lcyByZW1haW4/DQpBZGQgYSB3aXRoIHRoZSBudW1lcmljIHZhbHVlIG9mIGIuIGIgd2lsbCBuZWVkIHRvIGJlIGNvbnZlcnRlZCB0byBhIG51bWVyaWMgZm9yIHRoaXMgdG8gd29yay4NCg0KYGBge3J9DQojIEFkZCBhIGFuZCBiDQphK2INCg0KIyBBZGQgYSB3aXRoIHRoZSBudW1lcmljIHZhbHVlIG9mIGINCmEgKyBhcy5udW1lcmljKGIpDQpgYGANCg0KIyMjIE1hdGggd2l0aCBub24tb3ZlcmxhcHBpbmcgaW5kZXhlcw0KDQpUaGUgcHJldmlvdXMgZXhlcmNpc2UgaWxsdXN0cmF0ZWQgdGhlIGlucyBhbmQgb3V0cyBvZiBkb2luZyBiYXNpYyBtYXRoIHdpdGggeHRzIG9iamVjdHMuIEF0IHRoaXMgcG9pbnQgeW91IGFyZSBhd2FyZSB0aGF0IHh0cyByZXNwZWN0cyB0aW1lIGFuZCB3aWxsIG9ubHkgcmV0dXJuIHRoZSBpbnRlcnNlY3Rpb24gb2YgdGltZXMgd2hlbiBkb2luZyB2YXJpb3VzIG1hdGhlbWF0aWNhbCBvcGVyYXRpb25zLg0KDQpXZSBhbGx1ZGVkIHRvIGFub3RoZXIgd2F5IHRvIGhhbmRsZSB0aGlzIGJlaGF2aW9yIGluIHRoZSBsYXN0IGV4ZXJjaXNlLiBOYW1lbHksIHJlLWluZGV4aW5nIHlvdXIgZGF0YSBiZWZvcmUgYW4gb3BlcmF0aW9uLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIHByZXNlcnZlIHRoZSBkaW1lbnNpb25zIG9mIHlvdXIgZGF0YSBieSBsZXZlcmFnaW5nIHRoZSBzYW1lIG1lY2hhbmlzbSB0aGF0IHh0cyB1c2VzIGludGVybmFsbHkgaW4gaXRzIG93biBPcHMgbWV0aG9kICh0aGUgY29kZSBkaXNwYXRjaGVkIHdoZW4geW91IGNhbGwgKyBvciBzaW1pbGFyKS4NCg0KVGhlIHRoaXJkIHdheSBpbnZvbHZlcyBtb2RpZnlpbmcgdGhlIHR3byBzZXJpZXMgeW91IHdhbnQgYnkgYXNzdXJpbmcgeW91IGhhdmUgc29tZSB1bmlvbiBvZiBkYXRlcyAtIHRoZSBkYXRlcyB5b3UgcmVxdWlyZSBpbiB5b3VyIGZpbmFsIG91dHB1dC4gVG8gZG8gdGhpcyB5b3Ugd2lsbCBuZWVkIGEgZmV3IGZ1bmN0aW9ucyB0aGF0IHdvbid0IGJlIGRlYWx0IHdpdGggaW4gZGVwdGggdW50aWwgQ2hhcHRlciAzLCBidXQgYXJlIHZlcnkgdXNlZnVsIGhlcmUuDQoNCm1lcmdlKGIsIGluZGV4KGEpKQ0KRG9uJ3Qgd29ycnkgaWYgeW91IGFyZW4ndCB5ZXQgZmFtaWxpYXIgd2l0aCBtZXJnZSgpLiBUaGlzIGV4ZXJjaXNlIG1heSBiZSBlYXNpZXIgaWYgeW91IGp1c3QgZm9sbG93IGFsb25nIHdpdGggdGhlIGluc3RydWN0aW9ucy4NCg0KSW5zdHJ1Y3Rpb25zDQpVc2luZyBhIGFuZCBiIGZyb20gdGhlIHByZXZpb3VzIGV4ZXJjaXNlLCBnZXQgdGhlIHZhbHVlIG9mIGEgKyBiIGZvciBlYWNoIGRhdGUgaW4gYS4gSWYgbm8gYiBpcyBhdmFpbGFibGUgb24gYSBnaXZlbiBkYXRlLCB0aGUgYW5zd2VyIHNob3VsZCBiZSBhIG9uIHRoYXQgZGF0ZS4NCk5vdyBhZGQgYSB0byBiLCBidXQgdGhpcyB0aW1lIG1ha2Ugc3VyZSBhbGwgdmFsdWVzIG9mIGEgYXJlIGFkZGVkIHRvIHRoZSBsYXN0IGtub3duIHZhbHVlIG9mIGIgaW4gdGltZS4NCg0KYGBge3J9DQojIEFkZCBhIHRvIGIsIGFuZCBmaWxsIGFsbCBtaXNzaW5nIHJvd3Mgb2YgYiB3aXRoIDANCmEgKyBtZXJnZShiLCBpbmRleChhKSwgZmlsbCA9IDApDQoNCiMgQWRkIGEgdG8gYiBhbmQgZmlsbCBOQXMgd2l0aCB0aGUgbGFzdCBvYnNlcnZhdGlvbg0KYSArIG1lcmdlKGIsIGluZGV4KGEpLCBmaWxsID0gbmEubG9jZikNCmBgYA0KDQojIDMuIE1lcmdpbmcgYW5kIG1vZGlmeWluZyB0aW1lIHNlcmllcw0KDQojIyBNZXJnaW5nIGFuZCBtb2RpZnlpbmcgdGltZSBzZXJpZXMgLSBWaWRlbw0KDQojIyMgQ29tYmluaW5nIHh0cyBieSBjb2x1bW4gd2l0aCBtZXJnZQ0KDQp4dHMgbWFrZXMgaXQgZWFzeSB0byBqb2luIGRhdGEgYnkgY29sdW1uIGFuZCByb3cgdXNpbmcgYSBmZXcgZGlmZmVyZW50IGZ1bmN0aW9ucy4gQWxsIHJlc3VsdHMgd2lsbCBiZSBjb3JyZWN0bHkgb3JkZXJlZCBpbiB0aW1lLCByZWdhcmRsZXNzIG9mIG9yaWdpbmFsIGZyZXF1ZW5jaWVzIG9yIGRhdGUgY2xhc3MuIE9uZSBvZiB0aGUgbW9zdCBpbXBvcnRhbnQgZnVuY3Rpb25zIHRvIGFjY29tcGxpc2ggdGhpcyBpcyBtZXJnZSgpLiBJdCB0YWtlcyBvbmUgb3IgbW9yZSBzZXJpZXMgYW5kIGpvaW5zIHRoZW0gYnkgY29sdW1uLiBJdCdzIGFsc28gcG9zc2libGUgdG8gY29tYmluZSBhIHNlcmllcyB3aXRoIGEgdmVjdG9yIG9mIGRhdGVzLiBUaGlzIGlzIGVzcGVjaWFsbHkgdXNlZnVsIGZvciBub3JtYWxpemluZyBvYnNlcnZhdGlvbnMgdG8gYSBmaXhlZCBjYWxlbmRhci4NCg0KbWVyZ2UoKSB0YWtlcyB0aHJlZSBrZXkgYXJndW1lbnRzIHdoaWNoIHdlIHdpbGwgZW1waGFzaXplIGhlcmUuIEZpcnN0IGlzIHRoZSAuLi4sIHdoaWNoIGxldHMgeW91IHBhc3MgaW4gYW4gYXJiaXRyYXJ5IG51bWJlciBvZiBvYmplY3RzIHRvIGNvbWJpbmUuIFRoZSBzZWNvbmQgYXJndW1lbnQgaXMgam9pbiwgd2hpY2ggc3BlY2lmaWVzIGhvdyB0byBqb2luIHRoZSBzZXJpZXMgLSBhY2NlcHRpbmcgYXJndW1lbnRzIHN1Y2ggYXMgaW5uZXIgb3IgbGVmdC4gVGhpcyBpcyBzaW1pbGFyIHRvIGEgcmVsYXRpb25hbCBkYXRhYmFzZSBqb2luLCBvbmx5IGhlcmUsIHRoZSBpbmRleCBpcyB3aGF0IHdlIGpvaW4gb24uIFRoZSBmaW5hbCBhcmd1bWVudCBmb3IgdGhpcyBleGVyY2lzZSBpcyBmaWxsLiBUaGlzIGtleXdvcmQgc3BlY2lmaWVzIHdoYXQgdG8gZG8gd2l0aCB0aGUgbmV3IHZhbHVlcyBpbiBhIHNlcmllcyBpZiB0aGVyZSBpcyBtaXNzaW5nbmVzcyBpbnRyb2R1Y2VkIGFzIGEgcmVzdWx0IG9mIHRoZSBtZXJnZS4NCg0KDQpgYGB7cn0NCiMgQmFzaWMgYXJndW1lbnQgdXNlDQptZXJnZShhLCBiLCBqb2luID0gInJpZ2h0IiwgZmlsbCA9IDk5OTkpDQpgYGANCg0KRm9yIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIGV4cGxvcmUgc29tZSBvZiB0aGUgZGlmZmVyZW50IGpvaW4gdHlwZXMgdG8gZ2V0IGEgZmVlbCBmb3IgdXNpbmcgbWVyZ2UoKS4gVGhlIG9iamVjdHMgYSBhbmQgYiBoYXZlIGJlZW4gcHJlLWxvYWRlZCBpbnRvIHlvdXIgd29ya3NwYWNlLg0KDQpJbnN0cnVjdGlvbnMNCi0gTWVyZ2UgYSBhbmQgYiB1c2luZyBtZXJnZSgpIChvciBjYmluZCgpKSwgd2l0aCB0aGUgYXJndW1lbnQgam9pbiBzZXQgdG8gImlubmVyIi4NCi0gUGVyZm9ybSBhIGxlZnQtam9pbiBvZiBhIGFuZCBiLiBVc2UgbWVyZ2UoKSBhbmQgc2V0IHRoZSBhcmd1bWVudCBqb2luIHRvIHRoZSBjb3JyZWN0IHZhbHVlLiBGaWxsIGFsbCBtaXNzaW5nIHZhbHVlcyB3aXRoIHplcm8gKHVzZSB0aGUgZmlsbCBhcmd1bWVudCkuDQoNCg0KYGBge3J9DQojIFBlcmZvcm0gYW4gaW5uZXIgam9pbiBvZiBhIGFuZCBiDQptZXJnZShhLCBiLCBqb2luID0gImlubmVyIikNCg0KIyBQZXJmb3JtIGEgbGVmdC1qb2luIG9mIGEgYW5kIGIsIGZpbGwgbWlzc2luZyB2YWx1ZXMgd2l0aCAwDQptZXJnZShhLCBiLCBqb2luID0gImxlZnQiLCBmaWxsID0gMCkNCg0KYGBgDQoNCk1lcmdpbmcgeHRzIG9iamVjdHMgYnkgY29sdW1uIGNvbWVzIGluIGhhbmR5IHdoZW4gcHJlcGFyaW5nIGRhdGEgZm9yIHRpbWUgc2VyaWVzIGFuYWx5c2lzLg0KDQojIyMgQ29tYmluaW5nIHh0cyBieSByb3cgd2l0aCByYmluZA0KDQpOb3cgdGhhdCB5b3UgaGF2ZSBtZXJnZWQgZGF0YSBieSBjb2x1bW4sIHlvdSB3aWxsIGJlIGhhcHB5IHRvIGtub3cgaXQncyBqdXN0IGFzIGVhc3kgdG8gYWRkIG5ldyByb3dzIHRvIHlvdXIgZGF0YS4NCg0KeHRzIHByb3ZpZGVzIGl0cyBvd24gUzMgbWV0aG9kIHRvIHRoZSBiYXNlIHJiaW5kKCkgZ2VuZXJpYyBmdW5jdGlvbi4gVGhlIHh0cyByYmluZCBmdW5jdGlvbiBpcyBtdWNoIHNpbXBsZXIgdGhhbiBtZXJnZSgpLiBUaGUgb25seSBhcmd1bWVudCB0aGF0IG1hdHRlcnMgaXMgLi4uLCB3aGljaCB0YWtlcyBhbiBhcmJpdHJhcnkgbnVtYmVyIG9mIG9iamVjdHMgdG8gYmluZC4gV2hhdCBpcyBkaWZmZXJlbnQgaXMgdGhhdCByYmluZCByZXF1aXJlcyBhIHRpbWUgc2VyaWVzLCBzaW5jZSB3ZSBuZWVkIHRvIGhhdmUgdGltZXN0YW1wcyBmb3IgUiB0byBrbm93IHdoZXJlIHRvIGluc2VydCBuZXcgZGF0YS4NCg0KRm9yIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgdXBkYXRlIHlvdXIgdGVtcHMgZGF0YSB3aXRoIHRocmVlIG5ldyBvYnNlcnZhdGlvbnMuIE9uZSB3aWxsIGJlIGJlZm9yZSB0aGUgc2VyaWVzIHN0YXJ0ZWQgYW5kIHR3byB3aWxsIGJlIGFmdGVyLiBQYXkgYXR0ZW50aW9uIHRvIHlvdXIgZnVuY3Rpb24gY2FsbCwgZG9lcyBvcmRlciBtYXR0ZXI/DQoNCkluIHlvdXIgd29ya3NwYWNlLCB0aGUgb2JqZWN0cyB0ZW1wcywgdGVtcHNfanVuZTMwLCB0ZW1wc19qdWx5MTcgYW5kIHRlbXBzX2p1bHkxOCBhcmUgYWxyZWFkeSBsb2FkZWQuDQoNCkluc3RydWN0aW9ucw0KIC0gQmluZCB0aGUgcm93IGZyb20gSnVuZSAzMHRoICh0ZW1wc19qdW5lMzApIHRvIHRlbXBzLCBhbmQgY2FsbCB0aGlzIHRlbXBzMi4NCiAtIEJpbmQgdGhlIHJvd3MgZnJvbSBKdWx5IDE3dGggYW5kIDE4dGggdG8gdGVtcHMyLiBDYWxsIHRoaXMgdGVtcHMzLg0KDQpgYGB7cn0NCiMgUm93IGJpbmQgdGVtcHNfanVuZTMwIHRvIHRlbXBzLCBhc3NpZ24gdGhpcyB0byB0ZW1wczINCnRlbXBzMiA8LSByYmluZCh0ZW1wcywgdGVtcHNfanVuZTMwKQ0KDQojIFJvdyBiaW5kIHRlbXBzX2p1bHkxNyBhbmQgdGVtcHNfanVseTE4IHRvIHRlbXBzMiwgY2FsbCB0aGlzIHRlbXBzMw0KdGVtcHMzIDwtIHJiaW5kKHRlbXBzX2p1bHkxNywgdGVtcHNfanVseTE4LCB0ZW1wczIpDQpgYGANCg0KQmVjYXVzZSB4dHMgb2JqZWN0cyBhcmUgb3JkZXJlZCBieSB0aGVpciB0aW1lIGluZGV4LCB0aGUgb3JkZXIgb2YgYXJndW1lbnRzIGluIHh0cydzIHJiaW5kKCkgY29tbWFuZCBpcyB1bmltcG9ydGFudC4NCg0KIyMjIFdoYXQgdHlwZXMgb2YgZGF0YSBjYW4gYmUgY29tYmluZWQgdXNpbmcgbWVyZ2U/DQoNCkFsdGhvdWdoIHh0cyBpcyB2ZXJ5IGZsZXhpYmxlIHdoZW4gaXQgY29tZXMgdG8gYmluZGluZyBuZXcgY29sdW1ucyB0byBleGlzdGluZyBvYmplY3RzLCB0aGVyZSBhcmUgc3RpbGwgc29tZSBleGNlcHRpb25zLiBXaGljaCBvZiB0aGUgZm9sbG93aW5nIGlzIG5vdCBhYmxlIHRvIGJlIHN1Y2Nlc3NmdWxseSBtZXJnZWQgd2l0aCB0aGUgeHRzIG9iamVjdCBhPw0KDQpCZWZvcmUgeW91IGFuc3dlciwgdHJ5IGVhY2ggcG9zc2liaWxpdHkgaW4gdGhlIGNvbnNvbGUgdG8geW91ciByaWdodCB0byBzZWUgaG93IHRoZXkgYmVoYXZlLiBXZSd2ZSBwcm92aWRlZCB0d28gdGltZSBzZXJpZXMsIGEgYW5kIGIgZm9yIHlvdSB0byB3b3JrIHdpdGguDQoNClBvc3NpYmxlIEFuc3dlcnMNCiAtIHh0cyBvYmplY3RzIG9mIGlkZW50aWNhbCB0eXBlIChlLmcuIGludGVnZXIgKyBpbnRlZ2VyKS4NCiAtIGRhdGEuZnJhbWVzIHdpdGggdmFyaW91cyBjb2x1bW4gdHlwZXMuIChDb3JyZWN0KQ0KIC0gUE9TSVhjdCBkYXRlcyB2ZWN0b3IuDQogLSBBdG9taWMgdmVjdG9ycyBvZiB0aGUgc2FtZSB0eXBlIChlLmcuIG51bWVyaWMpLg0KIC0gQSBzaW5nbGUgTkEuIA0KIA0KIyMgSGFuZGxpbmcgbWlzc2luZ25lc3MgaW4geW91ciBkYXRhIC0gVmlkZW8NCg0KIyMjIEZpbGwgbWlzc2luZyB2YWx1ZXMgdXNpbmcgbGFzdCBvciBwcmV2aW91cyBvYnNlcnZhdGlvbg0KDQpBcyB5b3UndmUgZW5jb3VudGVyZWQgYWxyZWFkeSwgaXQncyBub3QgdW5jb21tb24gdG8gZmluZCB5b3Vyc2VsZiB3aXRoIG1pc3NpbmcgdmFsdWVzIChpLmUuIE5BcykgaW4geW91ciB0aW1lIHNlcmllcy4gVGhpcyBtYXkgYmUgdGhlIHJlc3VsdCBvZiBhIGRhdGEgb21pc3Npb24gb3Igc29tZSBtYXRoZW1hdGljYWwgb3IgbWVyZ2Ugb3BlcmF0aW9uIHlvdSBkbyBvbiB5b3VyIGRhdGEuDQoNClRoZSB4dHMgcGFja2FnZSBsZXZlcmFnZXMgdGhlIHBvd2VyIG9mIHpvbyBmb3IgaGVscCB3aXRoIHRoaXMuIHpvbyBwcm92aWRlcyBhIHZhcmlldHkgb2YgbWlzc2luZyBkYXRhIGhhbmRsaW5nIGZ1bmN0aW9ucyB3aGljaCBhcmUgdXNhYmxlIGJ5IHh0cy4NCg0KSW4gdGhpcyBleGVyY2lzZSB5b3Ugd2lsbCB1c2UgdGhlIG1vc3QgYmFzaWMgb2YgdGhlc2UsIG5hLmxvY2YoKS4gVGhpcyBmdW5jdGlvbiB0YWtlcyB0aGUgbGFzdCBvYnNlcnZhdGlvbiBjYXJyaWVkIGZvcndhcmQgYXBwcm9hY2guIEluIG1vc3QgY2lyY3Vtc3RhbmNlcyB0aGlzIGlzIHRoZSBjb3JyZWN0IHRoaW5nIHRvIGRvLiBJdCBib3RoIHByZXNlcnZlcyB0aGUgbGFzdCBrbm93biB2YWx1ZSBhbmQgcHJldmVudHMgYW55IGxvb2stYWhlYWQgYmlhcyBmcm9tIGVudGVyaW5nIGludG8gdGhlIGRhdGEuDQoNCllvdSBjYW4gYWxzbyBhcHBseSBuZXh0IG9ic2VydmF0aW9uIGNhcnJpZWQgYmFja3dhcmQgYnkgc2V0dGluZyBmcm9tTGFzdCA9IFRSVUUuDQoNCmBgYHtyfQ0KIyBMYXN0IG9icy4gY2FycmllZCBmb3J3YXJkDQpuYS5sb2NmKHgpICAgICAgICAgICAgICAgIA0KDQojIE5leHQgb2JzLiBjYXJyaWVkIGJhY2t3YXJkDQpuYS5sb2NmKHgsIGZyb21MYXN0ID0gVFJVRSkgDQpgYGANCg0KSW5zdHJ1Y3Rpb25zICANCg0KIC0gVXNpbmcgYSBzdWJzZXQgb2YgdGVtcHMsIGZpbGwgbWlzc2luZyBOQSBvYnNlcnZhdGlvbnMgd2l0aCB0aGUgbGFzdCBvYnNlcnZhdGlvbiBrbm93bi4gU3RvcmUgIC0gdGhlbSBpbiB0ZW1wc19sYXN0Lg0KIC0gVXNpbmcgYW5vdGhlciBzdWJzZXQgb2YgdGVtcHMsIGJhY2tmaWxsIG1pc3NpbmcgTkEgb2JzZXJ2YXRpb25zIHdpdGggdGhlIG5leHQgb2JzZXJ2YXRpb24uICAtIFN0b3JlIHRoZW0gaW4gdGVtcHNfbmV4dC4NCg0KYGBge3J9DQojIEZpbGwgbWlzc2luZyB2YWx1ZXMgaW4gdGVtcHMgdXNpbmcgdGhlIGxhc3Qgb2JzZXJ2YXRpb24NCnRlbXBzX2xhc3QgPC0gbmEubG9jZih0ZW1wcykgIA0KDQojIEZpbGwgbWlzc2luZyB2YWx1ZXMgaW4gdGVtcHMgdXNpbmcgdGhlIG5leHQgb2JzZXJ2YXRpb24NCnRlbXBzX25leHQgPC0gbmEubG9jZih0ZW1wcywgZnJvbUxhc3Q9VFJVRSkNCmBgYA0KDQojIyMgTkEgaW50ZXJwb2xhdGlvbiB1c2luZyBuYS5hcHByb3goKQ0KDQpPbiBvY2Nhc2lvbiwgYSBzaW1wbGUgY2FycnkgZm9yd2FyZCBhcHByb2FjaCB0byBtaXNzaW5nbmVzcyBpc24ndCBhcHByb3ByaWF0ZS4gSXQgbWF5IGJlIHRoYXQgYSBzZXJpZXMgaXMgbWlzc2luZyBhbiBvYnNlcnZhdGlvbiBkdWUgdG8gYSBoaWdoZXIgZnJlcXVlbmN5IHNhbXBsaW5nIHRoYW4gdGhlIGdlbmVyYXRpbmcgcHJvY2Vzcy4gWW91IG1pZ2h0IGFsc28gZW5jb3VudGVyIGFuIG9ic2VydmF0aW9uIHRoYXQgaXMgaW4gZXJyb3IsIHlldCBleHBlY3RlZCB0byBiZSBzb21ld2hlcmUgYmV0d2VlbiB0aGUgdmFsdWVzIG9mIGl0cyBuZWlnaGJvcmluZyBvYnNlcnZhdGlvbnMuDQoNClRoZXNlIGFyZSBzY2VuYXJpb3Mgd2hlcmUgaW50ZXJwb2xhdGlvbiBpcyB1c2VmdWwuIHpvbyBwcm92aWRlcyBhIHBvd2VyZnVsIHRvb2wgdG8gZG8gdGhpcy4gQmFzZWQgb24gc2ltcGxlIGxpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gcG9pbnRzLCBpbXBsZW1lbnRlZCB3aXRoIG5hLmFwcHJveCgpIHRoZSBkYXRhIHBvaW50cyBhcmUgYXBwcm94aW1hdGVkIHVzaW5nIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBpbmRleCB2YWx1ZXMuIEluIG90aGVyIHdvcmRzLCB0aGUgZXN0aW1hdGVkIHZhbHVlIGlzIGxpbmVhciBpbiB0aW1lLg0KDQpGb3IgdGhpcyBleGVyY2lzZSwgeW91J2xsIHVzZSBhIHNtYWxsZXIgeHRzIHZlcnNpb24gb2YgdGhlIEJveCBhbmQgSmVua2luJ3MgQWlyUGFzc2VuZ2VycyBkYXRhIHNldCB0aGF0IHNoaXBzIHdpdGggUi4gV2UndmUgcmVtb3ZlZCBhIGZldyBtb250aHMgb2YgZGF0YSB0byBpbGx1c3RyYXRlIHZhcmlvdXMgZmlsbCB0ZWNobmlxdWVzLg0KDQpPbmUgdGFrZWF3YXksIGFzaWRlIGZyb20gZ2V0dGluZyBhIGZlZWwgZm9yIHRoZSBmdW5jdGlvbnMsIGlzIHRvIHNlZSBob3cgdmFyaW91cyBmaWxsIHRlY2huaXF1ZXMgaW1wYWN0IHlvdXIgZGF0YSwgYW5kIGVzcGVjaWFsbHkgaG93IGl0IHdpbGwgaW1wYWN0IHlvdXIgdW5kZXJzdGFuZGluZyBvZiBpdC4NCg0KQ2F2ZWF0IEVtcHRvciENCg0KVGhlIEFpclBhc3NlbmdlcnMgZGF0YSBzZXQgaXMgYXZhaWxhYmxlIGluIHlvdXIgd29ya3NwYWNlIGFzIEFpclBhc3MuDQoNCkluc3RydWN0aW9ucw0KIC0gRmlsbCBpbiBtaXNzaW5nIG1vbnRocyBpbiBBaXJQYXNzIHdpdGggbGluZWFyIGludGVycG9sYXRpb24gdXNpbmcgbmEuYXBwcm94KCkuDQoNCmBgYHtyfQ0KIyBJbnRlcnBvbGF0ZSBOQXMgdXNpbmcgbGluZWFyIGFwcHJveGltYXRpb24NCm5hLmFwcHJveChBaXJQYXNzKQ0KYGBgDQpMaW5lYXIgaW50ZXJwb2xhdGlvbiBpcyBhIHN0cmFpZ2h0Zm9yd2FyZCB3YXkgdG8gYWNjb3VudCBmb3IgbWlzc2luZ25lc3MsIGFsdGhvdWdoIGl0IGlzIHVwIHRvIHlvdSB0byBkZXRlcm1pbmUgaXRzIGFwcGxpY2FiaWxpdHkuDQoNCiMjIExhZyBvcGVyYXRvcnMgYW5kIGRpZmZlcmVuY2Ugb3BlcmF0aW9ucw0KDQojIyMgQ29tYmluZSBhIGxlYWRpbmcgYW5kIGxhZ2dpbmcgdGltZSBzZXJpZXMNCg0KQW5vdGhlciBjb21tb24gbW9kaWZpY2F0aW9uIGZvciB0aW1lIHNlcmllcyBpcyB0aGUgYWJpbGl0eSB0byBsYWcgYSBzZXJpZXMuIEFsc28ga25vd24gYXMgYSBiYWNrc2hpZnQgb3BlcmF0aW9uLCBpdCdzIHR5cGljYWxseSBzaG93biBpbiBsaXRlcmF0dXJlIHVzaW5nIExrTGsgbm90YXRpb24sIGluZGljYXRpbmcgYSB0cmFuc2Zvcm1hdGlvbiBpbiB0aW1lIExrWD1YdD8/P2tMa1g9WHQ/Pz9rLiBUaGlzIGxldHMgeW91IHNlZSBvYnNlcnZhdGlvbnMgbGlrZSB5ZXN0ZXJkYXkncyB2YWx1ZSBpbiB0aGUgY29udGV4dCBvZiB0b2RheS4NCg0KQm90aCB6b28gYW5kIHh0cyBpbXBsZW1lbnQgdGhpcyBiZWhhdmlvciwgYW5kIGluIGZhY3QgZXh0ZW5kIGl0IGZyb20gdGhlIHRzIG9yaWdpbmFsIGluIFIuIFRoZXJlIGFyZSB0d28gbWFqb3IgZGlmZmVyZW5jZXMgYmV0d2VlbiB4dHMgYW5kIHpvbyBpbXBsZW1lbnRhdGlvbnMgdGhhdCB5b3UgbmVlZCB0byBiZSBhd2FyZSBvZi4gT25lIGlzIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGxhZyBmb3IgYSBnaXZlbiBrLiBUaGUgc2Vjb25kIGlzIGhvdyBtaXNzaW5nbmVzcyBpcyBoYW5kbGVkIGFmdGVyd2FyZHMuDQoNCkZvciBoaXN0b3JpY2FsIHJlYXNvbnMgaW4gUiwgem9vIHVzZXMgYSBjb252ZW50aW9uIGZvciB0aGUgc2lnbiBvZiBrIGluIHdoaWNoIG5lZ2F0aXZlIHZhbHVlcyBpbmRpY2F0ZSBsYWdzIGFuZCBwb3NpdGl2ZSB2YWx1ZXMgaW5kaWNhdGUgbGVhZHMuIFRoYXQgaXMsIGluIHpvbyBsYWcoeCwgayA9IDEpIHdpbGwgc2hpZnQgZnV0dXJlIHZhbHVlcyBvbmUgc3RlcCBiYWNrIGluIHRpbWUuIFRoaXMgaXMgaW5jb25zaXN0ZW50IHdpdGggdGhlIHZhc3QgbWFqb3JpdHkgb2YgdGhlIHRpbWUgc2VyaWVzIGxpdGVyYXR1cmUsIGJ1dCBpcyBjb25zaXN0ZW50IHdpdGggYmVoYXZpb3IgaW4gYmFzZSBSLiB4dHMgaW1wbGVtZW50cyB0aGUgZXhhY3Qgb3Bwb3NpdGUsIG5hbWVseSBmb3IgYSBwb3NpdGl2ZSBrLCB0aGUgc2VyaWVzIHdpbGwgc2hpZnQgdGhlIGxhc3QgdmFsdWUgaW4gdGltZSBvbmUgcGVyaW9kIGZvcndhcmQ7IHRoaXMgaXMgY29uc2lzdGVudCB3aXRoIGludHVpdGlvbiwgYnV0IHF1aXRlIGRpZmZlcmVudCB0aGFuIHpvby4NCg0KSW4gdGhpcyBleGVyY2lzZSwgeW91IHdpbGwgY29uc3RydWN0IGEgc2luZ2xlIHh0cyBvYmplY3Qgd2l0aCB0aHJlZSBjb2x1bW5zLiBUaGUgZmlyc3QgY29sdW1uIGlzIGRhdGEgb25lIGRheSBhaGVhZCwgdGhlIHNlY29uZCBjb2x1bW4gaXMgdGhlIG9yaWdpbmFsIGRhdGEsIGFuZCB0aGUgdGhpcmQgY29sdW1uIGlzIHRoZSBvbmUgZGF5IGJlaGluZCAtIGFsbCB1c2luZyB4dHMuIEEgc2ltcGxlIHh0cyBvYmplY3QsIHgsIGhhcyBiZWVuIGxvYWRlZCBpbnRvIHlvdXIgd29ya3NwYWNlLg0KDQpgYGB7cn0NCiMgWW91ciBmaW5hbCBvYmplY3QNCmNiaW5kKGxlYWRfeCwgeCwgbGFnX3gpDQpgYGANCg0KSW5zdHJ1Y3Rpb25zDQogLSBDcmVhdGUgYSBvbmUgcGVyaW9kIGxlYWQgb2YgeCBjYWxsZWQgbGVhZF94Lg0KIC0gQ3JlYXRlIGEgb25lIHBlcmlvZCBsYWcgb2YgeCBjYWxsZWQgbGFnX3guDQogLSBVc2luZyB0aGUgbWVyZ2UoKSBmdW5jdGlvbiwgY29tYmluZSBsZWFkICsgeCArIGxhZyBpbnRvIGEgbmV3IG9iamVjdCB6Lg0KIA0KYGBge3J9DQojIENyZWF0ZSBhIGxlYWRpbmcgb2JqZWN0IGNhbGxlZCBsZWFkX3gNCmxlYWRfeCA8LSBsYWcoeCwgayA9IC0xKQ0KDQojIENyZWF0ZSBhIGxhZ2dpbmcgb2JqZWN0IGNhbGxlZCBsYWdfeA0KbGFnX3ggPC0gbGFnKHgsIGsgPSAxKQ0KDQojIE1lcmdlIHlvdXIgdGhyZWUgc2VyaWVzIHRvZ2V0aGVyIGFuZCBhc3NpZ24gdG8geg0KeiA9IGNiaW5kKGxlYWRfeCwgeCwgbGFnX3gpDQpgYGANCg0KR2VuZXJhdGluZyBsZWFkcyBhbmQgbGFncyBjYW4gaGVscCB5b3UgdmlzdWFsaXplIHRyZW5kcyBpbiB5b3VyIHRpbWUgc2VyaWVzIGRhdGEgb3ZlciB0aW1lLg0KDQojIyMgQ2FsY3VsYXRlIGEgZGlmZmVyZW5jZSBvZiBhIHNlcmllcyB1c2luZyBkaWZmKCkNCg0KQW5vdGhlciBjb21tb24gb3BlcmF0aW9uIG9uIHRpbWUgc2VyaWVzLCB0eXBpY2FsbHkgb24gdGhvc2UgdGhhdCBhcmUgbm9uLXN0YXRpb25hcnksIGlzIHRvIHRha2UgYSBkaWZmZXJlbmNlIG9mIHRoZSBzZXJpZXMuIFRoZSBudW1iZXIgb2YgZGlmZmVyZW5jZXMgdG8gdGFrZSBvZiBhIHNlcmllcyBpcyBhbiBhcHBsaWNhdGlvbiBvZiByZWN1cnNpdmVseSBjYWxsaW5nIHRoZSBkaWZmZXJlbmNlIGZ1bmN0aW9uIG4gdGltZXMuDQoNCkEgc2ltcGxlIHdheSB0byB2aWV3IGEgc2luZ2xlIChvciAiZmlyc3Qgb3JkZXIiKSBkaWZmZXJlbmNlIGlzIHRvIHNlZSBpdCBhcyB4KHQpIC0geCh0LWspIHdoZXJlIGsgaXMgdGhlIG51bWJlciBvZiBsYWdzIHRvIGdvIGJhY2suIEhpZ2hlciBvcmRlciBkaWZmZXJlbmNlcyBhcmUgc2ltcGx5IHRoZSByZWFwcGxpY2F0aW9uIG9mIGEgZGlmZmVyZW5jZSB0byBlYWNoIHByaW9yIHJlc3VsdC4NCg0KSW4gUiwgdGhlIGRpZmZlcmVuY2Ugb3BlcmF0b3IgZm9yIHh0cyBpcyBtYWRlIGF2YWlsYWJsZSB1c2luZyB0aGUgZGlmZigpIGNvbW1hbmQuIFRoaXMgZnVuY3Rpb24gdGFrZXMgdHdvIGFyZ3VtZW50cyBvZiBub3RlLiBUaGUgZmlyc3QgaXMgdGhlIGxhZywgd2hpY2ggaXMgdGhlIG51bWJlciBvZiBwZXJpb2RzLCBhbmQgdGhlIHNlY29uZCBpcyBkaWZmZXJlbmNlcywgd2hpY2ggaXMgdGhlIG9yZGVyIG9mIHRoZSBkaWZmZXJlbmNlIChlLmcuIGhvdyBtYW55IHRpbWVzIGRpZmYoKSBpcyBjYWxsZWQpLg0KDQpgYGB7cn0NCiMgVGhlc2UgYXJlIHRoZSBzYW1lDQpkaWZmKHgsIGRpZmZlcmVuY2VzID0gMikNCmRpZmYoZGlmZih4KSkNCmBgYA0KDQpJbiB0aGlzIGV4ZXJjaXNlLCB5b3Ugd2lsbCByZXVzZSB0aGUgQWlyUGFzcyBkYXRhIGZyb20gZWFybGllciBpbiB0aGlzIGNoYXB0ZXIsIHRob3VnaCB0aGlzIHRpbWUgeW91IHdpbGwgdXNlIHRoZSBmdWxsIHNlcmllcyBmcm9tIDE5NDggdG8gMTk2MC4NCg0KSW5zdHJ1Y3Rpb25zICAgDQoNCiAtIENvbnN0cnVjdCBhIGZpcnN0IG9yZGVyIGRpZmZlcmVuY2Ugb2YgQWlyUGFzcyBieSBoYW5kLCB1c2luZyBsYWcoKSBhbmQgc3VidHJhY3Rpb24uIFNhdmUgdGhpcyAgLSBhcyBkaWZmX2J5X2hhbmQuDQogLSBUbyB2ZXJpZnkgdGhhdCB5b3VyIHJlc3VsdCBpcyBpZGVudGljYWwgdG8gdXNpbmcgZGlmZihBaXJQYXNzKSwgY29tYmluZSBhbmQgaW5zcGVjdCB0aGUgZmlyc3QgIC0gZmV3IHJvd3Mgb2YgYm90aCBpbiB5b3VyIGNvbnNvbGUuIFVzZSBtZXJnZSgpIGFuZCBoZWFkKCkgZm9yIHRoaXMuDQogLSBHZXQgdGhlIGZpcnN0IG9yZGVyIDEyIG1vbnRoIGRpZmZlcmVuY2Ugb2Ygc2VyaWVzIEFpclBhc3MuIEJlIHN1cmUgdG8gc3BlY2lmeSBib3RoIHRoZSBsYWcgYW5kIGRpZmZlcmVuY2VzIGFyZ3VtZW50cyBpbiBkaWZmKCkuDQogDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHRoZSBmaXJzdCBkaWZmZXJlbmNlIG9mIEFpclBhc3MgYW5kIGFzc2lnbiB0byBkaWZmX2J5X2hhbmQNCmRpZmZfYnlfaGFuZCA8LSBBaXJQYXNzIC0gbGFnKEFpclBhc3MsIGs9MSkNCg0KIyBVc2UgbWVyZ2UgdG8gY29tcGFyZSB0aGUgZmlyc3QgcGFydHMgb2YgZGlmZl9ieV9oYW5kIGFuZCBkaWZmKEFpclBhc3MpDQptZXJnZShoZWFkKGRpZmZfYnlfaGFuZCksIGhlYWQoZGlmZihBaXJQYXNzKSkpDQoNCiMgQ2FsY3VsYXRlIHRoZSBmaXJzdCBvcmRlciAxMiBtb250aCBkaWZmZXJlbmNlIG9mIEFpclBhc3MNCmRpZmYoQWlyUGFzcywgbGFnID0gMTIsIGRpZmZlcmVuY2VzID0gMSkNCmBgYA0KDQpBcyB5b3UgY2FuIHNlZSwgZGlmZmVyZW5jaW5nIHlvdXIgc2VyaWVzIGlzIG9ubHkgb25lIHN0ZXAgbW9yZSBjb21wbGV4IHRoYW4gZ2VuZXJhdGluZyBsYWdzIGFuZCBsZWFkcy4NCg0KIyMjIFdoYXQgaXMgdGhlIGtleSBkaWZmZXJlbmNlIGluIGxhZyBiZXR3ZWVuIHh0cyBhbmQgem9vDQoNCkFzIHlvdSd2ZSBzZWVuLCBnZW5lcmF0aW5nIGxhZ3MgYW5kIGxlYWRzIGFyZSBhbiBpbXBvcnRhbnQgdG9vbCBpbiB5b3VyIGFyc2VuYWwgZm9yIGhhbmRsaW5nIHRpbWUgc2VyaWVzIGRhdGEgaW4gUi4gSG93ZXZlciwgYmVjYXVzZSB4dHMgZW1wbG95cyBzbGlnaHRseSBkaWZmZXJlbnQgcHJvY2VkdXJlcyBmb3IgZ2VuZXJhdGluZyBsYWdzIGFuZCBsZWFkcyBjb21wYXJlZCB3aXRoIHpvbyBvZiBiYXNlLVIsIHlvdSBoYXZlIHRvIGJlIHZlcnkgcHJlY2lzZSBpbiB5b3VyIGNhbGxzIHRvIGxhZygpLg0KDQpXaGljaCBvZiB0aGUgZm9sbG93aW5nIGlzIEZBTFNFPw0KDQpQb3NzaWJsZSBBbnN3ZXJzDQogLSBUaGUgTkEgb2JzZXJ2YXRpb25zIGluIHh0cyByZXN1bHRpbmcgZnJvbSBsYWcoKSBhcmUgcHJlc2VydmVkLg0KIC0gVGhlIE5BIG9ic2VydmF0aW9ucyBpbiB6b28gcmVzdWx0aW5nIGZyb20gbGFnKCkgYXJlIGRyb3BwZWQuDQogLSBUaGUgayBhcmd1bWVudCBpbiB6b28gdXNlcyBwb3NpdGl2ZSB2YWx1ZXMgZm9yIHNoaWZ0aW5nIHBhc3Qgb2JzZXJ2YXRpb25zIGZvcndhcmQuIChDb3JyZWN0KQ0KIC0gVGhlIGsgYXJndW1lbnQgaW4geHRzIHVzZXMgcG9zaXRpdmUgdmFsdWVzIGZvciBzaGlmdGluZyBwYXN0IG9ic2VydmF0aW9ucyBmb3J3YXJkLg0KDQp4dHMgZm9sbG93cyB0aGUgbGl0ZXJhdHVyZSwgd2hpbGUgem9vIGNvbnRpbnVlcyB3aXRoIHRoZSBub3JtcyBvZiBiYXNlLVIuDQoNCg0KIyA0LiBBcHBseSBhbmQgYWdncmVnYXRlIGJ5IHRpbWUNCg0KIyMgQXBwbHkgYnkgVGltZSAtIFZpZGVvDQoNCj4gdGVtcHMNCiAgICAgICAgICAgVGVtcC5NYXggVGVtcC5NZWFuIFRlbXAuTWluDQoyMDE2LTA3LTAxICAgICAgIDc0ICAgICAgICA2OSAgICAgICA2MA0KMjAxNi0wNy0wMiAgICAgICA3OCAgICAgICAgNjYgICAgICAgNTYNCjIwMTYtMDctMDMgICAgICAgNzkgICAgICAgIDY4ICAgICAgIDU5DQoyMDE2LTA3LTA0ICAgICAgIDgwICAgICAgICA3NiAgICAgICA2OQ0KMjAxNi0wNy0wNSAgICAgICA5MCAgICAgICAgNzkgICAgICAgNjgNCjIwMTYtMDctMDYgICAgICAgODkgICAgICAgIDc5ICAgICAgIDcwDQoyMDE2LTA3LTA3ICAgICAgIDg3ICAgICAgICA3OCAgICAgICA3Mg0KMjAxNi0wNy0wOCAgICAgICA4OSAgICAgICAgODAgICAgICAgNzINCjIwMTYtMDctMDkgICAgICAgODEgICAgICAgIDczICAgICAgIDY3DQoyMDE2LTA3LTEwICAgICAgIDgzICAgICAgICA3MiAgICAgICA2NA0KMjAxNi0wNy0xMSAgICAgICA5MyAgICAgICAgODEgICAgICAgNjkNCjIwMTYtMDctMTIgICAgICAgODkgICAgICAgIDgyICAgICAgIDc3DQoyMDE2LTA3LTEzICAgICAgIDg2ICAgICAgICA3OCAgICAgICA2OA0KMjAxNi0wNy0xNCAgICAgICA4OSAgICAgICAgODAgICAgICAgNjgNCjIwMTYtMDctMTUgICAgICAgNzUgICAgICAgIDcyICAgICAgIDYwDQoyMDE2LTA3LTE2ICAgICAgIDc5ICAgICAgICA2OSAgICAgICA2MA0KDQojIyMgRmluZCBpbnRlcnZhbHMgYnkgdGltZSBpbiB4dHMNCg0KT25lIG9mIHRoZSBiZW5lZml0cyB0byB3b3JraW5nIHdpdGggdGltZSBzZXJpZXMgb2JqZWN0cyBpcyBob3cgZWFzeSBpdCBpcyB0byBhcHBseSBmdW5jdGlvbnMgYnkgdGltZS4NCg0KVGhlIG1haW4gZnVuY3Rpb24gaW4geHRzIHRvIGZhY2lsaXRhdGUgdGhpcyBpcyBlbmRwb2ludHMoKS4gSXQgdGFrZXMgYSB0aW1lIHNlcmllcyAob3IgYSB2ZWN0b3Igb2YgdGltZXMpIGFuZCByZXR1cm5zIHRoZSBsb2NhdGlvbnMgb2YgdGhlIGxhc3Qgb2JzZXJ2YXRpb25zIGluIGVhY2ggaW50ZXJ2YWwuDQoNCkZvciBleGFtcGxlLCB0aGUgY29kZSBiZWxvdyBsb2NhdGVzIHRoZSBsYXN0IG9ic2VydmF0aW9uIG9mIGVhY2ggeWVhciBmb3IgdGhlIEFpclBhc3MgZGF0YSBzZXQuDQoNCmVuZHBvaW50cyhBaXJQYXNzLCBvbiA9ICJ5ZWFycyIpDQpbMV0gMCAxMiAyNCAzNiA0OCA2MCA3MiA4NCA5NiAxMDggMTIwIDEzMiAxNDQNClRoZSBhcmd1bWVudCBvbiBzdXBwb3J0cyBhIHZhcmlldHkgb2YgcGVyaW9kcywgaW5jbHVkaW5nICJ5ZWFycyIsICJxdWFydGVycyIsICJtb250aHMiLCBhcyB3ZWxsIGFzIGludHJhZGF5IGludGVydmFscyBzdWNoIGFzICJob3VycyIsIGFuZCAibWludXRlcyIuIFdoYXQgaXMgcmV0dXJuZWQgaXMgYSB2ZWN0b3Igc3RhcnRpbmcgd2l0aCAwIGFuZCBlbmRpbmcgd2l0aCB0aGUgZXh0ZW50IChsYXN0IHJvdykgb2YgeW91ciBkYXRhLg0KDQpJbiBhZGRpdGlvbiB0byBlYWNoIHBlcmlvZCwgeW91IGNhbiBmaW5kIHRoZSBLdGhLdGggcGVyaW9kIGJ5IHV0aWxpemluZyB0aGUgayBhcmd1bWVudC4gRm9yIGV4YW1wbGUsIHNldHRpbmcgdGhlIGFyZ3VtZW50cyBvZiB5b3VyIGVuZHBvaW50cygpIGNhbGwgdG8gb24gPSAid2Vla3MiLCBrID0gMiwgd291bGQgZ2VuZXJhdGUgdGhlIGZpbmFsIGRheSBvZiBldmVyeSBvdGhlciB3ZWVrIGluIHlvdXIgZGF0YS4gTm90ZSB0aGF0IHRoZSBsYXN0IHZhbHVlIHJldHVybmVkIHdpbGwgYWx3YXlzIGJlIHRoZSBsZW5ndGggb2YgeW91ciBpbnB1dCBkYXRhLCBldmVuIGlmIGl0IGRvZXNuJ3QgY29ycmVzcG9uZCB0byBhIHNraXBwZWQgaW50ZXJ2YWwuDQoNCkluIHRoaXMgZXhlcmNpc2UgeW91J2xsIHVzZSBlbmRwb2ludHMoKSB0byBmaW5kIHR3byBzZXRzIG9mIGVuZHBvaW50cyBmb3IgdGhlIGRhaWx5IHRlbXBzIGRhdGEuDQoNCkluc3RydWN0aW9ucw0KIC0gVXNlIGVuZHBvaW50cygpIHRvIGxvY2F0ZSB0aGUgZW5kIG9mIHdlZWsgaW4geW91ciB0ZW1wcyBkYXRhLg0KIC0gVXNlIGVuZHBvaW50cygpIHRvIGxvY2F0ZSB0aGUgZW5kIG9mIGV2ZXJ5IHNlY29uZCB3ZWVrIGluIHlvdXIgdGVtcHMgZGF0YS4gUmVtZW1iZXIgdG8gdXNlIHRoZSBrIGFyZ3VtZW50Lg0KDQpgYGB7cn0NCiMgTG9jYXRlIHRoZSB3ZWVrcw0KZW5kcG9pbnRzKHRlbXBzLCBvbiA9ICJ3ZWVrcyIpDQoNCiMgTG9jYXRlIGV2ZXJ5IHR3byB3ZWVrcw0KZW5kcG9pbnRzKHRlbXBzLCBvbiA9ICJ3ZWVrcyIsIGsgPSAyKQ0KYGBgDQoNCkFzIHlvdSdsbCBzZWUgaW4gdGhlIG5leHQgZXhlcmNpc2UsIGxvY2F0aW5nIGVuZHBvaW50cyBjYW4gaGVscCBzcGVlZCB0aGUgcHJvY2VzcyBvZiBhZ2dyZWdhdGluZyB0aW1lIHNlcmllcyBkYXRhLg0KDQojIyMgQXBwbHkgYSBmdW5jdGlvbiBieSB0aW1lIHBlcmlvZChzKQ0KDQpBdCB0aGlzIHBvaW50IHlvdSBrbm93IGhvdyB0byBsb2NhdGUgdGhlIGVuZCBvZiBwZXJpb2RzIHVzaW5nIGVuZHBvaW50cygpLiBZb3UgbWF5IGJlIHdvbmRlcmluZyB3aGF0IGl0IGlzIHlvdSBkbyB3aXRoIHRoZXNlIHZhbHVlcy4NCg0KSW4gdGhlIG1vc3Qgc2ltcGxlIGNhc2UgeW91IGNhbiBzdWJzZXQgeW91ciBvYmplY3QgdG8gZ2V0IHRoZSBsYXN0IHZhbHVlcy4gSW4gY2VydGFpbiBjYXNlcyB0aGlzIG1heSBiZSB1c2VmdWwuIEZvciBleGFtcGxlLCB0byBpZGVudGlmeSB0aGUgbGFzdCBrbm93biB2YWx1ZSBvZiBhIHNlbnNvciBkdXJpbmcgdGhlIGhvdXIgb3IgZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgVVNEL0pQWSBleGNoYW5nZSByYXRlIGF0IHRoZSBzdGFydCBvZiB0aGUgZGF5LiBGb3IgbW9zdCBzZXJpZXMsIHlvdSB3aWxsIHdhbnQgdG8gYXBwbHkgYSBmdW5jdGlvbiB0byB0aGUgdmFsdWVzIGJldHdlZW4gZW5kcG9pbnRzLiBJbiBlc3NlbmNlLCB1c2UgdGhlIGJhc2UgZnVuY3Rpb24gYXBwbHkoKSwgYnV0IHVzZWQgb24gYSB3aW5kb3cgb2YgdGltZS4NCg0KVG8gZG8gdGhpcyBlYXNpbHksIHh0cyBwcm92aWRlcyB0aGUgcGVyaW9kLmFwcGx5KCkgY29tbWFuZCwgd2hpY2ggdGFrZXMgYSB0aW1lIHNlcmllcywgYW4gaW5kZXggb2YgZW5kcG9pbnRzLCBhbmQgYSBmdW5jdGlvbi4NCg0KcGVyaW9kLmFwcGx5KHgsIElOREVYLCBGVU4sIC4uLikNCkluIHRoaXMgZXhlcmNpc2UgeW91J2xsIHByYWN0aWNlIHVzaW5nIHBlcmlvZC5hcHBseSgpIGJ5IHRha2luZyB0aGUgd2Vla2x5IG1lYW4gb2YgeW91ciB0ZW1wcyBkYXRhLiBZb3UnbGwgYWxzbyBsb29rIGF0IG9uZSBvZiB0aGUgc2hvcnRjdXQgZnVuY3Rpb25zIHRoYXQgZG9lcyB0aGUgc2FtZSB0aGluZyB3aXRoIHNsaWdodGx5IGRpZmZlcmVudCBzeW50YXguDQoNCkluc3RydWN0aW9ucw0KIC0gQ2FsY3VsYXRlIHRoZSB3ZWVrbHkgZW5kcG9pbnRzIG9mIHRoZSB0ZW1wcyBzZXJpZXMgYW5kIGFzc2lnbiB0byBlcC4NCiAtIFVzaW5nIHBlcmlvZC5hcHBseSgpLCBjYWxjdWxhdGUgdGhlIHdlZWtseSBtZWFuIG9mIHRoZSBUZW1wLk1lYW4gY29sdW1uIG9mIHlvdXIgdGVtcHMgZGF0YS4gUmVtZW1iZXIgdGhhdCB5b3VyIGVuZHBvaW50cyB3ZXJlIGNhbGN1bGF0ZWQgd2Vla2x5Lg0KIA0KYGBge3J9DQojIENhbGN1bGF0ZSB0aGUgd2Vla2x5IGVuZHBvaW50cw0KZXAgPC0gZW5kcG9pbnRzKHRlbXBzLCBvbiA9ICJ3ZWVrcyIpDQoNCiMgTm93IGNhbGN1bGF0ZSB0aGUgd2Vla2x5IG1lYW4gYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMNCnBlcmlvZC5hcHBseSh0ZW1wc1ssICJUZW1wLk1lYW4iXSwgSU5ERVggPSBlcCwgRlVOID0gbWVhbikNCmBgYA0KDQogICAgICAgICAgIFRlbXAuTWVhbg0KMjAxNi0wNy0wMyAgNjcuNjY2NjcNCjIwMTYtMDctMTAgIDc2LjcxNDI5DQoyMDE2LTA3LTE2ICA3Ny4wMDAwMA0KDQpUaGUgcGVyaW9kLmFwcGx5KCkgY29tbWFuZCBhbGxvd3MgeW91IHRvIGVhc2lseSBjYWxjdWxhdGUgY29tcGxleCBxdWFsaXRpZXMgb2YgeW91ciB0aW1lIHNlcmllcyBkYXRhLg0KDQojIyMgVXNpbmcgbGFwcGx5KCkgYW5kIHNwbGl0KCkgdG8gYXBwbHkgZnVuY3Rpb25zIG9uIGludGVydmFscw0KDQpBbG9uZyB0aGUgc2FtZSBsaW5lcyBhcyB0aGUgcHJldmlvdXMgZXhlcmNpc2UsIHh0cyBnaXZlcyB5b3UgYW4gYWRkaXRpb25hbCBtZWNoYW5pc20gdG8gZGl2ZSBpbnRvIHBlcmlvZHMgb2YgeW91ciBkYXRhLiBPZnRlbiBpdCBpcyB1c2VmdWwgdG8gcGh5c2ljYWxseSBzcGxpdCB5b3VyIGRhdGEgaW50byBkaXNqb2ludCBjaHVua3MgYnkgdGltZSBhbmQgcGVyZm9ybSBzb21lIGNhbGN1bGF0aW9uIG9uIHRoZXNlIHBlcmlvZHMuDQoNCkZvciB0aGlzIGV4ZXJjaXNlIHlvdSdsbCBtYWtlIHVzZSBvZiB0aGUgeHRzIHNwbGl0KCkgY29tbWFuZCB0byBjaHVuayB5b3VyIGRhdGEgYnkgdGltZS4gVGhlIHNwbGl0KCkgZnVuY3Rpb24gY3JlYXRlcyBhIGxpc3QgY29udGFpbmluZyBhbiBlbGVtZW50IGZvciBlYWNoIHNwbGl0LiBUaGUgZiBhcmd1bWVudCBpbiBzcGxpdCgpIGlzIGEgY2hhcmFjdGVyIHN0cmluZyBkZXNjcmliaW5nIHRoZSBwZXJpb2QgdG8gc3BsaXQgYnkgKGkuZS4gIm1vbnRocyIsICJ5ZWFycyIsIGV0Yy4pLg0KDQpIZXJlIHlvdSB3aWxsIGZvbGxvdyB0aGUgc2FtZSBwcm9jZXNzIHlvdSBmb2xsb3dlZCBpbiB0aGUgcHJldmlvdXMgZXhlcmNpc2UuIEhvd2V2ZXIsIHRoaXMgdGltZSB5b3Ugd2lsbCBtYW51YWxseSBzcGxpdCB5b3VyIGRhdGEgZmlyc3QsIGFuZCB0aGVuIGFwcGx5IHRoZSBtZWFuKCkgZnVuY3Rpb24gdG8gZWFjaCBjaHVuay4gVGhlIGZ1bmN0aW9uIGxhcHBseSgpIGlzIHVzZWQgZm9yIHRoZSBtb3N0IGVmZmljaWVudCBjYWxjdWxhdGlvbnMuIEluIGNhc2VzIHdoZXJlIHlvdSBkb24ndCB3YW50IHRvIHJldHVybiBhIHRpbWUgc2VyaWVzLCB0aGlzIHByb3ZlcyB0byBiZSB2ZXJ5IGludHVpdGl2ZSBhbmQgZWZmZWN0aXZlLg0KDQpJbnN0cnVjdGlvbnMNCiAtIFVzZSBzcGxpdCgpIHRvIHNwbGl0IHlvdXIgdGVtcHMgZGF0YSBieSB3ZWVrcy4gQ2FsbCB0aGlzIHRlbXBzX3dlZWtseQ0KIC0gVXNlIGxhcHBseSgpIHRvIGdldCB0aGUgd2Vla2x5IG1lYW4gb2YgdGVtcHNfd2Vla2x5LiBDYWxsIHRoaXMgdGVtcHNfYXZnLiBQcmludCB0aGlzIGxpc3QuDQogDQogDQpgYGB7cn0NCiMgU3BsaXQgdGVtcHMgYnkgd2Vlaw0KdGVtcHNfd2Vla2x5IDwtIHNwbGl0KHRlbXBzLCBmID0gIndlZWtzIikNCg0KIyBDcmVhdGUgYSBsaXN0IG9mIHdlZWtseSBtZWFucywgdGVtcHNfYXZnLCBhbmQgcHJpbnQgdGhpcyBsaXN0DQp0ZW1wc19hdmcgPC0gbGFwcGx5KFggPSB0ZW1wc193ZWVrbHksIEZVTiA9IG1lYW4pDQp0ZW1wc19hdmcNCmBgYA0KQXMgeW91IGNhbiBzZWUsIHBlcmlvZC5hcHBseSgpIGlzIHNpbWlsYXIgdG8gdXNpbmcgYSBjb21iaW5hdGlvbiBvZiBzcGxpdCgpIGFuZCBsYXBwbHkoKQ0KDQojIyMgU2VsZWN0aW9uIGJ5IGVuZHBvaW50cyB2cy4gc3BsaXQtbGFwcGx5LXJiaW5kDQoNCkJ5IG5vdyB5b3UgaGF2ZSBzZWVuIHRoYXQgZXZlbiBpbiB4dHMgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSB3YXkgdG8gYWNjb21wbGlzaCBhIHRhc2suIEluIHRoaXMgZXhlcmNpc2Ugd2UnbGwgaGlnaGxpZ2h0IHRoaXMgZXhwbGljaXRseSBieSB0YWNrbGluZyB0aGUgc2FtZSBjaGFsbGVuZ2UgdXNpbmcgdHdvIGRpZmZlcmVudCBtZXRob2RzLiBXaGVuIHlvdSBhcmUgb24geW91ciBvd24sIHlvdSB3aWxsIGxpa2VseSBmaW5kIHNpdHVhdGlvbnMgd2hlcmUgb25lIG9yIHRoZSBvdGhlciB3aWxsIGJlIG1vcmUgaW50dWl0aXZlLCBidXQgZm9yIG5vdyB5b3Ugc2hvdWxkIG1ha2Ugc3VyZSB5b3UgYXJlIGFibGUgdG8gZG8gYm90aC4NCg0KU3RhcnRpbmcgd2l0aCB0aGUgc2FtZSBkYWlseSBzZXJpZXMgdGVtcHMsIHRoZSBjaGFsbGVuZ2Ugd2lsbCBiZSB0byBmaW5kIHRoZSBsYXN0IG9ic2VydmF0aW9uIGluIGVhY2ggd2Vlay4NCg0KTm90ZSB0aGF0IHRoZXNlIGZ1bmN0aW9ucyB3aWxsIGFsd2F5cyBmaW5kIHRoZSBkYXRlcyB0aGF0IGFyZSBpbiB0aGUgY2xvc2VkIGludGVydmFsIFtzdGFydCBvZiBwZXJpb2QsIGVuZCBvZiBwZXJpb2RdIGV2ZW4gaWYgdGhlcmUgaXMgbm8gb2JzZXJ2YXRpb24gYXQgdGhlIGV4YWN0IHN0YXJ0IG9yIGVuZC4geHRzIHJlcHJlc2VudHMgaXJyZWd1bGFyIHRpbWUgc2VyaWVzLCBzbyBpdCBpcyBwZXJmZWN0bHkgdmFsaWQgdG8gaGF2ZSBob2xlcyBpbiB0aGUgZGF0YSB3aGVyZSBvbmUgbWlnaHQgZXhwZWN0IGFuIG9ic2VydmF0aW9uLg0KDQpVc2luZyB0aGUgc2xpZGVzIGFuZCB2aWRlbyBleGFtcGxlcyBhcyBhIHJlZmVyZW5jZSwgZmluZCB0aGUgbGFzdCBvYnNlcnZhdGlvbiBmb3IgZWFjaCB3ZWVrIGluIG91ciB0ZW1wcyBkYXRhLg0KDQpJbnN0cnVjdGlvbnMNClVzZSB0aGUgc3BsaXQoKS1sYXBwbHkoKS1yYmluZCgpIHBhcmFkaWdtLCBnaXZlbiBmb3IgeW91IGluIHRoZSBzY3JpcHQsIHRvIGZpbmQgdGhlIGxhc3Qgb2JzZXJ2YXRpb24gaW4gZWFjaCB3ZWVrIGluIHRlbXBzLiBJdCBpcyBzdG9yZWQgaW4gdGVtcHNfMS4NClVzZSBlbmRwb2ludHMoKSB0byBmaW5kIHRoZSBsYXN0IGRheXMgb2YgdGhlIHdlZWsgaW4gdGVtcHMuIFN0b3JlIHRoZSByZXN1bHRpbmcgdmVjdG9yIGluIGxhc3RfZGF5X29mX3dlZWtzLg0KQ3JlYXRlIHRlbXBzXzIgYnkgc3Vic2V0dGluZyB0ZW1wcyB1c2luZyBsYXN0X2RheV9vZl93ZWVrcy4NCg0KYGBge3J9DQojIFVzZSB0aGUgcHJvcGVyIGNvbWJpbmF0aW9uIG9mIHNwbGl0LCBsYXBwbHkgYW5kIHJiaW5kDQp0ZW1wc18xIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzcGxpdCh0ZW1wcywgIndlZWtzIiksIGZ1bmN0aW9uKHcpIGxhc3QodywgbiA9ICIxIGRheSIpKSkNCg0KIyBDcmVhdGUgbGFzdF9kYXlfb2Zfd2Vla3MgdXNpbmcgZW5kcG9pbnRzKCkNCmxhc3RfZGF5X29mX3dlZWtzIDwtIGVuZHBvaW50cyh0ZW1wcywgIndlZWtzIikNCg0KIyBTdWJzZXQgdGVtcHMgdXNpbmcgbGFzdF9kYXlfb2Zfd2Vla3MgDQp0ZW1wc18yIDwtIHRlbXBzW2xhc3RfZGF5X29mX3dlZWtzXQ0KDQpgYGANCg0KIyMgQ29udmVydGluZyBwZXJpb2RpY2l0eSAtIFZpZGVvDQoNCiMjIyBDb252ZXJ0IHVuaXZhcmlhdGUgc2VyaWVzIHRvIE9ITEMgZGF0YQ0KDQpBZ2dyZWdhdGluZyB0aW1lIHNlcmllcyBjYW4gYmUgYSBmcnVzdHJhdGluZyB0YXNrLiBGb3IgZXhhbXBsZSwgaW4gZmluYW5jaWFsIHNlcmllcyBpdCBpcyBjb21tb24gdG8gZmluZCBPcGVuLUhpZ2gtTG93LUNsb3NlIGRhdGEgKG9yIE9ITEMpIGNhbGN1bGF0ZWQgb3ZlciBzb21lIHJlcGVhdGluZyBhbmQgcmVndWxhciBpbnRlcnZhbC4NCg0KQWxzbyBrbm93biBhcyByYW5nZSBiYXJzLCBhZ2dyZWdhdGluZyBhIHNlcmllcyBiYXNlZCBvbiBzb21lIHJlZ3VsYXIgd2luZG93IGNhbiBtYWtlIGFuYWx5c2lzIGVhc2llciBhbW9uZ3N0IHNlcmllcyB0aGF0IGhhdmUgdmFyeWluZyBmcmVxdWVuY2llcy4gQSB3ZWVrbHkgZWNvbm9taWMgc2VyaWVzIGFuZCBhIGRhaWx5IHN0b2NrIHNlcmllcyBjYW4gYmUgY29tcGFyZWQgbW9yZSBlYXNpbHkgaWYgdGhlIGRhaWx5IGlzIGNvbnZlcnRlZCB0byB3ZWVrbHkuDQoNCkluIHRoaXMgZXhlcmNpc2UsIHlvdSdsbCBjb252ZXJ0IGZyb20gYSB1bml2YXJpYXRlIHNlcmllcyBpbnRvIE9ITEMgc2VyaWVzLCBhbmQgdGhlbiBjb252ZXJ0IHlvdXIgZmluYWwgT0hMQyBzZXJpZXMgYmFjayBpbnRvIGEgdW5pdmFyaWF0ZSBzZXJpZXMgdXNpbmcgdGhlIHh0cyBmdW5jdGlvbiB0by5wZXJpb2QoKS4gVGhpcyBmdW5jdGlvbiB0YWtlcyBhIHRpbWUtc2VyaWVzLCB4LCBhbmQgYSBzdHJpbmcgZm9yIHRoZSBwZXJpb2QgKGkuZS4gbW9udGhzLCBkYXlzLCBldGMuKSwgaW4gYWRkaXRpb24gdG8gYSBudW1iZXIgb2Ygb3RoZXIgb3B0aW9uYWwgYXJndW1lbnRzLg0KDQp0by5wZXJpb2QoeCwNCiAgICAgICAgICBwZXJpb2QgPSAibW9udGhzIiwgDQogICAgICAgICAgayA9IDEsIA0KICAgICAgICAgIGluZGV4QXQsIA0KICAgICAgICAgIG5hbWU9TlVMTCwNCiAgICAgICAgICBPSExDID0gVFJVRSwNCiAgICAgICAgICAuLi4pDQpZb3Ugd2lsbCB1c2UgYSBuZXcgZGF0YSBzZXQgZm9yIHRoaXMgZXhlcmNpc2UsIHVzZF9ldXIsIGEgZGFpbHkgVVNEL0VVUiBleGNoYW5nZSByYXRlIGZyb20gMTk5OSB0byBBdWd1c3QgMjAxNiwgd2hpY2ggaGFzIGJlZW4gbG9hZGVkIGludG8geW91ciB3b3Jrc3BhY2UuDQoNCkluc3RydWN0aW9ucw0KIC0gQ29udmVydCB1c2RfZXVyIGludG8gYSB3ZWVrbHkgT0hMQyBzZXJpZXMgdXNpbmcgdG8ucGVyaW9kKCkuIENhbGwgdGhpcyBuZXcgc2VyaWVzIHVzZF9ldXJfd2Vla2x5LiBOb3RlIHRoYXQgYnkgZGVmYXVsdCBPSExDID0gVFJVRS4NCiAtIENvbnZlcnQgdXNkX2V1ciBpbnRvIGEgbW9udGhseSBPSExDIHNlcmllcy4gQ2FsbCB0aGlzIHNlcmllcyB1c2RfZXVyX21vbnRobHkuDQogLSBDb252ZXJ0IHVzZF9ldXIgaW50byBhIHllYXJseSB1bml2YXJpYXRlIChubyBPSExDIGJhcnMpIHNlcmllcy4gQ2FsbCB0aGlzIHNlcmllcyB1c2RfZXVyX3llYXJseS4NCiANCmBgYHtyfQ0KIyBDb252ZXJ0IHVzZF9ldXIgdG8gd2Vla2x5IGFuZCBhc3NpZ24gdG8gdXNkX2V1cl93ZWVrbHkNCnVzZF9ldXJfd2Vla2x5IDwtIHRvLnBlcmlvZCh1c2RfZXVyLCBwZXJpb2QgPSAid2Vla3MiKQ0KDQojIENvbnZlcnQgdXNkX2V1ciB0byBtb250aGx5IGFuZCBhc3NpZ24gdG8gdXNkX2V1cl9tb250aGx5DQp1c2RfZXVyX21vbnRobHkgPC0gdG8ucGVyaW9kKHVzZF9ldXIsIHBlcmlvZCA9ICJtb250aHMiKQ0KDQojIENvbnZlcnQgdXNkX2V1ciB0byB5ZWFybHkgdW5pdmFyaWF0ZSBhbmQgYXNzaWduIHRvIHVzZF9ldXJfeWVhcmx5DQp1c2RfZXVyX3llYXJseSA8LSB0by5wZXJpb2QodXNkX2V1ciwgcGVyaW9kID0gInllYXJzIiwgT0hMQyA9IEZBTFNFKQ0KYGBgDQoNCg0KIyMjIENvbnZlcnQgYSBzZXJpZXMgdG8gYSBsb3dlciBmcmVxdWVuY3kNCg0KQmVzaWRlcyBjb252ZXJ0aW5nIHVuaXZhcmlhdGUgdGltZSBzZXJpZXMgdG8gT0hMQyBzZXJpZXMsIHRvLnBlcmlvZCgpIGFsc28gbGV0cyB5b3UgY29udmVydCBPSExDIHRvIGxvd2VyIHJlZ3VsYXJpemVkIGZyZXF1ZW5jeSAtIHNvbWV0aGluZyBsaWtlIHN1YnNhbXBsaW5nIHlvdXIgZGF0YS4NCg0KRGVwZW5kaW5nIG9uIHRoZSBjaG9zZW4gZnJlcXVlbmN5LCB0aGUgaW5kZXggY2xhc3Mgb2YgeW91ciBkYXRhIG1heSBiZSBjb2VyY2VkIHRvIHNvbWV0aGluZyBtb3JlIGFwcHJvcHJpYXRlIHRvIHRoZSBuZXcgZGF0YS4gRm9yIGV4YW1wbGUsIHdoZW4gdXNpbmcgdGhlIHNob3J0Y3V0IGZ1bmN0aW9uIHRvLnF1YXJ0ZXJseSgpLCB4dHMgd2lsbCBjb252ZXJ0IHlvdXIgaW5kZXggdG8gdGhlIHllYXJxdHIgY2xhc3MgdG8gbWFrZSBwZXJpb2RzIG1vcmUgb2J2aW91cy4NCg0KV2UgY2FuIG92ZXJyaWRlIHRoaXMgYmVoYXZpb3IgYnkgdXNpbmcgdGhlIGluZGV4QXQgYXJndW1lbnQuIFNwZWNpZmljYWxseSwgdXNpbmcgZmlyc3RvZiB3b3VsZCBnaXZlIHlvdSB0aGUgdGltZSBmcm9tIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHBlcmlvZC4gSW4gYWRkaXRpb24sIHlvdSBjYW4gY2hhbmdlIHRoZSBiYXNlIG5hbWUgb2YgZWFjaCBjb2x1bW4gYnkgc3VwcGx5aW5nIGEgc3RyaW5nIHRvIHRoZSBhcmd1bWVudCBuYW1lLg0KDQpGb3IgdGhpcyBleGVyY2lzZSB3ZSdsbCBpbnRyb2R1Y2UgYSBuZXcgZGF0YXNldCwgdGhlIGVkaGVjIGhlZGdlIGZ1bmQgaW5kZXggZGF0YSBmcm9tIHRoZSBQZXJmb3JtYW5jZUFuYWx5dGljcyBwYWNrYWdlLg0KDQoNCkluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgdXNlIHRoZSBFcXVpdHkgTWFya2V0IE5ldXRyYWwgdGltZSBzZXJpZXMgZnJvbSB0aGUgZWRoZWMgZGF0YSwgd2hpY2ggd2UndmUgYXNzaWduZWQgdG8gZXFfbWt0Lg0KDQpJbnN0cnVjdGlvbnMNCiAtIENvbnZlcnQgZXFfbWt0IHRvIHF1YXJ0ZXJseSBPSExDIHVzaW5nIHRoZSBiYXNlIHRvLnBlcmlvZCgpLiBDYWxsIHRoaXMgbWt0X3F1YXJ0ZXJseS4NCiAtIENvbnZlcnQgdGhlIG9yaWdpbmFsIGVxX21rdCBhZ2FpbiwgdGhpcyB0aW1lIHVzaW5nIHRvLnF1YXJ0ZXJseSgpIGRpcmVjdGwgeS4gQ2hhbmdlIHRoZSBiYXNlIG5hbWUgb2YgZWFjaCBPSExDIGNvbHVtbiB0byBlZGhlY19lcXVpdHkgYW5kIGNoYW5nZSB0aGUgaW5kZXggdG8gImZpcnN0b2YiLiBDYWxsIHRoaXMgbWt0X3F1YXJ0ZXJseTIuDQogDQogDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoIlBlcmZvcm1hbmNlQW5hbHl0aWNzIikNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpkYXRhKGVkaGVjKQ0KZGltKGVkaGVjKQ0KbmFtZXMoZWRoZWMpDQplcV9ta3QgPC0gZWRoZWNbLCAiRXF1aXR5IE1hcmtldCBOZXV0cmFsIl0NCmRpbShlcV9ta3QpDQpgYGANCg0KYGBge3J9DQojIENvbnZlcnQgZXFfbWt0IHRvIHF1YXJ0ZXJseSBPSExDDQpta3RfcXVhcnRlcmx5IDwtIHRvLnBlcmlvZChlcV9ta3QsIHBlcmlvZCA9ICJxdWFydGVycyIpDQoNCiMgQ29udmVydCBlcV9ta3QgdG8gcXVhcnRlcmx5IHVzaW5nIHNob3J0Y3V0IGZ1bmN0aW9uDQpta3RfcXVhcnRlcmx5MiA8LSB0by5xdWFydGVybHkoZWRoZWMsIG5hbWUgPSAiZWRoZWNfcXVpdHkiLCBpbmRleEF0ID0gImZpcnN0b2YiKQ0KYGBgDQoNCiMjIFJvbGxpbmcgZnVuY3Rpb25zIC0gYXBwbHkgd2luZG93aW5nIGZ1bmN0aW9ucyB0byB0aW1lIHNlcmllcyBkYXRhIC0gVmlkZW8NCg0KIyMjIENhbGN1bGF0ZSBiYXNpYyByb2xsaW5nIHZhbHVlIG9mIHNlcmllcyBieSBtb250aA0KDQpPbmUgY29tbW9uIGFnZ3JlZ2F0aW9uIHlvdSBtYXkgd2FudCB0byBhcHBseSBpbnZvbHZlcyBkb2luZyBhIGNhbGN1bGF0aW9uIHdpdGhpbiB0aGUgY29udGV4dCBvZiBhIHBlcmlvZCwgYnV0IHJldHVybmluZyB0aGUgaW50ZXJpbSByZXN1bHRzIGZvciBlYWNoIG9ic2VydmF0aW9uIG9mIHRoZSBwZXJpb2QuDQoNCkZvciBleGFtcGxlLCB5b3UgbWF5IHdhbnQgdG8gY2FsY3VsYXRlIGEgcnVubmluZyBtb250aC10by1kYXRlIGN1bXVsYXRpdmUgc3VtIG9mIGEgc2VyaWVzLiBUaGlzIHdvdWxkIGJlIHJlbGV2YW50IHdoZW4gbG9va2luZyBhdCBtb250aGx5IHBlcmZvcm1hbmNlIG9mIGEgbXV0dWFsIGZ1bmQgeW91IGFyZSBpbnRlcmVzdGVkIGluIGludmVzdGluZyBpbi4NCg0KRm9yIHRoaXMgZXhlcmNpc2UsIHlvdSdsbCBjYWxjdWxhdGUgdGhlIGN1bXVsYXRpdmUgYW5udWFsIHJldHVybiB1c2luZyB0aGUgZWRoZWMgZnVuZCBkYXRhIGZyb20gdGhlIGxhc3QgZXhlcmNpc2UuIFRvIGRvIHRoaXMsIHlvdSdsbCBmb2xsb3cgdGhlIHNwbGl0KCktbGFwcGx5KCktcmJpbmQoKSBwYXR0ZXJuIGRlbW9uc3RyYXRlZCBiZWxvdzoNCg0KeF9zcGxpdCA8LSBzcGxpdCh4LCBmID0gIm1vbnRocyIpDQp4X2xpc3QgPC0gbGFwcGx5KHhfc3BsaXQsIGN1bW1heCkNCnhfbGlzdF9yYmluZCA8LSBkby5jYWxsKHJiaW5kLCB4X2xpc3QpDQpOb3RlIHRoZSBsYXN0IGNhbGwgdXNlcyBSJ3Mgc29tZXdoYXQgc3RyYW5nZSBkby5jYWxsKHJiaW5kLCAuLi4pIHN5bnRheCwgd2hpY2ggYWxsb3dzIHlvdSB0byBwYXNzIGEgbGlzdCB0byByYmluZCBpbnN0ZWFkIG9mIHBhc3NpbmcgZWFjaCBvYmplY3Qgb25lIGF0IGEgdGltZS4gVGhpcyBpcyBhIGhhbmR5IHNob3J0Y3V0IGZvciB5b3VyIFIgdG9vbGtpdC4NCg0KSW5zdHJ1Y3Rpb25zDQogLSBVc2luZyBzcGxpdCgpLCBicmVhayB1cCB0aGUgZWRoZWMgZGF0YSBpbnRvIHllYXJzLiBBc3NpZ24gdGhpcyB0byBlZGhlY195ZWFycy4NCiAtIFVzZSBsYXBwbHkoKSB0byBmaW5kIHRoZSBjdW1zdW0oKSBvZiB0aGUgcmV0dXJucyBwZXIgeWVhciBvbiBlZGhlY195ZWFycy4gQXNzaWduIHRoaXMgdG8gIGVkaGVjX3l0ZC4NCiAtIFVzZSBkby5jYWxsKCkgd2l0aCByYmluZCB0byBjb252ZXJ0IHlvdXIgcHJldmlvdXMgbGlzdCBvdXRwdXQgdG8gYSBzaW5nbGUgeHRzIG9iamVjdC4gQXNzaWduIHRoaXMgdG8gZWRoZWNfeHRzLg0KDQpgYGB7cn0NCiMgU3BsaXQgZWRoZWMgaW50byB5ZWFycw0KZWRoZWNfeWVhcnMgPC0gc3BsaXQoZWRoZWMgLCBmID0gInllYXJzIikNCg0KIyBVc2UgbGFwcGx5IHRvIGNhbGN1bGF0ZSB0aGUgY3Vtc3VtIGZvciBlYWNoIHllYXIgaW4gZWRoZWNfeWVhcnMNCmVkaGVjX3l0ZCA8LSBsYXBwbHkoZWRoZWNfeWVhcnMsIEZVTiA9IGN1bXN1bSkNCg0KIyBVc2UgZG8uY2FsbCB0byByYmluZCB0aGUgcmVzdWx0cw0KZWRoZWNfeHRzIDwtIGRvLmNhbGwocmJpbmQsIGVkaGVjX3l0ZCkNCg0KYGBgDQoNCiMjIyBDYWxjdWxhdGUgdGhlIHJvbGxpbmcgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGEgdGltZSBzZXJpZXMNCg0KQW5vdGhlciBjb21tb24gcmVxdWlyZW1lbnQgd2hlbiB3b3JraW5nIHdpdGggdGltZSBzZXJpZXMgZGF0YSBpcyB0byBhcHBseSBhIGZ1bmN0aW9uIG9uIGEgcm9sbGluZyB3aW5kb3cgb2YgZGF0YS4geHRzIHByb3ZpZGVzIHRoaXMgZmFjaWxpdHkgdGhyb3VnaCB0aGUgaW50dWl0aXZlbHkgbmFtZWQgem9vIGZ1bmN0aW9uIHJvbGxhcHBseSgpLg0KDQpUaGlzIGZ1bmN0aW9uIHRha2VzIGEgdGltZSBzZXJpZXMgb2JqZWN0IHgsIGEgd2luZG93IHNpemUgd2lkdGgsIGFuZCBhIGZ1bmN0aW9uIEZVTiB0byBhcHBseSB0byBlYWNoIHJvbGxpbmcgcGVyaW9kLiBUaGUgd2lkdGggYXJndW1lbnQgY2FuIGJlIHRyaWNreTsgYSBudW1iZXIgc3VwcGxpZWQgdG8gdGhlIHdpZHRoIGFyZ3VtZW50IHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiBhIHdpbmRvdy4gRm9yIGluc3RhbmNlLCB0byB0YWtlIHRoZSByb2xsaW5nIDEwLWRheSBtYXggb2YgYSBzZXJpZXMsIHlvdSB3b3VsZCB0eXBlIHRoZSBmb2xsb3dpbmc6DQoNCnJvbGxhcHBseSh4LCB3aWR0aCA9IDEwLCBGVU4gPSBtYXgsIG5hLnJtID0gVFJVRSkNCk5vdGUgdGhhdCB0aGUgYWJvdmUgd291bGQgb25seSB0YWtlIHRoZSAxMC1kYXkgbWF4IG9mIGEgc2VyaWVzIHdpdGggZGFpbHkgb2JzZXJ2YXRpb25zLiBJZiB0aGUgc2VyaWVzIGhhZCBtb250aGx5IG9ic2VydmF0aW9ucywgaXQgd291bGQgdGFrZSB0aGUgMTAtbW9udGggbWF4LiBBbHNvIG5vdGUgdGhhdCB5b3UgY2FuIHBhc3MgYWRkaXRpb25hbCBhcmd1bWVudHMgKGkuZS4gbmEucm0gdG8gdGhlIG1heCBmdW5jdGlvbikganVzdCBsaWtlIHlvdSB3b3VsZCB3aXRoIGFwcGx5KCkuDQoNCkluc3RydWN0aW9ucw0KIC0gVXNpbmcgcm9sbGFwcGx5KCksIGNhbGN1bGF0ZSB0aGUgMy1tb250aCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGVxX21rdCBzZXJpZXMuIE5vdGUgdGhhdCBlcV9ta3QgaGFzIG1vbnRobHkgb2JzZXJ2YXRpb25zLiBDYWxsIHlvdXIgMy1tb250aCByb2xsaW5nIHN0YW5kYXJkIGRldmlhdGlvbiBlcV9zZC4NCiANCiANCmBgYHtyfQ0KIyBVc2Ugcm9sbGFwcGx5IHRvIGNhbGN1bGF0ZSB0aGUgcm9sbGluZyAzIHBlcmlvZCBzZCBvZiBlcV9ta3QNCmVxX3NkIDwtIHJvbGxhcHBseShlcV9ta3QsIHdpZHRoPTMsIEZVTiA9IHNkKQ0KYGBgDQoNClJvbGxpbmcgdmFsdWVzIGFyZSBhIHVzZWZ1bCBtZXRyaWMgaW4gdGltZSBzZXJpZXMgZGF0YS4gTm93IHRoYXQgeW91IGFyZSBmYW1pbGlhciB3aXRoIHRoZSBjb3JlIGZlYXR1cmVzIG9mIHRoZSB4dHMgcGFja2FnZSwgdGhlIGZpbmFsIGNoYXB0ZXIgd2lsbCBleHBsb3JlIGEgZmV3IG1vcmUgYWR2YW5jZWQgdG9waWNzIHVzaW5nIHh0cy4NCg0KIyA1LiBFeHRyYSBmZWF0dXJlcyBvZiB4dHMNCg0KIyMgSW5kZXgsIEF0dHJpYnV0ZXMsIGFuZCBUaW1lem9uZXMgLSBWaWRlbw0KDQpUaW1lIHZpYSBpbmRleCgpDQo1MHhwDQpGb3IgdGhpcyBtdWx0aXBsZSBjaG9pY2UgcXVlc3Rpb24sIHlvdSB3aWxsIHVzZSB0aGUgcHJlLWxvYWRlZCB0ZW1wcyBkYXRhIHRvIGhlbHAgeW91IGZpbmQgdGhlIGNvcnJlY3QgYW5zd2VyLg0KDQpXaGljaCBvZiB0aGUgZm9sbG93aW5nIHN0YXRlbWVudHMgaXMgZmFsc2U/DQoNClBvc3NpYmxlIEFuc3dlcnMgICANCg0KIC0gVXNpbmcgdGhlIHRjbGFzcygpIGZ1bmN0aW9uIG9uIHRlbXBzIHJldHVybnMgdGhlIHNhbWUgb3V0cHV0IGFzIGRvZXMgaW5kZXhDbGFzcygpLg0KIC0gaW5kZXhGb3JtYXQodGVtcHMpIDwtICIlYiAlZCwgJVkiIGNoYW5nZXMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBlbnRyeSBvZiB0aGUgZGF0YSB0byBKdWwgMDEsIDIwMTYuDQogLSBUeXBpbmcgaGVscChPbHNvbk5hbWVzKSBpbnRvIHRoZSBjb25zb2xlIHdpbGwgcHJvdmlkZSBSIGRvY3VtZW50YXRpb24gZm9yIHRpbWUgem9uZXMuDQogLSBUaGUgdGltZSB6b25lIG9mIHRoZSB0ZW1wcyBkYXRhIHNldCBpcyBzZXQgdG8gIkFtZXJpY2EvTmV3X1lvcmsiLiAoQ29ycmVjdCkNCg0KDQoNCiMjIyBDbGFzcyBhdHRyaWJ1dGVzIC0gdGNsYXNzLCB0em9uZSwgYW5kIHRmb3JtYXQNCg0KeHRzIG9iamVjdHMgYXJlIHNvbWV3aGF0IHRyaWNreSB3aGVuIGl0IGNvbWVzIHRvIHRpbWUuIEludGVybmFsbHksIHdlIGhhdmUgbm93IHNlZW4gdGhhdCB0aGUgaW5kZXggYXR0cmlidXRlIGlzIHJlYWxseSBhIHZlY3RvciBvZiBudW1lcmljIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBzZWNvbmRzIHNpbmNlIHRoZSBVTklYIGVwb2NoICgxOTcwLTAxLTAxKS4NCg0KSG93IHRoZXNlIHZhbHVlcyBhcmUgZGlzcGxheWVkIG9uIHByaW50aW5nIGFuZCBob3cgdGhleSBhcmUgcmV0dXJuZWQgdG8gdGhlIHVzZXIgd2hlbiB1c2luZyB0aGUgaW5kZXgoKSBmdW5jdGlvbiBpcyBkZXBlbmRlbnQgb24gYSBmZXcga2V5IGludGVybmFsIGF0dHJpYnV0ZXMuDQoNClRoZSBpbmZvcm1hdGlvbiB0aGF0IGNvbnRyb2xzIHRoaXMgYmVoYXZpb3IgY2FuIGJlIHZpZXdlZCBhbmQgZXZlbiBjaGFuZ2VkIHRocm91Z2ggYSBzZXQgb2YgYWNjZXNzb3IgZnVuY3Rpb25zIGRldGFpbGVkIGhlcmU6DQoNClRoZSBpbmRleCBjbGFzcyB1c2luZyBpbmRleENsYXNzKCkgKGUuZy4gZnJvbSBEYXRlIHRvIGNocm9uKQ0KVGhlIHRpbWUgem9uZSB1c2luZyBpbmRleFRaKCkgKGUuZy4gZnJvbSBBbWVyaWNhL0NoaWNhZ28gdG8gRXVyb3BlL0xvbmRvbikNClRoZSB0aW1lIGZvcm1hdCB0byBiZSBkaXNwbGF5ZWQgdmlhIGluZGV4Rm9ybWF0KCkgKGUuZy4gWVlZWS1NTS1ERCkNCkluIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIHByYWN0aWNlIGVhY2ggb2YgdGhlc2UgZnVuY3Rpb25zIGFuZCB2aWV3IHRoZSByZXN1bHRzIG9mIHlvdXIgY2hhbmdlcy4gVG8gZG8gc28sIHlvdSdsbCBvbmNlIGFnYWluIHVzZSB0aGUgdGVtcHMgZGF0YSB0aGF0IGhhcyBiZWVuIHByZS1sb2FkZWQgaW50byB5b3VyIHdvcmtzcGFjZS4NCg0KSW5zdHJ1Y3Rpb25zDQpWaWV3IHRoZSBmaXJzdCB0aHJlZSByb3dzIG9mIHRoZSBpbmRleCBpbiB0aGUgY3VycmVudCB0ZW1wcyBkYXRhLg0KRmluZCB0aGUgaW5kZXggY2xhc3Mgb2YgdGVtcHMgdXNpbmcgdGhlIG1vc3QgcmVsZXZhbnQgY29tbWFuZCBhYm92ZS4NCkZpbmQgdGhlIHRpbWUgem9uZSBvZiB0ZW1wcywgYWdhaW4gdXNpbmcgdGhlIG1vc3QgcmVsZXZhbnQgY29tbWFuZCBhYm92ZS4NCkNoYW5nZSB0aGUgaW5kZXggZm9ybWF0IG9mIHRlbXBzIHRvICIlYi0lZC0lWSIuDQpWaWV3IHRoZSBuZXcgaW5kZXggZm9ybWF0IHVzaW5nIGhlYWQoKS4NCg0KYGBge3J9DQojIFZpZXcgdGhlIGZpcnN0IHRocmVlIGluZGV4ZXMgb2YgdGVtcHMNCmluZGV4KHRlbXBzKVsxOjNdDQoNCiMgR2V0IHRoZSBpbmRleCBjbGFzcyBvZiB0ZW1wcw0KaW5kZXhDbGFzcyh0ZW1wcykNCg0KIyBHZXQgdGhlIHRpbWV6b25lIG9mIHRlbXBzDQppbmRleFRaKHRlbXBzKQ0KDQojIENoYW5nZSB0aGUgZm9ybWF0IG9mIHRoZSB0aW1lIGRpc3BsYXkNCmluZGV4Rm9ybWF0KHRlbXBzKSA8LSAiJWItJWQtJVkiDQoNCiMgVmlldyB0aGUgbmV3IGZvcm1hdA0KaGVhZCh0ZW1wcykNCmBgYA0KDQojIyMgVGltZSBab25lcyAoYW5kIHdoeSB5b3Ugc2hvdWxkIGNhcmUhKQ0KDQpPbmUgb2YgdGhlIHRyaWNraWVzdCBwYXJ0cyB0byB3b3JraW5nIHdpdGggdGltZSBzZXJpZXMgaW4gZ2VuZXJhbCBpcyBkZWFsaW5nIHdpdGggdGltZSB6b25lcy4geHRzIHByb3ZpZGVzIGEgc2ltcGxlIHdheSB0byBsZXZlcmFnZSB0aW1lIHpvbmVzIG9uIGEgcGVyLXNlcmllcyBiYXNpcy4gV2hpbGUgUiBwcm92aWRlcyB0aW1lIHpvbmUgc3VwcG9ydCBpbiBuYXRpdmUgY2xhc3NlcyBQT1NJWGN0IGFuZCBQT1NJWGx0LCB4dHMgZXh0ZW5kcyB0aGlzIHBvd2VyIHRvIHRoZSBlbnRpcmUgb2JqZWN0LCBhbGxvd2luZyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB0aW1lIHpvbmVzIGFjcm9zcyB2YXJpb3VzIG9iamVjdHMuDQoNClNvbWUgaW50ZXJuYWwgb3BlcmF0aW9uIHN5c3RlbSBmdW5jdGlvbnMgcmVxdWlyZSBhIHRpbWUgem9uZSB0byBkbyBkYXRlIG1hdGguIElmIGEgdGltZSB6b25lIGlzbid0IGV4cGxpY2l0bHkgc2V0LCBvbmUgaXMgY2hvc2VuIGZvciB5b3UhIEJlIGNhcmVmdWwgdG8gYWx3YXlzIHNldCBhIHRpbWUgem9uZSBpbiB5b3VyIGVudmlyb25tZW50IHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gd29ya2luZyB3aXRoIGRhdGVzIGFuZCB0aW1lcy4NCg0KeHRzIHByb3ZpZGVzIHRoZSBmdW5jdGlvbiB0em9uZSgpLCB3aGljaCBhbGxvd3MgeW91IHRvIGV4dHJhY3Qgb3Igc2V0IHRpbWUgem9uZXMuDQoNCnR6b25lKHgpIDwtICJUaW1lX1pvbmUiDQpJbiB0aGlzIGV4ZXJjaXNlIHlvdSB3aWxsIHdvcmsgd2l0aCBhbiBvYmplY3QgY2FsbGVkIHRpbWVzIHRvIHByYWN0aWNlIGNvbnN0cnVjdGluZyB5b3VyIG93biB4dHMgb2JqZWN0cyB3aXRoIGN1c3RvbSB0aW1lIHpvbmVzLg0KDQpJbnN0cnVjdGlvbnMgICANCg0KIC0gQ29uc3RydWN0IGFuIHh0cyB0aW1lIHNlcmllcyBvZiB0aGUgbnVtYmVycyAxIHRocm91Z2ggMTAgY2FsbGVkIHRpbWVzX3h0cywgd2l0aCB0em9uZSBzZXQgdG8gIkFtZXJpY2EvQ2hpY2FnbyIsIGFuZCBpbmRleGVkIGJ5IHRoZSB0aW1lcyBvYmplY3QuDQogLSBNb2RpZnkgdGltZXNfeHRzIHRvIHNob3cgdGltZSBpbiAiQXNpYS9Ib25nX0tvbmciLg0KIC0gRXh0cmFjdCB0aGUgY3VycmVudCB0aW1lIHpvbmUgYXMgYSBzdHJpbmcuDQogDQpgYGB7cn0NCiMgQ29uc3RydWN0IHRpbWVzX3h0cyB3aXRoIHR6b25lIHNldCB0byBBbWVyaWNhL0NoaWNhZ28NCnRpbWVzX3h0cyA8LSB4dHMoMToxMCwgb3JkZXIuYnkgPSB0aW1lcywgdHpvbmUgPSAiQW1lcmljYS9DaGljYWdvIikNCg0KIyBDaGFuZ2UgdGhlIHRpbWUgem9uZSBvZiB0aW1lc194dHMgdG8gQXNpYS9Ib25nX0tvbmcNCnR6b25lKHRpbWVzX3h0cykgPC0gIkFzaWEvSG9uZ19Lb25nIg0KICANCiMgRXh0cmFjdCB0aGUgY3VycmVudCB0aW1lIHpvbmUgb2YgdGltZXNfeHRzDQppbmRleFRaKHRpbWVzX3h0cykNCmBgYA0KDQojIyBQZXJpb2RzLCBQZXJpb2RpY2l0eSBhbmQgVGltZXN0YW1wcyAtIFZpZGVvDQoNCkRldGVybWluaW5nIHBlcmlvZGljaXR5DQoxMDB4cA0KVGhlIGlkZWEgb2YgcGVyaW9kaWNpdHkgaXMgcHJldHR5IHNpbXBsZTogV2l0aCB3aGF0IHJlZ3VsYXJpdHkgZG9lcyB5b3VyIGRhdGEgcmVwZWF0PyBGb3Igc3RvY2sgbWFya2V0IGRhdGEsIHlvdSBtaWdodCBoYXZlIGhvdXJseSBwcmljZXMgb3IgbWF5YmUgZGFpbHkgb3Blbi1oaWdoLWxvdy1jbG9zZSBiYXJzLiBGb3IgbWFjcm9lY29ub21pYyBzZXJpZXMsIGl0IG1pZ2h0IGJlIG1vbnRobHkgb3Igd2Vla2x5IHN1cnZleSBudW1iZXJzLg0KDQp4dHMgcHJvdmlkZXMgYSBoYW5keSB0b29sIHRvIGRpc2NvdmVyIHRoaXMgcmVndWxhcml0eSBpbiB5b3VyIGRhdGEgYnkgZXN0aW1hdGluZyB0aGUgZnJlcXVlbmN5IG9mIHRoZSBvYnNlcnZhdGlvbnMgLSB3aGF0IHdlIGFyZSByZWZlcnJpbmcgdG8gYXMgcGVyaW9kaWNpdHkgLSB1c2luZyB0aGUgcGVyaW9kaWNpdHkoKSBjb21tYW5kDQoNCkluIHRoaXMgZXhlcmNpc2UsIHlvdSdsbCB0cnkgdGhpcyBvdXQgb24gYSBmZXcgc2FtcGxlIGRhdGEgc2V0cy4gSW4gcmVhbCBsaWZlIHlvdSBtaWdodCBmaW5kIHlvdXJzZWxmIGRvaW5nIHRoaXMgYXMgYSBmaXJzdCBzdGVwIHRvIHVuZGVyc3RhbmRpbmcgeW91ciBkYXRhIGJlZm9yZSBkaXZpbmcgaW4gZm9yIGZ1cnRoZXIgYW5hbHlzaXMuDQoNCkluc3RydWN0aW9ucw0KQ2FsY3VsYXRlIHRoZSBwZXJpb2RpY2l0eSBvZiB0aGUgdGVtcHMgZGF0YSBzZXQuDQpDYWxjdWxhdGUgdGhlIHBlcmlvZGljaXR5IG9mIHRoZSBlZGhlYyBkYXRhIHNldC4NCkNvbnZlcnQgdGhlIGVkaGVjIGRhdGEgdG8geWVhcmx5IHBlcmlvZGljaXR5IHVzaW5nIHRvLnllYXJseSgpLiBDYWxsIHRoaXMgZWRoZWNfeWVhcmx5Lg0KQ2FsY3VsYXRlIHRoZSBwZXJpb2RpY2l0eSBvZiBlZGhlY195ZWFybHkuDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdGhlIHBlcmlvZGljaXR5IG9mIHRlbXBzDQpwZXJpb2RpY2l0eSh0ZW1wcykNCg0KIyBDYWxjdWxhdGUgdGhlIHBlcmlvZGljaXR5IG9mIGVkaGVjDQpwZXJpb2RpY2l0eShlZGhlYykNCg0KIyBDb252ZXJ0IGVkaGVjIHRvIHllYXJseQ0KZWRoZWNfeWVhcmx5IDwtIHRvLnllYXJseShlZGhlYykNCg0KIyBDYWxjdWxhdGUgdGhlIHBlcmlvZGljaXR5IG9mIGVkaGVjX3llYXJseQ0KcGVyaW9kaWNpdHkoZWRoZWNfeWVhcmx5KQ0KYGBgDQoNCg0KVGhlIHBlcmlvZGljaXR5KCkgY29tbWFuZCBjb21iaW5lZCB3aXRoIHRoZSB0by5wZXJpb2QoKSBzZXQgb2YgY29tbWFuZHMgZ2l2ZXMgeW91IGEgc2ltcGxlIHdheSB0byBtYW5pcHVsYXRlIHlvdXIgdGltZSBzZXJpZXMgZGF0YS4NCg0KDQojIyMgRmluZCB0aGUgbnVtYmVyIG9mIHBlcmlvZHMgaW4geW91ciBkYXRhDQoNCk9mdGVuIGl0IGlzIGhhbmR5IHRvIGtub3cgbm90IGp1c3QgdGhlIHJhbmdlIG9mIHlvdXIgdGltZSBzZXJpZXMgaW5kZXgsIGJ1dCBhbHNvIGhvdyBtYW55IGRpc2NyZXRlIGlycmVndWxhciBwZXJpb2RzIHlvdXIgdGltZSBzZXJpZXMgZGF0YSBjb3ZlcnMuIFlvdSBzaG91bGRuJ3QgYmUgc3VycHJpc2VkIHRvIGxlYXJuIHRoYXQgeHRzIHByb3ZpZGVzIGEgc2V0IG9mIGZ1bmN0aW9ucyB0byBkbyBqdXN0IHRoYXQhDQoNCklmIHlvdSBoYXZlIGEgdGltZSBzZXJpZXMsIGl0IGlzIG5vdyBlYXN5IHRvIHNlZSBob3cgbWFueSBkYXlzLCB3ZWVrcyBvciB5ZWFycyB5b3VyIGRhdGEgY29udGFpbnMuIFRvIGRvIHNvLCBzaW1wbHkgdXNlIHRoZSBmdW5jdGlvbiBuZGF5cygpIGFuZCBpdHMgc2hvcnRjdXQgZnVuY3Rpb25zIG5tb250aHMoKSwgbnF1YXJ0ZXJzKCksIGFuZCBzbyBmb3J0aCwgbWFraW5nIGNvdW50aW5nIGlycmVndWxhciBwZXJpb2RzIGVhc3kuDQoNCkluc3RydWN0aW9ucyAgIA0KDQogLSBDb3VudCB0aGUgbW9udGhzIGluIGVkaGVjLg0KIC0gQ291bnQgdGhlIHF1YXJ0ZXJzIGluIGVkaGVjLg0KIC0gQ291bnQgdGhlIHllYXJzIGluIGVkaGVjLg0KIA0KYGBge3J9DQojIENvdW50IHRoZSBtb250aHMNCm5tb250aHMoZWRoZWMpDQoNCiMgQ291bnQgdGhlIHF1YXJ0ZXJzDQpucXVhcnRlcnMoZWRoZWMpDQoNCiMgQ291bnQgdGhlIHllYXJzDQpueWVhcnMoZWRoZWMpDQpgYGANCg0KIyMjIFNlY3JldCBpbmRleCB0b29scw0KDQp4dHMgdXNlcyBhIHZlcnkgc3BlY2lhbCBhdHRyaWJ1dGUgY2FsbGVkIGluZGV4IHRvIHByb3ZpZGUgdGltZSBzdXBwb3J0IHRvIHlvdXIgb2JqZWN0cy4gRm9yIHBlcmZvcm1hbmNlIGFuZCBkZXNpZ24gcmVhc29ucywgdGhlIGluZGV4IGlzIHN0b3JlZCBpbiBhIHNwZWNpYWwgd2F5LiBUaGlzIG1lYW5zIHRoYXQgcmVnYXJkbGVzcyBvZiB0aGUgY2xhc3Mgb2YgeW91ciBpbmRleCAoZS5nLiBEYXRlIG9yIHllYXJtb24pIGV2ZXJ5dGhpbmcgaW50ZXJuYWxseSBsb29rcyB0aGUgc2FtZSB0byB4dHMuIFRoZSByYXcgaW5kZXggaXMgYWN0dWFsbHkgYSBzaW1wbGUgdmVjdG9yIG9mIGZyYWN0aW9uYWwgc2Vjb25kcyBzaW5jZSB0aGUgVU5JWCBlcG9jaC4NCg0KTm9ybWFsbHkgeW91IHdhbnQgdG8gYWNjZXNzIHRoZSB0aW1lcyB5b3Ugc3RvcmVkLiBpbmRleCgpIGRvZXMgdGhpcyBtYWdpY2FsbHkgZm9yIHlvdSBieSB1c2luZyB5b3VyIGluZGV4Q2xhc3MuIFRvIGdldCB0byB0aGUgcmF3IHZlY3RvciBvZiB0aGUgaW5kZXgsIHlvdSBjYW4gdXNlIC5pbmRleCgpLiBOb3RlIHRoZSBjcml0aWNhbCBkb3QgYmVmb3JlIHRoZSBmdW5jdGlvbiBuYW1lLg0KDQpNb3JlIHVzZWZ1bCB0aGFuIGV4dHJhY3RpbmcgcmF3IHNlY29uZHMgaXMgdGhlIGFiaWxpdHkgdG8gZXh0cmFjdCB0aW1lIGNvbXBvbmVudHMgc2ltaWxhciB0byB0aGUgUE9TSVhsdCBjbGFzcywgd2hpY2ggY2xvc2VseSBtaXJyb3JzIHRoZSB1bmRlcmx5aW5nIFBPU0lYIGludGVybmFsIGNvbXBpbGVkIHN0cnVjdHVyZSB0bS4gVGhpcyBmdW5jdGlvbmFsaXR5IGlzIHByb3ZpZGVkIGJ5IGEgaGFuZGZ1bCBvZiBjb21tYW5kcyBzdWNoIGFzIC5pbmRleGRheSgpLCAuaW5kZXhtb24oKSwgLmluZGV4eWVhcigpLCBhbmQgbW9yZS4NCg0KSW4gdGhpcyBleGVyY2lzZSwgeW91J2xsIHRha2UgYSBsb29rIGF0IHRoZSB3ZWVrZW5kIHdlYXRoZXIgaW4gb3VyIHByZS1sb2FkZWQgdGVtcHMgZGF0YSB1c2luZyB0aGUgLmluZGV4d2RheSgpIGNvbW1hbmQuIE5vdGUgdGhhdCB0aGUgdmFsdWVzIHJhbmdlIGZyb20gMC02LCB3aXRoIFN1bmRheSBlcXVhbCB0byAwLiBSZWNhbGwgdGhhdCB5b3UgY2FuIHVzZSBhIGxvZ2ljYWwgdmVjdG9yIHRvIGV4dHJhY3QgZWxlbWVudHMgb2YgYW4geHRzIG9iamVjdC4NCg0KSW5zdHJ1Y3Rpb25zICAgDQoNCiAtIFByYWN0aWNlIGV4dHJhY3RpbmcgdGhlIHVuZGVybHlpbmcgdW5pdHMgb2YgeW91ciBpbmRleCBpbiB0aGUgdGVtcHMgZGF0YS4gVXNlIC5pbmRleCgpIHRvIHNlZSB0aGUgbnVtYmVyIG9mIHNlY29uZHMsIGFuZCAuaW5kZXh3ZGF5KCkgdG8gc2VlIHRoZSBkYXkgb2YgdGhlIHdlZWsgb2YgeW91ciBvYnNlcnZhdGlvbnMuDQogLSBDcmVhdGUgaW5kZXggdXNpbmcgdGhlIHdoaWNoKCkgZnVuY3Rpb24gdG8gZXh0cmFjdCB3ZWVrZW5kIG9ic2VydmF0aW9ucyBpbiB0ZW1wcy4NCiAtIFNlbGVjdCB0aGUgaW5kZXhlZCB2YWx1ZXMgZnJvbSB0ZW1wcy4NCiANCmBgYHtyfQ0KIyBFeHBsb3JlIHVuZGVybHlpbmcgdW5pdHMgb2YgdGVtcHMgaW4gdHdvIGNvbW1hbmRzOiAuaW5kZXgoKSBhbmQgLmluZGV4d2RheSgpDQouaW5kZXgodGVtcHMpDQouaW5kZXh3ZGF5KHRlbXBzKQ0KDQoNCiMgQ3JlYXRlIGFuIGluZGV4IG9mIHdlZWtlbmQgZGF5cyB1c2luZyB3aGljaCgpDQppbmRleCA8LSB3aGljaCguaW5kZXh3ZGF5KHRlbXBzKSA9PSAwIHwgLmluZGV4d2RheSh0ZW1wcykgPT0gNikNCg0KIyBTZWxlY3QgdGhlIGluZGV4DQp0ZW1wc1tpbmRleF0NCmBgYA0KDQojIyMgTW9kaWZ5aW5nIHRpbWVzdGFtcHMNCg0KTW9zdCB0aW1lIHNlcmllcyB3ZSd2ZSBzZWVuIGhhdmUgYmVlbiBkYWlseSBvciBsb3dlciBmcmVxdWVuY3kuIERlcGVuZGluZyBvbiB5b3VyIGZpZWxkLCB5b3UgbWlnaHQgZW5jb3VudGVyIGhpZ2hlciBmcmVxdWVuY3kgZGF0YSAtIHRoaW5rIGludHJhZGF5IHRyYWRpbmcgaW50ZXJ2YWxzLCBvciBzZW5zb3IgZGF0YSBmcm9tIG1lZGljYWwgZXF1aXBtZW50Lg0KDQpJbiB0aGVzZSBzaXR1YXRpb25zLCB0aGVyZSBhcmUgdHdvIGZ1bmN0aW9ucyBpbiB4dHMgdGhhdCBhcmUgaGFuZHkgdG8ga25vdy4NCg0KSWYgeW91IGZpbmQgdGhhdCB5b3UgaGF2ZSBvYnNlcnZhdGlvbnMgd2l0aCBpZGVudGljYWwgdGltZXN0YW1wcywgaXQgbWlnaHQgYmUgdXNlZnVsIHRvIHBlcnR1cmIgb3IgcmVtb3ZlIHRoZXNlIHRpbWVzIHRvIGFsbG93IGZvciB1bmlxdWVuZXNzLiB4dHMgcHJvdmlkZXMgdGhlIGZ1bmN0aW9uIG1ha2UuaW5kZXgudW5pcXVlKCkgZm9yIGp1c3QgdGhpcyBwdXJwb3NlLiBUaGUgZXBzIGFyZ3VtZW50LCBzaG9ydCBmb3IgZXBzaWxvbiBvciBzbWFsbCBjaGFuZ2UsIGNvbnRyb2xzIGhvdyBtdWNoIGlkZW50aWNhbCB0aW1lcyBzaG91bGQgYmUgcGVydHVyYmVkLCBhbmQgZHJvcCA9IFRSVUUgbGV0cyB5b3UganVzdCByZW1vdmUgZHVwbGljYXRlIG9ic2VydmF0aW9ucyBlbnRpcmVseS4NCg0KT24gb3RoZXIgb2Nhc3Npb25zIHlvdSBtaWdodCBmaW5kIHlvdXIgdGltZXN0YW1wcyBhIGJpdCB0b28gcHJlY2lzZS4gSW4gdGhlc2UgaW5zdGFuY2VzIGl0IG1pZ2h0IGJlIGJldHRlciB0byByb3VuZCB1cCB0byBzb21lIGZpeGVkIGludGVydmFsLCBmb3IgZXhhbXBsZSBhbiBvYnNlcnZhdGlvbiBtYXkgb2NjdXIgYXQgYW55IHBvaW50IGluIGFuIGhvdXIsIGJ1dCB5b3Ugd2FudCB0byByZWNvcmQgdGhlIGxhdGVzdCBhcyBvZiB0aGUgYmVnaW5uaW5nIG9mIHRoZSBuZXh0IGhvdXIuIEZvciB0aGlzIHNpdHVhdGlvbiwgdGhlIGFsaWduLnRpbWUoKSBjb21tYW5kIHdpbGwgZG8gd2hhdCB5b3UgbmVlZCwgc2V0dGluZyB0aGUgbiBhcmd1bWVudCB0byB0aGUgbnVtYmVyIG9mIHNlY29uZHMgeW91J2QgbGlrZSB0byByb3VuZCB0by4NCg0KbWFrZS5pbmRleC51bmlxdWUoeCwgZXBzID0gMWUtNCkgICMgUGVydHVyYg0KbWFrZS5pbmRleC51bmlxdWUoeCwgZHJvcCA9IFRSVUUpICMgRHJvcCBkdXBsaWNhdGVzDQphbGlnbi50aW1lKHgsIG4gPSA2MCkgIyBSb3VuZCB0byB0aGUgbWludXRlDQpJbiB0aGlzIGV4ZXJjaXNlLCB5b3UnbGwgdHJ5IHRoZSB0aHJlZSB1c2UgY2FzZXMgb24gYW4geHRzIG9iamVjdCBjYWxsZWQgei4NCg0KSW5zdHJ1Y3Rpb25zDQogLSBDb252ZXJ0IHRoZSB6IHNlcmllcyB0aW1lcyB0byBhIHVuaXF1ZSBzZXJpZXMgdXNpbmcgbWFrZS5pbmRleC51bmlxdWUoKSwgd2hlcmUgZXBzID0gMWUtNC4gU2F2ZSB0aGlzIHRvIHpfdW5pcXVlLg0KIC0gUmVtb3ZlIGR1cGxpY2F0ZSB0aW1lcyBpbiB6LiBTYXZlIHRoaXMgdG8gel9kdXAuDQogLSBBbGlnbiB6IHRvIHRoZSBuZWFyZXN0IGhvdXIgdXNpbmcgYWxpZ24udGltZSgpLiBTYXZlIHRoaXMgdG8gel9yb3VuZC4NCg0KYGBge3J9DQojIE1ha2UgeiBoYXZlIHVuaXF1ZSB0aW1lc3RhbXBzDQp6X3VuaXF1ZSA8LSBtYWtlLmluZGV4LnVuaXF1ZSh6LCBlcHMgPSAxZS00KQ0KDQojIFJlbW92ZSBkdXBsaWNhdGUgdGltZXMgaW4geg0Kel9kdXAgPC0gbWFrZS5pbmRleC51bmlxdWUoeiwgZHJvcCA9IFRSVUUpDQoNCiMgUm91bmQgb2JzZXJ2YXRpb25zIGluIHogdG8gdGhlIG5leHQgaG91cg0Kel9yb3VuZCA8LSBhbGlnbi50aW1lKHosIG4gPSAzNjAwKQ0KYGBgDQoNClRoZXNlIGZpbmFsIGNvbW1hbmRzIHNob3VsZCByb3VuZCBvdXQgeW91ciB4dHMga25vd2xlZGdlIGFuZCBnaXZlIHlvdSB0aGUgY29tcGxldGUgdG9vbHMgdG8gbWFuaXB1bGF0ZSB0aW1lIHNlcmllcyBkYXRhIGluIFIu