コグノスケ


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

link もっと前
2022年5月5日 >>> 2022年4月22日
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 この記事にコメントする



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

管理用メニュー

link 記事を新規作成

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

最近のコメント5件

  • 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サーバーに繋ぐ使い方をした...」

最近の記事3件

  • link 23年4月10日
    すずき (12/04 01:40)
    「[Linux - まとめリンク] 目次: Linux関係の深いまとめリンク。目次: RISC-V目次: ROCK64/ROCK...」
  • link 24年11月18日
    すずき (12/04 01:39)
    「[nvJPEGとNVJPGとJetson APIその1 - nvJPEG decoupled API] 目次: Linux半年...」
  • link 24年11月28日
    すずき (12/01 00:53)
    「[BIOS/UEFI画面に入る方法] PCは起動時にあるキーを押すとBIOS/UEFIの設定画面に遷移します。良く見るパターン...」
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

最終更新: 12/04 01:40