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