GCCからゴルーチンを達成するために、コードの言語とチャンネルを見に行きます

、キー文書を解析して行きます

フロントエンドの言語解釈コードはGCC-4.8.2を設置行く\ gccの\ \行く gofrontend \ parse.cc ファイル、解析::プログラムの開始のためのソースファイルを解析します。この機能の表情からは、ソースファイルの先頭には、パッケージで自分の名前を示す必要があり、輸入がある場合、彼らは最初の文の前に、背中のパッケージにヒットする必要があります。ビューの最高レベルのポイントから、ソースファイル全体では宣言で構成され、これらの宣言constの、タイプ、VAR、FUNC 4を含みます。HelloWorldの典型的な例として、用コンテンツ
パッケージメイン

輸入「FMT」

メインFUNC(){
fmt.Println(「こんにちは、世界」)
}
次輸入申告のパッケージ開始及び最終FUNC用組成物による。

二、達成するための構文を行きます

ランタイムライブラリ__go_goに行くための呼び出しを変換するために1、

GCC-4.8.2のgcc \ \ \ gofrontend \ runtime.defを行く
//新しいゴルーチンを開始します。
DEF_GO_RUNTIME( "__go_go"、GO、P2(FUNC_PTR、POINTER)、R0())


解析:: go_or_defer_stat()
{
......
声明*のstat。
もし(is_go)
STAT =ステートメント:: make_go_statement(call_expr、stat_location)。
他の
STAT =ステートメント:: make_defer_statement(call_expr、stat_location)。
this->ゴーゴー_-> add_statement(STAT)。
this->ゴーゴー_-> add_block(this->ゴーゴー_-> finish_block(stat_location)、
stat_location)。
}

声明*
ステートメント:: make_go_statement(Call_expression *コール、場所場所)
{
(、場所を呼び出す)新しいGo_statementを返します。
}

Bstatement *
Go_statement :: do_get_backend(Translate_context *コンテキスト)
{
式* FN;
式*引数。
(!this-> get_fn_and_arg(&FN、および引数))であれば
、戻り、コンテキスト>バックエンド() - > error_statement();

式*コール=ランタイム:: make_call(ランタイム:: GO、this->位置()、2、
FN、引数)。
ツリーcall_tree = call-> get_tree(コンテキスト)。
Bexpression * call_bexpr = tree_to_expr(call_tree)。
、コンテキストを返す>バックエンド() - > expression_statement(call_bexpr)。
}

2、ランタイム・ライブラリ__go_go実装

ゴルーチン構造は、次にrunqputランタイム関数によってキューに追加されるビューの実現の観点から、これが発現され、そして底部層は、glibcのコンテキストが実装切り替えることによって構築されます。
4.8.2-GCC \ libgo \ランタイム\ proc.c
G *の
__go_go(無効(* FN)(void *型)、void *型のArg)
{
...
//は避けによって上書きさ変数について警告を表し
// longjmp関数を。
バイト揮発性VSP * SP =;
size_tの揮発性vspsize = spsize;
G * = newg揮発性vnewg。

getcontext(&vnewg->コンテキスト);
vnewg-> context.uc_stack.ss_sp = VSP;
#ifdefのMAKECONTEXT_STACK_TOP
vnewg-> context.uc_stack.ss_sp + = vspsize。
#endifの
vnewg-> context.uc_stack.ss_size = vspsize。
MAKECONTEXT(&vnewg->コンテキスト、キックオフ、0);

runqput(M-> P、vnewg)。

(!!runtime_atomicload(&runtime_sched.npidle)= 0 && runtime_atomicload(&runtime_sched.nmspinning)== 0 && FN = runtime_main)// TODOの場合:高速の原子
wakep();
M-> locks--。
vnewg返します。
}

3、ゴルーチンスケジューリング

大まかに言えば、オペレーティング・システム内とゴルーチンをもとに、独自の仮想スレッドのスケジューリングに相当:以下の記事は参考https://tonybai.com/2017/06/23/an-intro-about-goroutine-scheduler/を持っています割り当てられた別のスケジューリングまでプロセッサ

三、チャネル実現

1、チャンネルの作成

式*
Builtin_call_expression :: do_lower(ゴーゴー*ゴーゴー、Named_object *機能、
Statement_inserter *インサータ、INT)
{
......
ケースBUILTIN_MAKE:
(this-> lower_makeを返します)。
......
}

