text:
0.4892" y1="8.6732" x2="60.96" y2="9.144" width="0.1524" layer="1"/>
<via x="60.96" y="9.144" extent="1-16" drill="0.35"/>
<wire x1="60.96" y1="9.144" x2="60.96" y2="10.323203125" width="0.1524" layer="16"/>
<wire x1="60.96" y1="10.323203125" x2="61.0108" y2="10.374003125" width="0.1524" layer="16"/>
</signal>
<signal name="USB_D_P">
<contactref element="U5" pad="3"/>
<contactref element="U6" pad="165"/>
<wire x1="51.409" y1="24.146" x2="52.40929375" y2="24.146" width="0.3048" layer="1"/>
<wire x1="59.78469375" y1="31.5214" x2="56.90745625" y2="28.6441625" width="0.3048" layer="1"/>
<wire x1="56.90745625" y1="28.6441625" x2="56.90745625" y2="28.32086875" width="0.3048" layer="1" curve="90"/>
<wire x1="56.90745625" y1="28.32086875" x2="56.915159375" y2="28.313165625" width="0.3048" layer="1"/>
<wire x1="56.915159375" y1="28.313165625" x2="56.915159375" y2="27.989871875" width="0.3048" layer="1" curve="-90"/>
<wire x1="56.915159375" y1="27.989871875" x2="56.854415625" y2="27.929128125" width="0.3048" layer="1"/>
<wire x1="56.854415625" y1="27.929128125" x2="56.531121875" y2="27.929128125" width="0.3048" layer="1" curve="-90"/>
<wire x1="56.531121875" y1="27.929128125" x2="56.52341875" y2="27.93683125" width="0.3048" layer="1"/>
<wire x1="56.52341875" y1="27.93683125" x2="56.200125" y2="27.93683125" width="0.3048" layer="1" curve="90"/>
<wire x1="56.200125" y1="27.93683125" x2="56.139378125" y2="27.876084375" width="0.3048" layer="1"/>
<wire x1="56.139378125" y1="27.876084375" x2="56.139378125" y2="27.552790625" width="0.3048" layer="1" curve="90"/>
<wire x1="56.139378125" y1="27.552790625" x2="56.14708125" y2="27.5450875" width="0.3048" layer="1"/>
<wire x1="56.14708125" y1="27.5450875" x2="56.14708125" y2="27.22179375" width="0.3048" layer="1" curve="-90"/>
<wire x1="56.14708125" y1="27.22179375" x2="56.0863375" y2="27.16105" width="0.3048" layer="1"/>
<wire x1="56.0863375" y1="27.16105" x2="55.76304375" y2="27.16105" width="0.3048" layer="1" curve="-90"/>
<wire x1="55.76304375" y1="27.16105" x2="55.755340625" y2="27.168753125" width="0.3048" layer="1"/>
<wire x1="55.755340625" y1="27.168753125" x2="55.432046875" y2="27.168753125" width="0.3048" layer="1" curve="90"/>
<wire x1="55.432046875" y1="27.168753125" x2="52.40929375" y2="24.146" width="0.3048" layer="1"/>
<wire x1="59.78469375" y1="31.5214" x2="63.59469375" y2="31.5214" width="0.3048" layer="1"/>
<wire x1="63.59469375" y1="31.5214" x2="65.405" y2="33.33170625" width="0.3048" layer="1"/>
<wire x1="65.405" y1="33.33170625" x2="65.405" y2="36.63370625" width="0.3048" layer="1"/>
<wire x1="65.405" y1="36.63370625" x2="65.744446875" y2="36.973153125" width="0.3048" layer="1"/>
<via x="65.903009375" y="36.8145875" extent="1-16" drill="0.3048"/>
<wire x1="65.744446875" y1="36.973153125" x2="65.903009375" y2="36.8145875" width="0.3048" layer="16"/>
<wire x1="65.744446875" y1="36.973153125" x2="65.903009375" y2="36.8145875" width="0.3048" layer="1"/>
<wire x1="65.744446875" y1="36.973153125" x2="65.98229375" y2="37.211" width="0.3048" layer="16"/>
<wire x1="65.98229375" y1="37.211" x2="66.1416" y2="37.211" width="0.3048" layer="16"/>
<wire x1="66.1416" y1="37.211" x2="66.1416" y2="36.322" width="0.3048" layer="16"/>
<wire x1="66.1416" y1="36.322" x2="66.04" y2="36.2204" width="0.3048" layer="16"/>
<wire x1="66.04" y1="36.2204" x2="66.04" y2="35.158" width="0.3048" layer="16"/>
<wire x1="66.04" y1="35.158" x2="66.024" y2="35.142" width="0.3048" layer="16"/>
</signal>
<signal name="USB_D_N">
<contactref element="U5" pad="4"/>
<contactref element="U6" pad="167"/>
<wire x1="51.409" y1="24.646" x2="52.26270625" y2="24.646" width="0.3048" layer="1"/>
<wire x1="59.59530625" y1="31.9786" x2="52.26270625" y2="24.646" width="0.3048" layer="1"/>
<wire x1="59.59530625" y1="31.9786" x2="63.40530625" y2="31.9786" width="0.3048" layer="1"/>
<wire x1="63.40530625" y1="31.9786" x2="64.9478" y2="33.52109375" width="0.3048" layer="1"/>
<wire x1="64.9478" y1="33.52109375" x2="64.9478" y2="36.82309375" width="0.3048" layer="1"/>
<wire x1="64.9478" y1="36.82309375" x2="65.421153125" y2="37.296446875" width="0.3048" layer="1"/>
<via x="65.2625875" y="37.455009375" extent="1-16" drill="0.3048"/>
<wire x1="65.421153125" y1="37.296446875" x2="65.2625875" y2="37.455009375" width="0.3048" layer="16"/>
<wire x1="65.421153125" y1="37.296446875" x2="65.2625875" y2="37.455009375" width="0.3048" layer="1"/>
<wire x1="65.421153125" y1="37.296446875" x2="65.79290625" y2="37.6682" width="0.3048" layer="16"/>
<wire x1="65.79290625" y1="37.6682" x2="66.5226" y2="37.6682" width="0.3048" layer="16"/>
<wire x1="66.5226" y1="37.6682" x2="66.9544" y2="37.2364" width="0.3048" layer="16"/>
<wire x1="66.9544" y1="37.2364" x2="66.9544" y2="36.576" width="0.3048" layer="16"/>
<wire x1="66.9544" y1="36.576" x2="66.6496" y2="36.2712" width="0.3048" layer="16"/>
<wire x1="66.6496" y1="36.2712" x2="66.6496" y2="35.1676" width="0.3048" layer="16"/>
<wire x1="66.6496" y1="35.1676" x2="66.624" y2="35.142" width="0.3048" layer="16"/>
</signal>
<signal name="N$53">
<contactref element="U6" pad="168"/>
<contactref element="R45" pad="1"/>
<wire x1="66.924" y1="27.342" x2="66.924" y2="25.136403125" width="0.1524" layer="16"/>
<wire x1="66.924" y1="25.136403125" x2="67.066803125" y2="24.9936" width="0.1524" layer="16"/>
</signal>
<signal name="N$54">
<contactref element="J8" pad="1"/>
<wire x1="2.5908" y1="34.9504" x2="4.572" y2="36.9316" width="0.1524" layer="1"/>
<wire x1="4.572" y1="36.9316" x2="12.446" y2="36.9316" width="0.1524" layer="1"/>
<wire x1="12.446" y1="36.9316" x2="13.1572" y2="37.6428" width="0.1524" layer="1"/>
<via x="13.1572" y="37.6428" extent="1-16" drill="0.35"/>
<wire x1="2.5908" y1="8.636" x2="2.5908" y2="29.2039625" width="0.1524" layer="1"/>
<wire x1="2.5908" y1="29.2039625" x2="3.7338" y2="30.0929625" width="0.1524" layer="1"/>
<wire x1="3.7338" y1="30.0929625" x2="3.7338" y2="32.5434375" width="0.1524" layer="1"/>
<wire x1="3.7338" y1="32.5434375" x2="2.5908" y2="33.4324375" width="0.1524" layer="1"/>
<wire x1="2.5908" y1="33.4324375" x2="2.5908" y2="34.9504" width="0.1524" layer="1"/>
<contactref element="U6" pad="15"/>
<wire x1="16.28905625" y1="37.0078" x2="16.6878" y2="37.0078" width="0.1524" layer="16"/>
<wire x1="16.6878" y1="37.0078" x2="17.4244" y2="36.2712" width="0.1524" layer="16"/>
<wire x1="15.65405625" y1="37.6428" x2="16.28905625" y2="37.0078" width="0.1524" layer="16"/>
<wire x1="17.4244" y1="36.2712" x2="17.4244" y2="35.1424" width="0.1524" layer="16"/>
<wire x1="17.4244" y1="35.1424" x2="17.424" y2="35.142" width="0.1524" layer="16"/>
<wire x1="13.1572" y1="37.6428" x2="15.65405625" y2="37.6428" width="0.1524" layer="16"/>
</signal>
<signal name="+1V8">
<contactref element="L3" pad="P$2"/>
<contactref element="C17" pad="2"/>
<contactref element="U16" pad="4"/>
<contactref element="C18" pad="2"/>
<wire x1="72.074" y1="33.262" x2="72.632" y2="33.262" width="0.1524" layer="1"/>
<wire x1="72.632" y1="33.262" x2="72.9996" y2="33.6296" width="0.1524" layer="1"/>
<wire x1="72.9996" y1="33.6296" x2="73.2536" y2="33.8836" width="0.1524" layer="1"/>
<wire x1="73.2536" y1="33.8836" x2="73.2536" y2="34.6456" width="0.1524" layer="1"/>
<wire x1="73.279" y1="34.671" x2="73.2536" y2="34.6456" width="0.1524" layer="1"/>
<wire x1="74.803" y1="30.496" x2="75.5556" y2="30.496" width="0.1524" layer="1"/>
<wire x1="76.0984" y1="31.0388" x2="75.5556" y2="30.496" width="0.1524" layer="1"/>
<wire x1="76.0984" y1="31.0388" x2="76.3016" y2="31.242" width="0.1524" layer="1"/>
<wire x1="76.3016" y1="31.242" x2="76.3016" y2="33.6804" width="0.1524" layer="1"/>
<wire x1="76.1238" y1="33.8582" x2="76.3016" y2="33.6804" width="0.1524" layer="1"/>
<wire x1="76.1238" y1="33.8582" x2="75.6412" y2="34.3408" width="0.1524" layer="1"/>
<wire x1="75.6412" y1="34.3408" x2="73.6092" y2="34.3408" width="0.1524" layer="1"/>
<wire x1="73.6092" y1="34.3408" x2="73.279" y2="34.671" width="0.1524" layer="1"/>
<contactref element="U6" pad="184"/>
<contactref element="U6" pad="186"/>
<wire x1="72.324" y1="27.342" x2="71.724" y2="27.342" width="0.1524" layer="16"/>
<contactref element="U6" pad="185"/>
<contactref element="U6" pad="183"/>
<wire x1="72.024" y1="35.142" x2="71.424" y2="35.142" width="0.1524" layer="16"/>
<wire x1="72.9996" y1="33.6296" x2="73.66" y2="33.6296" width="0.1524" layer="1"/>
<wire x1="73.66" y1="33.6296" x2="73.7616" y2="33.528" width="0.1524" layer="1"/>
<via x="73.7616" y="33.528" extent="1-16" drill="0.35"/>
<wire x1="73.7616" y1="33.528" x2="72.4916" y2="33.528" width="0.1524" layer="16"/>
<wire x1="72.4916" y1="33.528" x2="72.0344" y2="33.9852" width="0.1524" layer="16"/>
<wire x1="72.0344" y1="33.9852" x2="72.0344" y2="35.1316" width="0.1524" layer="16"/>
<wire x1="72.0344" y1="35.1316" x2="72.024" y2="35.142" width="0.1524" layer="16"/>
<wire x1="72.7202" y1="28.575" x2="74.4601" y2="28.575" width="0.1524" layer="1"/>
<wire x1="72.7202" y1="28.575" x2="72.39" y2="28.9052" width="0.1524" layer="1"/>
<via x="72.39" y="28.9052" extent="1-16" drill="0.35"/>
<wire x1="72.39" y1="28.9052" x2="72.39" y2="27.408" width="0.1524" layer="16"/>
<wire x1="72.39" y1="27.408" x2="72.324" y2="27.342" width="0.1524" layer="16"/>
<wire x1="74.4601" y1="28.575" x2="74.4601" y2="30.1531" width="0.1524" layer="1"/>
<wire x1="74.4601" y1="30.1531" x2="74.803" y2="30.496" width="0.1524" layer="1"/>
<contactref element="C23" pad="2"/>
<contactref element="U13" pad="3"/>
<contactref element="R39" pad="1"/>
<wire x1="42.353" y1="12.204" x2="43.4841" y2="12.204" width="0.1524" layer="1"/>
<wire x1="43.4841" y1="12.204" x2="44.5897" y2="13.3096" width="0.1524" layer="1"/>
<wire x1="58.3057" y1="34.1376" x2="59.182" y2="34.1376" width="0.1524" layer="1"/>
<wire x1="59.182" y1="34.1376" x2="60.5028" y2="35.4584" width="0.1524" layer="1"/>
<wire x1="60.5028" y1="35.4584" x2="62.3824" y2="35.4584" width="0.1524" layer="1"/>
<wire x1="62.3824" y1="35.4584" x2="62.8396" y2="35.9156" width="0.1524" layer="1"/>
<wire x1="62.8396" y1="35.9156" x2="62.8396" y2="37.0162" width="0.1524" layer="1"/>
<wire x1="62.8396" y1="37.0162" x2="62.2554" y2="37.6004" width="0.1524" layer="1"/>
<wire x1="62.2554" y1="37.6004" x2="62.2554" y2="38.2948" width="0.1524" layer="1"/>
<wire x1="62.7464" y1="38.7858" x2="62.7634" y2="38.7858" width="0.1524" layer="1"/>
<wire x1="62.7634" y1="38.7858" x2="62.8904" y2="38.9128" width="0.1524" layer="1"/>
<wire x1="62.8904" y1="38.9128" x2="62.8904" y2="39.6664" width="0.1524" layer="1"/>
<wire x1="62.2554" y1="38.2948" x2="62.7464" y2="38.7858" width="0.1524" layer="1"/>
<wire x1="63.3814" y1="40.1574" x2="65.041" y2="40.1574" width="0.1524" layer="1"/>
<wire x1="65.041" y1="40.1574" x2="65.3712" y2="39.8272" width="0.1524" layer="1"/>
<wire x1="65.3712" y1="39.8272" x2="65.6514625" y2="39.8272" width="0.1524" layer="1"/>
<wire x1="65.6514625" y1="39.8272" x2="65.8292625" y2="40.005" width="0.1524" layer="1"/>
<wire x1="62.8904" y1="39.6664" x2="63.3814" y2="40.1574" width="0.1524" layer="1"/>
<wire x1="66.8603375" y1="40.005" x2="67.0381375" y2="39.8272" width="0.1524" layer="1"/>
<wire x1="69.52054375" y1="39.8272" x2="69.72374375" y2="40.0304" width="0.1524" layer="1"/>
<wire x1="65.8292625" y1="40.005" x2="66.8603375" y2="40.005" width="0.1524" layer="1"/>
<wire x1="67.0381375" y1="39.8272" x2="69.52054375" y2="39.8272" width="0.1524" layer="1"/>
<wire x1="77.0128" y1="37.83834375" x2="77.0128" y2="37.39645625" width="0.1524" layer="1"/>
<wire x1="74.82074375" y1="40.0304" x2="77.0128" y2="37.83834375" width="0.1524" layer="1"/>
<wire x1="77.0128" y1="37.39645625" x2="76.1238" y2="36.50745625" width="0.1524" layer="1"/>
<wire x1="76.1238" y1="36.50745625" x2="76.1238" y2="33.8582" width="0.1524" layer="1"/>
<wire x1="69.72374375" y1="40.0304" x2="74.82074375" y2="40.0304" width="0.1524" layer="1"/>
<wire x1="44.5897" y1="13.3096" x2="44.5897" y2="12.8143" width="0.1524" layer="1"/>
<wire x1="44.5897" y1="12.8143" x2="45.6184" y2="11.7856" width="0.1524" layer="1"/>
<via x="45.6184" y="11.7856" extent="1-16" drill="0.35"/>
<wire x1="45.6184" y1="11.7856" x2="50.6476" y2="11.7856" width="0.1524" layer="16"/>
<wire x1="50.6476" y1="11.7856" x2="56.0324" y2="6.4008" width="0.1524" layer="16"/>
<wire x1="56.0324" y1="6.4008" x2="79.8068" y2="6.4008" width="0.1524" layer="16"/>
<wire x1="79.8068" y1="6.4008" x2="85.3948" y2="11.9888" width="0.1524" layer="16"/>
<wire x1="84.88171875" y1="26.44901875" x2="84.88171875" y2="27.28468125" width="0.1524" layer="16"/>
<wire x1="84.88171875" y1="27.28468125" x2="82.6008" y2="29.5656" width="0.1524" layer="16"/>
<wire x1="85.3948" y1="11.9888" x2="85.3948" y2="25.9359375" width="0.1524" layer="16"/>
<wire x1="85.3948" y1="25.9359375" x2="84.88171875" y2="26.44901875" width="0.1524" layer="16"/>
<wire x1="82.6008" y1="29.5656" x2="77.6732" y2="29.5656" width="0.1524" layer="16"/>
<wire x1="77.6732" y1="29.5656" x2="77.4192" y2="29.8196" width="0.1524" layer="16"/>
<via x="77.4192" y="29.8196" extent="1-16" drill="0.35"/>
<wire x1="77.4192" y1="29.8196" x2="77.3176" y2="29.8196" width="0.1524" layer="1"/>
<wire x1="77.3176" y1="29.8196" x2="76.0984" y2="31.0388" width="0.1524" layer="1"/>
</signal>
</signals>
<errors>
<approved hash="5,1,c02e9044b82a4de2"/>
<approved hash="5,1,90471044968ab698"/>
<approved hash="5,1,8a2703060b04b909"/>
<approved hash="5,1,9cfe5b6f5f509b31"/>
<approved hash="5,1,9d0a5a3b5e7f64d2"/>
<approved hash="5,1,437ef5b0ffe276b2"/>
<approved hash="4,1,091d846f13fefdb5"/>
<approved hash="4,1,06b8db86dbb1538e"/>
<approved hash="4,16,091d846f13fefdb5"/>
<approved hash="4,16,06b8db86dbb1538e"/>
<approved hash="5,16,f12824bccef7fc9f"/>
<approved hash="5,16,f12824bccef7fc9f"/>
<approved hash="5,16,911d66b58f21d88a"/>
<approved hash="19,16,b4356fde38a70353"/>
<approved hash="19,16,252674b4e46025f3"/>
<approved hash="19,16,252674b4e46025f3"/>
<approved hash="19,16,613fe4af746461f5"/>
<approved hash="19,16,26269496dc10c940"/>
<approved hash="19,16,6b5b172717976beb"/>
<approved hash="19,16,26269496dc10c940"/>
<approved hash="19,16,6b5b172717976beb"/>
<approved hash="19,16,9faeff2d3b2c5baf"/>
<approved hash="19,16,056952d866ae6312"/>
<approved hash="19,16,6b51172d17a96bd5"/>
<approved hash="19,16,6b51172d17a96bd5"/>
<approved hash="19,16,6a78160416066a7a"/>
<approved hash="19,16,59d205d86eb45545"/>
<approved hash="19,16,663d686919e43648"/>
<approved hash="19,16,6a78160416066a7a"/>
<approved hash="19,16,6a78160416066a7a"/>
<approved hash="19,16,6b5b172717976beb"/>
<approved hash="19,16,dbbbc04c08ec74e0"/>
<approved hash="5,16,f128c1fb076a6a0d"/>
<approved hash="19,16,056952d866ae6312"/>
<approved hash="19,16,bbe2b9bd5cc80f00"/>
<approved hash="19,16,6b51172d17a96bd5"/>
<approved hash="19,16,6a78160416066a7a"/>
<approved hash="19,16,663d686919e43648"/>
<approved hash="19,16,59d205d86eb45545"/>
<approved hash="5,16,f128c1fb076a6a0d"/>
<approved hash="19,16,ee216befab307226"/>
<approved hash="5,16,cecaf31d39c947e4"/>
<approved hash="1,20,64e1fa07fa706496"/>
<approved hash="1,20,70f80e1e0e977071"/>
<approved hash="1,20,7ce2020402747c92"/>
<approved hash="5,1,c39b8ccf766b9d76"/>
<approved hash="5,1,808d63fb23ddfeab"/>
<approved hash="5,1,504182ea22473d0e"/>
<approved hash="5,1,601483601adb4281"/>
<approved hash="19,1,b4404a424a21b423"/>
<approved hash="5,1,3d02addf2da2357c"/>
<approved hash="19,1,4844224621d34bd1"/>
<approved hash="5,1,3506a5df25a62d78"/>
<approved hash="5,1,0d0a9ddf1daa3574"/>
<approved hash="5,1,34871c569c4b0c91"/>
<approved hash="19,1,4c41da43da284c2a"/>
<approved hash="5,1,3c87e45ae447349e"/>
<approved hash="5,1,3506e5dfe5a53d78"/>
<approved hash="5,1,3d02eddfeda5357c"/>
<approved hash="5,1,3487ec5eec433c9e"/>
<approved hash="5,1,a31aa5da86cc2811"/>
<approved hash="5,1,fa9ba458d7835791"/>
<approved hash="5,1,f62ce7f466bdb61b"/>
<approved hash="5,1,65a793a7fd76b8af"/>
<approved hash="5,1,347325a0ef815b9d"/>
<approved hash="5,1,d06d829d54b0b94c"/>
<approved hash="5,1,07ae823ceedc4c52"/>
<approved hash="19,16,5cb3bfa71cae14b7"/>
<approved hash="19,16,62523e7e925f4108"/>
<approved hash="19,16,ea854b8b8894f710"/>
<approved hash="19,16,a5a100a30f1425e8"/>
<approved hash="19,1,5e246e0d71e48ff4"/>
<approved hash="19,1,b224723353e55dcb"/>
<approved hash="19,1,dc038e6d5b18adb2"/>
<approved hash="19,1,dc038e6d5b18adb2"/>
<approved hash="19,1,ce561a6825f7f1c9"/>
<approved hash="19,1,ce381a06241ff021"/>
<approved hash="19,1,56447fd3564a2dc7"/>
<approved hash="19,1,ce381a06241ff021"/>
<approved hash="19,1,56447fd3564a2dc7"/>
<approved hash="19,1,5f974940a1da13c9"/>
<approved hash="19,1,4e071a391a044e3a"/>
<approved hash="19,1,5acbfb92272438a3"/>
</errors>
</board>
</drawing>
<compatibility>
<note version="6.3" minversion="6.2.2" severity="warning">
Since Version 6.2.2 text objects can contain more than one line,
which will not be processed correctly with this version.
</note>
</compatibility>
</eagle>


