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