<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on Blog - enjuk</title>
    <link>https://enjuk.jp/blog/posts/</link>
    <description>Recent content in Posts on Blog - enjuk</description>
    <generator>Hugo</generator>
    <language>ja-JP</language>
    <lastBuildDate>Fri, 26 Dec 2025 09:39:52 +0000</lastBuildDate>
    <atom:link href="https://enjuk.jp/blog/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>scx_simple</title>
      <link>https://enjuk.jp/blog/posts/scx_simple/</link>
      <pubDate>Fri, 26 Dec 2025 09:39:52 +0000</pubDate>
      <guid>https://enjuk.jp/blog/posts/scx_simple/</guid>
      <description>&lt;h1 id=&#34;sched_ext&#34;&gt;sched_ext&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;./tools/sched_ext/*.bpf.c&lt;/code&gt;にBPFの実装がある。&lt;/li&gt;&#xA;&lt;li&gt;*.cはユーザー空間のローダーであり、中にはロジック本体を担うやつもありそう&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;scx_&#34;&gt;&lt;a href=&#34;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/sched_ext/scx_simple.bpf.c&#34;&gt;scx_simple.bpf.c&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;this scheduler should work reasonably well on CPUs with a uniform L3 cache topology&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;私が使ってるRyzen 9 9955HXでは、CCD(Core Complex Die)が二つあるので、scx_simpleは適してないかも。&lt;a href=&#34;#appendix&#34;&gt;Ryzen 9 9955HXのlstopo&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;scx_simpleのハンドラ. 必須なのは&lt;code&gt;.name&lt;/code&gt;のみであり、そのほかは欠けている場合にはscxのデフォルト実装が利用される。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SCX_OPS_DEFINE&lt;/span&gt;(simple_ops,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .select_cpu&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_select_cpu,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .enqueue&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_enqueue,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .dispatch&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_dispatch,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .running&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_running,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .stopping&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_stopping,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .enable&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_enable,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .init&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_init,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .exit&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)simple_exit,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;       .name&#x9;&#x9;&#x9;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;simple&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_select_cpu&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;scx_bpf_select_cpu_dfl()&lt;/code&gt;はidleCPUがなかったらprev_cpuを返す&lt;/li&gt;&#xA;&lt;li&gt;idle CPUがある場合には、そのCPUのlocal DSQに直接enqueueする&lt;/li&gt;&#xA;&lt;li&gt;idle CPUがない場合には、scx coreへのヒントとしてcpu(prev_cpu)を返す&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s32 &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_select_cpu, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p, s32 prev_cpu, u64 wake_flags)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; is_idle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;s32 cpu;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;cpu &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_select_cpu_dfl&lt;/span&gt;(p, prev_cpu, wake_flags, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;is_idle);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (is_idle) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;stat_inc&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;/* count local queueing */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_dsq_insert&lt;/span&gt;(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; cpu;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_enqueue&#xA;&lt;ul&gt;&#xA;&lt;li&gt;fifoの場合: 何もせず独自global DSQにenqueueする&lt;/li&gt;&#xA;&lt;li&gt;vtime考慮の場合: vtimeを設定した上で独自global DSQにenqueueする&#xA;&lt;ul&gt;&#xA;&lt;li&gt;なお、vtime(これまで消費した重みつきCPU時間)が短いほど優先される。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;vtimeの初期値は、task生成時のvtime_nowであり、これは相対的な値&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;vtimeをkeyとしてpriority queue(rb tree)で管理されている&lt;/li&gt;&#xA;&lt;li&gt;この時、vtimeが他のタスクと比べて&lt;code&gt;SCX_SLICE_DFL&lt;/code&gt;以上に短い場合には、vtimeの差が &lt;code&gt;SCX_SLICE_DFL&lt;/code&gt;となるように、vtimeを増やす。つまり、次回以降に必要以上にスケジュールされやすくするのを防ぐ&lt;/li&gt;&#xA;&lt;li&gt;sleepしてた状態のタスクが貯金できる予算を1 slice分に制限する&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_enqueue, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p, u64 enq_flags)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;stat_inc&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;/* count global queueing */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (fifo_sched) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_dsq_insert&lt;/span&gt;(p, SHARED_DSQ, SCX_SLICE_DFL, enq_flags);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;u64 vtime &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.dsq_vtime;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9; * Limit the amount of budget that an idling task can accumulate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9; * to one slice.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9; */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;time_before&lt;/span&gt;(vtime, vtime_now &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; SCX_SLICE_DFL))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;vtime &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; vtime_now &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; SCX_SLICE_DFL;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_dsq_insert_vtime&lt;/span&gt;(p, SHARED_DSQ, SCX_SLICE_DFL, vtime,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;&#x9;&#x9; enq_flags);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_dispatch&#xA;&lt;ul&gt;&#xA;&lt;li&gt;dispatchをcallしたCPUのlocal DSQに、独自 global DSQ からタスクを一つ移動させる&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_dispatch, s32 cpu, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;prev)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_dsq_move_to_local&lt;/span&gt;(SHARED_DSQ);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_running&#xA;&lt;ul&gt;&#xA;&lt;li&gt;taskがCPUで実行され始めた時に実行される&lt;/li&gt;&#xA;&lt;li&gt;taskのvtimeがvtime_now(global variable)より大きい場合には、vtime_nowを更新する&lt;/li&gt;&#xA;&lt;li&gt;fifoの場合には何もしない&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_running, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (fifo_sched)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * Global vtime always progresses forward as tasks start executing. The&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * test and update can be performed concurrently from multiple CPUs and&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * thus racy. Any error should be contained and temporary. Let&amp;#39;s just&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * live with it.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;time_before&lt;/span&gt;(vtime_now, p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.dsq_vtime))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;vtime_now &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.dsq_vtime;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_stopping&#xA;&lt;ul&gt;&#xA;&lt;li&gt;taskがCPUから剥がれた時に実行される&lt;/li&gt;&#xA;&lt;li&gt;vtimeを加算する処理を行う。scx.sliceは残りのtime slice&#xA;&lt;ul&gt;&#xA;&lt;li&gt;デフォルトではscx.sliceは0なので、頻繁にyieldするタスクに不利&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;fifoの場合には何もしない&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_stopping, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; runnable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (fifo_sched)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * Scale the execution time by the inverse of the weight and charge.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * Note that the default yield implementation yields by setting&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * @p-&amp;gt;scx.slice to zero and the following would treat the yielding task&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * as if it has consumed all its slice. If this penalizes yielding tasks&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * too much, determine the execution time by taking explicit timestamps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; * instead of depending on @p-&amp;gt;scx.slice.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9; */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.dsq_vtime &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; (SCX_SLICE_DFL &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.slice) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.weight;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_enable&#xA;&lt;ul&gt;&#xA;&lt;li&gt;タスクがsched_extの管理下にはいる時に実行される&#xA;&lt;ul&gt;&#xA;&lt;li&gt;新しいタスクが生成された時&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_enable, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; task_struct &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;p&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;scx.dsq_vtime &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; vtime_now;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_init&#xA;&lt;ul&gt;&#xA;&lt;li&gt;scx scheduler登録時に実行される&lt;/li&gt;&#xA;&lt;li&gt;scx_simple専用の独自DSQを作る&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s32 &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS_SLEEPABLE&lt;/span&gt;(simple_init)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scx_bpf_create_dsq&lt;/span&gt;(SHARED_DSQ, &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;simple_exit&#xA;&lt;ul&gt;&#xA;&lt;li&gt;scx scheduler登録解除時に実行される&lt;/li&gt;&#xA;&lt;li&gt;UEIはUser Exit Info らしい。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;scx schedulerが終了した理由をuserspaceに伝えるための仕組み&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;userspaceからは&lt;code&gt;uei&lt;/code&gt;をBPF Map経由で読める&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BPF_STRUCT_OPS&lt;/span&gt;(simple_exit, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; scx_exit_info &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ei)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#a6e22e&#34;&gt;UEI_RECORD&lt;/span&gt;(uei, ei);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define UEI_DEFINE(__name)&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;char RESIZABLE_ARRAY(data, __name##_dump);&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;const volatile u32 __name##_dump_len;&#x9;&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;struct user_exit_info __name SEC(&amp;#34;.data&amp;#34;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define UEI_RECORD(__uei_name, __ei) ({&#x9;&#x9;&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;bpf_probe_read_kernel_str(__uei_name.reason,&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;&#x9;&#x9;  sizeof(__uei_name.reason), (__ei)-&amp;gt;reason);&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;bpf_probe_read_kernel_str(__uei_name.msg,&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;&#x9;&#x9;  sizeof(__uei_name.msg), (__ei)-&amp;gt;msg);&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;bpf_probe_read_kernel_str(__uei_name##_dump,&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;&#x9;&#x9;  __uei_name##_dump_len, (__ei)-&amp;gt;dump);&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;if (bpf_core_field_exists((__ei)-&amp;gt;exit_code))&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;__uei_name.exit_code = (__ei)-&amp;gt;exit_code;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* use __sync to force memory barrier */&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;__sync_val_compare_and_swap(&amp;amp;__uei_name.kind, __uei_name.kind,&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&#x9;&#x9;&#x9;&#x9;    (__ei)-&amp;gt;kind);&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;appendix&#34;&gt;Appendix&lt;/h2&gt;&#xA;&lt;p&gt;&lt;img src=&#34;./lstopo.svg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>RSS Hash key の効果効用</title>
      <link>https://enjuk.jp/blog/posts/rss-key-distribution/</link>
      <pubDate>Mon, 08 Dec 2025 23:04:55 +0900</pubDate>
      <guid>https://enjuk.jp/blog/posts/rss-key-distribution/</guid>
      <description>&lt;h1 id=&#34;rssハッシュキーによる動作の変化を確認する&#34;&gt;RSSハッシュキーによる動作の変化を確認する&lt;/h1&gt;&#xA;&lt;h2 id=&#34;動機&#34;&gt;動機&lt;/h2&gt;&#xA;&lt;p&gt;igcのRSSハッシュキーの設定が行えるようにするパッチを出したので、実際に動作が変わっているかどうかを確認したい。&lt;/p&gt;&#xA;&lt;h2 id=&#34;前提&#34;&gt;前提&lt;/h2&gt;&#xA;&lt;p&gt;RSSが有効なNICがパケットを受信した際、複数存在するキューのうちどのキューにパケットを積むかという部分に注目する。&#xA;端的に言うと、NICは受信したパケットの要素(IPアドレス、ポートなど)を抽出し、あらかじめ設定されたハッシュキーとハッシュ関数を用いてハッシュ値を計算し、そのハッシュ値をRETA(Redirection table, 別名 Indirection table)のサイズで割った剰余をインデックスとして、RETAから対応するキュー番号を選択する。&lt;/p&gt;&#xA;&lt;p&gt;詳細については&lt;a href=&#34;https://doc.dpdk.org/guides/prog_guide/toeplitz_hash_lib.html&#34;&gt;DPDKのブログ&lt;/a&gt;やIntelのPDFに詳しく載っている。&lt;/p&gt;&#xA;&lt;p&gt;詳しく知りたい方は、RSS Toeplitzなどでググっていただくと、RSSハッシュキーなどを調整してRSSの動作を予測可能にするといった、ある程度高度な情報も見つかるので面白いと思う。&lt;/p&gt;&#xA;&lt;h2 id=&#34;実験&#34;&gt;実験&lt;/h2&gt;&#xA;&lt;p&gt;実際にパケットを受信して、以下の事項を確かめる&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;デフォルトのランダムなハッシュキー環境下で、十分に分散が行われていること&lt;/li&gt;&#xA;&lt;li&gt;値が全て0のハッシュキーをもつ極端な環境下で、パケットが一つのキューに集中すること&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;実験では以下の条件を利用する。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;デバイス: I226-V&lt;/li&gt;&#xA;&lt;li&gt;ドライバ: igc&lt;/li&gt;&#xA;&lt;li&gt;キュー数: 4&lt;/li&gt;&#xA;&lt;li&gt;ハッシュ関数: Toeplitz&lt;/li&gt;&#xA;&lt;li&gt;ハッシュキーのサイズ: 40 bytes&lt;/li&gt;&#xA;&lt;li&gt;ハッシュ計算に用いるフィールド: IP address (src, dst), UDP port (src, dst)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;なお、igcでは、デフォルトではハッシュ計算の入力にIP address (src, dst)のみを利用するようになっているため、あらかじめ以下のようなコマンドでUDP port (src, dst)もハッシュ計算に利用するように設定しておく&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# ethtool -N enp0s5 rx-flow-hash udp4 sdfn&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上記の環境にて、UDP port (src, dst)がランダムな1000個のパケットを受信する。パケット生成側のコードは適当。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; socket&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; time&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udp&lt;/span&gt;(dst_port: int, dst_address):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sock &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; socket&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;socket(socket&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;AF_INET, socket&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;SOCK_DGRAM)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sock&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sendto(&lt;span style=&#34;color:#e6db74&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;, (dst_address, dst_port))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sock&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;close()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; __name__ &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    times &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dst_address &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;100.100.100.154&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(times):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        send_udp(random&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;randint(&lt;span style=&#34;color:#ae81ff&#34;&gt;3000&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;65000&lt;/span&gt;), dst_address)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.001&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;1-デフォルトのランダムなハッシュキー環境&#34;&gt;1. デフォルトのランダムなハッシュキー環境&lt;/h3&gt;&#xA;&lt;p&gt;大抵のドライバではデフォルトのハッシュキーはランダムになっており(see netdev_rss_key_fill())、また通常RETAも分散しているため、ハッシュ関数への入力が分散している場合には、選択されるキューもある程度分散されることが期待される。&lt;/p&gt;</description>
    </item>
    <item>
      <title>実践 fault injection framework</title>
      <link>https://enjuk.jp/blog/posts/failslab/</link>
      <pubDate>Mon, 08 Dec 2025 23:01:55 +0900</pubDate>
      <guid>https://enjuk.jp/blog/posts/failslab/</guid>
      <description>&lt;h1 id=&#34;実践-fault-injection-framework&#34;&gt;実践 fault injection framework&lt;/h1&gt;&#xA;&lt;p&gt;fault injection framework の存在自体は認知していたものの、実際に手を動かして試してみるといったことをしないまま日々を過ごしていたところ、ひょんなことからその利便性を体験することができたので、実際の利用方法や活用できそうなシナリオ、Tips (とよべるかどうかわからない情報) を残しておきます。&lt;/p&gt;&#xA;&lt;p&gt;なお、一次情報はカーネルのソース・&lt;a href=&#34;https://docs.kernel.org/fault-injection/fault-injection.html&#34;&gt;ドキュメント&lt;/a&gt;に十分存在するため、網羅性については諦めています。&lt;/p&gt;&#xA;&lt;h2 id=&#34;fault-injection-framework-とは&#34;&gt;fault injection framework とは&lt;/h2&gt;&#xA;&lt;p&gt;端的には「実行タイミング」における障害注入フレームワークであり、主に debugfs をインターフェイスとしてカーネルの実行時に注入の有無や条件を設定することが可能です。&lt;/p&gt;&#xA;&lt;p&gt;対照的には、以下の最も単純な例に示すようにビルドタイミングにて障害注入を行うことも可能ですが、この極めてナイーブな例では条件を変える度&#xA;にビルドが必要となるなど、柔軟性に難点があります。&lt;br&gt;&#xA;もちろん、何かしらのインターフェイスで操作可能な custom_should_fail() のような関数を用意して注入することも可能だとは思いますが、そこまでしたいなら素直に fault injection framework に乗っかるのが良いでしょう。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;int foo() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-   if (bar())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;+   if (true || bar())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;&lt;/span&gt;        return -ENOMEM;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    return 0;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;fault injection framework には、失敗させたい操作ごとに&lt;a href=&#34;https://docs.kernel.org/fault-injection/fault-injection.html#available-fault-injection-capabilities&#34;&gt;異なるトリガー&lt;/a&gt;が用意されています。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;failslab: slab allocation (kmalloc() などの kmem_cache_alloc() を叩くやつ) を失敗させる&lt;/li&gt;&#xA;&lt;li&gt;fail_page_alloc: page allocation を失敗させる&lt;/li&gt;&#xA;&lt;li&gt;fail_usercopy: ユーザー空間、カーネル空間におけるメモリのコピーを失敗させる&lt;/li&gt;&#xA;&lt;li&gt;fail_function: ビルド時に予めマークされている関数の戻り値にエラーを注入する&lt;/li&gt;&#xA;&lt;li&gt;そのほか多数&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;なお、基本的な利用方法のほとんどは fail* で共通であるため、今回はたまたま利用することになった failslab のみに焦点を当てることとします。&#xA;網羅的なガイドは&lt;a href=&#34;https://docs.kernel.org/fault-injection/fault-injection.html#configure-fault-injection-capabilities-behavior&#34;&gt;Configure fault-injection capabilities behavior&lt;/a&gt;を参照ください。&lt;/p&gt;</description>
    </item>
    <item>
      <title>うわっ・・・わたしのロードアベレージ低すぎ・・・？</title>
      <link>https://enjuk.jp/blog/posts/loadavg/</link>
      <pubDate>Sat, 06 Dec 2025 14:44:03 +0900</pubDate>
      <guid>https://enjuk.jp/blog/posts/loadavg/</guid>
      <description>&lt;h1 id=&#34;はじめに&#34;&gt;はじめに&lt;/h1&gt;&#xA;&lt;p&gt;そもそもロードアベレージとはなんでしょうか。どの程度であれば正常で、どの程度の値であるべきでしょうか。&lt;br&gt;&#xA;「サーバーのロードアベレージが530000になっている！これは異常だ！」と連絡が来ていますが、果たして本当に異常でしょうか。&lt;/p&gt;&#xA;&lt;p&gt;本記事では、カーネルソースリーディングやカーネルモジュール作成を通じロードアベレージの理解を深めるとともに、あなたが未だかつてないロードアベレージを記録するためのTipsをお届けすることを目的としています。&lt;/p&gt;&#xA;&lt;h2 id=&#34;ロードアベレージって何&#34;&gt;ロードアベレージって何？&lt;/h2&gt;&#xA;&lt;p&gt;「実行中または実行可能 (R状態) 、および割り込み不可能 (D状態) なスレッドの数を移動平均したもの」です。&lt;br&gt;&#xA;馴染みがない方は参考として &lt;a href=&#34;https://access.redhat.com/solutions/906263&#34;&gt;Red Hat のナレッジベース&lt;/a&gt;を参照されることをお勧めいたします。&lt;/p&gt;&#xA;&lt;h3 id=&#34;ロードアベレージの正体&#34;&gt;ロードアベレージの正体&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;kernel/sched/load.c&lt;/code&gt;を読んだことがある方、興味のない方は読み飛ばしてください。&lt;/p&gt;&#xA;&lt;p&gt;簡単な定義・計算方法はコメントに記載のある通りであり、R状態およびD状態のスレッドを「アクティブスレッド」としてカウントし、それを指数移動平均することによって計算します。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; * The global load average is an exponentially decaying average of nr_running +&#xA; * nr_uninterruptible.&#xA; *&#xA; * Once every LOAD_FREQ:&#xA; *&#xA; *   nr_active = 0;&#xA; *   for_each_possible_cpu(cpu)&#xA; *&#x9;nr_active += cpu_of(cpu)-&amp;gt;nr_running + cpu_of(cpu)-&amp;gt;nr_uninterruptible;&#xA; *&#xA; *   avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;calc_global_load()&lt;/code&gt; が定期的に実行され、だいたい5秒に一度、「アクティブスレッド数」をもとにグローバル変数 &lt;code&gt;avenrun&lt;/code&gt; を更新しています。&lt;br&gt;&#xA;また、「アクティブスレッド数」は &lt;code&gt;calc_load_tasks&lt;/code&gt; 変数で管理されており、本関数内部やそのほかのコンテキスト (&lt;code&gt;calc_global_load_tick()&lt;/code&gt;)で更新されています。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
