コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2022年5月3日 >>> 2022年4月20日
link もっと後

2022年5月3日

GWの首都高事情

目次:

例年であればGWは実家に帰省していて、GWの首都高の様子なんて興味もなければ知りもしませんでしたが、今年のGWは珍しく実家に帰らなかったんです。

しかもGWの初日の今日、間違えて湾岸線の「下り」に乗ってしまいました。当然ながらエラい渋滞にはまりましたが、併走する下道は空いているようで不思議でした。

高速道路の下りだけ渋滞!?

ちょっと訳あって朝、昼の2回(高速上り、下り&高速上り、下道の下り)走ったためか、渋滞の傾向が良く見えました。首都高1号と湾岸高速の下りだけ1日中ずっと渋滞していました。湾岸線は北関東ナンバーの車で埋め尽くされていましたが、高速の上りや下道のR357、R15(第一京浜)は空いていました。

別の道、中央道と甲州街道を思い浮かべると、高速も下道もどちらも渋滞しそうなものです。たとえばR15(第一京浜)だって、首都高1号や横羽線とほぼずっと併走していますし、渋滞していそうなものですがめちゃ空いていて意外でした。まあ、大田区から向こうは知らないですけど……。なぜ首都高だけ例外なんでしょう、不思議ですね。

どこから来るかにもよりますが、C2や湾岸線下りの混雑を回避するなら、足立区辺りで降りてR4 → 都内 → R15が下道ルートでしょうか?そうするとですね、

  • 中央道と甲州街道のように高速と下道がわかりやすく併走していない
  • 都内の面倒な道を抜けなければならない
  • 首都高の高速料金を2回払うことになって高く付く

自分がもし北関東から来たお父さんホリデードライバーだとしたら、わざわざ降りるか?というと……まず降りませんね!普段運転しないならなおさら嫌です。都内の道なんか考えたくない、もし迷おうものなら家族のブーイングは必至。面倒です。

結論

というわけで「GW初日の湾岸高速は下りのみ2時間以上の渋滞、上りと、下りに併走する下道はがら空き」という役に立たないクソ知識を体得しました。

超どうでも良い!もう二度と使わなさそう!!

編集者:すずき(2023/09/30 15:21)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2022年4月29日

思い出のalsa-lib dmixのバグ

目次: ALSA

はるか昔、もう8年も前に見つけたalsa-libのバグ(2014年7月9日の日記参照)、今日見てもまだ直ってなかったっぽいです。激しくノイズが載ってしまう割と致命的なバグですが、発生条件が珍しくてあまり使われないコードのため、未だに誰も直すモチベーションがないと推測されます。せっかく思い出したので、パッチをぶん投げておきました。

パッチの投稿先がわからなくて困ったのですが、どうもalsa-libはGitHubを(リポジトリへのリンク)使っていて、IssueやPull Request管理しているようです。GitHub使ってるんですね。へー。

ALSA本体の場合

ALSAはユーザ空間のalsa-libの他に、カーネル空間のコードもあります。カーネル空間のコードはLinux Kernelの一部として開発されています。Linux KernelはGitHubをコード管理に使っておらず、ミラーだけしています(つまりGitHubのPull RequestやIssueは使わない)。

当然ながらLinux Kernelメンテナ達のリポジトリもGitHubではなくgit.kernel.orgに置かれていることが多いです。ALSAのカーネル側コードも例外ではなくgit.kernel.orgの下に置かれて(リポジトリへのリンク)います。

メモ: 技術系の話はFacebookから転記しておくことにした。合併と加筆。

編集者:すずき(2022/05/22 15:15)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2022年4月22日

glibcのスレッドローカルストレージ - TLS初期化編

目次: C言語とlibc

前回はtp(スレッドポインタ)レジスタの初期化を調べました。今回はTLSの初期化を見たいと思います。起動時に値が設定されている変数の初期化に関わる部分です。

TLSの初期化