text:
/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package interrupts exposes helpers for graceful handling of interrupt signals
package interrupts

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/sirupsen/logrus"
)

// only one instance of the manager ever exists
var single *manager

func init() {
	m := sync.Mutex{}
	single = &manager{
		c:  sync.NewCond(&m),
		wg: sync.WaitGroup{},
	}
	go handleInterrupt()
}

type manager struct {
	// only one signal handler should be installed, so we use a cond to
	// broadcast to workers that an interrupt has occurred
	c *sync.Cond
	// we record whether we've broadcast in the past
	seenSignal bool
	// we want to ensure that all registered servers and workers get a
	// change to gracefully shut down
	wg sync.WaitGroup
}

// handleInterrupt turns an interrupt into a broadcast for our condition.
// This must be called _first_ before any work is registered with the
// manager, or there will be a deadlock.
func handleInterrupt() {
	signalsLock.Lock()
	sigChan := signals()
	signalsLock.Unlock()
	s := <-sigChan
	logrus.WithField("signal", s).Info("Received signal.")
	single.c.L.Lock()
	single.seenSignal = true
	single.c.Broadcast()
	single.c.L.Unlock()
}

// test initialization will set the signals channel in another goroutine
// so we need to synchronize that in order to not trigger the race detector
// even though we know that init() calls will be serial and the test init()
// will fire first
var signalsLock = sync.Mutex{}

