ae2f_docs
Thrd.def.cc
1/**
2 * @file Thrd.auto.h
3 *
4 * @brief
5 * Contains various implementations which could be various
6 *
7 * @details
8 *
9 * Following operations would be implemented
10 *
11 * create
12 * join
13 * sleep
14 * yield
15 * delete
16 *
17 * */
18
19#ifndef ae2f_Sys_Thrd_auto_h
20#include <ae2f/Sys/Thrd.h>
21#define ae2f_Sys_Thrd_auto_h
22
23
25#else
26#include <ae2f/Macro.h>
27#endif
28
29struct timespec;
30
31#if ae2f_Sys__linux(!)0
32
33#include <errno.h>
34
35ae2f_MAC() __linux_ae2f_SysThrdMk_imp_call(
36 ae2f_eSysThrd_t ret_stat,
37 ae2f_SysThrdID_t ret_tid,
38 ae2f_SysThrdFn_t* const prm_func,
39 _ae2f_SysThrdRunnerPrm_t* const prm_stck,
40 void* const prm_stcktop,
41 size_t prm_stcksz
42 )
43{
44 (ret_tid) = clone(
45 ae2f_reinterpret_cast(ae2f_SysThrdFn_t*, _ae2f_SysThrdRunner)
46 , (prm_stcktop)
47 , (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
48 , (prm_stck)
49 );
50
51 if((ret_tid) == -1) {
52 (ret_stat) = ae2f_eSysThrdErr;
53
54 } else if((ret_tid) == 0)
55 {
56 syscall(SYS_exit, 0);
57 }
58 else
59 {
60 (ret_stat) = ae2f_eSysThrdSuccess;
61
62 }
63}
64
65
66
67/**
68 * @brief
69 * Create a thread.
70 * */
71ae2f_MAC() ae2f_SysThrdMk_imp(
72 ae2f_eSysThrd_t ret_stat,
73 ae2f_SysThrd ret_thrd,
74 ae2f_SysThrdFn_t* const prm_func,
75 void* const prm_arg,
76 const size_t prm_stcksz
77 )
78{
79 (ret_thrd).m_stck.m_void = mmap(
80 NULL, ((ret_thrd).m_stcksz = (
81 (prm_stcksz)
82 + sizeof(_ae2f_SysThrdRunnerPrm_t)
83 + sizeof(void*)
84 )
85 )
86 , PROT_READ | PROT_WRITE
87 , MAP_PRIVATE | MAP_STACK | MAP_ANONYMOUS
88 , -1, 0
89 );
90
91 if(MAP_FAILED == (ret_thrd).m_stck.m_void || !(ret_thrd).m_stck.m_void) {
92 (ret_stat) = ae2f_eSysThrdMemOut;
93 (ret_thrd).m_stck.m_void = NULL;
94 }
95 else {
96 (ret_thrd).m_stck.m_prm->m_arg = (prm_arg);
97 (ret_thrd).m_stck.m_prm->m_fn = (prm_func);
98 (ret_thrd).m_stck.m_prm->m_stcksz = (ret_thrd).m_stcksz;
99
100 ___linux_ae2f_SysThrdMk_imp_call(
101 ret_stat, (ret_thrd).m_id
102 , prm_func
103 , (ret_thrd).m_stck.m_prm
104 , __ae2f_SysThrdStckTopOper(((ret_thrd).m_stck.m_char), (prm_stcksz))
105 , prm_stcksz
106 );
107
108 if(ret_stat != ae2f_eSysThrdSuccess)
109 {
110 munmap(
111 (ret_thrd).m_stck.m_void
112 , (ret_thrd).m_stcksz
113 );
114 (ret_thrd).m_stck.m_void = NULL;
115 }
116 }
117}
118
119
120ae2f_MAC() ae2f_SysThrdJoin_imp(
121 ae2f_eSysThrd_t ret_stat,
122 ae2f_SysThrdRes_t ret_rtn,
123 const ae2f_SysThrd prm_thrd
124 )
125{
126 ae2f_SysFtxRet_t v_res;
127
128 unless((prm_thrd).m_stck.m_void) {
129 (ret_stat) = ae2f_eSysThrdErr;
130 }
131 else {
132 do {
133 if((prm_thrd).m_stck.m_prm->m_done)
134 {
135 break;
136 }
137
139 v_res
140 , &(prm_thrd).m_stck.m_prm->m_done
141 , 0
142 );
143
144 (ret_rtn) = (prm_thrd).m_stck.m_prm->m_ret;
145 munmap((prm_thrd).m_stck.m_void, (prm_thrd).m_stcksz);
146 } while(0);
147
148 if(v_res)
149 {
150 (ret_stat) = ae2f_eSysThrdErr;
151 } else {
152 (ret_stat) = ae2f_eSysThrdSuccess;
153 }
154 }
155}
156
157ae2f_MAC() ae2f_SysThrdYield_imp()
158{
159 syscall(SYS_sched_yield);
160}
161
162ae2f_MAC() ae2f_SysThrdSleep_imp(
163 int ret_stat
164 , const struct timespec * const prm_req
165 , struct timespec * const prm_rem
166 )
167{
168 (ret_stat) = syscall(SYS_nanosleep, prm_req, prm_rem);
169}
170
171#elif ae2f_Sys_WIN(!)0
172ae2f_MAC() ae2f_SysThrdMk_imp(
173 ae2f_eSysThrd_t ret_stat,
174 ae2f_SysThrd ret_thrd,
175 ae2f_SysThrdFn_t* const prm_func,
176 void* const prm_arg,
177 const size_t prm_stcksz
178 )
179{
180 (ret_thrd).m_id =
181 CreateThread(
182 NULL
183 , prm_stcksz
184 , prm_func
185 , prm_arg
186 , STACK_SIZE_PARAM_IS_A_RESERVATION
187 , NULL
188 );
189
190 unless((ret_thrd).m_id) {
191 (ret_stat) = ae2f_eSysThrdErr;
192 } else
193 (ret_stat) = ae2f_eSysThrdSuccess;
194}
195
196ae2f_MAC() ae2f_SysThrdJoin_imp(
197 ae2f_eSysThrd_t ret_stat,
198 ae2f_SysThrdRes_t ret_rtn,
199 const ae2f_SysThrd prm_thrd
200 )
201{
202 (ret_stat)
203 = (
204 WaitForSingleObject((prm_thrd).m_id, INFINITE)
205 && GetExitCodeThread((prm_thrd).m_id, &(ret_rtn))
206 && CloseHandle((prm_thrd).m_id)
207 ) ? ae2f_eSysThrdSuccess : ae2f_eSysThrdErr;
208}
209
210
211
212ae2f_MAC() ae2f_SysThrdYield_imp()
213{
214 SwitchToThread();
215}
216
217ae2f_MAC() ae2f_SysThrdSleep_imp(
218 int ret_stat
219 , const struct timespec * const prm_req
220 , struct timespec * const prm_rem
221 )
222{
223 if (
224 (prm_req) == NULL ||
225 (prm_req)->tv_sec < 0 ||
226 (prm_req)->tv_nsec < 0 ||
227 (prm_req)->tv_nsec >= 1000000000
228 )
229 {
230 SetLastError(ERROR_INVALID_PARAMETER);
231 (ret_stat) = -1;
232 } else do {
233 Sleep((DWORD)((prm_req)->tv_sec * 1000 + (prm_req)->tv_nsec / 1000000));
234 if ((prm_rem) != NULL) {
235 (prm_rem)->tv_sec = 0;
236 (prm_rem)->tv_nsec = 0;
237 }
238 (ret_stat) = 0;
239 } while(0);
240}
241
242
243
244#else
245
246/**
247 * @param prm_stacksz_unused is not used here.
248 * */
249ae2f_MAC() ae2f_SysThrdMk_imp(
250 ae2f_eSysThrd_t ret_stat,
251 ae2f_SysThrd ret_thrd,
252 ae2f_SysThrdFn_t* const prm_func,
253 void* const prm_arg,
254 const size_t prm_stcksz_unused
255 )
256{
257 (ret_stat) = pthread_create(
258 &(ret_thrd).m_id
259 , ae2f_reinterpret_cast(const pthread_attr_t*, NULL)
260 , prm_func
261 , prm_arg
262 );
263
264 switch(ret_stat) {
265 case 0:
266 (ret_stat) = ae2f_eSysThrdSuccess;
267 break;
268
269 case EAGAIN:
270 (ret_stat) = ae2f_eSysThrdMemOut;
271 break;
272
273 case EINVAL:
274 case EPERM:
275 default:
276 (ret_stat) = ae2f_eSysThrdErr;
277 break;
278 }
279}
280
281ae2f_MAC() ae2f_SysThrdJoin_imp(
282 ae2f_eSysThrd_t ret_stat,
283 ae2f_SysThrdRes_t ret_rtn,
284 ae2f_SysThrd ref_thrd
285 )
286{
287 switch(pthread_join((ref_thrd).m_id, &(ret_rtn)))
288 {
289 case EDEADLK:
290 (ret_stat) = ae2f_eSysThrdBusy;
291 break;
292 case EINVAL:
293 (ret_stat) = (ae2f_eSysThrdErr);
294 break;
295 case ESRCH:
296 (ret_stat) = (ae2f_eSysThrdMemOut);
297 break;
298 case 0:
299 (ret_stat) = ae2f_eSysThrdSuccess;
300 break;
301 }
302}
303
304
305ae2f_MAC() ae2f_SysThrdSleep_imp(
306 int ret_stat
307 , const struct timespec * const prm_req
308 , struct timespec * const prm_rem
309 )
310{
311 (ret_stat) = nanosleep(prm_req, prm_rem);
312}
313
314ae2f_MAC() ae2f_SysThrdYield_imp()
315{
316 sched_yield();
317}
318
319#endif
320#endif
#define ae2f_reinterpret_cast(t, v)
Definition Cast.h:52
#define unless(...)
Invokes when condition is false.
Definition Cast.h:103
#define __ae2f_MACRO_GENERATED
Definition Conv.auto.h:2
#define _ae2f_SysFtxWait(ret_err, prm_uaddr, prm_val)
Definition Ftx.auto.h:109
_ae2f_SysFtxRet_t ae2f_SysFtxRet_t
State for futex operation.
Definition Ftx.h:22
#define ae2f_Sys__linux
Definition Sys.h:14
@ ae2f_eSysThrdMemOut
Definition Thrd.h:38
@ ae2f_eSysThrdSuccess
Definition Thrd.h:35
_ae2f_SysThrdRes_t ae2f_SysThrdRes_t
Return type for thread.
Definition Thrd.h:14
ae2f_SysThrdRes_t ae2f_SysThrdFn_t(ae2f_SysThrdPrm_t)
Thread starting function type.
Definition Thrd.h:25
_ae2f_SysThrdID_t ae2f_SysThrdID_t
Thread ID.
Definition Thrd.h:22
#define ae2f_MAC(...)
Definition mac.h:28