/** * @file sc_threds.c * @bried スレッドモジュール * @author Nomura Kei * @copyright 2003 - 2022 Nomura Kei */ #include <sc.h> #include <sc_threads.h> #ifdef __STDC_NO_THREADS__ // C11 対応している状態かつ、標準のスレッドが未サポート // => スレッドを扱わないシステムとして、ダミー関数実装とする。 //////////////////////////////////////////////////////////////////////////////// // // スレッド // static thrd_t thrd_uniq_id = 0; /// ユニークなスレッドID生成用 static thrd_t thrd_current_id = 0; /// 現在のスレッドID /** * 本来はスレッドを開始しますが、 * ダミー実装として、指定された関数を呼び出します。 * * @param thr スレッド識別子 * @param func 実行する関数 * @param arg パラメータ * @return thrd_success (固定) */ int thrd_create(thrd_t* thr, thrd_start_t func, void* arg) { func(arg); thrd_uniq_id++; *thr = thrd_uniq_id; return thrd_success; } /** * 指定されたスレッドが同じスレッドを参照しているか否かを返します。 * * @param lhs 比較するスレッド1 * @param rhs 比較するスレッド2 * @return 非ゼロ/0 (同じ/異なる) */ int thrd_equal(thrd_t lhs, thrd_t rhs) { return !(lhs == rhs); } /** * 現在のスレッド識別子を返します。 * * @return 現在のスレッド識別子 */ thrd_t thrd_current(void) { return thrd_current_id; } #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) #include <time.h> /** * 少なくとも duration が経過するまで、現在のスレッドの実行をブロックします。 * 無視されない信号を受信すると、スリープが早期に再開される場合があります。 * このような場合、remaining が NULL 出ない場合、残りの時間を指すオブジェクトが格納されます。 * * @param duration スリープする期間へのポインタ * @param remaining 中断の残り時間を設定するオブジェクトへのポインタ * @return 0/-1/そのた負値 (成功/シグナル発生/その他エラー) */ int thrd_sleep(const struct timespec* duration, struct timespec* remaining) { return nanosleep(duration, remaining); } #else /** * 少なくとも duration が経過するまで、現在のスレッドの実行をブロックします。 * 無視されない信号を受信すると、スリープが早期に再開される場合があります。 * このような場合、remaining が NULL 出ない場合、残りの時間を指すオブジェクトが格納されます。 * * @param duration スリープする期間へのポインタ * @param remaining 中断の残り時間を設定するオブジェクトへのポインタ * @return 0/-1/そのた負値 (成功/シグナル発生/その他エラー) */ int thrd_sleep(const struct timespec* duration, struct timespec* remaining) { // サポートしていない return -2; } #endif /** * スレッドの実行を再スケジュールするためのヒントを実装に提供し、 * 他のスレッドを実行できるようにします。 * ダミー実装は、何もしません。 */ void thrd_yield(void) { // NOP } /** * スレッドを終了します。 */ void thrd_exit(int res) { (void) res; } /** * 指定されたスレッドを現在の環境から切り離します。 * スレッドが保持していたリソースは自動的に開放されます。 * ダミー実装は、スレッド自体起動していないため、何もせず成功を返します。 * * @param thr スレッド識別子 * @return thrd_success (固定) */ int thrd_detach(thrd_t thr) { (void) thr; return thrd_success; } /** * 本来はスレッドが終了するまで待ちますが、 * ダミー実装は、スレッド自体起動していないので、すぐに成功を返します。 * * @param thr スレッド識別子 * @param res 結果コード * @return thrd_success (固定) */ int thrd_join(thrd_t thr, int* res) { if (res != NULL) { *res = thrd_success; } return thrd_success; } //////////////////////////////////////////////////////////////////////////////// // // ミューテックス // #define MTX_TYPE(val) ((val >> 24) & 0xFF) #define MTX_IS_MATCH_TYPE(val, type) ((MTX_TYPE(val) & type) == type) static mtx_t mtx_uniq_id = 0; /// ユニークなミューテックスID生成用 /** * ミューティックスオブジェクトを作成します。 * * @param mutex ミューテックス * @param タイプ * @return thrd_success (固定) */ int mtx_init(mtx_t* mutex, int type) { mtx_uniq_id++; *mutex = (mtx_uniq_id | (type << 24)); return thrd_success; } /** * 指定されたミューテックスがロックされるまで、現在のスレッドをブロックします。 * * @param mutex ミューテックス * @return thrd_success (固定) */ int mtx_lock(mtx_t* mutex) { (void) mutex; return thrd_success; } /** * 指定されたミューテックスがロックされるか、指定された絶対カレンダー時点に達するまで * 現在のスレッドをブロックします。 * ミューテックスがタイムアウトをサポートしない場合、動作は未定義です。 * * @param mutex ミューテックス * @return thrd_success/thrd_error */ int mtx_timedlock(mtx_t* restrict mutex, const struct timespec time_point) { if (MTX_IS_MATCH_TYPE(*mutex, mtx_timed)) { return thrd_success; } return thrd_error; } /** * 指定したミューテックスをブロックせずにロックしようとします。 * ダミー実装では、mtx_lock と同じ動作となります。 * * @param mutex ミューテックス * @return thrd_success (固定) */ int mtx_trylock(mtx_t* mutex) { return mtx_lock(mutex); } /** * 指定したミューテックスをアンロックします。 * * @param mutex ミューテックス * @return thrd_success */ int mtx_unlock(mtx_t* mutex) { (void) mutex; return shrd_success; } /** * 指定したミューテックスを破棄します。 * * @param mutex ミューテックス * @return thrd_success */ void mtx_unlock(mtx_t* mutex) { (void) mutex; } #endif // __STDC_NO_THREADS__