var signalChannel = make(chan os.Signal, 1)

// Terminate can be called to trigger a termination
// to the current process.
func Terminate() {
	signalChannel <- os.Interrupt
}

// signals allows for injection of mock signals in testing
var signals = func() <-chan os.Signal {
	signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
	return signalChannel
}

// wait executes the cancel when an interrupt is seen or if one has already
// been handled
func wait(cancel func()) {
	single.c.L.Lock()
	if !single.seenSignal {
		single.c.Wait()
	}
	single.c.L.Unlock()
	cancel()
}

var gracePeriod = 1 * time.Minute

// WaitForGracefulShutdown waits until all registered servers and workers
// have had time to gracefully shut down, or times out. This function is
// blocking.
func WaitForGracefulShutdown() {
	wait(func() {
		logrus.Info("Interrupt received.")
	})
	finished := make(chan struct{})
	go func() {
		single.wg.Wait()
		close(finished)
	}()
	select {
	case <-finished:
		logrus.Info("All workers gracefully terminated, exiting.")
	case <-time.After(gracePeriod):
		logrus.Warn("Timed out waiting for workers to gracefully terminate, exiting.")
	}
}

// Context returns a context that is cancelled when an interrupt hits.
// Using this context is a weak guarantee that your work will finish before
// process exit as callers cannot signal that they are finished. Prefer to use
// Run().
func Context() context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	single.wg.Add(1)
	go wait(func() {
		cancel()
		single.wg.Done()
	})

	return ctx
}