初期化関数 __libc_setup_tls() ではtpの指す先(__sbrk() で確保したメモリ領域)も初期化しています。しかしこちらは結構複雑です。大雑把に言うと、

  • Auxiliary vectorのAT_PHDR(実行プログラムのプログラムヘッダーへのポインタ)を探す
  • もし存在しなければTLSの初期化は行わない
  • プログラムヘッダーからPT_TLSタイプのセグメントを探す
  • もし存在しなければTLSの初期化は行わない
  • PT_TLSタイプのセグメントのp_vaddrが指す位置からp_fileszバイトの初期データをTLSにコピー

このような処理が行われます。コードも見ておきましょう。

AT_PHDRを探す処理

// glibc/csu/libc-start.c

STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
		 int argc, char **argv,
#ifdef LIBC_START_MAIN_AUXVEC_ARG
		 ElfW(auxv_t) *auxvec,
#endif
		 __typeof (main) init,
		 void (*fini) (void),
		 void (*rtld_fini) (void), void *stack_end)
{

//...

# ifdef HAVE_AUX_VECTOR
  /* First process the auxiliary vector since we need to find the
     program header to locate an eventually present PT_TLS entry.  */
#  ifndef LIBC_START_MAIN_AUXVEC_ARG
  ElfW(auxv_t) *auxvec;
  {
    char **evp = ev;
    while (*evp++ != NULL)
      ;
    auxvec = (ElfW(auxv_t) *) evp;
  }
#  endif
  _dl_aux_init (auxvec);    //★これ★
  if (GL(dl_phdr) == NULL)
# endif


// glibc/elf/dl-support.c

void
_dl_aux_init (ElfW(auxv_t) *av)
{

//...

  _dl_auxv = av;
  for (; av->a_type != AT_NULL; ++av)
    switch (av->a_type)
      {
      case AT_PAGESZ:
	if (av->a_un.a_val != 0)
	  GLRO(dl_pagesize) = av->a_un.a_val;
	break;
      case AT_CLKTCK:
	GLRO(dl_clktck) = av->a_un.a_val;
	break;
      case AT_PHDR:
	GL(dl_phdr) = (const void *) av->a_un.a_val;    //★これ★
	break;
      case AT_PHNUM:
	GL(dl_phnum) = av->a_un.a_val;
	break;
PT_TLSエントリ探しと、初期データをTLSにコピー

// glibc/csu/libc-tls.c

void
__libc_setup_tls (void)
{

//...

  /* Look through the TLS segment if there is any.  */
  if (_dl_phdr != NULL)
    for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
      if (phdr->p_type == PT_TLS)
	{
	  /* Remember the values we need.  */
	  memsz = phdr->p_memsz;
	  filesz = phdr->p_filesz;
	  initimage = (void *) phdr->p_vaddr + main_map->l_addr;
	  align = phdr->p_align;
	  if (phdr->p_align > max_align)
	    max_align = phdr->p_align;
	  break;
	}

//...

  /* Initialize the TLS block.  */
#if TLS_TCB_AT_TP
  //...
#elif TLS_DTV_AT_TP   //★★RISC-Vではこちらのコードが使われる★★
  _dl_static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;    //★★TLSのアドレス★★
  main_map->l_tls_offset = tcb_offset;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
  _dl_static_dtv[2].pointer.to_free = NULL;
  /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
  memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz);    //★★TLSに初期データをコピー★★

PT_TLSタイプのプログラムヘッダーがどこに配置されているか?など調べたい場合は、実行ファイルをreadelfで見るとわかりやすいです。該当するヘッダがある場合は、Type欄がTLSとなるはずです。

readelfの結果
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000010000 0x0000000000010000
                 0x000000000005d944 0x000000000005d944  R E    0x1000
  LOAD           0x000000000005e4d0 0x000000000006f4d0 0x000000000006f4d0
                 0x0000000000002500 0x0000000000007938  RW     0x1000
  NOTE           0x0000000000000190 0x0000000000010190 0x0000000000010190
                 0x0000000000000020 0x0000000000000020  R      0x4
  TLS            0x000000000005e4d0 0x000000000006f4d0 0x000000000006f4d0  ★★TLS初期化に使われるセグメント★★
                 0x0000000000000020 0x0000000000000068  R      0x8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000005e4d0 0x000000000006f4d0 0x000000000006f4d0
                 0x0000000000000b30 0x0000000000000b30  R      0x1

PT_TLSが2つある場合はどうなるでしょう?実はPT_TLSは実行ファイルに1つまでなので気にしなくて良いです。プログラムヘッダは同属性のセクションをまとめて1つのセグメントにします。PT_TLSセグメントを1つだけにするには、TLSに関わるセクションを連続して配置する必要があります。

もしTLS関係のセクションを分散させて配置するとリンク時エラーになります。試しにリンカースクリプトを書き換えTLS関係の .tdataと .tbssセクションの間に、TLSと無関係の .dataセクションを挟む形にすると、

TLS関係のセクションが分散している場合のリンクエラー
riscv64-unknown-linux-gnu/bin/ld: hello: TLS sections are not adjacent:
riscv64-unknown-linux-gnu/bin/ld:            TLS: .tdata
riscv64-unknown-linux-gnu/bin/ld:        non-TLS: .data
riscv64-unknown-linux-gnu/bin/ld:            TLS: .tbss
riscv64-unknown-linux-gnu/bin/ld: map sections to segments failed: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:22: hello] エラー1

リンカーに "TLS sections are not adjacent" と怒られました。

編集者:すずき(2022/04/22 15:43)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2022年4月21日

ソーシャルメディアと年代

SNSの利用者層を語るときTwitterはオジサンばかり、若者はInstagramなどと言われますが、SNSの利用率は総務省が調査していて、情報通信メディアの利用時間と情報行動に関する調査 - 総務省から見ることができます。


ソーシャルメディア利用率(令和2年)

令和2年のデータだけを抜き出してグラフにしてみました。結構世代で違うもんですね。

  • 万人向け: LINE, YouTube
  • 若者向け(左が高い): Instagram, Tiktok, ニコ動
  • オジサン化進行中: Twitter
  • オジサン化(真ん中〜右が高い): Facebook
  • 老人化(右が高い): なし

今のところの傾向としてはこんなもんでしょうか。大体イメージ通りの結果でしたが、個人的に意外だったのはニコニコ動画です。ここまで利用者層が若返っているのは意外でした。

私は日本語圏のゲーム系動画を見るならなんだかんだでニコ動が一番面白いと思うので、いまだにプレミアム会員のまま使っていますが、利用者の私ですらもうニコ動には懐ゲー好きのオジサンしかいないのかな?と思っていたくらいでした……。

一昔前、ニコ動のプレミアム会員数が減り始めたくらいから「オワコン」呼ばわりする人達が増えた記憶がありますが、復活したんですね。以前のように皆が戻って来ると良いですねえ。

編集者:すずき(2022/05/20 05:20)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2022年4月20日

glibcのスレッドローカルストレージ - スレッドポインタ編

目次: C言語とlibc

前回はスレッドローカル変数のアドレス取得部分のコードを見て、tp(スレッドポインタ)レジスタが重要な役割をしていることがわかりました。今回はtpレジスタの初期化コードを見ます。

tpレジスタの初期化

レジスタの初期化は __libc_setup_tls() で行われます。少し長いですがコードを見ましょう。

TLSのメモリ領域確保とtpレジスタ初期化

// glibc/sysdeps/riscv/nptl/tls.h

/* The TP points to the start of the thread blocks.  */
# define TLS_DTV_AT_TP	1
# define TLS_TCB_AT_TP	0


// glibc/csu/libc-tls.c

void
__libc_setup_tls (void)
{
  void *tlsblock;

//...

  /* We have to set up the TCB block which also (possibly) contains
     'errno'.  Therefore we avoid 'malloc' which might touch 'errno'.
     Instead we use 'sbrk' which would only uses 'errno' if it fails.
     In this case we are right away out of memory and the user gets
     what she/he deserves.  */
#if TLS_TCB_AT_TP
  //...
#elif TLS_DTV_AT_TP    //★★RISC-Vではこちらのコードが使われる★★
  tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
  tlsblock = __sbrk (tcb_offset + memsz + max_align
		     + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus));
  tlsblock += TLS_PRE_TCB_SIZE;
#else
  /* In case a model with a different layout for the TCB and DTV
     is defined add another #elif here and in the following #ifs.  */
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif

//...

  /* Initialize the thread pointer.  */
#if TLS_TCB_AT_TP
  //...
#elif TLS_DTV_AT_TP    //★★RISC-Vではこちらのコードが使われる★★
  INSTALL_DTV (tlsblock, _dl_static_dtv);
  const char *lossage = TLS_INIT_TP (tlsblock);    //★★tpレジスタ初期化★★
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif


// glibc/sysdeps/riscv/nptl/tls.h

register void *__thread_self asm ("tp");
# define READ_THREAD_POINTER() ({ __thread_self; })

//...

/* Code to initially initialize the thread pointer.  */
# define TLS_INIT_TP(tcbp) \
  ({ __thread_self = (char*)tcbp + TLS_TCB_OFFSET; NULL; })


// glibc/sysdeps/riscv/nptl/tls.h

/* The thread pointer tp points to the end of the TCB.
   The pthread_descr structure is immediately in front of the TCB.  */
# define TLS_TCB_OFFSET	0

メモリ領域を__sbrk() で確保してアドレスをtpに格納しています。#ifdefで多少見づらいですが、そんなに難しくないはずです。

今まではTLSに含まれるスレッドローカル変数のうち、実行時に値を初期化する変数について見てきました。スレッドローカル変数は実行時に初期化するだけではなく、起動時に初期化される変数もあります。起動時に初期化される変数は、実行ファイルに初期値が含まれていてTLSの初期化時に値がコピーされる仕組みです。

次回はTLSの初期化を見たいと思います。

編集者:すずき(2022/04/22 15:43)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2022年5月3日 >>> 2022年4月20日
link もっと後

管理用メニュー

link 記事を新規作成

<2022>
<<<05>>>
1234567
891011121314
15161718192021
22232425262728
293031----

最近のコメント20件

  • link 21年9月20日
    すずきさん (11/19 01:04)
    「It was my pleasure.」
  • link 21年9月20日
    whtさん (11/17 23:41)
    「This blog solves my ...」
  • link 24年10月1日
    すずきさん (10/06 03:41)
    「xrdpで十分動作しているので、Wayl...」
  • link 24年10月1日
    hdkさん (10/03 19:05)
    「GNOMEをお使いでしたら今はWayla...」
  • link 24年10月1日
    すずきさん (10/03 10:12)
    「私は逆にVNCサーバーに繋ぐ使い方をした...」
  • link 24年10月1日
    hdkさん (10/03 08:30)
    「おー、面白いですね。xrdpはすでに立ち...」
  • link 14年6月13日
    2048player...さん (09/26 01:04)
    「最後に、この式を出すのに紙4枚(A4)も...」
  • link 14年6月13日
    2048playerさん (09/26 01:00)
    「今のところ最も簡略化した式です。\n--...」
  • link 14年6月13日
    2048playerさん (09/16 01:00)
    「返信ありがとうございます。\nコメントが...」
  • link 14年6月13日
    すずきさん (09/12 21:19)
    「コメントありがとうございます。同じ結果に...」
  • link 14年6月13日
    2048playerさん (09/08 17:30)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048さん (09/08 17:16)
    「私も2048の最高スコアを求めたのですが...」
  • link 14年6月13日
    2048playerさん (09/08 16:10)
    「私も2048の最高スコアを求めたのですが...」
  • link 02年8月4日
    lxbfYeaaさん (07/12 10:11)
    「555」
  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」
  • link 24年5月17日
    hdkさん (05/19 07:45)
    「なるほど、そういうことなんですね。Exc...」

最近の記事3件

  • link 23年4月10日
    すずき (11/15 23:48)
    「[Linux - まとめリンク] 目次: Linux関係の深いまとめリンク。目次: RISC-V目次: ROCK64/ROCK...」
  • link 24年11月6日
    すずき (11/15 23:47)
    「[Ubuntu 24.04 LTS on ThinkPad X1 Carbon Gen 12] 目次: Linux会社ではTh...」
  • link 24年11月11日
    すずき (11/15 23:26)
    「[Pythonのテストフレームワーク] 目次: Python最近Pythonを触ることが増えたのでテストについて調べようと思い...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 11/19 01:04