式*
Builtin_call_expression :: lower_make()
{
...
呼び出し=ランタイム:: make_call((have_big_args
ランタイム:: MAKEMAPBIG?
ランタイム:: makemapを)、
LOC、2、type_arg、len_arg)。
......
}

//ガベージコレクタはHchanだけスタックにポインタを含めることができると仮定され
、//ヒープへのポインタを含めることはできません。
構造体Hchan
{
uintgo qcount。Qにおける//総データ
dataqsiz uintgo。//円形のQのサイズ
uint16のにELEMSIZE。
BOOL閉じました。
UINT8 elemalign;
uintgo sendx; //インデックスを送信
recvx uintgo。//インデックス受信
WaitQのRECVQを。//のrecvウェイターのリスト
SENDQ WaitQ。ウェイターを送信する//リスト
ロック。
}。

2、ランタイムを送ります

Bstatement *
Send_statement :: do_get_backend(Translate_context *コンテキスト)
{
......
それ以外の場合は、(can_take_addressは)
{
//値のアドレスを渡す必要があります。機能は変更されません
ので、ちょうど直接そのアドレスを取る、//値を。
コード=ランタイム:: SEND_BIG。
ヴァル=式:: make_unary(OPERATOR_AND、ヴァル、LOC)。
}
......
式*ランタイム:: make_call(コード、LOC、3、TD、this-> channel_、ヴァル)=呼び出します。
......
}

単にデータのポインタを渡す、全く送信データが存在しない場合、見て自身のコピーを再ことができる
空隙
runtime_chansend(EP *バイト、PRES BOOL *、ボイド* PC chanTypeのT *、C * Hchan、)
{
......
mysg。 EP = ELEM;
mysg.g = G;
mysg.selgen = NOSELGEN;
G-> PARAM =ゼロ、
エンキュー(&C-> SENDQ、&mysg);
runtime_park(runtime_unlock、Cは、 "チャン送信");
......
}

第四に、いくつかの組み込みの予約語

GCC-4.8.2 \ libgo \行く\ BUILTIN \ builtin.go
FUNCメイク(タイプ、サイズIntegerType)タイプ

//新しい組み込み関数は、メモリを割り当てます。最初の引数は、型であり、
//ない値、および戻り値が新たにポインタで
そのタイプの//割り当てられたゼロ値。
FUNC新しい(タイプ)*タイプ

//複合組み込み関数は、二つの複素数値を構築
//浮動小数点値。実部と虚部は同じでなければなりません
のfloat32かのfloat64(またはそれらに割り当て)のどちらか、//サイズ、およびリターン
//値は、対応する複合型(のfloat32ためcomplex64、なり
のfloat64用// complex128)。
FUNC錯体(R、I FloatType)のComplexType

//実際の組み込み関数は、複素数cの実部を返します。
//戻り値は、Cの種類に対応する点の種類をフローティングされるであろう。
FUNC実数(CのComplexType)FloatType

GCC-4.8.2のgcc \ \行く\ gofrontend \ gogo.cc
[関数* complex_type =タイプ:: make_function_type(NULL、NULL、NULL、LOC)。
complex_type-> set_is_varargs();
complex_type-> set_is_builtin();
this->グローバル_-> add_function_declaration( "複合"、NULL、complex_type、LOC)。


GCC \ 4.8.2-gccの\ \ gofrontend \ gogo-tree.cc行く

ゴゴを:: allocate_memory(タイプ*型、ツリーのサイズ、場所の場所)
{
//パッケージの輸入安全ではない場合、それはしてゲームをプレイしてもよい
//整数のように見えるのポインタ。
IF(this-> imported_unsafe_ ||タイプ- > has_pointer())
{
静的ツリーnew_fndecl。
(&new_fndecl、午後:: call_builtinを返す
ロケーション、
"__go_new"、
1、
ptr_type_node、
たSizeType、
サイズ)。
}

{
静的ツリーnew_nopointers_fndecl。
返すゴーゴー:: call_builtin(&new_nopointers_fndecl、
場所、
"__go_new_nopointers"、
1、
、ptr_type_node
たSizeType、
サイズ);
}
}

おすすめ

転載: www.cnblogs.com/tsecer/p/11460552.html
おすすめ