// Run will do work until an interrupt is received, then signal the
// worker. This function is not blocking. Callers are expected to exit
// only after WaitForGracefulShutdown returns to ensure all workers have
// had time to shut down. This is preferable to getting the raw Context
// as we can ensure that the work is finished before releasing our share
// of the wait group on shutdown.
func Run(work func(ctx context.Context)) {
	ctx, cancel := context.WithCancel(context.Background())
	single.wg.Add(1)
	go func() {
		defer single.wg.Done()
		work(ctx)
	}()

	go wait(cancel)
}

// ListenAndServer is typically an http.Server
type ListenAndServer interface {
	Shutdownable
	ListenAndServe() error
}

// ListenAndServe runs the HTTP server and handles shutting it down
// gracefully on interrupts. This function is not blocking. Callers
// are expected to exit only after WaitForGracefulShutdown returns to
// ensure all servers have had time to shut down.
func ListenAndServe(server ListenAndServer, gracePeriod time.Duration) {
	single.wg.Add(1)
	go func() {
		defer single.wg.Done()
		logrus.WithError(server.ListenAndServe()).Info("Server exited.")
	}()

	go wait(shutdown(server, gracePeriod))
}

// ListenAndServeTLS runs the HTTP server and handles shutting it down
// gracefully on interrupts. This function is not blocking. Callers
// are expected to exit only after WaitForGracefulShutdown returns to
// ensure all servers have had time to shut down.
func ListenAndServeTLS(server *http.Server, certFile, keyFile string, gracePeriod time.Duration) {
	single.wg.Add(1)
	go func() {
		defer single.wg.Done()
		logrus.WithError(server.ListenAndServeTLS(certFile, keyFile)).Info("Server exited.")
	}()

	go wait(shutdown(server, gracePeriod))
}

