ときどきの雑記帖 RE* (新南口)
高速道路の星
今週のしずえさん
「葛飾北斎が生涯で93回行ったこと」
オーバースペック
逆の意味で使っている人を見た(2例目)。
化
「計測化」なる語を見かけて 「まーた適当に『化』をつけた単語を作って」 と思って調べてみたら…
MLB
- MLB「守備シフトの禁止」など3つの新ルール、23年から施行を希望か 米記者ツイート - MLB : 日刊スポーツ
- MLBが来季からのシフト禁止、ピッチクロック、ベース大型化導入へ前進 : スポーツ報知
守備シフト、ここで書かれてる内容だと外野は自由にシフトできる?
電動
電気を使わない「機械式計算機」がメカメカしくて格好よすぎた! :: デイリーポータルZ
機械式計算機でも電動のがあるんですがそれは… (動画でしか見たことないけど)
続Modernize
Modernizeの続き。 自分の中の「モヤモヤ」がまだ残っているのでもうちょっと粘ってみる。
Proposal for speculative safe list iterator [LWN.net] では、
- Category 1: &pos->other_member is used to determine if a certain element was found
- Category 2: pos is used to determine if a certain element was found
- Category 3: pos is used to determine if the list is empty (shouldn’t need fixing)
- Category 4: pos is used to determine if the break/goto was hit and the list is not empty
- Category 5: legitimately uses head pos for cmp
- Category 6: legitimately uses pos->member
のようなカテゴリー分けをした上で どのファイルの何行目がそれに該当しているか ということのリストアップをしているので、 実際それぞれがどんな記述なのかを確かめてみた。
メッセージの末尾を見ると 一つのまとまったパッチ(差分)があるようなのだけど どこに行けばそれを参照できるのかわからないので (知っている人いたら教えてプリーズ)、 ファイル名とそのパスを頼りに探してみた。 まずは
Category 1: &pos->other_member is used to determine if a certain element was found
から、リストの先頭にある
drivers/usb/gadget/udc/gr_udc.c:1717
を見てみる。
この1717行目はif (&req->req != _req) {
というものだった。
この行が含まれるのはちょっと長めの関数なので
範囲を絞って引用するとこう
gr_udc.c - drivers/usb/gadget/udc/gr_udc.c - Linux source code (v5.16.12) - Bootlin
/* Make sure it's actually queued on this endpoint */
list_for_each_entry(req, &ep->queue, queue) {
if (&req->req == _req)
break;
}
if (&req->req != _req) {
ret = -EINVAL;
goto out;
}
なるほど確かに
&pos->other_member is used to determine if a certain element was found
だ。
Category 2: pos is used to determine if a certain element was found
からはarch/x86/kernel/cpu/sgx/encl.c:466
を。
486行目近辺はこんな感じ。 encl.c - arch/x86/kernel/cpu/sgx/encl.c - Linux source code (v5.17-rc6) - Bootlin
spin_lock(&encl_mm->encl->mm_lock);
list_for_each_entry(tmp, &encl_mm->encl->mm_list, list) {
if (tmp == encl_mm) {
list_del_rcu(&encl_mm->list);
break;
}
}
spin_unlock(&encl_mm->encl->mm_lock);
Category 3: pos is used to determine if the list is empty (shouldn’t need fixing)
からはarch/powerpc/sysdev/fsl_gtm.c:106
を。
fsl_gtm.c - arch/powerpc/sysdev/fsl_gtm.c - Linux source code (v5.16.12) - Bootlin
struct gtm_timer *gtm_get_timer16(void)
{
struct gtm *gtm = NULL;
int i;
list_for_each_entry(gtm, >ms, list_node) {
spin_lock_irq(>m->lock);
for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
if (!gtm->timers[i].requested) {
gtm->timers[i].requested = true;
spin_unlock_irq(>m->lock);
return >m->timers[i];
}
}
spin_unlock_irq(>m->lock);
}
if (gtm)
return ERR_PTR(-EBUSY);
return ERR_PTR(-ENODEV);
}
Category 4: pos is used to determine if the break/goto was hit and the list is not empty
はarch/arm/mach-mmp/sram.c:54
から(drivers以下のものを避けて最初に目についたもの。特に深い意味はない。たぶん)。
sram.c - arch/arm/mach-mmp/sram.c - Linux source code (v5.16.12) - Bootlin
によると、問題の54行目は
if (&info->node == &sram_bank_list)
で、その前後を見てみると(小さい関数なのでその関数丸ごと)
struct gen_pool *sram_get_gpool(char *pool_name)
{
struct sram_bank_info *info = NULL;
if (!pool_name)
return NULL;
mutex_lock(&sram_lock);
list_for_each_entry(info, &sram_bank_list, node)
if (!strcmp(pool_name, info->pool_name))
break;
mutex_unlock(&sram_lock);
if (&info->node == &sram_bank_list)
return NULL;
return info->gpool;
}
ふむ。確かにカテゴリ4の説明にある
pos is used to determine if the break/goto was hit and the list is not empty
に該当しているようだ。
Category 5: legitimately uses head pos for cmp
net/ipv4/udp_tunnel_nic.c:849
udp_tunnel_nic.c - net/ipv4/udp_tunnel_nic.c - Linux source code (v5.17-rc6) - Bootlin
struct udp_tunnel_nic_shared_node *node, *first;
list_for_each_entry(node, &info->shared->devices, list)
if (node->dev == dev)
break;
if (list_entry_is_head(node, &info->shared->devices, list))
return;
list_del(&node->list);
Category 6: legitimately uses pos->member
net/core/gro.c:38
gro.c - net/core/gro.c - Linux source code (v5.17-rc6) - Bootlin
void dev_add_offload(struct packet_offload *po)
{
struct packet_offload *elem;
spin_lock(&offload_lock);
list_for_each_entry(elem, &offload_base, list) {
if (po->priority < elem->priority)
break;
}
list_add_rcu(&po->list, elem->list.prev);
spin_unlock(&offload_lock);
}
メーリングリストのやり取りの中でもあったと思うけど、ループ外で該当のメンバーを参照しない形に 書き換えられる…のかな?🤔
- LinuxカーネルのC言語が「C89」から「C11」に移行 | スラド Submission
- リーナス・トーバルズ氏、Linuxカーネルの開発を「C89」から「C11」に移行方針へ | スラド Linux
- Linux source code (v5.17-rc6) - Bootlin
- [RFC PATCH 03/13] usb: remove the usage of the list iterator after the loop [LWN.net]
- [RFC PATCH 00/13] Proposal for speculative safe list iterator [LWN.net]
Who says C is simple?
「C言語が単純だ」なんて誰が言った?
— 新山祐介 (Yusuke Shinyama) (@mootastic) March 4, 2022
たとえばsizeof()の値はつねにunsignedなので、 (1 - sizeof(int)) >> 32 は算術シフトではなく論理シフトになり、答えは-1でなく0となる。
こんなん全部知ってたら神だな。https://t.co/UVroy5P8TB
(1 - sizeof(int)) >> 32 を試してみると、-1 でも 0 でもなく 4294967295 になる。あぁ、64bit 環境だからか、ということで 32bit 環境でやると、right shift count >= width of type と警告が出る。この場合は undefined なので結果がどうなるかは決まっていない。まぁ、C言語が単純でないのは正しい https://t.co/7cqW6YSh0A
— Tanaka Akira (@tanaka_akr) March 5, 2022
ということで元記事読みに行ったらなかなか面白かった。 訳してもいいと思うけど許可取るのめn(ry
When I (George) started to write CIL I thought it was going to take two weeks. Exactly a year has passed since then and I am still fixing bugs in it. This gross underestimate was due to the fact that I thought parsing and making sense of C is simple. You probably think the same. What I did not expect was how many dark corners this language has, especially if you want to parse real-world programs such as those written for GCC or if you are more ambitious and you want to parse the Linux or Windows NT sources (both of these were written without any respect for the standard and with the expectation that compilers will be changed to accommodate the program).
The following examples were actually encountered either in real programs or are taken from the ISO C99 standard or from the GCC’s testcases. My first reaction when I saw these was: Is this C?. The second one was : What the hell does it mean?.
ちなみに問題は
16.1 Standard C
が9個
16.2 GCC ugliness
が8個
そして
16.3 Microsoft VC ugliness
が2個。
個人的に一番興味深かったのは変数のスコープかな。