1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Thread.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 25856 $
14  *---------------------------------------------------------------------------*/
15 
16 /*! @file
17     @brief      Thread に関する API の宣言
18 
19     :include nn/os.h
20 */
21 
22 #ifndef NN_OS_OS_THREAD_H_
23 #define NN_OS_OS_THREAD_H_
24 
25 #include <nn/types.h>
26 #include <nn/Handle.h>
27 #include <nn/os/os_Synchronization.h>
28 #include <nn/os/os_Result.h>
29 #include <nn/os/os_Tick.h>
30 #include <nn/os/os_SpinWaitSelect.h>
31 
32 #include <nn/util/util_Result.h>
33 #include <nn/util/util_TypeTraits.h>
34 
35 /*
36     @def    NN_OS_CORE_NO_ALL
37     @brief 対応する C++ 関数を参照してください。@ref nn::os::CORE_NO_ALL
38 */
39 #define NN_OS_CORE_NO_ALL                           (-1)
40 
41 /*
42     @def    NN_OS_CORE_NO_USE_PROCESS_VALUE
43     @brief 対応する C++ 関数を参照してください。@ref nn::os::CORE_NO_USE_PROCESS_VALUE
44 */
45 #define NN_OS_CORE_NO_USE_PROCESS_VALUE             (-2)
46 
47 #define NN_OS_THREAD_PRIORITY_RANGE_SIZE            32
48 
49 /*
50     @def    NN_OS_LOWEST_THREAD_PRIORITY
51     @brief 対応する C++ 関数を参照してください。@ref nn::os::LOWEST_THREAD_PRIORITY
52 */
53 #define NN_OS_LOWEST_THREAD_PRIORITY                (NN_OS_THREAD_PRIORITY_RANGE_SIZE - 1)
54 
55 /*
56     @def    NN_OS_HIGHEST_THREAD_PRIORITY
57     @brief 対応する C++ 関数を参照してください。@ref nn::os::HIGHEST_THREAD_PRIORITY
58 */
59 #define NN_OS_HIGHEST_THREAD_PRIORITY               0
60 
61 /*
62     @def    NN_OS_DEFAULT_THREAD_PRIORITY
63     @brief 対応する C++ 関数を参照してください。@ref nn::os::DEFAULT_THREAD_PRIORITY
64 */
65 #define NN_OS_DEFAULT_THREAD_PRIORITY               16
66 
67 
68 
69 #ifdef __cplusplus
70 
71 #include <nn/os/os_SvcTypes.autogen.h>
72 
73 namespace nn{ namespace os{
74 
75 namespace detail {
76     s32 ConvertSvcToLibraryPriority(s32 svc);
77     s32 ConvertLibraryToSvcPriority(s32 lib);
78 }
79 
80 /*
81     @brief スレッドの最低優先度を表す定数です。31 です。
82 */
83 const s32 LOWEST_THREAD_PRIORITY = NN_OS_LOWEST_THREAD_PRIORITY;
84 
85 /*
86     @brief スレッドの最高優先度を表す定数です。0 です。
87 */
88 const s32 HIGHEST_THREAD_PRIORITY = NN_OS_HIGHEST_THREAD_PRIORITY;
89 
90 /*
91     @brief デフォルトのスレッド優先度を表す定数です。16 です。
92 */
93 const s32 DEFAULT_THREAD_PRIORITY = NN_OS_DEFAULT_THREAD_PRIORITY;
94 
95 /*
96     @brief スレッドを実行するプロセッサ番号がどれでも良いことを表します。
97 */
98 const s32 CORE_NO_ALL = NN_OS_CORE_NO_ALL;
99 
100 /*
101     @brief スレッドの実行をするプロセッサ番号を指定する際、アプリケーションで設定されているデフォルトの番号を使うことを表します。
102 */
103 const s32 CORE_NO_USE_PROCESS_VALUE = NN_OS_CORE_NO_USE_PROCESS_VALUE;
104 
105 const s32 THREAD_PRIORITY_RANGE_SIZE = NN_OS_THREAD_PRIORITY_RANGE_SIZE;
106 
107 /* @typedef void (*ThreadFunc)(uptr param)
108     @brief スレッドで実行する関数の型を表します。
109 */
110 
111 /*!
112     @brief スレッドを表すクラスです。
113 
114     Bug:   現在の実装では、優先プロセッサやアフィニティマスクの設定はできません。
115 
116            スレッドには優先度があります。
117            スレッド優先度には 0~31 までの整数で指定することができ、0 が一番高い優先度を表します。
118            標準的なスレッドは @ref DEFAULT_THREAD_PRIORITY (16)を指定します。
119 
120            スレッドの動作にはスタック領域が必要ですが、
121            スタック領域の管理は、自分で管理することもライブラリに任せることもできます。
122 
123            自分でスタック領域を管理する場合は @ref Start 関数にスタック領域を渡し、スレッドを開始します。
124            スタック領域は uptr GetStackBottom() 関数を持つようなクラスのインスタンスを渡します。
125            @ref StackMemoryBlock や @ref StackBuffer はこの条件を満たすクラスのため、直接渡すことができます。
126            自分でスタック領域を管理する場合は、
127            スレッドが終了する前にスタック領域が無効になる(解放されるなど)ことがないように十分に注意してください。
128 
129            ライブラリにスタック領域の管理を任せる場合は @ref StartUsingAutoStack 関数にスタックサイズを渡し、スレッドを開始します。
130            ライブラリが確保するスタック領域のサイズは4096byte単位です。
131 
132            @ref Start によって開始された Thread オブジェクトを破棄する前には、
133            必ず明示的に @ref Joinを呼ぶ必要があります。
134            @ref Detach を呼ぶことはできません。
135 
136            @ref StartUsingAutoStack によって開始された Thread オブジェクトを破棄する前には、
137            必ず明示的に @ref Join か @ref Detach を呼ぶ必要があります。
138 
139            Thread オブジェクトは @ref WaitObject を継承しており、Wait 動作の解放はスレッドの終了を意味します。
140            @ref Join 動作をブロック無しに行う必要がある際は、
141            先に @ref WaitOne や @ref WaitObject::WaitAny などを呼んで Wait 動作の解放を確認しておきます。
142 
143            ※現在の実装では優先プロセッサやアフィニティマスクをスレッド開始時以外に指定することはできません。
144 
145            スレッドには、優先プロセッサおよびアフィニティマスクを指定することができます。
146            優先プロセッサには、0 ~ (コア数-1) まで指定することができます。
147            また、@ref CORE_NO_ALL を指定すると全てのプロセッサを平等に扱うように優先プロセッサを設定し、
148            全てのプロセッサを含むアフィニティマスクを使用します。
149            @ref CORE_NO_USE_PROCESS_VALUE を指定すると、所属するアプリケーションのデフォルトの値を使用します。
150            優先プロセッサを指定すると、スレッドは指定されたプロセッサ上で優先して動作しますが、
151            必ずしも指定どおりのプロセッサ上で動作するわけではありません。
152 
153            アフィニティマスクは、スレッドがどのプロセッサ上で実行されるべきかを指定するものです。
154            bit8の配列で表現し、各要素は下位1ビット目が最初のプロセッサを表します。
155            ビットを1にすることで、対象のプロセッサで走行する許可を与えます。
156            必ず、どれかのプロセッサをしてする必要があり、全てのビット0にしたマスクを指定することはできません。
157 
158            スレッドの開始時には優先プロセッサを指定することができますが、
159            ここでプロセッサ番号を指定した場合、
160            スレッド開始時のアフィニティマスクはそのプロセッサ番号のみが指定されたことになります。
161 */
162 
163 class Thread : public WaitObject
164 {
165 public:
166     class AutoStackManager
167     {
168     public:
169         virtual void* Construct(size_t stackSize) = 0;
170         virtual void Destruct(void* pStackBottom, bool isError) = 0;
171     };
172 
173 public:
174 
175     /*!
176     @brief        コンストラクタです。
177 
178                   スレッドを開始するには、@ref Start または @ref TryStart を使います。
179     */
Thread()180     Thread() : m_CanFinalize(true) {}
181 
182     /*!
183     @brief        デストラクタ
184 
185                   スレッドオブジェクトを破棄します。
186                   破棄時の注意は @ref Finalize を参照してください。
187     */
188     ~Thread();
189 
190     /*!
191     @brief        スレッドを初期化し実行します。
192 
193                   ユーザが用意したスタックを使ってスレッドを初期化し、スレッドを開始します。
194                   スレッドの終了が確認されるまで、スタック領域は維持されている必要があります。
195 
196     @param[in]    f             実行を開始する関数へのポインタ
197     @param[in]    stack         スタック領域を表すオブジェクト
198     @param[in]    priority      スレッドの優先度
199     @param[in]    coreNo        スレッドの優先プロセッサ
200 
201     @tparam       Stack         スタックを表す型
202 
203     @return       無し。
204 
205     :overload partialtemplate
206     */
207     template <typename Stack>
208     void Start(void (*f)(), Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
209 
210     /*!
211     @brief        スレッドを初期化し実行します。
212 
213                   ユーザが用意したスタックを使ってスレッドを初期化し、スレッドを開始します。
214                   スレッドの終了が確認されるまで、スタック領域は維持されている必要があります。
215 
216     @param[in]    f             実行を開始する関数へのポインタ
217     @param[in]    param         実行を開始する関数へ渡す引数
218     @param[in]    stack         スタック領域を表すオブジェクト
219     @param[in]    priority      スレッドの優先度
220     @param[in]    coreNo        スレッドの優先プロセッサ
221 
222     @tparam       T             実行する関数の引数の型(コピーできる型である必要があります)
223     @tparam       U             T に変換できる型
224     @tparam       Stack         スタックを表す型
225 
226     @return       無し。
227 
228     :overload fulltemplate
229     */
230     template <typename T, typename U, typename Stack>
231     void Start(void (*f)(T), U param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
232     template <typename T, typename Stack>
233     void Start(void (*f)(const T*), const T& param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
234     template <typename T, typename Stack>
235     void Start(void (*f)(const T&), const T& param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
236 
237     /*!
238     @brief        スレッドの初期化と実行を試みます。
239 
240                   スレッドを初期化し実行をしますが、
241                   リソース不足などが原因で失敗した場合にエラーを返します。
242 
243     @sa Start
244 
245     @param[in]    f             実行を開始する関数へのポインタ
246     @param[in]    stack         スタック領域を表すオブジェクト
247     @param[in]    priority      スレッドの優先度
248     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
249 
250     @tparam       Stack         スタックを表す型
251 
252     @return       関数の実行結果を返します。
253     */
254     template <typename Stack>
255     nn::Result TryStart(void (*f)(), Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
256 
257     /*!
258     @brief        スレッドの初期化と実行を試みます。
259 
260                   スレッドを初期化し実行をしますが、
261                   リソース不足などが原因で失敗した場合にエラーを返します。
262 
263     @sa Start
264 
265     @param[in]    f             実行を開始する関数へのポインタ
266     @param[in]    param         実行を開始する関数へ渡す引数
267     @param[in]    stack         スタック領域を表すオブジェクト
268     @param[in]    priority      スレッドの優先度
269     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
270 
271     @tparam       T             実行する関数の引数の型(コピーできる型である必要があります)
272     @tparam       U             T に変換できる型
273     @tparam       Stack         スタックを表す型
274 
275     @return       関数の実行結果を返します。
276     */
277     template <typename T, typename U, typename Stack>
278     nn::Result TryStart(void (*f)(T), U param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
279 
280     /*!
281     @brief        スレッドを初期化し実行します。
282 
283                   スタックは指定されたサイズ以上のサイズに自動的に確保され、
284                   スレッド終了時に自動的に破棄されます。
285 
286     @param[in]    f             実行を開始する関数へのポインタ
287     @param[in]    stackSize     スタックサイズ
288     @param[in]    priority      スレッドの優先度
289     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
290 
291     @return       無し。
292     */
293     void StartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
294 
295     /*!
296     @brief        スレッドを初期化し実行します。
297 
298                   スタックは指定されたサイズ以上のサイズに自動的に確保され、
299                   スレッド終了時に自動的に破棄されます。
300 
301     @param[in]    f             実行を開始する関数へのポインタ
302     @param[in]    param         実行を開始する関数へ渡す引数
303     @param[in]    stackSize     スタックサイズ
304     @param[in]    priority      スレッドの優先度
305     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
306 
307     @tparam       T             実行する関数の引数の型(コピーできる型である必要があります)
308     @tparam       U             T に変換できる型
309 
310     @return       無し。
311     */
312     template <typename T, typename U>
313     void StartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
314 
315     /*!
316     :overload notemplate
317 
318     @brief        スレッドの初期化と実行を試みます。
319 
320                   スレッドを初期化し実行をしますが、
321                   リソース不足などが原因で失敗した場合にエラーを返します。
322 
323     @sa StartUsingAutoStack
324 
325     @param[in]    f             実行を開始する関数へのポインタ
326     @param[in]    stackSize     スタックサイズ
327     @param[in]    priority      スレッドの優先度
328     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
329 
330     @return       関数の実行結果を返します。
331     */
332     nn::Result TryStartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
333 
334     /*!
335     :overload template
336 
337     @brief        スレッドの初期化と実行を試みます。
338 
339                   スレッドを初期化し実行をしますが、
340                   リソース不足などが原因で失敗した場合にエラーを返します。
341 
342     @sa StartUsingAutoStack
343 
344     @param[in]    f             実行を開始する関数へのポインタ
345     @param[in]    param         実行を開始する関数へ渡す引数
346     @param[in]    stackSize     スタックサイズ
347     @param[in]    priority      スレッドの優先度
348     @param[in]    coreNo        スレッドの優先プロセッサおよびアフィニティマスクの指定
349 
350     @tparam       T             実行する関数の引数の型(コピーできる型である必要があります)
351     @tparam       U             T に変換できる型
352 
353     @return       関数の実行結果を返します。
354     */
355     template <typename T, typename U>
356     nn::Result TryStartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
357 
358     /*!
359     @brief        スレッドオブジェクトを破棄します。
360 
361                   スレッドを破棄する前に、必ず @ref Detach か @ref Join を呼んでいる必要があります。
362                   呼んでいなかった場合、PANIC します。
363 
364 
365     @return       無し。
366     */
367     void Finalize();
368 
369     /*!
370     @brief        スレッドの終了を待ちます。
371 
372                   この関数はスレッドの終了を無条件で待ちます。
373                   タイムアウトつきで待つなど、細かい制御が必要な場合は、
374                   @ref WaitObject にある関数を使ってスレッドの終了を待った後、
375                   この関数を呼び出すようにしてください。
376 
377     @return       無し。
378     */
379     void Join();
380 
381     /*!
382     @brief        スレッドのデタッチを行います。
383 
384                   このオブジェクトがスレッドに対して今後一切の操作を行わないことを宣言します。
385                   このオブジェクトに対しては、@ref Finalize とデストラクタ以外を呼ぶことができなくなります。
386 
387                   @ref Start を使って開始したスレッドに対してこの関数を呼ぶことはできません。
388 
389     @return       無し。
390     */
391     void Detach();
392 
393     /*!
394     @brief        スレッドが生きているかどうかを取得します。
395 
396     @return       スレッドが生きているならtrue、そうでないならfalseを返します。
397     */
IsAlive()398     bool IsAlive() const { return !const_cast<Thread*>(this)->WaitOne(0); }
399 
400     /*!
401     @brief        カレントスレッドを指定時間だけ休止状態にします。
402 
403     @param[in]    span  休止する時間
404 
405     @return       無し。
406     */
407     static void Sleep(nn::fnd::TimeSpan span);
408 
409     /*!
410     @brief        カレントスレッドと同じ優先度のスレッドに実行機会を与えます。
411 
412                   スケジューラは優先度スケジューリングを行いますので
413                   常に実行可能なスレッドの中で最高優先度のスレッドが動作しています。
414                   最高優先度のスレッドが複数存在する場合、
415                   スケジューラはカレントスレッドを継続して動作させようと試みますので
416                   通常はカレントスレッドが実行可能でなくならない限り
417                   同優先度の他のスレッドは実行されません。
418 
419                   この関数はカレントスレッドを実行可能としたまま
420                   同優先度の他のスレッドに実行権を明け渡します。
421                   同優先度のスレッドが存在しない場合は何も起りません。
422 
423     @return       無し。
424     */
425     static void Yield();
426 
427     // スレッドの状態の取得・設定
428     // 非 static メンバ関数は、インスタンスに対して作用する。
429     // "Current" を含む名前の static メンバ関数は、カレントスレッドに対して作用する。
430     // "Default" を含む名前の static メンバ関数は、CreateThread で coreNo = CORE_NO_USE_PROCESS_VALUE のとき、
431     // 作成されるスレッドの属性のデフォルト値に作用する。
432 
433     // コンテキストの取得
434     //   TODO: 未実装
435     // void GetContext(nn::os::ThreadContext* pContext) const;
436     // static void GetCurrentContext(nn::os::ThreadContext* pContext);
437 
438     /*!
439     @brief        インスタンスのスレッドのスレッド ID を取得します。
440 
441     @return       インスタンスのスレッドのスレッド ID を返します。
442     */
443     bit32 GetId() const;
444 
445     /*!
446     @brief        カレントスレッドのスレッド ID を取得します。
447 
448     @return       カレントスレッドのスレッド ID を返します。
449     */
450     static bit32 GetCurrentId();
451 
452     /*!
453     @brief        インスタンスのスレッドの優先度を取得します。
454 
455     @return       インスタンスのスレッドの優先度を返します。
456     */
457     s32 GetPriority() const;
458 
459     /*!
460     @brief        カレントスレッドの優先度を取得します。
461 
462     @return       カレントスレッドの優先度を返します。
463     */
464     static s32 GetCurrentPriority();
465 
466     /*!
467     @brief        インスタンスのスレッドの優先度を設定します。
468 
469     @param[in]    priority  スレッドの優先度を指定します。
470 
471     @return       無し。
472     */
473     void ChangePriority(s32 priority);
474 
475     /*!
476     @brief        カレントスレッドの優先度を設定します。
477 
478     @param[in]    priority  スレッドの優先度を指定します。
479 
480     @return       無し。
481     */
482     static void ChangeCurrentPriority(s32 priority);
483 
484     // スレッド Affinity の設定・取得
485     //   AffinityMask は構造体やクラスで包む?
486     /*!
487     @brief        インスタンスのアフィニティマスクを取得します。
488 
489     @param[out]   pAffinityMask     取得したアフィニティマスクを格納するバッファを指定します。
490     @param[in]    numProcessor      pAffinityMask が指すバッファのビット数を指定します。
491 
492     @return       無し。
493 
494     Bug:          この関数は未実装です。この関数を使わないでください。
495     */
496     void GetAffinityMask(bit8* pAffinityMask, s32 numProcessor) const;
497 
498     /*!
499     @brief        カレントスレッドのアフィニティマスクを取得します。
500 
501     @param[out]   pAffinityMask     取得したアフィニティマスクを格納するバッファを指定します。
502     @param[in]    numProcessor      pAffinityMask が指すバッファのビット数を指定します。
503 
504     @return       無し。
505 
506     Bug:          この関数は未実装です。この関数を使わないでください。
507     */
508     static void GetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor);
509 
510     /*!
511     @brief        coreNo = CORE_NO_USE_PROCESS_VALUE で作成されるスレッドのアフィニティマスクを取得します。
512 
513     @param[out]   pAffinityMask     取得したアフィニティマスクを格納するバッファを指定します。
514     @param[in]    numProcessor      pAffinityMask が指すバッファのビット数を指定します。
515 
516     @return       無し。
517 
518     Bug:          この関数は未実装です。この関数を使わないでください。
519     */
520     static void GetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor);
521 
522     /*!
523     @brief        インスタンスのアフィニティマスクを設定します。
524 
525     @param[in]    pAffinityMask    新しく設定するアフィニティマスクを指定します。
526     @param[in]    numProcessor     pAffinityMask が指すビット列の有効なビット数を指定します。
527 
528     @return       無し。
529 
530     Bug:          この関数は未実装です。この関数を使わないでください。
531     */
532     void ChangeAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
533 
534     /*!
535     @brief        カレントスレッドのアフィニティマスクを設定します。
536 
537     @param[in]    pAffinityMask    新しく設定するアフィニティマスクを指定します。
538     @param[in]    numProcessor     pAffinityMask が指すビット列の有効なビット数を指定します。
539 
540     @return       無し。
541 
542     Bug:          この関数は未実装です。この関数を使わないでください。
543     */
544     static void ChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
545 
546     /*!
547     @brief        coreNo = CORE_NO_USE_PROCESS_VALUE で作成されるスレッドのアフィニティマスクを設定します。
548 
549     @param[in]    pAffinityMask     新しく設定するアフィニティマスクを指定します。
550     @param[in]    numProcessor     pAffinityMask が指すビット列の有効なビット数を指定します。
551 
552     @return       無し。
553 
554     Bug:          この関数は未実装です。この関数を使わないでください。
555     */
556     static void SetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
557 
558     // IdealProcessor の取得・設定
559     /*!
560     @brief        インスタンスの優先プロセッサ番号を取得します。
561 
562     @return       優先プロセッサ番号を返します。
563 
564     Bug:          この関数は未実装です。この関数を使わないでください。
565     */
566     s32 GetIdealProcessor() const;
567 
568     /*!
569     @brief        カレントスレッドの優先プロセッサ番号を取得します。
570 
571     @return       優先プロセッサ番号を返します。
572 
573     Bug:          この関数は未実装です。この関数を使わないでください。
574     */
575     static s32 GetCurrentIdealProcessor();
576 
577     /*!
578     @brief        coreNo = CORE_NO_USE_PROCESS_VALUE で作成されるスレッドの優先プロセッサ番号を取得します。
579 
580     @return       優先プロセッサ番号を返します。
581 
582     Bug:          この関数は未実装です。この関数を使わないでください。
583     */
584     static s32 GetDefaultIdealProcessor();
585 
586     /*!
587     @brief        インスタンスの優先プロセッサ番号を設定します。
588 
589     @param[in]    coreNo     優先プロセッサ番号
590 
591     @return       無し。
592 
593     Bug:          この関数は未実装です。この関数を使わないでください。
594     */
595     void ChangeIdealProcessor(s32 coreNo);
596 
597     /*!
598     @brief        カレントスレッドの優先プロセッサ番号を設定します。
599 
600     @param[in]    coreNo     優先プロセッサ番号
601 
602     @return       無し。
603 
604     Bug:          この関数は未実装です。この関数を使わないでください。
605     */
606     static void ChangeCurrentIdealProcessor(s32 coreNo);
607 
608     /*!
609     @brief        coreNo = CORE_NO_USE_PROCESS_VALUE で作成されるスレッドの IdealProcessor を設定します。
610 
611     @param[in]    coreNo     優先プロセッサ番号
612 
613     @return       無し。
614 
615     Bug:          この関数は未実装です。この関数を使わないでください。
616     */
617     static void SetDefaultIdealProcessor(s32 coreNo);
618 
619     /*!
620     @brief        カレントスレッドの動作しているプロセッサ番号の取得
621 
622     @return       カレントスレッドの動作しているプロセッサ番号を返します。
623 
624     Bug:          この関数は未実装です。この関数を使わないでください。
625     */
626     static s32 GetCurrentProcessorNumber();
627 
628     /*!
629     @brief        メインスレッドを表すオブジェクトを取得します。
630     @return       メインスレッドを表すオブジェクト。
631     */
GetMainThread()632     static Thread& GetMainThread() { return s_MainThread; }
633 
634     static void SetAutoStackManager(AutoStackManager* pManager);
635 
636 
637 private:
638     struct InitializeAsCurrentTag {};
639     struct TypeInfo;
640     struct FunctionInfo;
641 
642 private:
643     bool        m_CanFinalize;
644     bool        m_UsingAutoStack;
645     NN_PADDING2;
646 
647     static Thread               s_MainThread;
648     static AutoStackManager*    s_pAutoStackManager;
649 
650 private:
651     Thread(const InitializeAsCurrentTag&);
652     void FinalizeImpl();
653 
654     Result TryInitializeAndStartImpl(const TypeInfo& typeInfo, ThreadFunc f, const void* p, uptr stackBottom, s32 priority, s32 coreNo, bool isAutoStack);
655     Result TryInitializeAndStartImplUsingAutoStack(const TypeInfo& typeInfo, ThreadFunc f, const void* p, size_t stackSize, s32 priority, s32 coreNo);
656 
657 private:
658     static void OnThreadStart();
659     static void OnThreadExit();
660 
661     static void ThreadStart(uptr);
662     static void ThreadStartUsingAutoStack(uptr);
663     static void NoParameterFunc(void (*)());
664     static void SleepImpl(nn::fnd::TimeSpan span);
665 
666     static void CallDestructorAndExit(void* pStackBottom);
667 };
668 
669 /*!
670     @brief スレッド用のスタックを、static 領域や構造体の中などに配置したい場合に使うクラステンプレートです。
671 
672            @ref GetStackBottom 関数の戻り値を @ref Thread::Start 関数などに渡すことで、
673            スレッドのスタックとしてこの領域を使用することができます。
674 
675     @tparam Size スタックのサイズを表します。
676 */
677 template <size_t Size>
678 class StackBuffer
679 {
680 private:
681     typename nn::util::aligned_storage<Size, 8>::type m_Buffer;
682 public:
683 
684     /*!
685     @brief        スタックの底アドレスを返します。
686 
687     @return       スタックの底アドレス。
688     */
GetStackBottom()689     uptr GetStackBottom() const { return reinterpret_cast<uptr>(this + 1); }
690 };
691 
692 }}
693 
694 // インライン実装
695 
696 #ifdef NN_SYSTEM_PROCESS
697 
698 #include <new>
699 
700 #include <nn/dbg/dbg_Logger.h>
701 
702 namespace nn { namespace os {
703 
704 struct Thread::TypeInfo
705 {
706 private:
707 
708     template <typename T, typename U>
CopyTypeInfo709     static void Copy(const void* src, void* dst)
710     {
711         new (dst) T(*reinterpret_cast<const U*>(src));
712     }
713     template <typename T>
CopyTypeInfo714     static void Copy(const void* src, void* dst)
715     {
716         new (dst) T(*reinterpret_cast<const T*>(src));
717     }
718 
719     template <typename T>
DestroyTypeInfo720     static void Destroy(void* p)
721     {
722         reinterpret_cast<T*>(p)->~T();
723     }
724 
725     template <typename T>
InvokeTypeInfo726     static void Invoke(ThreadFunc f, const void* p)
727     {
728         (*reinterpret_cast<void (*)(T)>(f))(*reinterpret_cast<const T*>(p));
729     }
730     template <typename T>
Invoke2TypeInfo731     static void Invoke2(ThreadFunc f, const void* p)
732     {
733         (*reinterpret_cast<void (*)(const T*)>(f))(reinterpret_cast<const T*>(p));
734     }
735 
736 public:
737 
738     size_t size;
739     void (*copy)(const void* src, void* dst);
740     void (*destroy)(void* p);
741     void (*invoke)(ThreadFunc f, const void* p);
742 
743     template <typename T, typename U>
744     void SetData(typename nn::util::enable_if<nn::util::is_convertible<U, T>::value>::type* = 0)
745     {
746         this->size = sizeof(T);
747         this->copy = &(Copy<T, U>);
748         this->destroy = &(Destroy<T>);
749         this->invoke = &(Invoke<T>);
750     }
751     template <typename T>
SetDataTypeInfo752     void SetData()
753     {
754         this->size = sizeof(T);
755         this->copy = &(Copy<T>);
756         this->destroy = &(Destroy<T>);
757         this->invoke = &(Invoke2<T>);
758     }
759 
760 };
761 
762 template <typename T, typename U, typename Stack>
Start(void (* f)(T),U param,Stack & stack,s32 priority,s32 coreNo)763 inline void Thread::Start(void (*f)(T), U param, Stack& stack, s32 priority, s32 coreNo)
764 {
765     TypeInfo info;
766     info.SetData<T, U>();
767     NN_UTIL_PANIC_IF_FAILED(TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false));
768 }
769 
770 template <typename T, typename Stack>
Start(void (* f)(const T *),const T & param,Stack & stack,s32 priority,s32 coreNo)771 inline void Thread::Start(void (*f)(const T*), const T& param, Stack& stack, s32 priority, s32 coreNo)
772 {
773     TypeInfo info;
774     info.SetData<T>();
775     NN_UTIL_PANIC_IF_FAILED(TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false));
776 }
777 
778 template <typename Stack>
Start(void (* f)(),Stack & stack,s32 priority,s32 coreNo)779 inline void Thread::Start(void (*f)(), Stack& stack, s32 priority, s32 coreNo)
780 {
781     Start(NoParameterFunc, f, stack, priority, coreNo);
782 }
783 
784 template <typename T, typename U, typename Stack>
TryStart(void (* f)(T),U param,Stack & stack,s32 priority,s32 coreNo)785 inline nn::Result Thread::TryStart(void (*f)(T), U param, Stack& stack, s32 priority, s32 coreNo)
786 {
787     TypeInfo info;
788     info.SetData<T, U>();
789     Result result = TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false);
790     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
791     {
792         return result;
793     }
794     NN_UTIL_PANIC_IF_FAILED(result);
795     return result;
796 }
797 
798 template <typename Stack>
TryStart(void (* f)(),Stack & stack,s32 priority,s32 coreNo)799 inline nn::Result Thread::TryStart(void (*f)(), Stack& stack, s32 priority, s32 coreNo)
800 {
801     return TryStart(NoParameterFunc, f, stack, priority, coreNo);
802 }
803 
804 template <typename T, typename U>
StartUsingAutoStack(void (* f)(T),U param,size_t stackSize,s32 priority,s32 coreNo)805 inline void Thread::StartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority, s32 coreNo)
806 {
807     TypeInfo info;
808     info.SetData<T, U>();
809     NN_UTIL_PANIC_IF_FAILED(TryInitializeAndStartImplUsingAutoStack(info, reinterpret_cast<ThreadFunc>(f), &param, stackSize, priority, coreNo));
810 }
811 
StartUsingAutoStack(void (* f)(),size_t stackSize,s32 priority,s32 coreNo)812 inline void Thread::StartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority, s32 coreNo)
813 {
814     StartUsingAutoStack(NoParameterFunc, f, stackSize, priority, coreNo);
815 }
816 
817 template <typename T, typename U>
TryStartUsingAutoStack(void (* f)(T),U param,size_t stackSize,s32 priority,s32 coreNo)818 inline nn::Result Thread::TryStartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority, s32 coreNo)
819 {
820     TypeInfo info;
821     info.SetData<T, U>();
822     Result result = TryInitializeAndStartImplUsingAutoStack(info, reinterpret_cast<ThreadFunc>(f), &param, stackSize, priority, coreNo);
823     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
824     {
825         return result;
826     }
827     NN_UTIL_PANIC_IF_FAILED(result);
828     return result;
829 }
830 
TryStartUsingAutoStack(void (* f)(),size_t stackSize,s32 priority,s32 coreNo)831 inline nn::Result Thread::TryStartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority, s32 coreNo)
832 {
833     return TryStartUsingAutoStack(NoParameterFunc, f, stackSize, priority, coreNo);
834 }
835 
FinalizeImpl()836 inline void Thread::FinalizeImpl()
837 {
838     if (!m_CanFinalize)
839     {
840         NN_TPANIC_("Thread is not Joined or Detached either.");
841     }
842 }
843 
Finalize()844 inline void Thread::Finalize()
845 {
846     FinalizeImpl();
847     this->WaitObject::Finalize();
848 }
849 
~Thread()850 inline Thread::~Thread()
851 {
852     FinalizeImpl();
853 }
854 
Join()855 inline void Thread::Join()
856 {
857     this->WaitOne();
858     this->m_CanFinalize = true;
859 }
860 
Detach()861 inline void Thread::Detach()
862 {
863     NN_TASSERT_(m_UsingAutoStack);
864     this->m_CanFinalize = true;
865     Finalize();
866 }
867 
Sleep(nn::fnd::TimeSpan span)868 inline void Thread::Sleep(nn::fnd::TimeSpan span)
869 {
870     SleepImpl(span);
871 }
872 
Yield()873 inline void Thread::Yield()
874 {
875     nn::svc::SleepThread(0);
876 }
877 
GetId()878 inline bit32 Thread::GetId() const
879 {
880     bit32 ret;
881     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadId(&ret, GetHandle()));
882     return ret;
883 }
884 
GetCurrentId()885 inline bit32 Thread::GetCurrentId()
886 {
887     bit32 ret;
888     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadId(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
889     return ret;
890 }
891 
GetPriority()892 inline s32 Thread::GetPriority() const
893 {
894     s32 ret;
895     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadPriority(&ret, GetHandle()));
896     return os::detail::ConvertSvcToLibraryPriority(ret);
897 }
898 
GetCurrentPriority()899 inline s32 Thread::GetCurrentPriority()
900 {
901     s32 ret;
902     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadPriority(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
903     return os::detail::ConvertSvcToLibraryPriority(ret);
904 }
905 
ChangePriority(s32 priority)906 inline void Thread::ChangePriority(s32 priority)
907 {
908     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadPriority(GetHandle(), os::detail::ConvertLibraryToSvcPriority(priority)));
909 }
910 
ChangeCurrentPriority(s32 priority)911 inline void Thread::ChangeCurrentPriority(s32 priority)
912 {
913     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadPriority(PSEUDO_HANDLE_CURRENT_THREAD, os::detail::ConvertLibraryToSvcPriority(priority)));
914 }
915 
GetAffinityMask(bit8 * pAffinityMask,s32 numProcessor)916 inline void Thread::GetAffinityMask(bit8* pAffinityMask, s32 numProcessor) const
917 {
918     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadAffinityMask(pAffinityMask, GetHandle(), numProcessor));
919 }
920 
GetCurrentAffinityMask(bit8 * pAffinityMask,s32 numProcessor)921 inline void Thread::GetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor)
922 {
923     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadAffinityMask(pAffinityMask, PSEUDO_HANDLE_CURRENT_THREAD, numProcessor));
924 }
925 
GetDefaultAffinityMask(bit8 * pAffinityMask,s32 numProcessor)926 inline void Thread::GetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor)
927 {
928     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetProcessAffinityMask(pAffinityMask, PSEUDO_HANDLE_CURRENT_PROCESS, numProcessor));
929 }
930 
ChangeAffinityMask(const bit8 * pAffinityMask,s32 numProcessor)931 inline void Thread::ChangeAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
932 {
933     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadAffinityMask(GetHandle(), pAffinityMask, numProcessor));
934 }
935 
ChangeCurrentAffinityMask(const bit8 * pAffinityMask,s32 numProcessor)936 inline void Thread::ChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
937 {
938     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadAffinityMask(PSEUDO_HANDLE_CURRENT_THREAD, pAffinityMask, numProcessor));
939 }
940 
SetDefaultAffinityMask(const bit8 * pAffinityMask,s32 numProcessor)941 inline void Thread::SetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
942 {
943     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetProcessAffinityMask(PSEUDO_HANDLE_CURRENT_PROCESS, pAffinityMask, numProcessor));
944 }
945 
GetIdealProcessor()946 inline s32 Thread::GetIdealProcessor() const
947 {
948     s32 ret;
949     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadIdealProcessor(&ret, GetHandle()));
950     return ret;
951 }
952 
GetCurrentIdealProcessor()953 inline s32 Thread::GetCurrentIdealProcessor()
954 {
955     s32 ret;
956     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetThreadIdealProcessor(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
957     return ret;
958 }
959 
GetDefaultIdealProcessor()960 inline s32 Thread::GetDefaultIdealProcessor()
961 {
962     s32 ret;
963     NN_UTIL_PANIC_IF_FAILED(nn::svc::GetProcessIdealProcessor(&ret, PSEUDO_HANDLE_CURRENT_PROCESS));
964     return ret;
965 }
966 
ChangeIdealProcessor(s32 coreNo)967 inline void Thread::ChangeIdealProcessor(s32 coreNo)
968 {
969     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadIdealProcessor(GetHandle(), coreNo));
970 }
971 
ChangeCurrentIdealProcessor(s32 coreNo)972 inline void Thread::ChangeCurrentIdealProcessor(s32 coreNo)
973 {
974     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetThreadIdealProcessor(PSEUDO_HANDLE_CURRENT_THREAD, coreNo));
975 }
976 
SetDefaultIdealProcessor(s32 coreNo)977 inline void Thread::SetDefaultIdealProcessor(s32 coreNo)
978 {
979     NN_UTIL_PANIC_IF_FAILED(nn::svc::SetProcessIdealProcessor(PSEUDO_HANDLE_CURRENT_PROCESS, coreNo));
980 }
981 
GetCurrentProcessorNumber()982 inline s32 Thread::GetCurrentProcessorNumber()
983 {
984     return nn::svc::GetCurrentProcessorNumber();
985 }
986 
987 
988 /*!
989   @}
990 */
991 /*!
992   @}
993 */
994 
995 }} // namespace nn::os
996 
997 #endif // NN_SYSTEM_PROCESS
998 
999 #endif // __cplusplus
1000 
1001 // 以下、C 用宣言
1002 
1003 #include <nn/util/detail/util_CLibImpl.h>
1004 
1005 
1006 /*!
1007   @addtogroup   nn_os               os
1008   @{
1009 
1010   @defgroup     nn_os_Thread_c    Thread (C)
1011 
1012   @brief        @ref nn::os::Thread の C インタフェースモジュールです。
1013 
1014   @{
1015 */
1016 
1017 /*!
1018   @struct       nnosThread
1019   @brief        スレッドを表す C の構造体です。
1020 
1021   @brief 対応するクラス @ref nn::os::Thread を参照してください。
1022 */
1023 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosThread, nn::os::Thread, 8, u32);
1024 
1025 /*!
1026   @brief 対応する C++ 関数 @ref nn::os::Thread::Start を参照してください。
1027 */
1028 NN_EXTERN_C void nnosThreadInitializeAndStart(nnosThread* this_, void (*f)(uptr), uptr param, uptr stackBottom, s32 priority, s32 coreNo);
1029 
1030 /*!
1031   @brief 対応する C++ 関数 @ref nn::os::Thread::TryStart を参照してください。
1032 */
1033 NN_EXTERN_C bool nnosThreadTryInitializeAndStart(nnosThread* this_, void (*f)(uptr), uptr param, uptr stackBottom, s32 priority, s32 coreNo);
1034 
1035 /*!
1036   @brief 対応する C++ 関数 @ref nn::os::Thread::Finalize を参照してください。
1037 */
1038 NN_EXTERN_C void nnosThreadFinalize(nnosThread* this_);
1039 
1040 /*!
1041   @brief 対応する C++ 関数 @ref nn::os::Thread::Join を参照してください。
1042 */
1043 NN_EXTERN_C void nnosThreadJoin(nnosThread* this_);
1044 
1045 /*!
1046   @brief 対応する C++ 関数 @ref nn::os::Thread::Sleep を参照してください。
1047 */
1048 NN_EXTERN_C void nnosThreadSleep(s64 nanoSeconds);
1049 
1050 /*!
1051   @brief 対応する C++ 関数 @ref nn::os::Thread::Yield を参照してください。
1052 */
1053 NN_EXTERN_C void nnosThreadYield(void);
1054 
1055 /*!
1056   @brief 対応する C++ 関数 @ref nn::os::Thread::GetCurrentId を参照してください。
1057 */
1058 NN_EXTERN_C bit32 nnosThreadGetCurrentId(void);
1059 
1060 /*!
1061   @brief 対応する C++ 関数 @ref nn::os::Thread::GetPriority を参照してください。
1062 */
1063 NN_EXTERN_C s32 nnosThreadGetPriority(const nnosThread* this_);
1064 
1065 /*!
1066   @brief 対応する C++ 関数 @ref nn::os::Thread::GetCurrentPriority を参照してください。
1067 */
1068 NN_EXTERN_C s32 nnosThreadGetCurrentPriority(void);
1069 
1070 /*!
1071   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangePriority を参照してください。
1072 */
1073 NN_EXTERN_C void nnosThreadChangePriority(nnosThread* this_, s32 priority);
1074 
1075 /*!
1076   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangeCurrentPriority を参照してください。
1077 */
1078 NN_EXTERN_C void nnosThreadChangeCurrentPriority(s32 priority);
1079 
1080     // スレッド Affinity の設定・取得
1081 
1082 /*!
1083   @brief 対応する C++ 関数 @ref nn::os::Thread::GetAffinityMask を参照してください。
1084 */
1085 NN_EXTERN_C void nnosThreadGetAffinityMask(const nnosThread* this_, bit8* pAffinityMask, s32 numProcessor);
1086 
1087 /*!
1088   @brief 対応する C++ 関数 @ref nn::os::Thread::GetCurrentAffinityMask を参照してください。
1089 */
1090 NN_EXTERN_C void nnosThreadGetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor);
1091 
1092 /*!
1093   @brief 対応する C++ 関数 @ref nn::os::Thread::GetDefaultAffinityMask を参照してください。
1094 */
1095 NN_EXTERN_C void nnosThreadGetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor);
1096 
1097 /*!
1098   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangeAffinityMask を参照してください。
1099 */
1100 NN_EXTERN_C void nnosThreadChangeAffinityMask(nnosThread* this_, const bit8* pAffinityMask, s32 numProcessor);
1101 
1102 /*!
1103   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangeCurrentAffinityMask を参照してください。
1104 */
1105 NN_EXTERN_C void nnosThreadChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
1106 
1107 /*!
1108   @brief 対応する C++ 関数 @ref nn::os::Thread::SetDefaultAffinityMask を参照してください。
1109 */
1110 NN_EXTERN_C void nnosThreadSetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
1111 
1112     // IdealProcessor の取得・設定
1113 
1114 /*!
1115   @brief 対応する C++ 関数 @ref nn::os::Thread::GetIdealProcessor を参照してください。
1116 */
1117 NN_EXTERN_C s32 nnosThreadGetIdealProcessor(const nnosThread* this_);
1118 
1119 /*!
1120   @brief 対応する C++ 関数 @ref nn::os::Thread::GetCurrentIdealProcessor を参照してください。
1121 */
1122 NN_EXTERN_C s32 nnosThreadGetCurrentIdealProcessor(void);
1123 
1124 /*!
1125   @brief 対応する C++ 関数 @ref nn::os::Thread::GetDefaultIdealProcessor を参照してください。
1126 */
1127 NN_EXTERN_C s32 nnosThreadGetDefaultIdealProcessor(void);
1128 
1129 /*!
1130   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangeIdealProcessor を参照してください。
1131 */
1132 NN_EXTERN_C void nnosThreadChangeIdealProcessor(nnosThread* this_, s32 coreNo);
1133 
1134 /*!
1135   @brief 対応する C++ 関数 @ref nn::os::Thread::ChangeCurrentIdealProcessor を参照してください。
1136 */
1137 NN_EXTERN_C void nnosThreadChangeCurrentIdealProcessor(s32 coreNo);
1138 
1139 /*!
1140   @brief 対応する C++ 関数 @ref nn::os::Thread::SetDefaultIdealProcessor を参照してください。
1141 */
1142 NN_EXTERN_C void nnosThreadSetDefaultIdealProcessor(s32 coreNo);
1143 
1144     // カレントスレッドの動作しているプロセッサ番号の取得
1145 
1146 /*!
1147   @brief 対応する C++ 関数 @ref nn::os::Thread::GetCurrentProcessorNumber を参照してください。
1148 */
1149 NN_EXTERN_C s32 nnosThreadGetCurrentProcessorNumber(void);
1150 
1151 /*!
1152   @brief 対応する C++ 関数 @ref nn::os::Thread::GetID を参照してください。
1153 */
1154 NN_EXTERN_C bit32 nnosThreadGetId(nnosThread* this_);
1155 
1156 /*!
1157   @brief 対応する C++ 関数 @ref nn::os::Thread::IsAlive を参照してください。
1158 */
1159 NN_EXTERN_C bool nnosThreadIsAlive(nnosThread* this_);
1160 
1161 /*!
1162   @brief 対応する C++ 関数 @ref nn::os::Thread::GetMainThread を参照してください。
1163 */
1164 NN_EXTERN_C nnosThread* nnosThreadGetMainThread(void);
1165 
1166 /*!
1167   @}
1168   @}
1169 */
1170 
1171 /* NN_OS_THREAD_H_ */
1172 #endif
1173 
1174