// Shutdownable is typically an http.Server
type Shutdownable interface {
	Shutdown(context.Context) error
}

// shutdown will shut down the server
func shutdown(server Shutdownable, gracePeriod time.Duration) func() {
	return func() {
		logrus.Info("Server shutting down...")
		ctx, cancel := context.WithTimeout(context.Background(), gracePeriod)
		if err := server.Shutdown(ctx); err != nil {
			logrus.WithError(err).Info("Error shutting down server...")
		}
		cancel()
	}
}

// Tick will do work on a dynamically determined interval until an
// interrupt is received. This function is not blocking. Callers are
// expected to exit only after WaitForGracefulShutdown returns to
// ensure all workers have had time to shut down.
func Tick(work func(), interval func() time.Duration) {
	before := time.Time{} // we want to do work right away
	sig := make(chan int, 1)
	single.wg.Add(1)
	go func() {
		defer single.wg.Done()
		for {
			nextInterval := interval()
			nextTick := before.Add(nextInterval)
			sleep := time.Until(nextTick)
			logrus.WithFields(logrus.Fields{
				"before":   before,
				"interval": nextInterval,
				"sleep":    sleep,
			}).Debug("Resolved next tick interval.")
			select {
			case <-time.After(sleep):
				before = time.Now()
				work()
			case <-sig:
				logrus.Info("Worker shutting down...")
				return
			}
		}
	}()

	go wait(func() {
		sig <- 1
	})
}

// TickLiteral runs Tick with an unchanging interval.
func TickLiteral(work func(), interval time.Duration) {
	Tick(work, func() time.Duration {
		return interval
	})
}

// OnInterrupt ensures that work is done when an interrupt is fired
// and that we wait for the work to be finished before we consider
// the process cleaned up. This function is not blocking.
func OnInterrupt(work func()) {
	single.wg.Add(1)
	go wait(func() {
		work()
		single.wg.Done()
	})
}

repository: kubernetes/test-infra

license_type: permissive

repo_name: kubernetes/test-infra

branch_name: refs/heads/master

gha_language: Go

extension: go


text:
// Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use
// of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.

package sstable

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"testing"
	"time"
	"unsafe"

	"github.com/cockroachdb/datadriven"
	"github.com/cockroachdb/pebble/internal/base"
	"github.com/stretchr/testify/require"
	"golang.org/x/exp/rand"
)

func ikey(s string) InternalKey {
	return InternalKey{UserKey: []byte(s)}
}

func TestBlockWriter(t *testing.T) {
	w := &rawBlockWriter{
		blockWriter: blockWriter{restartInterval: 16},
	}
	w.add(ikey("apple"), nil)
	w.add(ikey("apricot"), nil)
	w.add(ikey("banana"), nil)
	block := w.finish()

	expected := []byte(
		"\x00\x05\x00apple" +
			"\x02\x05\x00ricot" +
			"\x00\x06\x00banana" +
			"\x00\x00\x00\x00\x01\x00\x00\x00")
	if !bytes.Equal(expected, block) {
		t.Fatalf("expected\n%q\nfound\n%q", expected, block)
	}
}

func TestBlockWriterWithPrefix(t *testing.T) {
	w := &rawBlockWriter{
		blockWriter: blockWriter{restartInterval: 2},
	}
	curKey := func() string {
		return string(base.DecodeInternalKey(w.curKey).UserKey)
	}
	addAdapter := func(
		key InternalKey,
		value []byte,
		addValuePrefix bool,
		valuePrefix valuePrefix,
		setHasSameKeyPrefix bool) {
		w.addWithOptionalValuePrefix(
			key, false, value, len(key.UserKey), addValuePrefix, valuePrefix, setHasSameKeyPrefix)
	}
	addAdapter(
		ikey("apple"), []byte("red"), false, 0, true)
	require.Equal(t, "apple", curKey())
	require.Equal(t, "red", string(w.curValue))
	addAdapter(
		ikey("apricot"), []byte("orange"), true, '\xff', false)
	require.Equal(t, "apricot", curKey())
	require.Equal(t, "orange", string(w.curValue))
	// Even though this call has setHasSameKeyPrefix=true, the previous call,
	// which was after the last restart set it to false. So the restart encoded
	// with banana has this cumulative bit set to false.
	addAdapter(
		ikey("banana"), []byte("yellow"), true, '\x00', true)
	require.Equal(t, "banana", curKey())
	require.Equal(t, "yellow", string(w.curValue))
	addAdapter(
		ikey("cherry"), []byte("red"), false, 0, true)
	require.Equal(t, "cherry", curKey())
	require.Equal(t, "red", string(w.curValue))
	// All intervening calls has setHasSameKeyPrefix=true, so the cumulative bit
	// will be set to true in this restart.
	addAdapter(
		ikey("mango"), []byte("juicy"), false, 0, true)
	require.Equal(t, "mango", curKey())
	require.Equal(t, "juicy", string(w.curValue))

	block := w.finish()

	expected := []byte(
		"\x00\x0d\x03apple\x00\x00\x00\x00\x00\x00\x00\x00red" +
			"\x02\x0d\x07ricot\x00\x00\x00\x00\x00\x00\x00\x00\xfforange" +
			"\x00\x0e\x07banana\x00\x00\x00\x00\x00\x00\x00\x00\x00yellow" +
			"\x00\x0e\x03cherry\x00\x00\x00\x00\x00\x00\x00\x00red" +
			"\x00\x0d\x05mango\x00\x00\x00\x00\x00\x00\x00\x00juicy" +
			// Restarts are:
			// 00000000 (restart at apple), 2a000000 (restart at banana), 56000080 (restart at mango)
			// 03000000 (number of restart, i.e., 3). The restart at mango has 1 in the most significant
			// bit of the uint32, so the last byte in the little endian encoding is \x80.
			"\x00\x00\x00\x00\x2a\x00\x00\x00\x56\x00\x00\x80\x03\x00\x00\x00")
	if !bytes.Equal(expected, block) {
		t.Fatalf("expected\n%x\nfound\n%x", expected, block)
	}
}

