1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Thread.h
4 
5   Copyright (C)2009-2012 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: 50238 $
14  *---------------------------------------------------------------------------*/
15 
16 /* Please see man pages for details
17 
18 
19 
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 #include <nn/os/os_ErrorHandlerSelect.h>
32 #include <nn/os/os_AutoStackManager.h>
33 #include <nn/os/os_SvcTypes.autogen.h>
34 
35 #include <nn/util/util_Result.h>
36 #include <nn/util/util_TypeTraits.h>
37 
38 /*
39 
40 
41 */
42 #define NN_OS_CORE_NO_ALL                           (-1)
43 
44 /*
45 
46 
47 */
48 #define NN_OS_CORE_NO_USE_PROCESS_VALUE             (-2)
49 
50 #define NN_OS_THREAD_PRIORITY_RANGE_SIZE            32
51 
52 /*
53 
54 
55 */
56 #define NN_OS_LOWEST_THREAD_PRIORITY                (NN_OS_THREAD_PRIORITY_RANGE_SIZE - 1)
57 
58 /*
59 
60 
61 */
62 #define NN_OS_HIGHEST_THREAD_PRIORITY               0
63 
64 /*
65 
66 
67 */
68 #define NN_OS_DEFAULT_THREAD_PRIORITY               16
69 
70 
71 
72 #ifdef __cplusplus
73 
74 #include <nn/os/os_SvcTypes.autogen.h>
75 
76 namespace nn{ namespace os{
77 
78 namespace detail {
79     s32 ConvertSvcToLibraryPriority(s32 svc);
80     s32 ConvertLibraryToSvcPriority(s32 lib);
81     void InitializeThreadEnvrionment();
82 }
83 
84 /*
85 
86 */
87 const s32 LOWEST_THREAD_PRIORITY = NN_OS_LOWEST_THREAD_PRIORITY;
88 
89 /*
90 
91 */
92 const s32 HIGHEST_THREAD_PRIORITY = NN_OS_HIGHEST_THREAD_PRIORITY;
93 
94 /*
95 
96 */
97 const s32 DEFAULT_THREAD_PRIORITY = NN_OS_DEFAULT_THREAD_PRIORITY;
98 
99 /*
100 
101 */
102 const s32 CORE_NO_ALL = NN_OS_CORE_NO_ALL;
103 
104 /*
105 
106 */
107 const s32 CORE_NO_USE_PROCESS_VALUE = NN_OS_CORE_NO_USE_PROCESS_VALUE;
108 
109 const s32 THREAD_PRIORITY_RANGE_SIZE = NN_OS_THREAD_PRIORITY_RANGE_SIZE;
110 
111 /*
112 
113 */
114 
115 class ManagedThread;
116 
117 /* Please see man pages for details
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
141 
142 
143 
144 
145 
146 
147 
148 
149 
150 
151 
152 
153 
154 */
155 
156 class Thread : public WaitObject
157 {
158 public:
159     typedef nn::os::AutoStackManager AutoStackManager;
160 
161 public:
162 
163 //
164 //
165 
166     /* Please see man pages for details
167 
168 
169 
170     */
Thread()171     Thread() : m_CanFinalize(true) {}
172 
173     /* Please see man pages for details
174 
175 
176 
177 
178     */
179     ~Thread();
180 
181 //
182 
183 //
184 //
185 
186     /* Please see man pages for details
187 
188 
189 
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202     */
203     template <typename Stack>
204     void Start(void (*f)(), Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
205 
206     /* Please see man pages for details
207 
208 
209 
210 
211 
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224 
225     */
226     template <typename T, typename U, typename Stack>
227     void Start(void (*f)(T), U param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
228     template <typename T, typename Stack>
229     void Start(void (*f)(T*), T& param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
230     template <typename T, typename Stack>
231     void Start(void (*f)(const T&), const T& param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
232 
233     /* Please see man pages for details
234 
235 
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251     */
252     template <typename Stack>
253     nn::Result TryStart(void (*f)(), Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
254 
255     /* Please see man pages for details
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 
268 
269 
270 
271 
272 
273 
274 
275 
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     template <typename T, typename Stack>
280     nn::Result TryStart(void (*f)(T*), T& param, Stack& stack, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
281 
282     /* Please see man pages for details
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 
293 
294 
295 
296 
297     */
298     void StartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
299 
300     /* Please see man pages for details
301 
302 
303 
304 
305 
306 
307 
308 
309 
310 
311 
312 
313 
314 
315 
316 
317 
318     */
319     template <typename T, typename U>
320     void StartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
321 
322     /* Please see man pages for details
323 
324 
325 
326 
327 
328 
329 
330 
331 
332 
333 
334 
335 
336 
337 
338 
339     */
340     nn::Result TryStartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
341     nn::Result TryStartUsingAutoStack(ThreadFunc f, size_t stackSize, const void* pParam, size_t paramSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
342 
343     /* Please see man pages for details
344 
345 
346 
347 
348 
349 
350 
351 
352 
353 
354 
355 
356 
357 
358 
359 
360 
361 
362 
363 
364 
365     */
366     template <typename T, typename U>
367     nn::Result TryStartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority = DEFAULT_THREAD_PRIORITY, s32 coreNo = CORE_NO_USE_PROCESS_VALUE);
368 
369 //
370 
371 //
372 //
373 
374     /* Please see man pages for details
375 
376 
377 
378 
379 
380 
381     */
382     void Finalize();
383 
384     /* Please see man pages for details
385 
386 
387 
388 
389 
390 
391 
392 
393     */
394     void Join();
395 
396     //----------------------------------------------------------------------
397     //
398     //
399     //
400     //
401     //
402     //
403     //
404     //
405     //
406     //
407     //
408     //
409     //
410     //
411     //
412     //
413     //
414     //----------------------------------------------------------------------
415     void Detach();
416 
417     /* Please see man pages for details
418 
419 
420 
421     */
422     bool IsAlive() const;
423 
424 //
425 
426 
427 //
428 //
429 
430     /* Please see man pages for details
431 
432 
433 
434 
435 
436     */
437     static void Sleep(nn::fnd::TimeSpan span);
438 
439     /* Please see man pages for details
440 
441 
442 
443 
444 
445 
446 
447 
448 
449 
450 
451 
452 
453 
454     */
455     static void Yield();
456 
457 //
458 
459 //
460 //
461 
462     // Get/set the thread status
463     // Non-static member functions act on the instance.
464     // Static member functions that include "Current" in their name act on the current thread.
465     // static member functions with "Default" included in their names act on the default value of the attributes of the created thread when coreNo = CORE_NO_USE_PROCESS_VALUE in CreateThread.
466     //
467 
468     // Get the context
469     //   TODO: Not implemented.
470     // void GetContext(nn::os::ThreadContext* pContext) const;
471     // static void GetCurrentContext(nn::os::ThreadContext* pContext);
472 
473     /* Please see man pages for details
474 
475 
476 
477     */
478     bit32 GetId() const;
479 
480     /* Please see man pages for details
481 
482 
483 
484     */
485     static bit32 GetCurrentId();
486 
487     /* Please see man pages for details
488 
489 
490 
491     */
492     s32 GetPriority() const;
493 
494     /* Please see man pages for details
495 
496 
497 
498     */
499     static s32 GetCurrentPriority();
500 
501     /* Please see man pages for details
502 
503 
504 
505 
506 
507     */
508     void ChangePriority(s32 priority);
509 
510     /* Please see man pages for details
511 
512 
513 
514 
515 
516     */
517     static void ChangeCurrentPriority(s32 priority);
518 
519     // Get/set the thread affinity
520 
521     /*
522 
523 
524 
525 
526 
527 
528     */
529     //void GetAffinityMask(bit8* pAffinityMask, s32 numProcessor) const;
530 
531     /*
532 
533 
534 
535 
536 
537 
538     */
539     //static void GetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor);
540 
541     /*
542 
543 
544 
545 
546 
547 
548     */
549     //static void GetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor);
550 
551     /*
552 
553 
554 
555 
556 
557 
558     */
559     //void ChangeAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
560 
561     /*
562 
563 
564 
565 
566 
567 
568     */
569     //static void ChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
570 
571     /*
572 
573 
574 
575 
576 
577 
578     */
579     //static void SetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
580 
581     // Get/set IdealProcessor
582     /* Please see man pages for details
583 
584 
585 
586     */
587     s32 GetIdealProcessor() const;
588 
589     /*
590 
591 
592 
593     */
594     //static s32 GetCurrentIdealProcessor();
595 
596     /*
597 
598 
599 
600     */
601     static s32 GetDefaultIdealProcessor();
602 
603     /*
604 
605 
606 
607 
608 
609     */
610     //void ChangeIdealProcessor(s32 coreNo);
611 
612     /*
613 
614 
615 
616 
617 
618     */
619     //static void ChangeCurrentIdealProcessor(s32 coreNo);
620 
621     /*
622 
623 
624 
625 
626 
627     */
628     //static void SetDefaultIdealProcessor(s32 coreNo);
629 
630     /* Please see man pages for details
631 
632 
633 
634     */
635     static s32 GetCurrentProcessorNumber();
636 
637 //
638 
639 //
640 //
641 
642     /* Please see man pages for details
643 
644 
645     */
GetMainThread()646     static Thread& GetMainThread() { return s_MainThread; }
647 
648     /* Please see man pages for details
649 
650 
651 
652 
653 
654 
655 
656 
657 
658 
659 
660     */
661     static void SetAutoStackManager(AutoStackManager* pManager);
662 
663     //----------------------------------------------------------------------
664     //
665     //
666     //
667     //
668     //
669     //
670     //
671     //
672     //----------------------------------------------------------------------
673     static s32  GetCurrentCount();
674 
675     //----------------------------------------------------------------------
676     //
677     //
678     //
679     //----------------------------------------------------------------------
680     static s32  GetMaxCount();
681 
682 //
683 
684 private:
685     struct InitializeAsCurrentTag {};
686     struct TypeInfo;
687     struct FunctionInfo;
688 
689 private:
690     bool        m_CanFinalize;
691     bool        m_UsingAutoStack;
692     NN_PADDING2;
693 
694     static Thread               s_MainThread;
695     static AutoStackManager*    s_pAutoStackManager;
696 
697 private:
698     Thread(const InitializeAsCurrentTag&);
699     void FinalizeImpl();
700 
701     Result TryInitializeAndStartImpl(const TypeInfo& typeInfo, ThreadFunc f, const void* p, uptr stackBottom, s32 priority, s32 coreNo, bool isAutoStack);
702     Result TryInitializeAndStartImpl(const TypeInfo& typeInfo, ThreadFunc f, const void* p, uptr stackBottom, s32 priority, s32 coreNo, uptr autoStackBuffer);
703     Result TryInitializeAndStartImplUsingAutoStack(const TypeInfo& typeInfo, ThreadFunc f, const void* p, size_t stackSize, s32 priority, s32 coreNo);
704     uptr   PreStartUsingAutoStack(size_t stackSize);
705     Result PostStartUsingAutoStack(Result result, uptr stackBottom);
706 
707 private:
708     static void OnThreadStart();
709     static void OnThreadExit();
710 
711     static void ThreadStart(uptr);
712     static void ThreadStartUsingAutoStack(uptr);
713     static void NoParameterFunc(void (*)());
714     static void SleepImpl(nn::fnd::TimeSpan span);
715 
716     static void CallDestructorAndExit(void* pStackBottom);
717 
718 public:
719     class ProtectedAccessor
720     {
721     private:
722         friend class ::nn::os::ManagedThread;
723 
PreStartUsingAutoStack(Thread * pThread,size_t stackSize)724         static uptr PreStartUsingAutoStack(Thread* pThread, size_t stackSize)
725         {
726             return pThread->PreStartUsingAutoStack(stackSize);
727         }
PostStartUsingAutoStack(Thread * pThread,Result result,uptr stackBottom)728         static Result PostStartUsingAutoStack(Thread* pThread, Result result, uptr stackBottom)
729         {
730             return pThread->PostStartUsingAutoStack(result, stackBottom);
731         }
732         template <typename T, typename Stack>
733         static Result TryStart(Thread* pThread, void (*f)(T*), T& param, Stack& stack, s32 priority, s32 coreNo, uptr autoStackBuffer);
734         static void InitializeAsMainThread(void* p);
735     };
736 };
737 
738 /* Please see man pages for details
739 
740 
741 
742 
743 
744 
745 
746 
747 */
748 template <size_t Size>
749 class StackBuffer
750 {
751 private:
752     typename nn::util::aligned_storage<Size, 8>::type m_Buffer;
753 public:
754 
755     /* Please see man pages for details
756 
757 
758 
759     */
GetStackBottom()760     uptr GetStackBottom() const { return reinterpret_cast<uptr>(this + 1); }
761 
762     /* Please see man pages for details
763 
764 
765 
766     */
GetStackSize()767     size_t GetStackSize() const { return Size; }
768 
769     void MarkCanary(bit32 value = 0xDEADBEEF) { reinterpret_cast<bit32*>(this)[0] = value; }
770     bool CheckCanary(bit32 value = 0xDEADBEEF) const { return reinterpret_cast<const bit32*>(this)[0] == value; }
771 };
772 
773 }}
774 
775 // In-line implementation
776 
777 #ifdef NN_SYSTEM_PROCESS
778 
779 #include <new>
780 
781 #include <nn/dbg/dbg_Logger.h>
782 
783 namespace nn { namespace os {
784 
785 struct Thread::TypeInfo
786 {
787 private:
788 
789     template <typename T, typename U>
CopyTypeInfo790     static void Copy(const void* src, void* dst)
791     {
792         new (dst) T(*reinterpret_cast<const U*>(src));
793     }
794     template <typename T>
CopyTypeInfo795     static void Copy(const void* src, void* dst)
796     {
797         new (dst) T(*reinterpret_cast<const T*>(src));
798     }
799 
800     template <typename T>
DestroyTypeInfo801     static void Destroy(void* p)
802     {
803         reinterpret_cast<T*>(p)->~T();
804     }
805 
806     template <typename T>
InvokeTypeInfo807     static void Invoke(ThreadFunc f, const void* p)
808     {
809         (*reinterpret_cast<void (*)(T)>(f))(*reinterpret_cast<const T*>(p));
810     }
811     template <typename T>
Invoke2TypeInfo812     static void Invoke2(ThreadFunc f, const void* p)
813     {
814         (*reinterpret_cast<void (*)(const T*)>(f))(reinterpret_cast<const T*>(p));
815     }
816 
817 public:
818 
819     size_t size;
820     void (*copy)(const void* src, void* dst);
821     void (*destroy)(void* p);
822     void (*invoke)(ThreadFunc f, const void* p);
823 
824     template <typename T, typename U>
825     void SetData(typename nn::util::enable_if<nn::util::is_convertible<U, T>::value>::type* = 0)
826     {
827         this->size = sizeof(T);
828         this->copy = &(Copy<T, U>);
829         this->destroy = &(Destroy<T>);
830         this->invoke = &(Invoke<T>);
831     }
832     template <typename T>
SetDataTypeInfo833     void SetData()
834     {
835         this->size = sizeof(T);
836         this->copy = &(Copy<T>);
837         this->destroy = &(Destroy<T>);
838         this->invoke = &(Invoke2<T>);
839     }
840 };
841 
842 
843 template <typename T, typename U, typename Stack>
Start(void (* f)(T),U param,Stack & stack,s32 priority,s32 coreNo)844 inline void Thread::Start(void (*f)(T), U param, Stack& stack, s32 priority, s32 coreNo)
845 {
846     TypeInfo info;
847     info.SetData<T, U>();
848     NN_OS_ERROR_IF_FAILED(TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false));
849 }
850 
851 template <typename T, typename Stack>
Start(void (* f)(T *),T & param,Stack & stack,s32 priority,s32 coreNo)852 inline void Thread::Start(void (*f)(T*), T& param, Stack& stack, s32 priority, s32 coreNo)
853 {
854     TypeInfo info;
855     info.SetData<T>();
856     NN_OS_ERROR_IF_FAILED(TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false));
857 }
858 
859 //template <typename T, typename Stack>
860 //inline void Thread::Start(void (*f)(const T&), const T& param, Stack& stack, s32 priority, s32 coreNo)
861 //{
862 //    TypeInfo info;
863 //    info.SetData<T>();
864 //    NN_OS_ERROR_IF_FAILED(TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false));
865 //}
866 
867 template <typename Stack>
Start(void (* f)(),Stack & stack,s32 priority,s32 coreNo)868 inline void Thread::Start(void (*f)(), Stack& stack, s32 priority, s32 coreNo)
869 {
870     Start(NoParameterFunc, f, stack, priority, coreNo);
871 }
872 
873 template <typename T, typename Stack>
TryStart(Thread * pThread,void (* f)(T *),T & param,Stack & stack,s32 priority,s32 coreNo,uptr autoStackBuffer)874 inline nn::Result Thread::ProtectedAccessor::TryStart(Thread* pThread, void (*f)(T*), T& param, Stack& stack, s32 priority, s32 coreNo, uptr autoStackBuffer)
875 {
876     TypeInfo info;
877     info.SetData<T>();
878     Result result = pThread->TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, autoStackBuffer);
879     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
880     {
881         return result;
882     }
883     NN_OS_ERROR_IF_FAILED(result);
884     return result;
885 }
886 
887 template <typename T, typename U, typename Stack>
TryStart(void (* f)(T),U param,Stack & stack,s32 priority,s32 coreNo)888 inline nn::Result Thread::TryStart(void (*f)(T), U param, Stack& stack, s32 priority, s32 coreNo)
889 {
890     TypeInfo info;
891     info.SetData<T, U>();
892     Result result = TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false);
893     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
894     {
895         return result;
896     }
897     NN_OS_ERROR_IF_FAILED(result);
898     return result;
899 }
900 
901 template <typename Stack>
TryStart(void (* f)(),Stack & stack,s32 priority,s32 coreNo)902 inline nn::Result Thread::TryStart(void (*f)(), Stack& stack, s32 priority, s32 coreNo)
903 {
904     return TryStart(NoParameterFunc, f, stack, priority, coreNo);
905 }
906 
907 template <typename T, typename Stack>
TryStart(void (* f)(T *),T & param,Stack & stack,s32 priority,s32 coreNo)908 inline nn::Result Thread::TryStart(void (*f)(T*), T& param, Stack& stack, s32 priority, s32 coreNo)
909 {
910     TypeInfo info;
911     info.SetData<T>();
912     Result result = TryInitializeAndStartImpl(info, reinterpret_cast<ThreadFunc>(f), &param, stack.GetStackBottom(), priority, coreNo, false);
913     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
914     {
915         return result;
916     }
917     NN_OS_ERROR_IF_FAILED(result);
918     return result;
919 }
920 
921 template <typename T, typename U>
StartUsingAutoStack(void (* f)(T),U param,size_t stackSize,s32 priority,s32 coreNo)922 inline void Thread::StartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority, s32 coreNo)
923 {
924     TypeInfo info;
925     info.SetData<T, U>();
926     NN_OS_ERROR_IF_FAILED(TryInitializeAndStartImplUsingAutoStack(info, reinterpret_cast<ThreadFunc>(f), &param, stackSize, priority, coreNo));
927 }
928 
StartUsingAutoStack(void (* f)(),size_t stackSize,s32 priority,s32 coreNo)929 inline void Thread::StartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority, s32 coreNo)
930 {
931     StartUsingAutoStack(NoParameterFunc, f, stackSize, priority, coreNo);
932 }
933 
934 template <typename T, typename U>
TryStartUsingAutoStack(void (* f)(T),U param,size_t stackSize,s32 priority,s32 coreNo)935 inline nn::Result Thread::TryStartUsingAutoStack(void (*f)(T), U param, size_t stackSize, s32 priority, s32 coreNo)
936 {
937     TypeInfo info;
938     info.SetData<T, U>();
939     Result result = TryInitializeAndStartImplUsingAutoStack(info, reinterpret_cast<ThreadFunc>(f), &param, stackSize, priority, coreNo);
940     if (result.GetSummary() == Result::SUMMARY_OUT_OF_RESOURCE)
941     {
942         return result;
943     }
944     NN_OS_ERROR_IF_FAILED(result);
945     return result;
946 }
947 
TryStartUsingAutoStack(void (* f)(),size_t stackSize,s32 priority,s32 coreNo)948 inline nn::Result Thread::TryStartUsingAutoStack(void (*f)(), size_t stackSize, s32 priority, s32 coreNo)
949 {
950     return TryStartUsingAutoStack(NoParameterFunc, f, stackSize, priority, coreNo);
951 }
952 
Finalize()953 inline void Thread::Finalize()
954 {
955     FinalizeImpl();
956     this->WaitObject::Finalize();
957 }
958 
~Thread()959 inline Thread::~Thread()
960 {
961     FinalizeImpl();
962 }
963 
Join()964 inline void Thread::Join()
965 {
966     this->WaitOne();
967     this->m_CanFinalize = true;
968 }
969 
Detach()970 inline void Thread::Detach()
971 {
972     NN_TASSERT_(m_UsingAutoStack);
973     this->m_CanFinalize = true;
974     Finalize();
975 }
976 
IsAlive()977 inline bool Thread::IsAlive() const
978 {
979     if (IsValid())
980     {
981         return !const_cast<Thread*>(this)->WaitOne(0);
982     }
983     else
984     {
985         return false;
986     }
987 }
988 
Sleep(nn::fnd::TimeSpan span)989 inline void Thread::Sleep(nn::fnd::TimeSpan span)
990 {
991     SleepImpl(span);
992 }
993 
Yield()994 inline void Thread::Yield()
995 {
996     nn::svc::SleepThread(0);
997 }
998 
GetId()999 inline bit32 Thread::GetId() const
1000 {
1001     bit32 ret;
1002     NN_OS_ERROR_IF_FAILED(nn::svc::GetThreadId(&ret, GetHandle()));
1003     return ret;
1004 }
1005 
GetCurrentId()1006 inline bit32 Thread::GetCurrentId()
1007 {
1008     bit32 ret;
1009     NN_OS_ERROR_IF_FAILED(nn::svc::GetThreadId(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
1010     return ret;
1011 }
1012 
GetPriority()1013 inline s32 Thread::GetPriority() const
1014 {
1015     s32 ret;
1016     NN_OS_ERROR_IF_FAILED(nn::svc::GetThreadPriority(&ret, GetHandle()));
1017     return os::detail::ConvertSvcToLibraryPriority(ret);
1018 }
1019 
GetCurrentPriority()1020 inline s32 Thread::GetCurrentPriority()
1021 {
1022     s32 ret;
1023     NN_OS_ERROR_IF_FAILED(nn::svc::GetThreadPriority(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
1024     return os::detail::ConvertSvcToLibraryPriority(ret);
1025 }
1026 
ChangePriority(s32 priority)1027 inline void Thread::ChangePriority(s32 priority)
1028 {
1029     NN_OS_ERROR_IF_FAILED(nn::svc::SetThreadPriority(GetHandle(), os::detail::ConvertLibraryToSvcPriority(priority)));
1030 }
1031 
ChangeCurrentPriority(s32 priority)1032 inline void Thread::ChangeCurrentPriority(s32 priority)
1033 {
1034     NN_OS_ERROR_IF_FAILED(nn::svc::SetThreadPriority(PSEUDO_HANDLE_CURRENT_THREAD, os::detail::ConvertLibraryToSvcPriority(priority)));
1035 }
1036 
1037 //inline void Thread::GetAffinityMask(bit8* pAffinityMask, s32 numProcessor) const
1038 //{
1039 //    NN_ERR_THROW_FATAL(nn::svc::GetThreadAffinityMask(pAffinityMask, GetHandle(), numProcessor));
1040 //}
1041 //
1042 //inline void Thread::GetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor)
1043 //{
1044 //    NN_ERR_THROW_FATAL(nn::svc::GetThreadAffinityMask(pAffinityMask, PSEUDO_HANDLE_CURRENT_THREAD, numProcessor));
1045 //}
1046 //
1047 //inline void Thread::GetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor)
1048 //{
1049 //    NN_ERR_THROW_FATAL(nn::svc::GetProcessAffinityMask(pAffinityMask, PSEUDO_HANDLE_CURRENT_PROCESS, numProcessor));
1050 //}
1051 //
1052 //inline void Thread::ChangeAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
1053 //{
1054 //    NN_ERR_THROW_FATAL(nn::svc::SetThreadAffinityMask(GetHandle(), pAffinityMask, numProcessor));
1055 //}
1056 //
1057 //inline void Thread::ChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
1058 //{
1059 //    NN_ERR_THROW_FATAL(nn::svc::SetThreadAffinityMask(PSEUDO_HANDLE_CURRENT_THREAD, pAffinityMask, numProcessor));
1060 //}
1061 //
1062 //inline void Thread::SetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor)
1063 //{
1064 //    NN_ERR_THROW_FATAL(nn::svc::SetProcessAffinityMask(PSEUDO_HANDLE_CURRENT_PROCESS, pAffinityMask, numProcessor));
1065 //}
1066 
GetIdealProcessor()1067 inline s32 Thread::GetIdealProcessor() const
1068 {
1069     s32 ret;
1070     NN_OS_ERROR_IF_FAILED(nn::svc::GetThreadIdealProcessor(&ret, GetHandle()));
1071     return ret;
1072 }
1073 
1074 //inline s32 Thread::GetCurrentIdealProcessor()
1075 //{
1076 //    s32 ret;
1077 //    NN_ERR_THROW_FATAL(nn::svc::GetThreadIdealProcessor(&ret, PSEUDO_HANDLE_CURRENT_THREAD));
1078 //    return ret;
1079 //}
1080 
GetDefaultIdealProcessor()1081 inline s32 Thread::GetDefaultIdealProcessor()
1082 {
1083     s32 ret;
1084     NN_OS_ERROR_IF_FAILED(nn::svc::GetProcessIdealProcessor(&ret, PSEUDO_HANDLE_CURRENT_PROCESS));
1085     return ret;
1086 }
1087 
1088 //inline void Thread::ChangeIdealProcessor(s32 coreNo)
1089 //{
1090 //    NN_ERR_THROW_FATAL(nn::svc::SetThreadIdealProcessor(GetHandle(), coreNo));
1091 //}
1092 //
1093 //inline void Thread::ChangeCurrentIdealProcessor(s32 coreNo)
1094 //{
1095 //    NN_ERR_THROW_FATAL(nn::svc::SetThreadIdealProcessor(PSEUDO_HANDLE_CURRENT_THREAD, coreNo));
1096 //}
1097 //
1098 //inline void Thread::SetDefaultIdealProcessor(s32 coreNo)
1099 //{
1100 //    NN_ERR_THROW_FATAL(nn::svc::SetProcessIdealProcessor(PSEUDO_HANDLE_CURRENT_PROCESS, coreNo));
1101 //}
1102 
GetCurrentProcessorNumber()1103 inline s32 Thread::GetCurrentProcessorNumber()
1104 {
1105     return nn::svc::GetCurrentProcessorNumber();
1106 }
1107 
InitializeAsMainThread(void * p)1108 inline void Thread::ProtectedAccessor::InitializeAsMainThread(void* p)
1109 {
1110     new(p) Thread(Thread::InitializeAsCurrentTag());
1111 }
1112 
1113 
1114 /*
1115 
1116 */
1117 /*
1118 
1119 */
1120 
1121 }} // namespace nn::os
1122 
1123 #endif // NN_SYSTEM_PROCESS
1124 
1125 #endif // __cplusplus
1126 
1127 // Below is the C declaration
1128 
1129 #include <nn/util/detail/util_CLibImpl.h>
1130 
1131 
1132 /* Please see man pages for details
1133 
1134 
1135 
1136 
1137 
1138 
1139 
1140 
1141 */
1142 
1143 /* Please see man pages for details
1144 
1145 
1146 
1147 
1148 */
1149 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosThread, nn::os::Thread, 8, u32);
1150 
1151 /* Please see man pages for details
1152 
1153 */
1154 NN_EXTERN_C void nnosThreadInitializeAndStart(nnosThread* this_, void (*f)(uptr), uptr param, uptr stackBottom, s32 priority, s32 coreNo);
1155 
1156 /* Please see man pages for details
1157 
1158 */
1159 NN_EXTERN_C bool nnosThreadTryInitializeAndStart(nnosThread* this_, void (*f)(uptr), uptr param, uptr stackBottom, s32 priority, s32 coreNo);
1160 
1161 /* Please see man pages for details
1162 
1163 */
1164 NN_EXTERN_C void nnosThreadFinalize(nnosThread* this_);
1165 
1166 /* Please see man pages for details
1167 
1168 */
1169 NN_EXTERN_C void nnosThreadJoin(nnosThread* this_);
1170 
1171 /* Please see man pages for details
1172 
1173 */
1174 NN_EXTERN_C void nnosThreadSleep(s64 nanoSeconds);
1175 
1176 /* Please see man pages for details
1177 
1178 */
1179 NN_EXTERN_C void nnosThreadYield(void);
1180 
1181 /* Please see man pages for details
1182 
1183 */
1184 NN_EXTERN_C bit32 nnosThreadGetCurrentId(void);
1185 
1186 /* Please see man pages for details
1187 
1188 */
1189 NN_EXTERN_C s32 nnosThreadGetPriority(const nnosThread* this_);
1190 
1191 /* Please see man pages for details
1192 
1193 */
1194 NN_EXTERN_C s32 nnosThreadGetCurrentPriority(void);
1195 
1196 /* Please see man pages for details
1197 
1198 */
1199 NN_EXTERN_C void nnosThreadChangePriority(nnosThread* this_, s32 priority);
1200 
1201 /* Please see man pages for details
1202 
1203 */
1204 NN_EXTERN_C void nnosThreadChangeCurrentPriority(s32 priority);
1205 
1206     // Get/set the thread affinity
1207 
1208 /*
1209 
1210 */
1211 //NN_EXTERN_C void nnosThreadGetAffinityMask(const nnosThread* this_, bit8* pAffinityMask, s32 numProcessor);
1212 
1213 /*
1214 
1215 */
1216 //NN_EXTERN_C void nnosThreadGetCurrentAffinityMask(bit8* pAffinityMask, s32 numProcessor);
1217 
1218 /*
1219 
1220 */
1221 //NN_EXTERN_C void nnosThreadGetDefaultAffinityMask(bit8* pAffinityMask, s32 numProcessor);
1222 
1223 /*
1224 
1225 */
1226 //NN_EXTERN_C void nnosThreadChangeAffinityMask(nnosThread* this_, const bit8* pAffinityMask, s32 numProcessor);
1227 
1228 /*
1229 
1230 */
1231 //NN_EXTERN_C void nnosThreadChangeCurrentAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
1232 
1233 /*
1234 
1235 */
1236 //NN_EXTERN_C void nnosThreadSetDefaultAffinityMask(const bit8* pAffinityMask, s32 numProcessor);
1237 
1238     // Get/set IdealProcessor
1239 
1240 /* Please see man pages for details
1241 
1242 */
1243 NN_EXTERN_C s32 nnosThreadGetIdealProcessor(const nnosThread* this_);
1244 
1245 /*
1246 
1247 */
1248 //NN_EXTERN_C s32 nnosThreadGetCurrentIdealProcessor(void);
1249 
1250 /* Please see man pages for details
1251 
1252 */
1253 NN_EXTERN_C s32 nnosThreadGetDefaultIdealProcessor(void);
1254 
1255 /*
1256 
1257 */
1258 //NN_EXTERN_C void nnosThreadChangeIdealProcessor(nnosThread* this_, s32 coreNo);
1259 
1260 /*
1261 
1262 */
1263 //NN_EXTERN_C void nnosThreadChangeCurrentIdealProcessor(s32 coreNo);
1264 
1265 /*
1266 
1267 */
1268 //NN_EXTERN_C void nnosThreadSetDefaultIdealProcessor(s32 coreNo);
1269 
1270     // Get the processor number operating the current thread
1271 
1272 /* Please see man pages for details
1273 
1274 */
1275 NN_EXTERN_C s32 nnosThreadGetCurrentProcessorNumber(void);
1276 
1277 /* Please see man pages for details
1278 
1279 */
1280 NN_EXTERN_C bit32 nnosThreadGetId(nnosThread* this_);
1281 
1282 /* Please see man pages for details
1283 
1284 */
1285 NN_EXTERN_C bool nnosThreadIsAlive(nnosThread* this_);
1286 
1287 /* Please see man pages for details
1288 
1289 */
1290 NN_EXTERN_C nnosThread* nnosThreadGetMainThread(void);
1291 
1292 /*
1293 
1294 
1295 */
1296 
1297 /* NN_OS_THREAD_H_ */
1298 #endif
1299 
1300