Line data Source code
1 1 : /**
2 : * @file arch/thread.c
3 : *
4 : * @brief Generic architecture management facilities
5 : *
6 : * This module provides generic facilities for thread and core management.
7 : * In particular, helper functions to startup worker threads are exposed,
8 : * and a function to synchronize multiple threads on a software barrier.
9 : *
10 : * The software barrier also offers a leader election facility, so that
11 : * once all threads are synchronized on the barrier, the function returns
12 : * true to only one of them.
13 : *
14 : * SPDX-FileCopyrightText: 2008-2021 HPDCS Group <rootsim@googlegroups.com>
15 : * SPDX-License-Identifier: GPL-3.0-only
16 : */
17 : #include <arch/thread.h>
18 :
19 : /**
20 : * @fn thread_start(thr_id_t *thr_p, thr_run_fnc t_fnc, void *t_fnc_arg)
21 : * @brief Creates a thread
22 : * @param thr_p A pointer to the location where the created thread identifier
23 : * will be copied
24 : * @param t_fnc The new thread entry point
25 : * @param t_fnc_arg A pointer to the argument to be passed to the new thread
26 : * entry point
27 : * @return 0 if successful, -1 otherwise
28 : */
29 :
30 : /**
31 : * @fn thread_affinity_set(thr_id_t thr, unsigned core)
32 : * @brief Sets a core affinity for a thread
33 : * @param thr The identifier of the thread targeted for the affinity change
34 : * @param core The core id where the target thread will be pinned on
35 : * @return 0 if successful, -1 otherwise
36 : */
37 :
38 : /**
39 : * @fn thread_wait(thr_id_t thr, thr_ret_t *ret)
40 : * @brief Wait for specified thread to complete execution
41 : * @param thr The identifier of the thread to wait for
42 : * @param ret A pointer to the location where the return value will be copied,
43 : * or alternatively NULL
44 : * @return 0 if successful, -1 otherwise
45 : */
46 :
47 : /**
48 : * @fn thread_cores_count(void)
49 : * @brief Computes the count of available cores on the machine
50 : * @return the count of the processing cores available on the machine
51 : */
52 :
53 : #ifdef __POSIX
54 : #include <sched.h>
55 : #include <signal.h>
56 : #include <unistd.h>
57 :
58 : #ifdef __MACOS
59 : #include <mach/thread_act.h>
60 :
61 : int thread_affinity_set(thr_id_t thr, unsigned core)
62 : {
63 : thread_affinity_policy_data_t policy = {core};
64 : thread_port_t mach_thread = pthread_mach_thread_np(thr);
65 : kern_return_t ret = thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY,
66 : (thread_policy_t) &policy, 1);
67 : return -(ret != KERN_SUCCESS);
68 : }
69 :
70 : #else
71 :
72 : int thread_affinity_set(thr_id_t thr, unsigned core)
73 : {
74 : cpu_set_t cpuset;
75 : CPU_ZERO(&cpuset);
76 : CPU_SET(core, &cpuset);
77 : return -(pthread_setaffinity_np(thr, sizeof(cpuset), &cpuset) != 0);
78 : }
79 :
80 : #endif
81 :
82 : unsigned thread_cores_count(void)
83 : {
84 : long ret = sysconf(_SC_NPROCESSORS_ONLN);
85 : return ret < 1 ? 1 : (unsigned)ret;
86 : }
87 :
88 : int thread_start(thr_id_t *thr_p, thr_run_fnc t_fnc, void *t_fnc_arg)
89 : {
90 : return -(pthread_create(thr_p, NULL, t_fnc, t_fnc_arg) != 0);
91 : }
92 :
93 : int thread_wait(thr_id_t thr, thr_ret_t *ret)
94 : {
95 : return -(pthread_join(thr, ret) != 0);
96 : }
97 :
98 : #endif
99 :
100 : #ifdef __WINDOWS
101 : #define WIN32_LEAN_AND_MEAN
102 : #ifndef _WIN32_WINNT
103 : #define _WIN32_WINNT _WIN32_WINNT_NT4
104 : #endif
105 : #include <windows.h>
106 :
107 : unsigned thread_cores_count(void)
108 : {
109 : SYSTEM_INFO sys_info;
110 : GetSystemInfo(&sys_info);
111 : return sys_info.dwNumberOfProcessors;
112 : }
113 :
114 : int thread_start(thr_id_t *thr_p, thr_run_fnc t_fnc, void *t_fnc_arg)
115 : {
116 : *thr_p = CreateThread(NULL, 0, t_fnc, arg, 0, NULL);
117 : return -(*thr_p == NULL);
118 : }
119 :
120 : int thread_affinity_set(thr_id_t thr, unsigned core)
121 : {
122 : return -(SetThreadAffinityMask(thr, 1 << core) != 0);
123 : }
124 :
125 : int thread_wait(thr_id_t thr, thr_ret_t *ret)
126 : {
127 : if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
128 : return -1;
129 :
130 : if (ret)
131 : return -(GetExitCodeThread(thr, ret) == 0);
132 :
133 : return 0;
134 : }
135 :
136 : #endif
|