C スタックフル コルーチン ライブラリを簡単に拡張できます。
識別名は、分岐することを意味する日本語のディスカバー ブンキ (分岐) です。 私は、コルーチン ライブラリに非常に適した ID を単に google 画像 (分岐) として認識していることを覚えておいてください。さらに、私が示すものを垣間見ることができます。 x86_64 と Buy64 x64_86 呼び出し規約、および aarch64.
懸念や PR は大歓迎です
- 例
- 建物
- 定義
- API
- bunki_init
- bunki_stack_min_size
- bunki_init_stack_ctx
- bunki_prepare_ctx
- bunki_init_prepare_ctx
- 二段ベッド i_resume
- bunki_ctx_resume
- bunki_yield
- bunki_stack_push
- bunki_stack_push_data
- bunki_ctx_data_get
- bunki_ctx_data_set
- bunki_ctx_call
- ノート
- TODO
著作権とライセンス #includeuintptr_t print_unsigned(voidarg) { uintptr_t val=(uintptr_t)arg; printf(“The value is: 0x%lxn”, val); return 0;}uintptr_t my_coroutine(voidarg) { // Save a value to the thread context storage bunki_ctx_data_set((void*)0xcafe); // Call a function on the current threads stack bunki_ctx_call((void*)0xf00d, print_unsigned); bunki_yield(10); // print out the value we save before last yield bunki_ctx_call((void*)bunki_ctx_data_get(), print_unsigned); // print the arg bunki_ctx_call(arg, print_unsigned); bunki_yield(12);}int main() { // only call once before using the library // The library will now expect stack memory to // aligned by 256 bytes and be 256 bytes in size. if(bunki_init(256)) { fprintf(stderr, “Failed to initialize!n”); return 1; } voidstack_mem=aligned_alloc(256, 256); if(stack_mem==NULL) { fprintf(stderr, “Failed to allocate memory!n”); return 1; } bunki_t ctx=bunki_init_prepare_ctx(stack_mem, my_coroutine, (void*)0xbeef); printf(“Returned: %un”, bunki_resume(ctx)); printf(“Returned: %un”, bunki_resume(ctx)); free(stack_mem); return 0;}” dir=”auto”> #encompass 」bunki.h 」 #encompass > #encompass
)> uintptr_t print_unsigned (空所arg) { uintptr_t val=(uintptr_t)引数; printf ( )”レートは: 0x%lx n”、値); 戻る 0; } uintptr_t my_coroutine (空所引数) { // 価値を保存スレッドコンテキストストレージへ bunki_ctx_data_set ((空所*) 0xcafe ); // コンテンポラリー スレッド スタックで特性を呼び出します bunki_ctx_call(( 空所*)0xf00d, print_unsigned); bunki_yield (10 ); //
利回りを閉じる前に確立した価値を出力します bunki_ctx_call ((
空所*)bunki_ctx_data_get(), print_unsigned); // argを出力します bunki_ctx_call - (arg, print_unsigned); bunki_yield (12 ); } int 主要() {
// ライブラリを使用する前に 1 回だけ最上位呼び出しを行う // ライブラリは、スタック メモリからレコードデータを検索します // 256 バイトでアラインされ、256 になる次元のバイト。 もしも( bunki_init(256 )) { fprintf
(stderr, " 初期化されませんでした!
n”); 戻る 1 ; } 空所stack_mem= aligned_alloc(256, 256); もしも(stack_mem== ヌル) { fprintf(stderr, "メモリを割り当てませんでした!n
"); 戻る 1 ; } bunki_t ctx= bunki_init_prepare_ctx (stack_mem, my_coroutine, (void*)
0xbeef
); printf ( )"戻ってきた: %un " , bunki_resume(ctx)); printf ( )"戻ってきた: %un " , bunki_resume(ctx)); 無料(stack_mem); 戻る 0; }プロジェクトは、ライブラリを所有するメイクファイルを保持しています。 単に滑らせるだけ 製造
そして静的ライブラリは間違いなくビルドされ、所有アイテムにコピーされます. 所有のアイテム化は、2 つのフォルダー lib と include を所有します。 ライブラリのアイテム化には、反対にリンクする静的ライブラリがあり、包含のアイテム化には hea が含まれます。 makefile コンパイルを使用しない場合 bunki_setup.c、bunki_common.c
- 。 それはたった4つのレコードデータです.
定義 -
BUNKI_STACK_CONST justify を使用すると、ライブラリのバージョンを所有できるため、呼び出しなしでは脆弱になります bunki_init()。 主な注意点は、実行時のコード パッチを回避し、コンパイラがスタック サイズを固定して最適化できるようにすることです。 makefile 内の CFLAGS に追加するだけです – DBUNKI_STACK_CONST=。 スタック次元は 2 のエネルギーでなければなりません。
- BUNKI_SHARE_FCW_MXCSR
この正当化は、x86_64 ビルドに適用されます。 横に BUNKI_SHARE_FCW_MXCSR
正当化として、コンテキストスワップの仮定を適度に小さくします。 また、あなたのコルーチンが MXCSR レジスタと FPU 保留通知の現代的な価値を消費しないことも可能です. - BUNKI_NO_WIN64_XMM
この正当化の一番上は、Windows 上の x86_64 に適用されます。 正当化は で脆弱でなければなりません注意
。 この正当化は、x86_64 上のウィンドウに適用され、 この正当化で浮動小数点演算を消費する可能性が最も高いままですが、スタックがないことは明らかです。コンテキスト スワップの上のフレームは、レジスタ内に浮動またはベクトルの仮定を格納していませんBUNKI_NO_WIN64_XMM
非-揮発性 xmm- BUNKI_AARCH64_NO_VEC_FLOAT
この正当化の一番上は aarch64 に適用されます。 justify は BUNKI_NO_WIN64_XMM
、これから保存されるコンテキスト レコードデータの量を想定しても、 Windows ほど巨大であってはなりません。 ターゲットとするハードウェアが SIMD に対応するハードウェアを維持していない場合、これを定義することを強くお勧めします と 浮動レベル番号。 コンテキスト スワップをより小さく/より速く作成するために使用する場合は、注意. bunki_init 署名なし bunki_init(uint32_t stack_size);
再開されるコルーチンが、この特性に対する決定よりも前に行われたかのように認識されます。 追加定義 BUNKI_STACK_CONSTイニシャル図書館の環境を脆くする。 この特性の引数は、消費すると見なされるスタックのサイズ (バイト単位) です。 スケールは 2 のエネルギーである必要があります。これは、ライブラリがそれを使用して、ほんの数個のコルーチン コンテキストのガイドラインを即座にキャッチするためです。 この特性は いいえ
この特性をノーオペレーションで製造
- 特性は成功時に 0 を返します。
- 特性スタックが単純すぎるか、2 のエネルギーでない場合は 1 を返します。必要な値を含むパッチ コード。
空所);
この特性は、2 スタック次元の最小エネルギーをバイト単位で返します。 コンテキストを作成するために分配されるメモリは、この量以上に引き上げる必要があります。 さらに、これは bunki_init() が解決する最小の次元です.
bunki_init_stack_ctx 指定されたメモリからbunki_tコンテキストを作成します。 stack_mem パラメータのスケール しなければならない bunki_init() に提供される次元と等しくなる) このメモリのアラインメント
しなければならない は、その寸法分だけ整列されます。 例として、スタックのサイズが 256 バイトの場合 stack_mem は256 バイト アラインメント。 コルーチンの実行を譲り、呼び出し元を再開します。 呼び出し側は、引数に渡された値を取得します ret が返ってきました。 この特徴
しなければならない コルーチンのオープンエアとして知られることはありません. bunki_stack_push 空所
bunki_stack_push (
bunki_tctx, size_t allocation_length);
bunki_stack_push()
を使用すると、コルーチン スタック上にレコードデータを格納するためのメモリを確保できます。 パラメータ allocation_lengthは、予約するバイト数です。 これは、コルーチンの起動特性の起動引数として提供する構造を格納するための例として手に入れることもできます。 コルーチンにアクセスできるスタック アリーナの量を大幅に削減することに注意してください。 この特徴
レコードデータ);しなければならない bunki_prepare_ctx() を呼び出した後はわからないまたは bunki_init_prepare_ctx()。 この特性は、呼び出し後に虚弱になることを意味します bunki_init_stack_ctx() ただし、コルーチンが完全に終了する前に- 戻り値は、コルーチン スタック上に分配されたメモリへのポインタです。
この特徴ほぼ正確に動作します bunki_stack_push() ただし、さらにコピーします3番目のパラメータからコルーチンスタックに確保されたメモリへのガイドライン.
bunki_ctx_data_get この特性により、以前にスレッド コンテキスト ストレージに保持されていた値を取得できます。 . この特徴
しなければならない 内部コルーチンとして知られている最上位 bunki_ctx_data_set (
void
この特徴と bunki_ctx_data_get() は、スレッド ネイティブ ストレージを作成するためのビルディング ブロックです。
空所*
、自由にメモリを割り当てて、そのメモリへのポインタを別のメモリとして dawdle してください。 コルーチンが完了したら解放することを怠らないでください😉。 この特徴
しなければならない 内部コルーチンとして知られている最上位 bunki_ctx_call uintptr_t bunki_ctx_call (voidarg, uintptr_t (*機能)(空所*));
スタックフル コルーチンを使用する場合、理想的には分単位のスタックが必要です。 その苦境は、深い呼び出しスタックを生成する関数を呼び出さない可能性が最も高いということです。 この特性により、スレッド スタックの 2 番目の引数に提供された特性ポインタを別のポインタとして呼び出すことで、その苦境を回避できます。
最初のパラメータ arg に渡されますfunc として知られている場合。 戻り値は、
この特性 として知られているときに、特性ポインターから返される値です。 しなければならない v すべてのトップはコルーチンの内部として知られ、次にスレッドのスタック上にある間 bunki_yield および で始まる任意の特性)bunki_ctx しなければならない
*));
この特性は、単に尊重する振る舞いをします bunki_ctx_call()、ただし には 2 つの引数が渡されます) funcの場合
- BUNKI_SHARE_FCW_MXCSR
- API
- 定義