[io-layer] Extract thread MonoW32HandleOps
[mono.git] / mono / utils / mono-threads.h
1 /*
2  * mono-threads.h: Low-level threading
3  *
4  * Author:
5  *      Rodrigo Kumpera (kumpera@gmail.com)
6  *
7  * (C) 2011 Novell, Inc
8  */
9
10 #ifndef __MONO_THREADS_H__
11 #define __MONO_THREADS_H__
12
13 #include <mono/utils/mono-os-semaphore.h>
14 #include <mono/utils/mono-stack-unwinding.h>
15 #include <mono/utils/mono-linked-list-set.h>
16 #include <mono/utils/mono-tls.h>
17 #include <mono/utils/mono-coop-semaphore.h>
18
19 #include <mono/io-layer/io-layer.h>
20
21 #include <glib.h>
22 #include <config.h>
23 #ifdef HOST_WIN32
24
25 #include <windows.h>
26
27 typedef DWORD MonoNativeThreadId;
28 typedef HANDLE MonoNativeThreadHandle; /* unused */
29
30 typedef DWORD mono_native_thread_return_t;
31
32 #define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (tid)
33 #define MONO_UINT_TO_NATIVE_THREAD_ID(tid) ((MonoNativeThreadId)(tid))
34
35 #else
36
37 #include <pthread.h>
38
39 #if defined(__MACH__)
40 #include <mono/utils/mach-support.h>
41
42 typedef thread_port_t MonoNativeThreadHandle;
43
44 #else
45
46 #include <unistd.h>
47
48 typedef pid_t MonoNativeThreadHandle;
49
50 #endif /* defined(__MACH__) */
51
52 typedef pthread_t MonoNativeThreadId;
53
54 typedef void* mono_native_thread_return_t;
55
56 #define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (gsize)(tid)
57 #define MONO_UINT_TO_NATIVE_THREAD_ID(tid) (MonoNativeThreadId)(gsize)(tid)
58
59 #endif /* #ifdef HOST_WIN32 */
60
61 /*
62 THREAD_INFO_TYPE is a way to make the mono-threads module parametric - or sort of.
63 The GC using mono-threads might extend the MonoThreadInfo struct to add its own
64 data, this avoid a pointer indirection on what is on a lot of hot paths.
65
66 But extending MonoThreadInfo has de disavantage that all functions here return type
67 would require a cast, something like the following:
68
69 typedef struct {
70         MonoThreadInfo info;
71         int stuff;
72 }  MyThreadInfo;
73
74 ...
75 ((MyThreadInfo*)mono_thread_info_current ())->stuff = 1;
76
77 While porting sgen to use mono-threads, the number of casts required was too much and
78 code ended up looking horrible. So we use this cute little hack. The idea is that
79 whomever is including this header can set the expected type to be used by functions here
80 and reduce the number of casts drastically.
81
82 */
83 #ifndef THREAD_INFO_TYPE
84 #define THREAD_INFO_TYPE MonoThreadInfo
85 #endif
86
87 /* Mono Threads internal configuration knows*/
88
89 /* Logging - enable them below if you need specific logging for the category you need */
90 #define MOSTLY_ASYNC_SAFE_PRINTF(...) do { \
91         char __buff[1024];      __buff [0] = '\0'; \
92         g_snprintf (__buff, sizeof (__buff), __VA_ARGS__);      \
93         write (1, __buff, strlen (__buff));     \
94 } while (0)
95
96
97 #if 1
98 #define THREADS_DEBUG(...)
99 #else
100 #define THREADS_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
101 #endif
102
103 #if 1
104 #define THREADS_STW_DEBUG(...)
105 #else
106 #define THREADS_STW_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
107 #endif
108
109 #if 1
110 #define THREADS_SUSPEND_DEBUG(...)
111 #else
112 #define THREADS_SUSPEND_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
113 #endif
114
115 #if 1
116 #define THREADS_STATE_MACHINE_DEBUG(...)
117 #else
118 #define THREADS_STATE_MACHINE_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
119 #endif
120
121 #if 1
122 #define THREADS_INTERRUPT_DEBUG(...)
123 #else
124 #define THREADS_INTERRUPT_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
125 #endif
126
127 /* If this is defined, use the signals backed on Mach. Debug only as signals can't be made usable on OSX. */
128 // #define USE_SIGNALS_ON_MACH
129
130 #if defined (_POSIX_VERSION) || defined (__native_client__)
131 #if defined (__MACH__) && !defined (USE_SIGNALS_ON_MACH)
132 #define USE_MACH_BACKEND
133 #else
134 #define USE_POSIX_BACKEND
135 #endif
136 #elif HOST_WIN32
137 #define USE_WINDOWS_BACKEND
138 #else
139 #error "no backend support for current platform"
140 #endif /* defined (_POSIX_VERSION) || defined (__native_client__) */
141
142 enum {
143         STATE_STARTING                          = 0x00,
144         STATE_RUNNING                           = 0x01,
145         STATE_DETACHED                          = 0x02,
146
147         STATE_ASYNC_SUSPENDED                   = 0x03,
148         STATE_SELF_SUSPENDED                    = 0x04,
149         STATE_ASYNC_SUSPEND_REQUESTED   = 0x05,
150         STATE_SELF_SUSPEND_REQUESTED    = 0x06,
151         STATE_BLOCKING                                  = 0x07,
152         STATE_BLOCKING_AND_SUSPENDED    = 0x8,
153
154         STATE_MAX                                               = 0x08,
155
156         THREAD_STATE_MASK                       = 0x00FF,
157         THREAD_SUSPEND_COUNT_MASK       = 0xFF00,
158         THREAD_SUSPEND_COUNT_SHIFT      = 8,
159         THREAD_SUSPEND_COUNT_MAX        = 0xFF,
160
161         SELF_SUSPEND_STATE_INDEX = 0,
162         ASYNC_SUSPEND_STATE_INDEX = 1,
163 };
164
165 typedef struct _MonoThreadInfoInterruptToken MonoThreadInfoInterruptToken;
166
167 typedef struct {
168         MonoLinkedListSetNode node;
169         guint32 small_id; /*Used by hazard pointers */
170         MonoNativeThreadHandle native_handle; /* Valid on mach and android */
171         int thread_state;
172
173         /*Tells if this thread was created by the runtime or not.*/
174         gboolean runtime_thread;
175
176         /* Tells if this thread should be ignored or not by runtime services such as GC and profiling */
177         gboolean tools_thread;
178
179         /* Max stack bounds, all valid addresses must be between [stack_start_limit, stack_end[ */
180         void *stack_start_limit, *stack_end;
181
182         /* suspend machinery, fields protected by suspend_semaphore */
183         MonoSemType suspend_semaphore;
184         int suspend_count;
185
186         MonoSemType resume_semaphore;
187
188         /* only needed by the posix backend */
189 #if defined(USE_POSIX_BACKEND)
190         MonoSemType finish_resume_semaphore;
191         gboolean syscall_break_signal;
192         int signal;
193 #endif
194
195         gboolean suspend_can_continue;
196
197         /* This memory pool is used by coop GC to save stack data roots between GC unsafe regions */
198         GByteArray *stackdata;
199
200         /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
201         MonoThreadUnwindState thread_saved_state [2]; //0 is self suspend, 1 is async suspend.
202
203         /*async call machinery, thread MUST be suspended before accessing those fields*/
204         void (*async_target)(void*);
205         void *user_data;
206
207         /*
208         If true, this thread is running a critical region of code and cannot be suspended.
209         A critical session is implicitly started when you call mono_thread_info_safe_suspend_sync
210         and is ended when you call either mono_thread_info_resume or mono_thread_info_finish_suspend.
211         */
212         gboolean inside_critical_region;
213
214         /*
215          * If TRUE, the thread is in async context. Code can use this information to avoid async-unsafe
216          * operations like locking without having to pass an 'async' parameter around.
217          */
218         gboolean is_async_context;
219
220         gboolean create_suspended;
221
222         /* Semaphore used to implement CREATE_SUSPENDED */
223         MonoCoopSem create_suspended_sem;
224
225         /*
226          * Values of TLS variables for this thread.
227          * This can be used to obtain the values of TLS variable for threads
228          * other than the current one.
229          */
230         gpointer tls [TLS_KEY_NUM];
231
232         /* IO layer handle for this thread */
233         /* Set when the thread is started, or in _wapi_thread_duplicate () */
234         HANDLE handle;
235
236         void *jit_data;
237
238         MonoThreadInfoInterruptToken *interrupt_token;
239
240         /* HandleStack for coop handles */
241         gpointer handle_stack;
242
243         /* Stack mark for targets that explicitly require one */
244         gpointer stack_mark;
245 } MonoThreadInfo;
246
247 typedef struct {
248         void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
249         /*
250         This callback is called with @info still on the thread list.
251         This call is made while holding the suspend lock, so don't do callbacks.
252         SMR remains functional as its small_id has not been reclaimed.
253         */
254         void (*thread_unregister)(THREAD_INFO_TYPE *info);
255         /*
256         This callback is called right before thread_unregister. This is called
257         without any locks held so it's the place for complicated cleanup.
258
259         The thread must remain operational between this call and thread_unregister.
260         It must be possible to successfully suspend it after thread_unregister completes.
261         */
262         void (*thread_detach)(THREAD_INFO_TYPE *info);
263         void (*thread_attach)(THREAD_INFO_TYPE *info);
264         gboolean (*mono_method_is_critical) (void *method);
265         gboolean (*mono_thread_in_critical_region) (THREAD_INFO_TYPE *info);
266 } MonoThreadInfoCallbacks;
267
268 typedef struct {
269         void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
270         gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
271         gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoThreadInfo *info);
272         void (*thread_state_init) (MonoThreadUnwindState *tctx);
273 } MonoThreadInfoRuntimeCallbacks;
274
275 //Not using 0 and 1 to ensure callbacks are not returning bad data
276 typedef enum {
277         MonoResumeThread = 0x1234,
278         KeepSuspended = 0x4321,
279 } SuspendThreadResult;
280
281 typedef SuspendThreadResult (*MonoSuspendThreadCallback) (THREAD_INFO_TYPE *info, gpointer user_data);
282
283 /*
284  * Parameters to pass for thread creation
285  */
286 typedef struct {
287         int priority;
288         guint32 creation_flags; 
289         guint32 stack_size;             
290 } MonoThreadParm;
291
292 typedef enum {
293         MONO_THREAD_PRIORITY_LOWEST       = 0,
294         MONO_THREAD_PRIORITY_BELOW_NORMAL = 1,
295         MONO_THREAD_PRIORITY_NORMAL       = 2,
296         MONO_THREAD_PRIORITY_ABOVE_NORMAL = 3,
297         MONO_THREAD_PRIORITY_HIGHEST      = 4,
298 } MonoThreadPriority;
299
300 static inline gboolean
301 mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
302 {
303         return !((MonoThreadInfo*)info)->tools_thread;
304 }
305
306 /*
307 Requires the world to be stoped
308 */
309 #define FOREACH_THREAD(thread) \
310         MONO_LLS_FOREACH_FILTERED (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
311
312 #define FOREACH_THREAD_END \
313         MONO_LLS_FOREACH_END
314
315 /*
316 Snapshot iteration.
317 */
318 #define FOREACH_THREAD_SAFE(thread) \
319         MONO_LLS_FOREACH_FILTERED_SAFE (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
320
321 #define FOREACH_THREAD_SAFE_END \
322         MONO_LLS_FOREACH_SAFE_END
323
324 static inline MonoNativeThreadId
325 mono_thread_info_get_tid (THREAD_INFO_TYPE *info)
326 {
327         return MONO_UINT_TO_NATIVE_THREAD_ID (((MonoThreadInfo*) info)->node.key);
328 }
329
330 static inline void
331 mono_thread_info_set_tid (THREAD_INFO_TYPE *info, MonoNativeThreadId tid)
332 {
333         ((MonoThreadInfo*) info)->node.key = (uintptr_t) MONO_NATIVE_THREAD_ID_TO_UINT (tid);
334 }
335
336 /*
337  * @thread_info_size is sizeof (GcThreadInfo), a struct the GC defines to make it possible to have
338  * a single block with info from both camps. 
339  */
340 void
341 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size);
342
343 void
344 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks);
345
346 MonoThreadInfoRuntimeCallbacks *
347 mono_threads_get_runtime_callbacks (void);
348
349 int
350 mono_thread_info_register_small_id (void);
351
352 THREAD_INFO_TYPE *
353 mono_thread_info_attach (void *baseptr);
354
355 MONO_API void
356 mono_thread_info_detach (void);
357
358 gboolean
359 mono_thread_info_is_exiting (void);
360
361 THREAD_INFO_TYPE *
362 mono_thread_info_current (void);
363
364 THREAD_INFO_TYPE*
365 mono_thread_info_current_unchecked (void);
366
367 int
368 mono_thread_info_get_small_id (void);
369
370 MonoLinkedListSet*
371 mono_thread_info_list_head (void);
372
373 THREAD_INFO_TYPE*
374 mono_thread_info_lookup (MonoNativeThreadId id);
375
376 gboolean
377 mono_thread_info_resume (MonoNativeThreadId tid);
378
379 void
380 mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data);
381
382 //XXX new API, fix the world
383 void
384 mono_thread_info_begin_self_suspend (void);
385
386 void
387 mono_thread_info_end_self_suspend (void);
388
389 //END of new API
390
391 gboolean
392 mono_thread_info_unified_management_enabled (void);
393
394 void
395 mono_thread_info_setup_async_call (THREAD_INFO_TYPE *info, void (*target_func)(void*), void *user_data);
396
397 void
398 mono_thread_info_suspend_lock (void);
399
400 void
401 mono_thread_info_suspend_unlock (void);
402
403 void
404 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid);
405
406 void
407 mono_thread_info_set_is_async_context (gboolean async_context);
408
409 gboolean
410 mono_thread_info_is_async_context (void);
411
412 void
413 mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize);
414
415 gboolean
416 mono_thread_info_yield (void);
417
418 gint
419 mono_thread_info_sleep (guint32 ms, gboolean *alerted);
420
421 gint
422 mono_thread_info_usleep (guint64 us);
423
424 gpointer
425 mono_thread_info_tls_get (THREAD_INFO_TYPE *info, MonoTlsKey key);
426
427 void
428 mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value);
429
430 void
431 mono_thread_info_exit (void);
432
433 HANDLE
434 mono_thread_info_open_handle (void);
435
436 void
437 mono_thread_info_set_exited (THREAD_INFO_TYPE *info);
438
439 void
440 mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted);
441
442 void
443 mono_thread_info_uninstall_interrupt (gboolean *interrupted);
444
445 MonoThreadInfoInterruptToken*
446 mono_thread_info_prepare_interrupt (THREAD_INFO_TYPE *info);
447
448 void
449 mono_thread_info_finish_interrupt (MonoThreadInfoInterruptToken *token);
450
451 void
452 mono_thread_info_self_interrupt (void);
453
454 void
455 mono_thread_info_clear_self_interrupt (void);
456
457 gboolean
458 mono_thread_info_is_interrupt_state (THREAD_INFO_TYPE *info);
459
460 void
461 mono_thread_info_describe_interrupt_token (THREAD_INFO_TYPE *info, GString *text);
462
463 gboolean
464 mono_thread_info_is_live (THREAD_INFO_TYPE *info);
465
466 HANDLE
467 mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid);
468
469 int
470 mono_threads_get_max_stack_size (void);
471
472 HANDLE
473 mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
474
475 MONO_API void
476 mono_threads_attach_tools_thread (void);
477
478
479 #if !defined(HOST_WIN32)
480
481 /*Use this instead of pthread_kill */
482 int
483 mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum);
484
485 #endif /* !defined(HOST_WIN32) */
486
487 /* Internal API between mono-threads and its backends. */
488
489 /* Backend functions - a backend must implement all of the following */
490 /*
491 This is called very early in the runtime, it cannot access any runtime facilities.
492
493 */
494 void mono_threads_suspend_init (void); //ok
495
496 void mono_threads_platform_init (void);
497
498 void mono_threads_coop_init (void);
499
500 void mono_threads_abort_syscall_init (void);
501
502 /*
503 This begins async suspend. This function must do the following:
504
505 -Ensure the target will EINTR any syscalls if @interrupt_kernel is true
506 -Call mono_threads_transition_finish_async_suspend as part of its async suspend.
507 -Register the thread for pending suspend with mono_threads_add_to_pending_operation_set if needed.
508
509 If begin suspend fails the thread must be left uninterrupted and resumed.
510 */
511 gboolean mono_threads_suspend_begin_async_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel);
512
513 /*
514 This verifies the outcome of an async suspend operation.
515
516 Some targets, such as posix, verify suspend results assynchronously. Suspend results must be
517 available (in a non blocking way) after mono_threads_wait_pending_operations completes.
518 */
519 gboolean mono_threads_suspend_check_suspend_result (THREAD_INFO_TYPE *info);
520
521 /*
522 This begins async resume. This function must do the following:
523
524 - Install an async target if one was requested.
525 - Notify the target to resume.
526 - Register the thread for pending ack with mono_threads_add_to_pending_operation_set if needed.
527 */
528 gboolean mono_threads_suspend_begin_async_resume (THREAD_INFO_TYPE *info);
529
530 void mono_threads_suspend_register (THREAD_INFO_TYPE *info); //ok
531 void mono_threads_suspend_free (THREAD_INFO_TYPE *info);
532 void mono_threads_suspend_abort_syscall (THREAD_INFO_TYPE *info);
533 gboolean mono_threads_suspend_needs_abort_syscall (void);
534
535 HANDLE mono_threads_platform_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, MonoThreadParm *, MonoNativeThreadId *out_tid);
536 void mono_threads_platform_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid);
537 void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize);
538 gboolean mono_threads_platform_yield (void);
539 void mono_threads_platform_exit (int exit_code);
540 void mono_threads_platform_unregister (THREAD_INFO_TYPE *info);
541 HANDLE mono_threads_platform_open_handle (void);
542 HANDLE mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
543 void mono_threads_platform_set_exited (THREAD_INFO_TYPE *info);
544 void mono_threads_platform_describe (THREAD_INFO_TYPE *info, GString *text);
545 void mono_threads_platform_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
546 void mono_threads_platform_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
547 MonoThreadPriority mono_threads_platform_get_priority (THREAD_INFO_TYPE *info);
548 gboolean mono_threads_platform_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
549
550 void mono_threads_coop_begin_global_suspend (void);
551 void mono_threads_coop_end_global_suspend (void);
552
553 MONO_API MonoNativeThreadId
554 mono_native_thread_id_get (void);
555
556 gboolean
557 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2);
558
559 gboolean
560 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg);
561
562 MONO_API void
563 mono_native_thread_set_name (MonoNativeThreadId tid, const char *name);
564
565 /*Mach specific internals */
566 void mono_threads_init_dead_letter (void);
567 void mono_threads_install_dead_letter (void);
568
569 /* mono-threads internal API used by the backends. */
570 /*
571 This tells the suspend initiator that we completed suspend and will now be waiting for resume.
572 */
573 void mono_threads_notify_initiator_of_suspend (THREAD_INFO_TYPE* info);
574 /*
575 This tells the resume initiator that we completed resume duties and will return to runnable state.
576 */
577 void mono_threads_notify_initiator_of_resume (THREAD_INFO_TYPE* info);
578
579 /*
580 This tells the resume initiator that we completed abort duties and will return to previous state.
581 */
582 void mono_threads_notify_initiator_of_abort (THREAD_INFO_TYPE* info);
583
584 /* Thread state machine functions */
585
586 typedef enum {
587         ResumeError,
588         ResumeOk,
589         ResumeInitSelfResume,
590         ResumeInitAsyncResume,
591         ResumeInitBlockingResume,
592 } MonoResumeResult;
593
594 typedef enum {
595         SelfSuspendResumed,
596         SelfSuspendWait,
597         SelfSuspendNotifyAndWait,
598 } MonoSelfSupendResult;
599
600 typedef enum {
601         AsyncSuspendAlreadySuspended,
602         AsyncSuspendWait,
603         AsyncSuspendInitSuspend,
604         AsyncSuspendBlocking,
605 } MonoRequestAsyncSuspendResult;
606
607 typedef enum {
608         DoBlockingContinue, //in blocking mode, continue
609         DoBlockingPollAndRetry, //async suspend raced blocking and won, pool and retry
610 } MonoDoBlockingResult;
611
612 typedef enum {
613         DoneBlockingOk, //exited blocking fine
614         DoneBlockingWait, //thread should end suspended
615 } MonoDoneBlockingResult;
616
617
618 typedef enum {
619         AbortBlockingIgnore, //Ignore
620         AbortBlockingIgnoreAndPoll, //Ignore and poll
621         AbortBlockingOk, //Abort worked
622         AbortBlockingWait, //Abort worked, but should wait for resume
623 } MonoAbortBlockingResult;
624
625
626 void mono_threads_transition_attach (THREAD_INFO_TYPE* info);
627 gboolean mono_threads_transition_detach (THREAD_INFO_TYPE *info);
628 void mono_threads_transition_request_self_suspension (THREAD_INFO_TYPE *info);
629 MonoRequestAsyncSuspendResult mono_threads_transition_request_async_suspension (THREAD_INFO_TYPE *info);
630 MonoSelfSupendResult mono_threads_transition_state_poll (THREAD_INFO_TYPE *info);
631 MonoResumeResult mono_threads_transition_request_resume (THREAD_INFO_TYPE* info);
632 gboolean mono_threads_transition_finish_async_suspend (THREAD_INFO_TYPE* info);
633 MonoDoBlockingResult mono_threads_transition_do_blocking (THREAD_INFO_TYPE* info);
634 MonoDoneBlockingResult mono_threads_transition_done_blocking (THREAD_INFO_TYPE* info);
635 MonoAbortBlockingResult mono_threads_transition_abort_blocking (THREAD_INFO_TYPE* info);
636
637 MonoThreadUnwindState* mono_thread_info_get_suspend_state (THREAD_INFO_TYPE *info);
638
639 gpointer
640 mono_threads_enter_gc_unsafe_region_cookie (void);
641
642
643 void mono_thread_info_wait_for_resume (THREAD_INFO_TYPE *info);
644 /* Advanced suspend API, used for suspending multiple threads as once. */
645 gboolean mono_thread_info_is_running (THREAD_INFO_TYPE *info);
646 gboolean mono_thread_info_is_live (THREAD_INFO_TYPE *info);
647 int mono_thread_info_suspend_count (THREAD_INFO_TYPE *info);
648 int mono_thread_info_current_state (THREAD_INFO_TYPE *info);
649 const char* mono_thread_state_name (int state);
650
651 gboolean mono_thread_info_in_critical_location (THREAD_INFO_TYPE *info);
652 gboolean mono_thread_info_begin_suspend (THREAD_INFO_TYPE *info);
653 gboolean mono_thread_info_begin_resume (THREAD_INFO_TYPE *info);
654
655 void mono_threads_add_to_pending_operation_set (THREAD_INFO_TYPE* info); //XXX rename to something to reflect the fact that this is used for both suspend and resume
656 gboolean mono_threads_wait_pending_operations (void);
657 void mono_threads_begin_global_suspend (void);
658 void mono_threads_end_global_suspend (void);
659
660 gboolean
661 mono_thread_info_is_current (THREAD_INFO_TYPE *info);
662
663 gpointer
664 mono_thread_info_get_handle (THREAD_INFO_TYPE *info);
665
666 void
667 mono_thread_info_describe (THREAD_INFO_TYPE *info, GString *text);
668
669 void
670 mono_thread_info_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
671
672 void
673 mono_thread_info_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
674
675 MonoThreadPriority
676 mono_thread_info_get_priority (THREAD_INFO_TYPE *info);
677
678 gboolean
679 mono_thread_info_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
680
681 #endif /* __MONO_THREADS_H__ */