[インデックス 17021] ファイルの概要
本コミットは、Goランタイムにおける未使用のスケジューラノブ(blockingsyscall
フラグ)を削除するものです。このフラグは、かつてWindows環境のnet
パッケージで使用されていましたが、現在は使用されていないため、コードベースから削除されました。これにより、ランタイムのコードが整理され、不要な複雑さが排除されます。
コミット
commit 49217cf5fd35e17b1e0b97a5eaad968402dc505d
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Sun Aug 4 23:32:40 2013 +0400
runtime: remove unused scheduler knob
Blockingsyscall was used in net package on windows,
it's not used anymore.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12436043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d
元コミット内容
このコミットは、Goランタイムからblockingsyscall
という未使用のスケジューラノブを削除します。このノブは、以前はWindows上のnet
パッケージで、次のシステムコールがブロックされることをスケジューラにヒントとして伝えるために使用されていましたが、現在は使用されていません。
変更の背景
Goランタイムは、効率的なゴルーチン(goroutine)スケジューリングを実現するために、システムコール(syscall)の挙動を考慮する必要があります。特に、ブロッキングシステムコールは、そのシステムコールが完了するまでゴルーチンをブロックするため、スケジューラは他のゴルーチンにCPUを譲る必要があります。
過去には、Windows環境のnet
パッケージにおいて、ネットワーク操作がブロッキングシステムコールを呼び出す際に、スケジューラにその旨を明示的に伝えるためのblockingsyscall
フラグが導入されていました。これは、g->blockingsyscall = true;
を設定し、その後runtime·entersyscallblock()
を呼び出すことで実現されていました。これにより、スケジューラはブロッキングシステムコール中にM(OSスレッド)を解放し、他の実行可能なゴルーチンに割り当てることができました。
しかし、Goランタイムの進化に伴い、システムコールハンドリングのメカニズムが改善され、このblockingsyscall
フラグが不要になったと考えられます。具体的には、非同期I/Oやその他のスケジューリング最適化により、明示的なヒントなしにブロッキングシステムコールを適切に処理できるようになりました。このコミットは、もはや使用されていないコードを削除し、ランタイムの保守性を向上させることを目的としています。
前提知識の解説
Goランタイムとスケジューラ
Go言語は、独自のランタイムとスケジューラを持っています。これは、OSのスケジューラとは独立して、Goのゴルーチンを効率的に管理するためのものです。
- ゴルーチン (Goroutine): Goにおける軽量な実行単位です。OSのスレッドよりもはるかに軽量で、数百万のゴルーチンを同時に実行できます。
- M (Machine): OSのスレッドを表します。Goランタイムは、M上でゴルーチンを実行します。
- P (Processor): 論理プロセッサを表します。PはMにアタッチされ、ゴルーチンを実行するためのコンテキストを提供します。
GOMAXPROCS
環境変数によってPの数が制御されます。 - スケジューラ: G-M-Pモデルに基づいてゴルーチンをMに割り当て、実行を管理します。
システムコールとスケジューリング
Goのゴルーチンがシステムコール(例: ファイルI/O、ネットワーク通信)を実行する際、そのシステムコールがブロッキング(完了するまで待機する)か非ブロッキングかによって、スケジューラの挙動が変わります。
- 非ブロッキングシステムコール: システムコールがすぐに完了する場合、ゴルーチンはMを保持したまま実行を続けます。
- ブロッキングシステムコール: システムコールが完了するまで時間がかかる場合(例: ネットワークからのデータ受信待ち)、そのゴルーチンはMを解放し、スケジューラは他の実行可能なゴルーチンをそのMに割り当てます。これにより、CPUリソースの有効活用が図られます。
runtime·entersyscall()
と runtime·entersyscallblock()
Goランタイムには、システムコールに入る際に呼び出される関数があります。
runtime·entersyscall()
: 一般的なシステムコールに入る際に呼び出されます。runtime·entersyscallblock()
: ブロッキングシステムコールに入る際に呼び出されます。この関数は、現在のMをスケジューラから一時的に切り離し、他のゴルーチンがそのMを使用できるようにします。システムコールが完了すると、runtime·exitsyscall()
が呼び出され、Mがスケジューラに戻されます。
g->blockingsyscall
と m->blockingsyscall
Goランタイムの内部構造体であるG
(ゴルーチン)とM
(OSスレッド)には、それぞれblockingsyscall
というブール型のフラグが存在していました。
g->blockingsyscall
: 現在のゴルーチンが次にブロッキングシステムコールを実行するかどうかを示すヒント。m->blockingsyscall
: 現在のMがブロッキングシステムコール中であるかどうかを示すフラグ。
これらのフラグは、スケジューラがブロッキングシステムコールをより効率的に処理するための情報として使用されていました。
技術的詳細
このコミットは、Goランタイムのsrc/pkg/runtime/cgocall.c
とsrc/pkg/runtime/runtime.h
の2つのファイルを変更しています。
src/pkg/runtime/cgocall.c
の変更点
このファイルは、Cgo(GoとC言語の相互運用)呼び出しに関連するランタイムコードを含んでいます。以前は、net·runtime_blockingSyscallHint
という関数が存在し、g->blockingsyscall = true;
を設定していました。また、runtime·cgocall
関数内でg->blockingsyscall
の値をチェックし、true
であればruntime·entersyscallblock()
を呼び出し、そうでなければruntime·entersyscall()
を呼び出すという条件分岐がありました。
このコミットでは、以下の変更が行われました。
net·runtime_blockingSyscallHint
関数の削除。この関数はもはや呼び出されないため、完全に削除されました。runtime·cgocall
関数内の条件分岐の削除。g->blockingsyscall
のチェックが削除され、常にruntime·entersyscall()
が呼び出されるようになりました。これは、blockingsyscall
フラグが不要になったことを意味します。
変更前:
// Gives a hint that the next syscall
// executed by the current goroutine will block.
// Currently used only on windows.
void
net·runtime_blockingSyscallHint(void)
{
g->blockingsyscall = true;
}
// ...
if(g->blockingsyscall) {
g->blockingsyscall = false;
runtime·entersyscallblock();
} else
runtime·entersyscall();
変更後:
// ...
runtime·entersyscall();
この変更は、Goランタイムがブロッキングシステムコールを処理する方法が進化し、明示的なヒントが不要になったことを示唆しています。現代のGoランタイムでは、システムコールがブロッキングするかどうかを自動的に判断し、必要に応じてMを解放するメカニズムがより洗練されていると考えられます。
src/pkg/runtime/runtime.h
の変更点
このヘッダーファイルは、Goランタイムの主要なデータ構造(G
とM
)の定義を含んでいます。
このコミットでは、以下のフィールドが削除されました。
struct G
からbool blockingsyscall; // hint that the next syscall will block
の削除。struct M
からbool blockingsyscall;
の削除。
これらのフラグがデータ構造から削除されたことは、ランタイムがこれらのヒントや状態を追跡する必要がなくなったことを明確に示しています。これにより、メモリ使用量がわずかに削減され、コードの複雑さが軽減されます。
コアとなるコードの変更箇所
src/pkg/runtime/cgocall.c
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -98,15 +98,6 @@ static void unwindm(void);\n static void endcgo(void);\n static FuncVal endcgoV = { endcgo };\n \n-// Gives a hint that the next syscall\n-// executed by the current goroutine will block.\n-// Currently used only on windows.\n-void\n-net·runtime_blockingSyscallHint(void)\n-{\n-\tg->blockingsyscall = true;\n-}\n-\n void\n runtime·cgocall(void (*fn)(void*), void *arg)\n {\n@@ -158,11 +149,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)\n \t * so it is safe to call while \"in a system call\", outside\n \t * the $GOMAXPROCS accounting.\n \t */\n-\tif(g->blockingsyscall) {\n-\t\tg->blockingsyscall = false;\n-\t\truntime·entersyscallblock();\n-\t} else\n-\t\truntime·entersyscall();\n+\truntime·entersyscall();\n \truntime·asmcgocall(fn, arg);\n \truntime·exitsyscall();\n \n```
### `src/pkg/runtime/runtime.h`
```diff
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -269,7 +269,6 @@ struct G\n \tbool\tispanic;\n \tbool\tissystem;\t// do not output in stack dump\n \tbool\tisbackground;\t// ignore in deadlock detector\n-\tbool\tblockingsyscall;\t// hint that the next syscall will block\n \tbool\tpreempt;\t// preemption signal, duplicates stackguard0 = StackPreempt\n \tint8\traceignore;\t// ignore race detection events\n \tM*\tm;\t\t// for debuggers, but offset not hard-coded\n@@ -313,7 +312,6 @@ struct M\n \tint32\tdying;\n \tint32\tprofilehz;\n \tint32\thelpgc;\n-\tbool\tblockingsyscall;\n \tbool\tspinning;\n \tuint32\tfastrand;\n \tuint64\tncgocall;\t// number of cgo calls in total\n```
## コアとなるコードの解説
`src/pkg/runtime/cgocall.c`では、`net·runtime_blockingSyscallHint`関数が完全に削除されました。この関数は、ゴルーチンがブロッキングシステムコールを実行する前に`g->blockingsyscall`フラグを設定するために使用されていました。この関数の削除は、このヒントメカニズムがもはや不要であることを意味します。
さらに、`runtime·cgocall`関数内の条件分岐が削除され、常に`runtime·entersyscall()`が呼び出されるようになりました。以前は、`g->blockingsyscall`が`true`の場合に`runtime·entersyscallblock()`が呼び出されていましたが、このロジックが削除されたことで、ランタイムがシステムコールのブロッキング特性をより動的に、または別のメカニズムで処理するようになったことが示唆されます。
`src/pkg/runtime/runtime.h`では、`G`構造体と`M`構造体から`blockingsyscall`フィールドが削除されました。これは、これらのフラグがランタイムの内部状態として維持する必要がなくなったことを直接的に示しています。これにより、ランタイムのデータ構造が簡素化され、メモリフットプリントがわずかに削減されます。
これらの変更は、Goランタイムのスケジューラが進化し、ブロッキングシステムコールの処理がより洗練されたことを反映しています。おそらく、非同期I/Oの利用拡大や、OSレベルのI/O完了ポート(IOCP)などのメカニズムとのより緊密な統合により、明示的な`blockingsyscall`ヒントが不要になったと考えられます。
## 関連リンク
* Go言語のスケジューラに関する公式ドキュメントやブログ記事(コミット当時の情報を見つけるのは難しい可能性がありますが、一般的なGoスケジューラの概念は理解に役立ちます)
* GoのCgoに関するドキュメント
## 参考にした情報源リンク
* [https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d](https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d)
* Go言語の公式ドキュメント (Go runtime, scheduler, cgo)
* Go言語のソースコード(特に`src/pkg/runtime`ディレクトリ)
* GoのIssueトラッカーやメーリングリストのアーカイブ(`blockingsyscall`に関する議論があるかもしれません)# [インデックス 17021] ファイルの概要
本コミットは、Goランタイムにおける未使用のスケジューラノブ(`blockingsyscall`フラグ)を削除するものです。このフラグは、かつてWindows環境の`net`パッケージで使用されていましたが、現在は使用されていないため、コードベースから削除されました。これにより、ランタイムのコードが整理され、不要な複雑さが排除されます。
## コミット
commit 49217cf5fd35e17b1e0b97a5eaad968402dc505d Author: Dmitriy Vyukov dvyukov@google.com Date: Sun Aug 4 23:32:40 2013 +0400
runtime: remove unused scheduler knob
Blockingsyscall was used in net package on windows,
it's not used anymore.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12436043
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d](https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d)
## 元コミット内容
このコミットは、Goランタイムから`blockingsyscall`という未使用のスケジューラノブを削除します。このノブは、以前はWindows上の`net`パッケージで、次のシステムコールがブロックされることをスケジューラにヒントとして伝えるために使用されていましたが、現在は使用されていません。
## 変更の背景
Goランタイムは、効率的なゴルーチン(goroutine)スケジューリングを実現するために、システムコール(syscall)の挙動を考慮する必要があります。特に、ブロッキングシステムコールは、そのシステムコールが完了するまでゴルーチンをブロックするため、スケジューラは他のゴルーチンにCPUを譲る必要があります。
過去には、Windows環境の`net`パッケージにおいて、ネットワーク操作がブロッキングシステムコールを呼び出す際に、スケジューラにその旨を明示的に伝えるための`blockingsyscall`フラグが導入されていました。これは、`g->blockingsyscall = true;`を設定し、その後`runtime·entersyscallblock()`を呼び出すことで実現されていました。これにより、スケジューラはブロッキングシステムコール中にM(OSスレッド)を解放し、他の実行可能なゴルーチンに割り当てることができました。
しかし、Goランタイムの進化に伴い、システムコールハンドリングのメカニズムが改善され、この`blockingsyscall`フラグが不要になったと考えられます。具体的には、非同期I/Oやその他のスケジューリング最適化により、明示的なヒントなしにブロッキングシステムコールを適切に処理できるようになりました。このコミットは、もはや使用されていないコードを削除し、ランタイムの保守性を向上させることを目的としています。
## 前提知識の解説
### Goランタイムとスケジューラ
Go言語は、独自のランタイムとスケジューラを持っています。これは、OSのスケジューラとは独立して、Goのゴルーチンを効率的に管理するためのものです。
* **ゴルーチン (Goroutine)**: Goにおける軽量な実行単位です。OSのスレッドよりもはるかに軽量で、数百万のゴルーチンを同時に実行できます。
* **M (Machine)**: OSのスレッドを表します。Goランタイムは、M上でゴルーチンを実行します。
* **P (Processor)**: 論理プロセッサを表します。PはMにアタッチされ、ゴルーチンを実行するためのコンテキストを提供します。`GOMAXPROCS`環境変数によってPの数が制御されます。
* **スケジューラ**: G-M-Pモデルに基づいてゴルーチンをMに割り当て、実行を管理します。
### システムコールとスケジューリング
Goのゴルーチンがシステムコール(例: ファイルI/O、ネットワーク通信)を実行する際、そのシステムコールがブロッキング(完了するまで待機する)か非ブロッキングかによって、スケジューラの挙動が変わります。
* **非ブロッキングシステムコール**: システムコールがすぐに完了する場合、ゴルーチンはMを保持したまま実行を続けます。
* **ブロッキングシステムコール**: システムコールが完了するまで時間がかかる場合(例: ネットワークからのデータ受信待ち)、そのゴルーチンはMを解放し、スケジューラは他の実行可能なゴルーチンをそのMに割り当てます。これにより、CPUリソースの有効活用が図られます。
### `runtime·entersyscall()` と `runtime·entersyscallblock()`
Goランタイムには、システムコールに入る際に呼び出される関数があります。
* `runtime·entersyscall()`: 一般的なシステムコールに入る際に呼び出されます。
* `runtime·entersyscallblock()`: ブロッキングシステムコールに入る際に呼び出されます。この関数は、現在のMをスケジューラから一時的に切り離し、他のゴルーチンがそのMを使用できるようにします。システムコールが完了すると、`runtime·exitsyscall()`が呼び出され、Mがスケジューラに戻されます。
### `g->blockingsyscall` と `m->blockingsyscall`
Goランタイムの内部構造体である`G`(ゴルーチン)と`M`(OSスレッド)には、それぞれ`blockingsyscall`というブール型のフラグが存在していました。
* `g->blockingsyscall`: 現在のゴルーチンが次にブロッキングシステムコールを実行するかどうかを示すヒント。
* `m->blockingsyscall`: 現在のMがブロッキングシステムコール中であるかどうかを示すフラグ。
これらのフラグは、スケジューラがブロッキングシステムコールをより効率的に処理するための情報として使用されていました。
## 技術的詳細
このコミットは、Goランタイムの`src/pkg/runtime/cgocall.c`と`src/pkg/runtime/runtime.h`の2つのファイルを変更しています。
### `src/pkg/runtime/cgocall.c`の変更点
このファイルは、Cgo(GoとC言語の相互運用)呼び出しに関連するランタイムコードを含んでいます。以前は、`net·runtime_blockingSyscallHint`という関数が存在し、`g->blockingsyscall = true;`を設定していました。また、`runtime·cgocall`関数内で`g->blockingsyscall`の値をチェックし、`true`であれば`runtime·entersyscallblock()`を呼び出し、そうでなければ`runtime·entersyscall()`を呼び出すという条件分岐がありました。
このコミットでは、以下の変更が行われました。
1. `net·runtime_blockingSyscallHint`関数の削除。この関数はもはや呼び出されないため、完全に削除されました。
2. `runtime·cgocall`関数内の条件分岐の削除。`g->blockingsyscall`のチェックが削除され、常に`runtime·entersyscall()`が呼び出されるようになりました。これは、`blockingsyscall`フラグが不要になったことを意味します。
変更前:
```c
// Gives a hint that the next syscall
// executed by the current goroutine will block.
// Currently used only on windows.
void
net·runtime_blockingSyscallHint(void)
{
g->blockingsyscall = true;
}
// ...
if(g->blockingsyscall) {
g->blockingsyscall = false;
runtime·entersyscallblock();
} else
runtime·entersyscall();
変更後:
// ...
runtime·entersyscall();
この変更は、Goランタイムがブロッキングシステムコールを処理する方法が進化し、明示的なヒントが不要になったことを示唆しています。現代のGoランタイムでは、システムコールがブロッキングするかどうかを自動的に判断し、必要に応じてMを解放するメカニズムがより洗練されていると考えられます。
src/pkg/runtime/runtime.h
の変更点
このヘッダーファイルは、Goランタイムの主要なデータ構造(G
とM
)の定義を含んでいます。
このコミットでは、以下のフィールドが削除されました。
struct G
からbool blockingsyscall; // hint that the next syscall will block
の削除。struct M
からbool blockingsyscall;
の削除。
これらのフラグがデータ構造から削除されたことは、ランタイムがこれらのヒントや状態を追跡する必要がなくなったことを明確に示しています。これにより、メモリ使用量がわずかに削減され、コードの複雑さが軽減されます。
コアとなるコードの変更箇所
src/pkg/runtime/cgocall.c
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -98,15 +98,6 @@ static void unwindm(void);\n static void endcgo(void);\n static FuncVal endcgoV = { endcgo };\n \n-// Gives a hint that the next syscall\n-// executed by the current goroutine will block.\n-// Currently used only on windows.\n-void\n-net·runtime_blockingSyscallHint(void)\n-{\n-\tg->blockingsyscall = true;\n-}\n-\n void\n runtime·cgocall(void (*fn)(void*), void *arg)\n {\n@@ -158,11 +149,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)\n \t * so it is safe to call while \"in a system call\", outside\n \t * the $GOMAXPROCS accounting.\n \t */\n-\tif(g->blockingsyscall) {\n-\t\tg->blockingsyscall = false;\n-\t\truntime·entersyscallblock();\n-\t} else\n-\t\truntime·entersyscall();\n+\truntime·entersyscall();\n \truntime·asmcgocall(fn, arg);\n \truntime·exitsyscall();\n \n```
### `src/pkg/runtime/runtime.h`
```diff
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -269,7 +269,6 @@ struct G\n \tbool\tispanic;\n \tbool\tissystem;\t// do not output in stack dump\n \tbool\tisbackground;\t// ignore in deadlock detector\n-\tbool\tblockingsyscall;\t// hint that the next syscall will block\n \tbool\tpreempt;\t// preemption signal, duplicates stackguard0 = StackPreempt\n \tint8\traceignore;\t// ignore race detection events\n \tM*\tm;\t\t// for debuggers, but offset not hard-coded\n@@ -313,7 +312,6 @@ struct M\n \tint32\tdying;\n \tint32\tprofilehz;\n \tint32\thelpgc;\n-\tbool\tblockingsyscall;\n \tbool\tspinning;\n \tuint32\tfastrand;\n \tuint64\tncgocall;\t// number of cgo calls in total\n```
## コアとなるコードの解説
`src/pkg/runtime/cgocall.c`では、`net·runtime_blockingSyscallHint`関数が完全に削除されました。この関数は、ゴルーチンがブロッキングシステムコールを実行する前に`g->blockingsyscall`フラグを設定するために使用されていました。この関数の削除は、このヒントメカニズムがもはや不要であることを意味します。
さらに、`runtime·cgocall`関数内の条件分岐が削除され、常に`runtime·entersyscall()`が呼び出されるようになりました。以前は、`g->blockingsyscall`が`true`の場合に`runtime·entersyscallblock()`が呼び出されていましたが、このロジックが削除されたことで、ランタイムがシステムコールのブロッキング特性をより動的に、または別のメカニズムで処理するようになったことが示唆されます。
`src/pkg/runtime/runtime.h`では、`G`構造体と`M`構造体から`blockingsyscall`フィールドが削除されました。これは、これらのフラグがランタイムの内部状態として維持する必要がなくなったことを直接的に示しています。これにより、ランタイムのデータ構造が簡素化され、メモリフットプリントがわずかに削減されます。
これらの変更は、Goランタイムのスケジューラが進化し、ブロッキングシステムコールの処理がより洗練されたことを反映しています。おそらく、非同期I/Oの利用拡大や、OSレベルのI/O完了ポート(IOCP)などのメカニズムとのより緊密な統合により、明示的な`blockingsyscall`ヒントが不要になったと考えられます。
## 関連リンク
* Go言語のスケジューラに関する公式ドキュメントやブログ記事(コミット当時の情報を見つけるのは難しい可能性がありますが、一般的なGoスケジューラの概念は理解に役立ちます)
* GoのCgoに関するドキュメント
## 参考にした情報源リンク
* [https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d](https://github.com/golang/go/commit/49217cf5fd35e17b1e0b97a5eaad968402dc505d)
* Go言語の公式ドキュメント (Go runtime, scheduler, cgo)
* Go言語のソースコード(特に`src/pkg/runtime`ディレクトリ)
* GoのIssueトラッカーやメーリングリストのアーカイブ(`blockingsyscall`に関する議論があるかもしれません)