Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeale Ferguson <neale@sinenomine.net>2016-06-20 17:26:51 +0300
committerAleksey Kliger (λgeek) <akliger@gmail.com>2016-06-20 17:26:51 +0300
commit89bf42b05f064ec66d142af0e8c92e45b26c821f (patch)
tree0830e9407fce743a30ee037782a47c497b2a8f03
parent081781dd93463f369922475b3c19dd1170579240 (diff)
Use thread priority at thread start time (#3123)new-logging
* An enhancement to the thread priority work added earlier. This will support starting a thread with a specified priority. Currently, the thread will start with the priority of the creator. The semantics of threads allow you to specify the priority of a thread before it has started. Therefore, we take note of this value at thread creation time. * Missed committing this file the first time * Correct typo * Fix creation_flags reference * MonoThreadParm really should not be in objects-internal * Place priority in MonoInternalThread where it can be accessed by GetThreadPriority(). This enablses the priority to be set/retrieved before the thread is started. It also ensures that new threads default to a priority of THREAD_PRIORITY_NORMAL rather than inheriting the parent thread's priority. * Revert changes to MonoInternalThread/Thread.cs. Properly use the handle for thread lookup. Initialize priority at thread creation time. Use stored value of priority if thread has not been started. * Add code to handle retrieving the thread priority from a started thread that had been set before thread had started. This is necessary as before the thread is started the priority value can be manipulated. This value is stored in the MonoThread structure. Before the thread is started the value can be interrogated so we return this value rather than invoking the GetThreadPriority() API. When a thread is started this value is used to set the threads priority (if scheduling policy is SCHED_FIFO or SCHED_RR). For POSIX threads, after the thread is started we now keep the priority in the _Wapi_thread structure which is located via the thread handle. This structure doesn't exist until after the thread is started so we can't store the value there but after we can cache the priority value there and return it for non-SCHED_[RR|FIFO] threads. This way the expected value will always be set and returned by ThreadPriority property (currently for these threads it will simply return Normal). A test case has been added to the mono/tests directory. * Use a copy of creation_flags so local modifications aren't propagated * Use pthread_setschedparam as OSX doesn't support pthread_setschedprio
-rw-r--r--mono/io-layer/handles.c3
-rw-r--r--mono/io-layer/thread-private.h1
-rw-r--r--mono/io-layer/threads.h13
-rw-r--r--mono/io-layer/wthreads.c49
-rw-r--r--mono/metadata/appdomain.c6
-rw-r--r--mono/metadata/attach.c7
-rw-r--r--mono/metadata/object-internals.h1
-rw-r--r--mono/metadata/threads.c21
-rw-r--r--mono/mini/aot-compiler.c6
-rw-r--r--mono/mini/debugger-agent.c7
-rw-r--r--mono/tests/Makefile.am3
-rw-r--r--mono/tests/priority.cs88
-rw-r--r--mono/utils/mono-threads-posix.c25
-rw-r--r--mono/utils/mono-threads-windows.c5
-rw-r--r--mono/utils/mono-threads.c4
-rw-r--r--mono/utils/mono-threads.h13
16 files changed, 210 insertions, 42 deletions
diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c
index 814d216fe5c..a1df5bc4c60 100644
--- a/mono/io-layer/handles.c
+++ b/mono/io-layer/handles.c
@@ -708,7 +708,8 @@ gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
return(GUINT_TO_POINTER(fd));
}
-gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
+gboolean
+_wapi_lookup_handle (gpointer handle, WapiHandleType type,
gpointer *handle_specific)
{
struct _WapiHandleUnshared *handle_data;
diff --git a/mono/io-layer/thread-private.h b/mono/io-layer/thread-private.h
index 3cf5535c5b8..a950e5e6da8 100644
--- a/mono/io-layer/thread-private.h
+++ b/mono/io-layer/thread-private.h
@@ -23,6 +23,7 @@ struct _WapiHandle_thread
{
pthread_t id;
GPtrArray *owned_mutexes;
+ gint32 priority;
};
typedef struct _WapiHandle_thread WapiHandle_thread;
diff --git a/mono/io-layer/threads.h b/mono/io-layer/threads.h
index a00569d1a99..f26cefb548e 100644
--- a/mono/io-layer/threads.h
+++ b/mono/io-layer/threads.h
@@ -25,16 +25,27 @@ G_BEGIN_DECLS
#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3ff)
typedef guint32 (*WapiThreadStart)(gpointer);
+
+typedef enum {
+ THREAD_PRIORITY_LOWEST = -2,
+ THREAD_PRIORITY_BELOW_NORMAL = -1,
+ THREAD_PRIORITY_NORMAL = 0,
+ THREAD_PRIORITY_ABOVE_NORMAL = 1,
+ THREAD_PRIORITY_HIGHEST = 2
+} WapiThreadPriority;
gpointer wapi_create_thread_handle (void);
void wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus);
void wapi_ref_thread_handle (gpointer handle);
gpointer wapi_get_current_thread_handle (void);
-char* wapi_current_thread_desc (void);
+char *wapi_current_thread_desc (void);
extern gint32 GetThreadPriority (gpointer handle);
extern gboolean SetThreadPriority (gpointer handle, gint32 priority);
+extern int wapi_thread_priority_to_posix_priority (WapiThreadPriority, int);
+extern void wapi_init_thread_info_priority (gpointer, gint32);
+
G_END_DECLS
#endif /* _WAPI_THREADS_H_ */
diff --git a/mono/io-layer/wthreads.c b/mono/io-layer/wthreads.c
index 304fd35adf8..26246bbaa08 100644
--- a/mono/io-layer/wthreads.c
+++ b/mono/io-layer/wthreads.c
@@ -46,14 +46,6 @@ struct _WapiHandleOps _wapi_thread_ops = {
NULL, /* special_wait */
NULL /* prewait */
};
-
-typedef enum {
- THREAD_PRIORITY_LOWEST = -2,
- THREAD_PRIORITY_BELOW_NORMAL = -1,
- THREAD_PRIORITY_NORMAL = 0,
- THREAD_PRIORITY_ABOVE_NORMAL = 1,
- THREAD_PRIORITY_HIGHEST = 2
-} WapiThreadPriority;
static mono_once_t thread_ops_once = MONO_ONCE_INIT;
@@ -227,6 +219,24 @@ _wapi_thread_disown_mutex (gpointer mutex)
}
/**
+ * wapi_init_thread_info_priority:
+ * @param handle: The thread handle to set.
+ * @param priority: Priority to initialize with
+ *
+ * Initialize the priority field of the thread info
+ */
+void
+wapi_init_thread_info_priority (gpointer handle, gint32 priority)
+{
+ struct _WapiHandle_thread *thread_handle = NULL;
+ gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ (gpointer *)&thread_handle);
+
+ if (ok == TRUE)
+ thread_handle->priority = priority;
+}
+
+/**
* _wapi_thread_posix_priority_to_priority:
*
* Convert a POSIX priority to a WapiThreadPriority.
@@ -280,14 +290,14 @@ _wapi_thread_posix_priority_to_priority (int sched_priority, int policy)
}
/**
- * _wapi_thread_priority_to_posix_priority:
+ * wapi_thread_priority_to_posix_priority:
*
* Convert a WapiThreadPriority to a POSIX priority.
* priority is a WapiThreadPriority,
* policy is the current scheduling policy
*/
-static int
-_wapi_thread_priority_to_posix_priority (WapiThreadPriority priority, int policy)
+int
+wapi_thread_priority_to_posix_priority (WapiThreadPriority priority, int policy)
{
/* Necessary to get valid priority range */
#ifdef _POSIX_PRIORITY_SCHEDULING
@@ -351,19 +361,21 @@ _wapi_thread_priority_to_posix_priority (WapiThreadPriority priority, int policy
gint32
GetThreadPriority (gpointer handle)
{
- struct _WapiHandle_thread *thread_handle;
+ struct _WapiHandle_thread *thread_handle = NULL;
int policy;
struct sched_param param;
gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
(gpointer *)&thread_handle);
- if (ok == FALSE) {
+ if (ok == FALSE)
return (THREAD_PRIORITY_NORMAL);
- }
switch (pthread_getschedparam (thread_handle->id, &policy, &param)) {
case 0:
- return (_wapi_thread_posix_priority_to_priority (param.sched_priority, policy));
+ if ((policy == SCHED_FIFO) || (policy == SCHED_RR))
+ return (_wapi_thread_posix_priority_to_priority (param.sched_priority, policy));
+ else
+ return (thread_handle->priority);
case ESRCH:
g_warning ("pthread_getschedparam: error looking up thread id %x", (gsize)thread_handle->id);
}
@@ -382,7 +394,7 @@ GetThreadPriority (gpointer handle)
gboolean
SetThreadPriority (gpointer handle, gint32 priority)
{
- struct _WapiHandle_thread *thread_handle;
+ struct _WapiHandle_thread *thread_handle = NULL;
int policy,
posix_priority,
rv;
@@ -401,16 +413,17 @@ SetThreadPriority (gpointer handle, gint32 priority)
return FALSE;
}
- posix_priority = _wapi_thread_priority_to_posix_priority (priority, policy);
+ posix_priority = wapi_thread_priority_to_posix_priority (priority, policy);
if (0 > posix_priority)
return FALSE;
param.sched_priority = posix_priority;
switch (pthread_setschedparam (thread_handle->id, policy, &param)) {
case 0:
+ thread_handle->priority = priority;
return TRUE;
case ESRCH:
- g_warning ("pthread_setschedparam: error looking up thread id %x", (gsize)thread_handle->id);
+ g_warning ("pthread_setschedprio: error looking up thread id %x", (gsize)thread_handle->id);
break;
case ENOTSUP:
g_warning ("%s: priority %d not supported", __func__, priority);
diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c
index c57d8e9fb5b..1fc251f56f9 100644
--- a/mono/metadata/appdomain.c
+++ b/mono/metadata/appdomain.c
@@ -2593,6 +2593,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
unload_data *thread_data;
MonoNativeThreadId tid;
MonoDomain *caller_domain = mono_domain_get ();
+ MonoThreadParm tp;
/* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
@@ -2649,7 +2650,10 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
* First we create a separate thread for unloading, since
* we might have to abort some threads, including the current one.
*/
- thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)unload_thread_main, thread_data, 0, CREATE_SUSPENDED, &tid);
+ tp.priority = 0;
+ tp.stack_size = 0;
+ tp.creation_flags = CREATE_SUSPENDED;
+ thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)unload_thread_main, thread_data, &tp, &tid);
if (thread_handle == NULL)
return;
mono_thread_info_resume (tid);
diff --git a/mono/metadata/attach.c b/mono/metadata/attach.c
index 9f6f1e6a836..f1d52f5607d 100644
--- a/mono/metadata/attach.c
+++ b/mono/metadata/attach.c
@@ -475,12 +475,17 @@ transport_send (int fd, guint8 *data, int len)
static void
transport_start_receive (void)
{
+ MonoThreadParm tp;
+
transport_connect ();
if (!listen_fd)
return;
- receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, 0, 0, NULL);
+ tp.priority = 0;
+ tp.stack_size = 0;
+ tp.creation_flags = 0;
+ receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, &tp, NULL);
g_assert (receiver_thread_handle);
}
diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h
index fb76fb8a72f..62851d633a9 100644
--- a/mono/metadata/object-internals.h
+++ b/mono/metadata/object-internals.h
@@ -391,6 +391,7 @@ struct _MonoThread {
struct _MonoInternalThread *internal_thread;
MonoObject *start_obj;
MonoException *pending_exception;
+ gint32 priority;
};
typedef struct {
diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
index 0c518966310..b4f3f091597 100644
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -591,6 +591,7 @@ new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
MonoThread *thread;
thread = create_thread_object (domain);
+ thread->priority = THREAD_PRIORITY_NORMAL;
MONO_OBJECT_SETREF (thread, internal_thread, internal);
@@ -800,7 +801,7 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
{
HANDLE thread_handle;
MonoNativeThreadId tid;
- guint32 create_flags;
+ MonoThreadParm tp;
/*
* Join joinable threads to prevent running out of threads since the finalizer
@@ -839,10 +840,11 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
/* Create suspended, so we can do some housekeeping before the thread
* starts
*/
- create_flags = CREATE_SUSPENDED;
+ tp.priority = thread->priority;
+ tp.stack_size = stack_size;
+ tp.creation_flags = CREATE_SUSPENDED;
- thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info,
- stack_size, create_flags, &tid);
+ thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info, &tp, &tid);
if (thread_handle == NULL) {
/* The thread couldn't be created, so set an exception */
@@ -1419,7 +1421,10 @@ ves_icall_System_Threading_Thread_GetPriority (MonoThread *this_obj)
MonoInternalThread *internal = this_obj->internal_thread;
LOCK_THREAD (internal);
- priority = GetThreadPriority (internal->handle) + 2;
+ if (internal->handle != NULL)
+ priority = GetThreadPriority (internal->handle) + 2;
+ else
+ priority = this_obj->priority + 2;
UNLOCK_THREAD (internal);
return priority;
}
@@ -1437,7 +1442,9 @@ ves_icall_System_Threading_Thread_SetPriority (MonoThread *this_obj, int priorit
MonoInternalThread *internal = this_obj->internal_thread;
LOCK_THREAD (internal);
- SetThreadPriority (internal->handle, priority - 2);
+ this_obj->priority = priority - 2;
+ if (internal->handle != NULL)
+ SetThreadPriority (internal->handle, this_obj->priority);
UNLOCK_THREAD (internal);
}
@@ -5083,7 +5090,7 @@ gpointer
mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy)
{
MonoDomain *orig;
- gboolean fresh_thread;
+ gboolean fresh_thread = FALSE;
if (!domain) {
/* Happens when called from AOTed code which is only used in the root domain. */
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index ea63749c65d..b08afe75043 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -9718,6 +9718,7 @@ compile_methods (MonoAotCompile *acfg)
HANDLE handle;
gpointer *user_data;
MonoMethod **methods;
+ MonoThreadParm tp;
methods_len = acfg->methods->len;
@@ -9748,7 +9749,10 @@ compile_methods (MonoAotCompile *acfg)
user_data [1] = acfg;
user_data [2] = frag;
- handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)compile_thread_main, user_data, 0, 0, NULL);
+ tp.priority = 0;
+ tp.stack_size = 0;
+ tp.creation_flags = 0;
+ handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)compile_thread_main, user_data, &tp, NULL);
g_ptr_array_add (threads, handle);
}
g_free (methods);
diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c
index e567ed30fa7..ece1fddf5e8 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -1627,7 +1627,12 @@ stop_debugger_thread (void)
static void
start_debugger_thread (void)
{
- debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, 0, 0, NULL);
+ MonoThreadParm tp;
+
+ tp.priority = 0;
+ tp.stack_size = 0;
+ tp.creation_flags = 0;
+ debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, &tp, NULL);
g_assert (debugger_thread_handle);
}
diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am
index 8b5d106bd53..2bd8f5dff12 100644
--- a/mono/tests/Makefile.am
+++ b/mono/tests/Makefile.am
@@ -442,7 +442,8 @@ BASE_TEST_CS_SRC= \
pinvoke_ppci.cs \
pinvoke_ppcf.cs \
pinvoke_ppcd.cs \
- bug-29585.cs
+ bug-29585.cs \
+ priority.cs
TEST_CS_SRC_DIST= \
$(BASE_TEST_CS_SRC) \
diff --git a/mono/tests/priority.cs b/mono/tests/priority.cs
new file mode 100644
index 00000000000..67591ddcc06
--- /dev/null
+++ b/mono/tests/priority.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Threading;
+using System.Runtime;
+using System.Text;
+
+public class Tests
+{
+ public static int Main ()
+ {
+ return TestDriver.RunTests (typeof (Tests));
+ }
+
+ public static void TestMethod()
+ {
+ Console.WriteLine("{0} with {1} priority",
+ Thread.CurrentThread.Name,
+ Thread.CurrentThread.Priority.ToString());
+ Thread.Sleep(6000);
+ Console.WriteLine("{0} with {1} priority",
+ Thread.CurrentThread.Name,
+ Thread.CurrentThread.Priority.ToString());
+ }
+
+ public static int test_0_thread_priority ()
+ {
+ int res = 0;
+
+ Thread Me = Thread.CurrentThread;
+ Thread TestThread = new Thread(new ThreadStart(TestMethod));
+
+ Console.WriteLine("Starting test thread with priority to AboveNormal");
+ ThreadPriority before = TestThread.Priority;
+ TestThread.Priority = ThreadPriority.AboveNormal;
+ TestThread.Name = "TestMethod";
+ TestThread.Start();
+ ThreadPriority after = TestThread.Priority;
+ Console.WriteLine("Priority: {0} {1}",before,after);
+ if (before != ThreadPriority.Normal)
+ res = 1;
+ else if (after != ThreadPriority.AboveNormal)
+ res = 2;
+ else {
+ TestThread.Priority = ThreadPriority.Normal;
+ after = TestThread.Priority;
+ Console.WriteLine("Setting test thread priority to Normal");
+ Thread.Sleep(1000);
+ Console.WriteLine("Priority: {0} {1}",before,after);
+
+ if (after != ThreadPriority.Normal)
+ res = 3;
+ else {
+ Console.WriteLine("Setting test thread priority to AboveNormal");
+ before = after;
+ TestThread.Priority=ThreadPriority.AboveNormal;
+ after = TestThread.Priority;
+ Thread.Sleep(1000);
+ Console.WriteLine("Priority: {0} {1}",before,after);
+
+ if (after != ThreadPriority.AboveNormal)
+ res = 4;
+ else {
+ before = after;
+ Console.WriteLine("Setting test thread priority to BelowNormal");
+ TestThread.Priority=ThreadPriority.BelowNormal;
+ after = TestThread.Priority;
+ Console.WriteLine("Priority: {0} {1}",before,after);
+ Thread.Sleep(1000);
+
+ if (after != ThreadPriority.BelowNormal)
+ res = 5;
+ else {
+ before = after;
+ Console.WriteLine("Setting test thread priority back to Normal");
+ TestThread.Priority=ThreadPriority.Normal;
+ after = TestThread.Priority;
+ Console.WriteLine("Priority: {0} {1}",before,after);
+ Thread.Sleep(1000);
+
+ if (after != ThreadPriority.Normal)
+ res = 6;
+ }
+ }
+ }
+ }
+ TestThread.Join();
+ return(res);
+ }
+}
diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c
index 0111d5fd908..adf14f22eaf 100644
--- a/mono/utils/mono-threads-posix.c
+++ b/mono/utils/mono-threads-posix.c
@@ -41,6 +41,7 @@ typedef struct {
void *(*start_routine)(void*);
void *arg;
int flags;
+ gint32 priority;
MonoCoopSem registered;
HANDLE handle;
} StartInfo;
@@ -71,6 +72,8 @@ inner_start_thread (void *arg)
info->runtime_thread = TRUE;
info->handle = handle;
+ wapi_init_thread_info_priority(handle, start_info->priority);
+
if (flags & CREATE_SUSPENDED) {
info->create_suspended = TRUE;
mono_coop_sem_init (&info->create_suspended_sem, 0);
@@ -96,17 +99,20 @@ inner_start_thread (void *arg)
}
HANDLE
-mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
+mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
{
pthread_attr_t attr;
int res;
pthread_t thread;
StartInfo start_info;
+ guint32 stack_size;
+ int policy;
+ struct sched_param sp;
res = pthread_attr_init (&attr);
g_assert (!res);
- if (stack_size == 0) {
+ if (tp->stack_size == 0) {
#if HAVE_VALGRIND_MEMCHECK_H
if (RUNNING_ON_VALGRIND)
stack_size = 1 << 20;
@@ -115,7 +121,8 @@ mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer
#else
stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024;
#endif
- }
+ } else
+ stack_size = tp->stack_size;
#ifdef PTHREAD_STACK_MIN
if (stack_size < PTHREAD_STACK_MIN)
@@ -127,10 +134,20 @@ mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer
g_assert (!res);
#endif
+ /*
+ * For policies that respect priorities set the prirority for the new thread
+ */
+ pthread_getschedparam(pthread_self(), &policy, &sp);
+ if ((policy == SCHED_FIFO) || (policy == SCHED_RR)) {
+ sp.sched_priority = wapi_thread_priority_to_posix_priority (tp->priority, policy);
+ res = pthread_attr_setschedparam (&attr, &sp);
+ }
+
memset (&start_info, 0, sizeof (StartInfo));
start_info.start_routine = (void *(*)(void *)) start_routine;
start_info.arg = arg;
- start_info.flags = creation_flags;
+ start_info.flags = tp->creation_flags;
+ start_info.priority = tp->priority;
mono_coop_sem_init (&(start_info.registered), 0);
/* Actually start the thread */
diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c
index 2ec53e35bc2..1b9dd43daf1 100644
--- a/mono/utils/mono-threads-windows.c
+++ b/mono/utils/mono-threads-windows.c
@@ -172,11 +172,12 @@ inner_start_thread (LPVOID arg)
}
HANDLE
-mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
+mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
{
ThreadStartInfo *start_info;
HANDLE result;
DWORD thread_id;
+ guint32 creation_flags = tp->creation_flags;
int res;
start_info = g_malloc0 (sizeof (ThreadStartInfo));
@@ -193,7 +194,7 @@ mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer
return NULL;
}
- result = CreateThread (NULL, stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
+ result = CreateThread (NULL, tp->stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
if (result) {
res = mono_coop_sem_wait (&(start_info->registered), MONO_SEM_FLAGS_NONE);
g_assert (res != -1);
diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c
index a92d250b290..fbc208213d3 100644
--- a/mono/utils/mono-threads.c
+++ b/mono/utils/mono-threads.c
@@ -1111,9 +1111,9 @@ mono_thread_info_is_async_context (void)
* Returns: a windows or io-layer handle for the thread.
*/
HANDLE
-mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
+mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
{
- return mono_threads_core_create_thread (start, arg, stack_size, creation_flags, out_tid);
+ return mono_threads_core_create_thread (start, arg, tp, out_tid);
}
/*
diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h
index 7f304295fcd..eaab83591e5 100644
--- a/mono/utils/mono-threads.h
+++ b/mono/utils/mono-threads.h
@@ -280,6 +280,15 @@ typedef enum {
typedef SuspendThreadResult (*MonoSuspendThreadCallback) (THREAD_INFO_TYPE *info, gpointer user_data);
+/*
+ * Parameters to pass for thread creation
+ */
+typedef struct {
+ int priority;
+ guint32 creation_flags;
+ guint32 stack_size;
+} MonoThreadParm;
+
static inline gboolean
mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
{
@@ -444,7 +453,7 @@ gboolean
mono_thread_info_is_live (THREAD_INFO_TYPE *info);
HANDLE
-mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid);
+mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid);
int
mono_threads_get_max_stack_size (void);
@@ -509,7 +518,7 @@ void mono_threads_platform_register (THREAD_INFO_TYPE *info); //ok
void mono_threads_platform_free (THREAD_INFO_TYPE *info);
void mono_threads_core_abort_syscall (THREAD_INFO_TYPE *info);
gboolean mono_threads_core_needs_abort_syscall (void);
-HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid);
+HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *, MonoNativeThreadId *out_tid);
void mono_threads_core_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid);
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize);
gboolean mono_threads_core_yield (void);