1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * Threading subsystem implementation file. *
7 * Copyright (C) 2011-2019 Oleh Derevenko. All rights reserved. *
8 * e-mail: odar@eleks.com (change all "a" to "e") *
10 * This library is free software; you can redistribute it and/or *
11 * modify it under the terms of EITHER: *
12 * (1) The GNU Lesser General Public License as published by the Free *
13 * Software Foundation; either version 2.1 of the License, or (at *
14 * your option) any later version. The text of the GNU Lesser *
15 * General Public License is included with this library in the *
17 * (2) The BSD-style license that is included with this library in *
18 * the file LICENSE-BSD.TXT. *
20 * This library is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
23 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
25 *************************************************************************/
28 * Subsystem APIs implementation for built-in threading support provider.
32 #include <ode/common.h>
33 #include <ode/threading_impl.h>
35 #include "threading_impl_posix.h"
36 #include "threading_impl_win.h"
37 #include "threading_impl.h"
40 static dMutexGroupID
AllocMutexGroup(dThreadingImplementationID impl
, dmutexindex_t Mutex_count
, const char *const *Mutex_names_ptr
/*=NULL*/);
41 static void FreeMutexGroup(dThreadingImplementationID impl
, dMutexGroupID mutex_group
);
42 static void LockMutexGroupMutex(dThreadingImplementationID impl
, dMutexGroupID mutex_group
, dmutexindex_t mutex_index
);
43 // static int TryLockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index);
44 static void UnlockMutexGroupMutex(dThreadingImplementationID impl
, dMutexGroupID mutex_group
, dmutexindex_t mutex_index
);
46 static dCallWaitID
AllocThreadedCallWait(dThreadingImplementationID impl
);
47 static void ResetThreadedCallWait(dThreadingImplementationID impl
, dCallWaitID call_wait
);
48 static void FreeThreadedCallWait(dThreadingImplementationID impl
, dCallWaitID call_wait
);
50 static void PostThreadedCall(
51 dThreadingImplementationID impl
, int *out_summary_fault
/*=NULL*/,
52 dCallReleaseeID
*out_post_releasee
/*=NULL*/, ddependencycount_t dependencies_count
, dCallReleaseeID dependent_releasee
/*=NULL*/,
53 dCallWaitID call_wait
/*=NULL*/,
54 dThreadedCallFunction
*call_func
, void *call_context
, dcallindex_t instance_index
,
55 const char *call_name
/*=NULL*/);
56 static void AlterThreadedCallDependenciesCount(
57 dThreadingImplementationID impl
, dCallReleaseeID target_releasee
,
58 ddependencychange_t dependencies_count_change
);
59 static void WaitThreadedCall(
60 dThreadingImplementationID impl
, int *out_wait_status
/*=NULL*/,
61 dCallWaitID call_wait
, const dThreadedWaitTime
*timeout_time_ptr
/*=NULL*/,
62 const char *wait_name
/*=NULL*/);
64 static unsigned RetrieveThreadingThreadCount(dThreadingImplementationID impl
);
65 static int PreallocateResourcesForThreadedCalls(dThreadingImplementationID impl
, ddependencycount_t max_simultaneous_calls_estimate
);
68 static const dxThreadingFunctionsInfo g_builtin_threading_functions
=
70 sizeof(dxThreadingFunctionsInfo
), // unsigned struct_size;
72 &AllocMutexGroup
, // dMutexGroupAllocFunction *alloc_mutex_group;
73 &FreeMutexGroup
, // dMutexGroupFreeFunction *free_mutex_group;
74 &LockMutexGroupMutex
, // dMutexGroupMutexLockFunction *lock_group_mutex;
75 &UnlockMutexGroupMutex
, // dMutexGroupMutexUnlockFunction *unlock_group_mutex;
77 &AllocThreadedCallWait
, // dThreadedCallWaitAllocFunction *alloc_call_wait;
78 &ResetThreadedCallWait
, // dThreadedCallWaitResetFunction *reset_call_wait;
79 &FreeThreadedCallWait
, // dThreadedCallWaitFreeFunction *free_call_wait;
81 &PostThreadedCall
, // dThreadedCallPostFunction *post_call;
82 &AlterThreadedCallDependenciesCount
, // dThreadedCallDependenciesCountAlterFunction *alter_call_dependencies_count;
83 &WaitThreadedCall
, // dThreadedCallWaitFunction *wait_call;
85 &RetrieveThreadingThreadCount
, // dThreadingImplThreadCountRetrieveFunction *retrieve_thread_count;
86 &PreallocateResourcesForThreadedCalls
, // dThreadingImplResourcesForCallsPreallocateFunction *preallocate_resources_for_calls;
88 // &TryLockMutexGroupMutex, // dMutexGroupMutexTryLockFunction *trylock_group_mutex;
92 /*extern */dThreadingImplementationID
dThreadingAllocateSelfThreadedImplementation()
94 dxSelfThreadedThreading
*threading
= new dxSelfThreadedThreading();
96 if (threading
!= NULL
&& !threading
->InitializeObject())
102 dxIThreadingImplementation
*impl
= threading
;
103 return (dThreadingImplementationID
)impl
;
106 /*extern */dThreadingImplementationID
dThreadingAllocateMultiThreadedImplementation()
108 #if dBUILTIN_THREADING_IMPL_ENABLED
109 dxMultiThreadedThreading
*threading
= new dxMultiThreadedThreading();
111 if (threading
!= NULL
&& !threading
->InitializeObject())
117 dxIThreadingImplementation
*threading
= NULL
;
118 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
120 dxIThreadingImplementation
*impl
= threading
;
121 return (dThreadingImplementationID
)impl
;
124 /*extern */const dThreadingFunctionsInfo
*dThreadingImplementationGetFunctions(dThreadingImplementationID impl
)
126 #if dBUILTIN_THREADING_IMPL_ENABLED
127 dAASSERT(impl
!= NULL
);
128 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
130 const dThreadingFunctionsInfo
*functions
= NULL
;
132 #if !dBUILTIN_THREADING_IMPL_ENABLED
134 #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED
136 functions
= &g_builtin_threading_functions
;
142 /*extern */void dThreadingImplementationShutdownProcessing(dThreadingImplementationID impl
)
144 #if dBUILTIN_THREADING_IMPL_ENABLED
145 dAASSERT(impl
!= NULL
);
146 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
148 #if !dBUILTIN_THREADING_IMPL_ENABLED
150 #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED
152 ((dxIThreadingImplementation
*)impl
)->ShutdownProcessing();
156 /*extern */void dThreadingImplementationCleanupForRestart(dThreadingImplementationID impl
)
158 #if dBUILTIN_THREADING_IMPL_ENABLED
159 dAASSERT(impl
!= NULL
);
160 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
162 #if !dBUILTIN_THREADING_IMPL_ENABLED
164 #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED
166 ((dxIThreadingImplementation
*)impl
)->CleanupForRestart();
170 /*extern */void dThreadingFreeImplementation(dThreadingImplementationID impl
)
174 ((dxIThreadingImplementation
*)impl
)->FreeInstance();
179 /*extern */void dExternalThreadingServeMultiThreadedImplementation(dThreadingImplementationID impl
,
180 dThreadReadyToServeCallback
*readiness_callback
/*=NULL*/, void *callback_context
/*=NULL*/)
182 #if dBUILTIN_THREADING_IMPL_ENABLED
183 dAASSERT(impl
!= NULL
);
184 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
186 #if !dBUILTIN_THREADING_IMPL_ENABLED
188 #endif // #if !dBUILTIN_THREADING_IMPL_ENABLED
190 ((dxIThreadingImplementation
*)impl
)->StickToJobsProcessing(readiness_callback
, callback_context
);
195 //////////////////////////////////////////////////////////////////////////
197 static dMutexGroupID
AllocMutexGroup(dThreadingImplementationID impl
, dmutexindex_t Mutex_count
, const char *const *Mutex_names_ptr
/*=NULL*/)
199 (void)Mutex_names_ptr
; // unused
200 dIMutexGroup
*mutex_group
= ((dxIThreadingImplementation
*)impl
)->AllocMutexGroup(Mutex_count
);
201 return (dMutexGroupID
)mutex_group
;
204 static void FreeMutexGroup(dThreadingImplementationID impl
, dMutexGroupID mutex_group
)
206 ((dxIThreadingImplementation
*)impl
)->FreeMutexGroup((dIMutexGroup
*)mutex_group
);
209 static void LockMutexGroupMutex(dThreadingImplementationID impl
, dMutexGroupID mutex_group
, dmutexindex_t mutex_index
)
211 ((dxIThreadingImplementation
*)impl
)->LockMutexGroupMutex((dIMutexGroup
*)mutex_group
, mutex_index
);
214 // static int TryLockMutexGroupMutex(dThreadingImplementationID impl, dMutexGroupID mutex_group, dmutexindex_t mutex_index)
216 // bool trylock_result = ((dxIThreadingImplementation *)impl)->TryLockMutexGroupMutex((dIMutexGroup *)mutex_group, mutex_index);
217 // return trylock_result;
220 static void UnlockMutexGroupMutex(dThreadingImplementationID impl
, dMutexGroupID mutex_group
, dmutexindex_t mutex_index
)
222 ((dxIThreadingImplementation
*)impl
)->UnlockMutexGroupMutex((dIMutexGroup
*)mutex_group
, mutex_index
);
226 static dCallWaitID
AllocThreadedCallWait(dThreadingImplementationID impl
)
228 dxICallWait
*call_wait
= ((dxIThreadingImplementation
*)impl
)->AllocACallWait();
229 return (dCallWaitID
)call_wait
;
232 static void ResetThreadedCallWait(dThreadingImplementationID impl
, dCallWaitID call_wait
)
234 ((dxIThreadingImplementation
*)impl
)->ResetACallWait((dxICallWait
*)call_wait
);
237 static void FreeThreadedCallWait(dThreadingImplementationID impl
, dCallWaitID call_wait
)
239 ((dxIThreadingImplementation
*)impl
)->FreeACallWait((dxICallWait
*)call_wait
);
243 static void PostThreadedCall(
244 dThreadingImplementationID impl
, int *out_summary_fault
/*=NULL*/,
245 dCallReleaseeID
*out_post_releasee
/*=NULL*/, ddependencycount_t dependencies_count
, dCallReleaseeID dependent_releasee
/*=NULL*/,
246 dCallWaitID call_wait
/*=NULL*/,
247 dThreadedCallFunction
*call_func
, void *call_context
, dcallindex_t instance_index
,
248 const char *call_name
/*=NULL*/)
250 (void)call_name
; // unused
251 ((dxIThreadingImplementation
*)impl
)->ScheduleNewJob(out_summary_fault
, out_post_releasee
,
252 dependencies_count
, dependent_releasee
, (dxICallWait
*)call_wait
, call_func
, call_context
, instance_index
);
255 static void AlterThreadedCallDependenciesCount(
256 dThreadingImplementationID impl
, dCallReleaseeID target_releasee
,
257 ddependencychange_t dependencies_count_change
)
259 ((dxIThreadingImplementation
*)impl
)->AlterJobDependenciesCount(target_releasee
, dependencies_count_change
);
262 static void WaitThreadedCall(
263 dThreadingImplementationID impl
, int *out_wait_status
/*=NULL*/,
264 dCallWaitID call_wait
, const dThreadedWaitTime
*timeout_time_ptr
/*=NULL*/,
265 const char *wait_name
/*=NULL*/)
267 (void)wait_name
; // unused
268 ((dxIThreadingImplementation
*)impl
)->WaitJobCompletion(out_wait_status
, (dxICallWait
*)call_wait
, timeout_time_ptr
);
272 static unsigned RetrieveThreadingThreadCount(dThreadingImplementationID impl
)
274 return ((dxIThreadingImplementation
*)impl
)->RetrieveActiveThreadsCount();
277 static int PreallocateResourcesForThreadedCalls(dThreadingImplementationID impl
, ddependencycount_t max_simultaneous_calls_estimate
)
279 return ((dxIThreadingImplementation
*)impl
)->PreallocateJobInfos(max_simultaneous_calls_estimate
);