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), ¶m, 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), ¶m, 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), ¶m, 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), ¶m, 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), ¶m, 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), ¶m, 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), ¶m, 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), ¶m, 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