func testBlockCleared(t *testing.T, w, b *blockWriter) {
	require.Equal(t, w.restartInterval, b.restartInterval)
	require.Equal(t, w.nEntries, b.nEntries)
	require.Equal(t, w.nextRestart, b.nextRestart)
	require.Equal(t, len(w.buf), len(b.buf))
	require.Equal(t, len(w.restarts), len(b.restarts))
	require.Equal(t, len(w.curKey), len(b.curKey))
	require.Equal(t, len(w.prevKey), len(b.prevKey))
	require.Equal(t, len(w.curValue), len(b.curValue))
	require.Equal(t, w.tmp, b.tmp)

	// Make sure that we didn't lose the allocated byte slices.
	require.True(t, cap(w.buf) > 0 && cap(b.buf) == 0)
	require.True(t, cap(w.restarts) > 0 && cap(b.restarts) == 0)
	require.True(t, cap(w.curKey) > 0 && cap(b.curKey) == 0)
	require.True(t, cap(w.prevKey) > 0 && cap(b.prevKey) == 0)
	require.True(t, cap(w.curValue) > 0 && cap(b.curValue) == 0)
}

func TestBlockClear(t *testing.T) {
	w := blockWriter{restartInterval: 16}
	w.add(ikey("apple"), nil)
	w.add(ikey("apricot"), nil)
	w.add(ikey("banana"), nil)

	w.clear()

	// Once a block is cleared, we expect its fields to be cleared, but we expect
	// it to keep its allocated byte slices.
	b := blockWriter{}
	testBlockCleared(t, &w, &b)
}

func TestInvalidInternalKeyDecoding(t *testing.T) {
	// Invalid keys since they don't have an 8 byte trailer.
	testCases := []string{
		"",
		"\x01\x02\x03\x04\x05\x06\x07",
		"foo",
	}
	for _, tc := range testCases {
		i := blockIter{}
		i.decodeInternalKey([]byte(tc))
		require.Nil(t, i.ikey.UserKey)
		require.Equal(t, uint64(InternalKeyKindInvalid), i.ikey.Trailer)
	}
}

func TestBlockIter(t *testing.T) {
	// k is a block that maps three keys "apple", "apricot", "banana" to empty strings.
	k := block([]byte(
		"\x00\x05\x00apple" +
			"\x02\x05\x00ricot" +
			"\x00\x06\x00banana" +
			"\x00\x00\x00\x00\x01\x00\x00\x00"))
	var testcases = []struct {
		index int
		key   string
	}{
		{0, ""},
		{0, "a"},
		{0, "aaaaaaaaaaaaaaa"},
		{0, "app"},
		{0, "apple"},
		{1, "appliance"},
		{1, "apricos"},
		{1, "apricot"},
		{2, "azzzzzzzzzzzzzz"},
		{2, "b"},
		{2, "banan"},
		{2, "banana"},
		{3, "banana\x00"},
		{3, "c"},
	}
	for _, tc := range testcases {
		i, err := newRawBlockIter(bytes.Compare, k)
		require.NoError(t, err)
		i.SeekGE([]byte(tc.key))
		for j, keyWant := range []string{"apple", "apricot", "banana"}[tc.index:] {
			if !i.Valid() {
				t.Fatalf("key=%q, index=%d, j=%d: Valid got false, keyWant true", tc.key, tc.index, j)
			}
			if keyGot := string(i.Key().UserKey); keyGot != keyWant {
				t.Fatalf("key=%q, index=%d, j=%d: got %q, keyWant %q", tc.key, tc.index, j, keyGot, keyWant)
			}
			i.Next()
		}
		if i.Valid() {
			t.Fatalf("key=%q, index=%d: Valid got true, keyWant false", tc.key, tc.index)
		}
		if err := i.Close(); err != nil {
			t.Fatalf("key=%q, index=%d: got err=%v", tc.key, tc.index, err)
		}
	}

	{
		i, err := newRawBlockIter(bytes.Compare, k)
		require.NoError(t, err)
		i.Last()
		for j, keyWant := range []string{"banana", "apricot", "apple"} {
			if !i.Valid() {
				t.Fatalf("j=%d: Valid got false, want true", j)
			}
			if keyGot := string(i.Key().UserKey); keyGot != keyWant {
				t.Fatalf("j=%d: got %q, want %q", j, keyGot, keyWant)
			}
			i.Prev()
		}
		if i.Valid() {
			t.Fatalf("Valid got true, want false")
		}
		if err := i.Close(); err != nil {
			t.Fatalf("got err=%v", err)
		}
	}
}

func TestBlockIter2(t *testing.T) {
	makeIkey := func(s string) InternalKey {
		j := strings.Index(s, ":")
		seqNum, err := strconv.Atoi(s[j+1:])
		if err != nil {
			panic(err)
		}
		return base.MakeInternalKey([]byte(s[:j]), uint64(seqNum), InternalKeyKindSet)
	}

	var block []byte

	for _, r := range []int{1, 2, 3, 4} {
		t.Run(fmt.Sprintf("restart=%d", r), func(t *testing.T) {
			datadriven.RunTest(t, "testdata/block", func(t *testing.T, d *datadriven.TestData) string {
				switch d.Cmd {
				case "build":
					w := &blockWriter{restartInterval: r}
					for _, e := range strings.Split(strings.TrimSpace(d.Input), ",") {
						w.add(makeIkey(e), nil)
					}
					block = w.finish()
					return ""

				case "iter":
					iter, err := newBlockIter(bytes.Compare, block)
					if err != nil {
						return err.Error()
					}

					iter.globalSeqNum, err = scanGlobalSeqNum(d)
					if err != nil {
						return err.Error()
					}

					var b bytes.Buffer
					for _, line := range strings.Split(d.Input, "\n") {
						parts := strings.Fields(line)
						if len(parts) == 0 {
							continue
						}
						switch parts[0] {
						case "seek-ge":
							if len(parts) != 2 {
								return "seek-ge <key>\n"
							}
							iter.SeekGE([]byte(strings.TrimSpace(parts[1])), base.SeekGEFlagsNone)
						case "seek-lt":
							if len(parts) != 2 {
								return "seek-lt <key>\n"
							}
							iter.SeekLT([]byte(strings.TrimSpace(parts[1])), base.SeekLTFlagsNone)
						case "first":
							iter.First()
						case "last":
							iter.Last()
						case "next":
							iter.Next()
						case "prev":
							iter.Prev()
						}
						if iter.valid() {
							fmt.Fprintf(&b, "<%s:%d>", iter.Key().UserKey, iter.Key().SeqNum())
						} else if err := iter.Error(); err != nil {
							fmt.Fprintf(&b, "<err=%v>", err)
						} else {
							fmt.Fprintf(&b, ".")
						}
					}
					b.WriteString("\n")
					return b.String()

				default:
					return fmt.Sprintf("unknown command: %s", d.Cmd)
				}
			})
		})
	}
}

