Use thread priority at thread start time (#3123)
authorNeale Ferguson <neale@sinenomine.net>
Mon, 20 Jun 2016 14:26:51 +0000 (10:26 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 20 Jun 2016 14:26:51 +0000 (10:26 -0400)
* 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

16 files changed:
mono/io-layer/handles.c
mono/io-layer/thread-private.h
mono/io-layer/threads.h
mono/io-layer/wthreads.c
mono/metadata/appdomain.c
mono/metadata/attach.c
mono/metadata/object-internals.h
mono/metadata/threads.c
mono/mini/aot-compiler.c
mono/mini/debugger-agent.c
mono/tests/Makefile.am
mono/tests/priority.cs [new file with mode: 0644]
mono/utils/mono-threads-posix.c
mono/utils/mono-threads-windows.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index 814d216fe5cc24351bdcef16c47b34d417dcdcee..a1df5bc4c603807a11b3a9dab580964e1fcc1ed7 100644 (file)
@@ -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;
index 3cf5535c5b821492f971a9c347cc1144a4f0ba28..a950e5e6da816eff181f36feedb215c71283522b 100644 (file)
@@ -23,6 +23,7 @@ struct _WapiHandle_thread
 {
        pthread_t id;
        GPtrArray *owned_mutexes;
+       gint32 priority;
 };
 
 typedef struct _WapiHandle_thread WapiHandle_thread;
index a00569d1a99a34f20708bd86650d0591e54f19fb..f26cefb548e2ed758025bfa23fe3a333ccd2b6da 100644 (file)
@@ -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);
 
-charwapi_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_ */
index 304fd35adf807e349c77529ee2813686d0e6553a..26246bbaa081b5a997b7c0d68a696584ccd47a71 100644 (file)
@@ -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;
 
@@ -226,6 +218,24 @@ _wapi_thread_disown_mutex (gpointer mutex)
        g_ptr_array_remove (thread->owned_mutexes, 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:
  *
@@ -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);
index c57d8e9fb5b9f9db68819846e311953c5a4e6671..1fc251f56f93417d91a07388e4a283b36d425ca2 100644 (file)
@@ -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);
index 9f6f1e6a836f794dca7bbc2ae4453786b1845f6c..f1d52f5607d7dc558a677f2bdc6c46590bcb6888 100644 (file)
@@ -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);
 }
 
index fb76fb8a72f53055f229ff31089b5021f0e33cfd..62851d633a9dc976d4c91ff97955169af180977f 100644 (file)
@@ -391,6 +391,7 @@ struct _MonoThread {
        struct _MonoInternalThread *internal_thread;
        MonoObject *start_obj;
        MonoException *pending_exception;
+       gint32 priority;
 };
 
 typedef struct {
index 0c518966310178a55d9b7f10023d296498134352..b4f3f09159770eda404b8011b8fb8c3f1d7ebdb4 100644 (file)
@@ -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. */
index ea63749c65db837b4e7e1527c72eec0086489446..b08afe7504316ae74cd361e399026d319dea174c 100644 (file)
@@ -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);
index e567ed30fa797879ff151a594832f666603638f2..ece1fddf5e8044e456386d65d6d0ed7c212d1d0e 100644 (file)
@@ -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);
 }
 
index 8b5d106bd5321da3236afb01c682d88e075a7218..2bd8f5dff12e5266fa7c39893d1b5e7fdb1fec29 100644 (file)
@@ -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 (file)
index 0000000..67591dd
--- /dev/null
@@ -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);
+       }
+}
index 0111d5fd9086a939033748796442d08902d2a8d6..adf14f22eaf802f541bcabef1e24cba8fb8f1d99 100644 (file)
@@ -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 */
index 2ec53e35bc2380a018e381b7c459a5198593285c..1b9dd43daf1f9350fc5aac916c862b8ae42c7451 100644 (file)
@@ -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);
index a92d250b290448698ece831e6809b4c99a8f3cdd..fbc208213d3adcae4bb87a2e3ffc8c90459846c7 100644 (file)
@@ -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);
 }
 
 /*
index 7f304295fcd4c42e86fb15374e443921c29381b4..eaab83591e53a1fbc9fdf8f6341b82976155ade6 100644 (file)
@@ -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);