[corlib] ParseNumber.StringToInt now check for overflows.
[mono.git] / mono / io-layer / wthreads.c
1 /*
2  * threads.c:  Thread handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002-2006 Ximian, Inc.
8  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include <glib.h>
15 #include <string.h>
16 #include <pthread.h>
17 #include <sched.h>
18 #include <sys/time.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <mono/io-layer/wapi.h>
24 #include <mono/io-layer/wapi-private.h>
25 #include <mono/io-layer/handles-private.h>
26 #include <mono/io-layer/misc-private.h>
27 #include <mono/io-layer/thread-private.h>
28 #include <mono/io-layer/mutex-private.h>
29
30 #include <mono/utils/mono-threads.h>
31 #include <mono/utils/atomic.h>
32 #include <mono/utils/mono-mutex.h>
33
34 #ifdef HAVE_VALGRIND_MEMCHECK_H
35 #include <valgrind/memcheck.h>
36 #endif
37
38 #if 0
39 #define DEBUG(...) g_message(__VA_ARGS__)
40 #else
41 #define DEBUG(...)
42 #endif
43
44 #if 0
45 #define WAIT_DEBUG(code) do { code } while (0)
46 #else
47 #define WAIT_DEBUG(code) do { } while (0)
48 #endif
49
50 struct _WapiHandleOps _wapi_thread_ops = {
51         NULL,                           /* close */
52         NULL,                           /* signal */
53         NULL,                           /* own */
54         NULL,                           /* is_owned */
55         NULL,                           /* special_wait */
56         NULL                            /* prewait */
57 };
58
59 static mono_once_t thread_ops_once = MONO_ONCE_INIT;
60
61 static void
62 thread_ops_init (void)
63 {
64         _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
65                                             WAPI_HANDLE_CAP_WAIT);
66 }
67
68 void
69 _wapi_thread_cleanup (void)
70 {
71 }
72
73 static gpointer
74 get_current_thread_handle (void)
75 {
76         MonoThreadInfo *info;
77
78         info = mono_thread_info_current ();
79         g_assert (info);
80         g_assert (info->handle);
81         return info->handle;
82 }
83
84 static WapiHandle_thread*
85 lookup_thread (HANDLE handle)
86 {
87         WapiHandle_thread *thread;
88         gboolean ok;
89
90         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
91                                                           (gpointer *)&thread);
92         g_assert (ok);
93         return thread;
94 }
95
96 static WapiHandle_thread*
97 get_current_thread (void)
98 {
99         gpointer handle;
100
101         handle = get_current_thread_handle ();
102         return lookup_thread (handle);
103 }
104
105 void
106 wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus)
107 {
108         WapiHandle_thread *thread_handle;
109         int i, thr_ret;
110         pid_t pid = _wapi_getpid ();
111         pthread_t tid = pthread_self ();
112         
113         if (_wapi_handle_issignalled (handle) ||
114             _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
115                 /* We must have already deliberately finished with
116                  * this thread, so don't do any more now
117                  */
118                 return;
119         }
120
121         DEBUG ("%s: Thread %p terminating", __func__, handle);
122
123         thread_handle = lookup_thread (handle);
124
125         DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
126
127         for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
128                 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
129
130                 _wapi_mutex_abandon (mutex, pid, tid);
131                 _wapi_thread_disown_mutex (mutex);
132         }
133         g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
134         
135         thr_ret = _wapi_handle_lock_handle (handle);
136         g_assert (thr_ret == 0);
137
138         _wapi_handle_set_signal_state (handle, TRUE, TRUE);
139
140         thr_ret = _wapi_handle_unlock_handle (handle);
141         g_assert (thr_ret == 0);
142         
143         DEBUG("%s: Recording thread handle %p id %ld status as %d",
144                   __func__, handle, thread_handle->id, exitstatus);
145         
146         /* The thread is no longer active, so unref it */
147         _wapi_handle_unref (handle);
148 }
149
150 /*
151  * wapi_create_thread_handle:
152  *
153  *   Create a thread handle for the current thread.
154  */
155 gpointer
156 wapi_create_thread_handle (void)
157 {
158         WapiHandle_thread thread_handle = {0}, *thread;
159         gpointer handle;
160
161         mono_once (&thread_ops_once, thread_ops_init);
162
163         thread_handle.owned_mutexes = g_ptr_array_new ();
164
165         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
166         if (handle == _WAPI_HANDLE_INVALID) {
167                 g_warning ("%s: error creating thread handle", __func__);
168                 SetLastError (ERROR_GEN_FAILURE);
169                 
170                 return NULL;
171         }
172
173         thread = lookup_thread (handle);
174
175         thread->id = pthread_self ();
176
177         /*
178          * Hold a reference while the thread is active, because we use
179          * the handle to store thread exit information
180          */
181         _wapi_handle_ref (handle);
182
183         DEBUG ("%s: started thread id %ld", __func__, thread->id);
184         
185         return handle;
186 }
187
188 void
189 wapi_ref_thread_handle (gpointer handle)
190 {
191         _wapi_handle_ref (handle);
192 }
193
194 gpointer
195 wapi_get_current_thread_handle (void)
196 {
197         return get_current_thread_handle ();
198 }
199
200 /**
201  * GetCurrentThreadId:
202  *
203  * Looks up the thread ID of the current thread.  This ID can be
204  * passed to OpenThread() to create a new handle on this thread.
205  *
206  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
207  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
208  * and amd64.  This doesn't really break the API, it just embraces and
209  * extends it on 64bit platforms :)
210  */
211 gsize
212 GetCurrentThreadId (void)
213 {
214         MonoNativeThreadId id;
215
216         id = mono_native_thread_id_get ();
217         return MONO_NATIVE_THREAD_ID_TO_UINT (id);
218 }
219
220 /**
221  * SleepEx:
222  * @ms: The time in milliseconds to suspend for
223  * @alertable: if TRUE, the wait can be interrupted by an APC call
224  *
225  * Suspends execution of the current thread for @ms milliseconds.  A
226  * value of zero causes the thread to relinquish its time slice.  A
227  * value of %INFINITE causes an infinite delay.
228  */
229 guint32
230 SleepEx (guint32 ms, gboolean alertable)
231 {
232         int ms_quot, ms_rem;
233         int ret;
234         gpointer current_thread = NULL;
235 #if defined (__linux__) && !defined(PLATFORM_ANDROID)
236         struct timespec start, target;
237 #else
238         struct timespec rem;
239 #endif
240         
241         DEBUG("%s: Sleeping for %d ms", __func__, ms);
242
243         if (alertable) {
244                 current_thread = get_current_thread_handle ();
245                 
246                 if (_wapi_thread_apc_pending (current_thread))
247                         return WAIT_IO_COMPLETION;
248         }
249         
250         if(ms==0) {
251                 sched_yield();
252                 return 0;
253         }
254         
255         /* FIXME: check for INFINITE and sleep forever */
256         ms_quot = ms / 1000;
257         ms_rem = ms % 1000;
258         
259 #if defined (__linux__) && !defined(PLATFORM_ANDROID)
260         /* Use clock_nanosleep () to prevent time drifting problems when nanosleep () is interrupted by signals */
261         ret = clock_gettime (CLOCK_MONOTONIC, &start);
262         g_assert (ret == 0);
263         target = start;
264         target.tv_sec += ms_quot;
265         target.tv_nsec += ms_rem * 1000000;
266         if (target.tv_nsec > 999999999) {
267                 target.tv_nsec -= 999999999;
268                 target.tv_sec ++;
269         }
270
271         while (TRUE) {
272                 ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
273
274                 if (alertable && _wapi_thread_apc_pending (current_thread))
275                         return WAIT_IO_COMPLETION;
276
277                 if (ret == 0)
278                         break;
279         }
280
281 #else
282         struct timespec req;
283
284         req.tv_sec=ms_quot;
285         req.tv_nsec=ms_rem*1000000;
286
287 again:
288         memset (&rem, 0, sizeof (rem));
289         ret=nanosleep(&req, &rem);
290
291         if (alertable && _wapi_thread_apc_pending (current_thread))
292                 return WAIT_IO_COMPLETION;
293         
294         if(ret==-1) {
295                 /* Sleep interrupted with rem time remaining */
296 #ifdef DEBUG_ENABLED
297                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
298                 
299                 g_message("%s: Still got %d ms to go", __func__, rems);
300 #endif
301                 req=rem;
302                 goto again;
303         }
304
305 #endif /* __linux__ */
306
307         return 0;
308 }
309
310 void
311 Sleep(guint32 ms)
312 {
313         SleepEx(ms, FALSE);
314 }
315
316 gboolean
317 _wapi_thread_cur_apc_pending (void)
318 {
319         return _wapi_thread_apc_pending (get_current_thread_handle ());
320 }
321
322 gboolean
323 _wapi_thread_apc_pending (gpointer handle)
324 {
325         WapiHandle_thread *thread;
326
327         thread = lookup_thread (handle);
328         
329         return thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE;
330 }
331
332 /*
333  * wapi_interrupt_thread:
334  *
335  * The state of the thread handle HANDLE is set to 'interrupted' which means that
336  * if the thread calls one of the WaitFor functions, the function will return with 
337  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
338  * this function was called, the wait will be broken.
339  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
340  * target thread didn't receive the interrupt signal yet, in this case it should
341  * call the wait function again. This essentially means that the target thread will
342  * busy wait until it is ready to process the interruption.
343  */
344 void
345 wapi_interrupt_thread (gpointer thread_handle)
346 {
347         gpointer wait_handle;
348
349         wait_handle = wapi_prepare_interrupt_thread (thread_handle);
350         wapi_finish_interrupt_thread (wait_handle);
351 }
352
353 gpointer
354 wapi_prepare_interrupt_thread (gpointer thread_handle)
355 {
356         WapiHandle_thread *thread;
357         gpointer prev_handle, wait_handle;
358
359         thread = lookup_thread (thread_handle); /* FIXME this is wrong, move this whole thing to MonoThreads where it can be done lockfree */
360
361         while (TRUE) {
362                 wait_handle = thread->wait_handle;
363
364                 /* 
365                  * Atomically obtain the handle the thread is waiting on, and
366                  * change it to a flag value.
367                  */
368                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
369                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
370                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
371                         /* Already interrupted */
372                         return 0;
373                 if (prev_handle == wait_handle)
374                         break;
375
376                 /* Try again */
377         }
378
379         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
380
381         return wait_handle;
382 }
383
384 void
385 wapi_finish_interrupt_thread (gpointer wait_handle)
386 {
387         pthread_cond_t *cond;
388         mono_mutex_t *mutex;
389         guint32 idx;
390
391         if (!wait_handle)
392                 /* Not waiting */
393                 return;
394
395         /* If we reach here, then wait_handle is set to the flag value, 
396          * which means that the target thread is either
397          * - before the first CAS in timedwait, which means it won't enter the
398          * wait.
399          * - it is after the first CAS, so it is already waiting, or it will 
400          * enter the wait, and it will be interrupted by the broadcast.
401          */
402         idx = GPOINTER_TO_UINT(wait_handle);
403         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
404         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
405
406         mono_mutex_lock (mutex);
407         mono_cond_broadcast (cond);
408         mono_mutex_unlock (mutex);
409
410         /* ref added by set_wait_handle */
411         _wapi_handle_unref (wait_handle);
412 }
413
414 /*
415  * wapi_self_interrupt:
416  *
417  *   This is not part of the WIN32 API.
418  * Set the 'interrupted' state of the calling thread if it's NULL.
419  */
420 void
421 wapi_self_interrupt (void)
422 {
423         gpointer wait_handle;
424
425         wait_handle = wapi_prepare_interrupt_thread (get_current_thread_handle ());
426         if (wait_handle)
427                 /* ref added by set_wait_handle */
428                 _wapi_handle_unref (wait_handle);
429 }
430
431 /*
432  * wapi_clear_interruption:
433  *
434  *   This is not part of the WIN32 API. 
435  * Clear the 'interrupted' state of the calling thread.
436  * This function is signal safe
437  */
438 void
439 wapi_clear_interruption (void)
440 {
441         WapiHandle_thread *thread;
442         gpointer prev_handle;
443
444         thread = get_current_thread ();
445
446         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
447                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
448         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
449                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
450 }
451
452 /**
453  * wapi_thread_set_wait_handle:
454  *
455  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
456  * if the thread is in interrupted state, and cannot start waiting.
457  */
458 gboolean
459 wapi_thread_set_wait_handle (gpointer handle)
460 {
461         WapiHandle_thread *thread;
462         gpointer prev_handle;
463
464         thread = get_current_thread ();
465
466         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
467                                                                                                          handle, NULL);
468         if (prev_handle == NULL) {
469                 /* thread->wait_handle acts as an additional reference to the handle */
470                 _wapi_handle_ref (handle);
471
472                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
473         } else {
474                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
475                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
476         }
477
478         return prev_handle == NULL;
479 }
480
481 /**
482  * wapi_thread_clear_wait_handle:
483  *
484  *   Clear the wait handle of the current thread.
485  */
486 void
487 wapi_thread_clear_wait_handle (gpointer handle)
488 {
489         WapiHandle_thread *thread;
490         gpointer prev_handle;
491
492         thread = get_current_thread ();
493
494         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
495                                                                                                          NULL, handle);
496         if (prev_handle == handle) {
497                 _wapi_handle_unref (handle);
498                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
499         } else {
500                 /*It can be NULL if it was asynchronously cleared*/
501                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
502                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
503         }
504 }
505
506 void
507 _wapi_thread_own_mutex (gpointer mutex)
508 {
509         WapiHandle_thread *thread;
510         
511         thread = get_current_thread ();
512
513         _wapi_handle_ref (mutex);
514         
515         g_ptr_array_add (thread->owned_mutexes, mutex);
516 }
517
518 void
519 _wapi_thread_disown_mutex (gpointer mutex)
520 {
521         WapiHandle_thread *thread;
522
523         thread = get_current_thread ();
524
525         _wapi_handle_unref (mutex);
526         
527         g_ptr_array_remove (thread->owned_mutexes, mutex);
528 }
529
530 char*
531 wapi_current_thread_desc (void)
532 {
533         WapiHandle_thread *thread;
534         gpointer thread_handle;
535         int i;
536         gpointer handle;
537         GString* text;
538         char *res;
539
540         thread_handle = get_current_thread_handle ();
541         thread = lookup_thread (thread_handle);
542
543         handle = thread->wait_handle;
544         text = g_string_new (0);
545         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
546
547         if (!handle)
548                 g_string_append_printf (text, "not waiting");
549         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
550                 g_string_append_printf (text, "interrupted state");
551         else
552                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
553         g_string_append_printf (text, " owns (");
554         for (i = 0; i < thread->owned_mutexes->len; i++) {
555                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
556                 if (i > 0)
557                         g_string_append_printf (text, ", %p", mutex);
558                 else
559                         g_string_append_printf (text, "%p", mutex);
560         }
561         g_string_append_printf (text, ")");
562
563         res = text->str;
564         g_string_free (text, FALSE);
565         return res;
566 }