func TestBlockIterKeyStability(t *testing.T) {
	w := &blockWriter{restartInterval: 1}
	expected := [][]byte{
		[]byte("apple"),
		[]byte("apricot"),
		[]byte("banana"),
	}
	for i := range expected {
		w.add(InternalKey{UserKey: expected[i]}, nil)
	}
	block := w.finish()

	i, err := newBlockIter(bytes.Compare, block)
	require.NoError(t, err)

	// Check that the supplied slice resides within the bounds of the block.
	check := func(v []byte) {
		t.Helper()
		begin := unsafe.Pointer(&v[0])
		end := unsafe.Pointer(uintptr(begin) + uintptr(len(v)))
		blockBegin := unsafe.Pointer(&block[0])
		blockEnd := unsafe.Pointer(uintptr(blockBegin) + uintptr(len(block)))
		if uintptr(begin) < uintptr(blockBegin) || uintptr(end) > uintptr(blockEnd) {
			t.Fatalf("key %p-%p resides outside of block %p-%p", begin, end, blockBegin, blockEnd)
		}
	}

	// Check that various means of iterating over the data match our expected
	// values. Note that this is only guaranteed because of the usage of a
	// restart-interval of 1 so that prefix compression was not performed.
	for j := range expected {
		keys := [][]byte{}
		for key, _ := i.SeekGE(expected[j], base.SeekGEFlagsNone); key != nil; key, _ = i.Next() {
			check(key.UserKey)
			keys = append(keys, key.UserKey)
		}
		require.EqualValues(t, expected[j:], keys)
	}

	for j := range expected {
		keys := [][]byte{}
		for key, _ := i.SeekLT(expected[j], base.SeekLTFlagsNone); key != nil; key, _ = i.Prev() {
			check(key.UserKey)
			keys = append(keys, key.UserKey)
		}
		for i, j := 0, len(keys)-1; i < j; i, j = i+1, j-1 {
			keys[i], keys[j] = keys[j], keys[i]
		}
		require.EqualValues(t, expected[:j], keys)
	}
}

// Regression test for a bug in blockIter.Next where it was failing to handle
// the case where it is switching from reverse to forward iteration. When that
// switch occurs we need to populate blockIter.fullKey so that prefix
// decompression works properly.
func TestBlockIterReverseDirections(t *testing.T) {
	w := &blockWriter{restartInterval: 4}
	keys := [][]byte{
		[]byte("apple0"),
		[]byte("apple1"),
		[]byte("apple2"),
		[]byte("banana"),
		[]byte("carrot"),
	}
	for i := range keys {
		w.add(InternalKey{UserKey: keys[i]}, nil)
	}
	block := w.finish()

	for targetPos := 0; targetPos < w.restartInterval; targetPos++ {
		t.Run("", func(t *testing.T) {
			i, err := newBlockIter(bytes.Compare, block)
			require.NoError(t, err)

			pos := 3
			if key, _ := i.SeekLT([]byte("carrot"), base.SeekLTFlagsNone); !bytes.Equal(keys[pos], key.UserKey) {
				t.Fatalf("expected %s, but found %s", keys[pos], key.UserKey)
			}
			for pos > targetPos {
				pos--
				if key, _ := i.Prev(); !bytes.Equal(keys[pos], key.UserKey) {
					t.Fatalf("expected %s, but found %s", keys[pos], key.UserKey)
				}
			}
			pos++
			if key, _ := i.Next(); !bytes.Equal(keys[pos], key.UserKey) {
				t.Fatalf("expected %s, but found %s", keys[pos], key.UserKey)
			}
		})
	}
}

func BenchmarkBlockIterSeekGE(b *testing.B) {
	const blockSize = 32 << 10

	for _, restartInterval := range []int{16} {
		b.Run(fmt.Sprintf("restart=%d", restartInterval),
			func(b *testing.B) {
				w := &blockWriter{
					restartInterval: restartInterval,
				}

				var ikey InternalKey
				var keys [][]byte
				for i := 0; w.estimatedSize() < blockSize; i++ {
					key := []byte(fmt.Sprintf("%05d", i))
					keys = append(keys, key)
					ikey.UserKey = key
					w.add(ikey, nil)
				}

				it, err := newBlockIter(bytes.Compare, w.finish())
				if err != nil {
					b.Fatal(err)
				}
				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))

				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					k := keys[rng.Intn(len(keys))]
					it.SeekGE(k, base.SeekGEFlagsNone)
					if testing.Verbose() {
						if !it.valid() {
							b.Fatal("expected to find key")
						}
						if !bytes.Equal(k, it.Key().UserKey) {
							b.Fatalf("expected %s, but found %s", k, it.Key().UserKey)
						}
					}
				}
			})
	}
}

func BenchmarkBlockIterSeekLT(b *testing.B) {
	const blockSize = 32 << 10

	for _, restartInterval := range []int{16} {
		b.Run(fmt.Sprintf("restart=%d", restartInterval),
			func(b *testing.B) {
				w := &blockWriter{
					restartInterval: restartInterval,
				}

				var ikey InternalKey
				var keys [][]byte
				for i := 0; w.estimatedSize() < blockSize; i++ {
					key := []byte(fmt.Sprintf("%05d", i))
					keys = append(keys, key)
					ikey.UserKey = key
					w.add(ikey, nil)
				}

				it, err := newBlockIter(bytes.Compare, w.finish())
				if err != nil {
					b.Fatal(err)
				}
				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))

				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					j := rng.Intn(len(keys))
					it.SeekLT(keys[j], base.SeekLTFlagsNone)
					if testing.Verbose() {
						if j == 0 {
							if it.valid() {
								b.Fatal("unexpected key")
							}
						} else {
							if !it.valid() {
								b.Fatal("expected to find key")
							}
							k := keys[j-1]
							if !bytes.Equal(k, it.Key().UserKey) {
								b.Fatalf("expected %s, but found %s", k, it.Key().UserKey)
							}
						}
					}
				}
			})
	}
}

func BenchmarkBlockIterNext(b *testing.B) {
	const blockSize = 32 << 10

	for _, restartInterval := range []int{16} {
		b.Run(fmt.Sprintf("restart=%d", restartInterval),
			func(b *testing.B) {
				w := &blockWriter{
					restartInterval: restartInterval,
				}

				var ikey InternalKey
				for i := 0; w.estimatedSize() < blockSize; i++ {
					ikey.UserKey = []byte(fmt.Sprintf("%05d", i))
					w.add(ikey, nil)
				}

				it, err := newBlockIter(bytes.Compare, w.finish())
				if err != nil {
					b.Fatal(err)
				}

				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					if !it.valid() {
						it.First()
					}
					it.Next()
				}
			})
	}
}

func BenchmarkBlockIterPrev(b *testing.B) {
	const blockSize = 32 << 10

	for _, restartInterval := range []int{16} {
		b.Run(fmt.Sprintf("restart=%d", restartInterval),
			func(b *testing.B) {
				w := &blockWriter{
					restartInterval: restartInterval,
				}

				var ikey InternalKey
				for i := 0; w.estimatedSize() < blockSize; i++ {
					ikey.UserKey = []byte(fmt.Sprintf("%05d", i))
					w.add(ikey, nil)
				}

				it, err := newBlockIter(bytes.Compare, w.finish())
				if err != nil {
					b.Fatal(err)
				}

				b.ResetTimer()
				for i := 0; i < b.N; i++ {
					if !it.valid() {
						it.Last()
					}
					it.Prev()
				}
			})
	}
}

repository: cockroachdb/pebble

repo_name: cockroachdb/pebble


text:
require u-boot-common_${PV}.inc

SRC_URI += "file://default-gcc.patch"

SUMMARY = "U-Boot bootloader fw_printenv/setenv utilities"
DEPENDS = "mtd-utils mem-map-config m3-loaders"

INSANE_SKIP_${PN} = "already-stripped"

CFLAGS += '-I${STAGING_INCDIR}/sta_mem_map'
EXTRA_OEMAKE_class-target = 'CROSS_COMPILE=${TARGET_PREFIX} CC="${CC} ${CFLAGS} ${LDFLAGS}" HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" V=1'
EXTRA_OEMAKE_class-cross = 'ARCH=${TARGET_ARCH} CC="${CC} ${CFLAGS} ${LDFLAGS}" V=1'

UBOOT_ATF_CONFIG = "# CONFIG_ARMV7_NONSEC is not set"
UBOOT_NON_ATF_CONFIG = "CONFIG_ARMV7_NONSEC=y\n# CONFIG_ARMV7_BOOT_SEC_DEFAULT is not set\nCONFIG_ARMV7_PSCI_NR_CPUS=4"

#Let's use our external source tree
inherit externalsrc
EXTERNALSRC_pn-${PN} = "${ST_LOCAL_SRC}/u-boot"
SRCTREECOVEREDTASKS = "do_unpack do_fetch"

inherit uboot-config

do_configure () {
	unset LDFLAGS
	unset CFLAGS
	unset CPPFLAGS

	UBOOT_SOC_CONFIG="$(mktemp)"
	case "${TARGET_SOC_ID}" in
		"SOCID_STA1295")
			echo "CONFIG_SOC_STA1295=y" > ${UBOOT_SOC_CONFIG}
			;;
		"SOCID_STA1195")
			echo "CONFIG_SOC_STA1195=y" > ${UBOOT_SOC_CONFIG}
			;;
		"SOCID_STA1385")
			echo "CONFIG_SOC_STA1385=y" > ${UBOOT_SOC_CONFIG}
			;;
		"SOCID_STA1275")
			echo "CONFIG_SOC_STA1275=y" > ${UBOOT_SOC_CONFIG}
			;;
		*)
			;;
	esac
	echo "${@bb.utils.contains('MACHINE_FEATURES', 'atf', '${UBOOT_ATF_CONFIG}', '${UBOOT_NON_ATF_CONFIG}', d)}" >> ${UBOOT_SOC_CONFIG}
	oe_runmake -C ${S} O=${B} ${CURRENT_XLDR_CONFIG}
	${S}/scripts/kconfig/merge_config.sh -m -r -O "${B}" "${B}/.config" ${UBOOT_SOC_CONFIG} 1>&2
	cat ${UBOOT_SOC_CONFIG}
	rm ${UBOOT_SOC_CONFIG}
}

do_compile () {
	unset LDFLAGS
	unset CFLAGS
	unset CPPFLAGS

	oe_runmake -C ${S} O=${B} env
}

do_install () {
	install -d ${D}${base_sbindir}
	install -d ${D}${sysconfdir}
	install -m 755 ${B}/tools/env/fw_printenv ${D}${base_sbindir}/fw_printenv
	install -m 755 ${B}/tools/env/fw_printenv ${D}${base_sbindir}/fw_setenv
	install -m 0644 ${S}/tools/env/fw_env.config ${D}${sysconfdir}/fw_env.config
}

do_install_class-cross () {
	install -d ${D}${bindir_cross}
	install -m 755 ${B}/tools/env/fw_printenv ${D}${bindir_cross}/fw_printenv
	install -m 755 ${B}/tools/env/fw_printenv ${D}${bindir_cross}/fw_setenv
}

SYSROOT_DIRS_append_class-cross = " ${bindir_cross}"

PACKAGE_ARCH = "${MACHINE_ARCH}"
BBCLASSEXTEND = "cross"

python __anonymous() {
    list = d.getVar("UBOOT_MACHINE", True).lstrip().split(' ')
    xloader_item = [item for item in list if "xloader" in item]
    d.setVar('CURRENT_XLDR_CONFIG', ''.join(xloader_item))
}

license: MIT

extension: bb


text:
# A recipe which installs all the DTB files from KERNEL_DEVICETREE into the
# "dtb" folder of the boot partition.

LICENSE = "GPL-2.0"

FILES_${PN} = " ${MENDER_BOOT_PART_MOUNT_LOCATION}/dtb"

DEPENDS = "virtual/kernel"

do_install() {
    install -d -m 755 ${D}/${MENDER_BOOT_PART_MOUNT_LOCATION}/dtb

    for dtb_path in ${KERNEL_DEVICETREE}; do
        install -m 0644 ${DEPLOY_DIR_IMAGE}/$(basename $dtb_path) ${D}/${MENDER_BOOT_PART_MOUNT_LOCATION}/dtb/
    done
}
do_install[depends] = "virtual/kernel:do_deploy"

repository: madisongh/meta-mender

repo_name: madisongh/meta-mender

gha_license_id: NOASSERTION

gha_language: Python