* configure.in: Use AC_CHECK_LIB() to check for pthread instead of
[mono.git] / mono / io-layer / collection.c
1 /*
2  * collection.c:  Garbage collection for handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2004-2006 Novell, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <signal.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16
17 #include <mono/io-layer/wapi.h>
18 #include <mono/io-layer/collection.h>
19 #include <mono/io-layer/handles-private.h>
20
21 #define LOGDEBUG(...)
22 // #define LOGDEBUG(...) g_message(__VA_ARGS__)
23
24 static pthread_t collection_thread_id;
25
26 static gpointer collection_thread (gpointer unused G_GNUC_UNUSED)
27 {
28         struct timespec sleepytime;
29
30         sleepytime.tv_sec = _WAPI_HANDLE_COLLECTION_UPDATE_INTERVAL;
31         sleepytime.tv_nsec = 0;
32
33         while (_wapi_has_shut_down == FALSE) {
34                 nanosleep (&sleepytime, NULL);
35
36                 //_wapi_handle_dump ();
37                 _wapi_handle_update_refs ();
38
39                 /* This is an abuse of the collection thread, but it's
40                  * better than creating a new thread just for one more
41                  * function.
42                  */
43                 _wapi_process_reap ();
44         }
45
46         pthread_exit (NULL);
47
48         return(NULL);
49 }
50
51 void _wapi_collection_init (void)
52 {
53         pthread_attr_t attr;
54         int ret;
55         int set_stacksize = 0;
56
57  retry:
58         ret = pthread_attr_init (&attr);
59         g_assert (ret == 0);
60
61 /* Android implements pthread_attr_setstacksize(), but errors out when using
62  * PTHREAD_STACK_MIN: http://code.google.com/p/android/issues/detail?id=7808
63  */
64 #if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && !defined(PLATFORM_ANDROID)
65         if (set_stacksize == 0) {
66 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
67                         ret = pthread_attr_setstacksize (&attr, 65536);
68 #else
69                         ret = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
70 #endif
71                         g_assert (ret == 0);
72         } else if (set_stacksize == 1) {
73                         ret = pthread_attr_setstacksize (&attr, 131072);
74                         g_assert (ret == 0);
75         }
76 #endif
77
78         ret = pthread_create (&collection_thread_id, &attr, collection_thread,
79                               NULL);
80         if (ret != 0 && set_stacksize < 2) {
81                 set_stacksize++;
82                 goto retry;
83         }
84         if (ret != 0) {
85                 g_error ("%s: Couldn't create handle collection thread: %s",
86                          __func__, g_strerror (ret));
87         }
88 }
89
90 void _wapi_handle_collect (void)
91 {
92         guint32 count = _wapi_shared_layout->collection_count;
93         int i, thr_ret;
94         
95         LOGDEBUG ("%s: (%d) Starting a collection", __func__, _wapi_getpid ());
96
97         /* Become the collection master */
98         thr_ret = _wapi_handle_lock_shared_handles ();
99         g_assert (thr_ret == 0);
100         
101         LOGDEBUG ("%s: (%d) Master set", __func__, _wapi_getpid ());
102         
103         /* If count has changed, someone else jumped in as master */
104         if (count == _wapi_shared_layout->collection_count) {
105                 guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
106
107                 for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
108                         struct _WapiHandleShared *data;
109                         
110                         data = &_wapi_shared_layout->handles[i];
111                         if (data->timestamp < too_old) {
112                                 LOGDEBUG ("%s: (%d) Deleting handle 0x%x", __func__, _wapi_getpid (), i);
113                                 memset (&_wapi_shared_layout->handles[i], '\0', sizeof(struct _WapiHandleShared));
114                         }
115                 }
116
117                 for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
118                         struct _WapiFileShare *file_share = &_wapi_fileshare_layout->share_info[i];
119                         
120                         if (file_share->timestamp < too_old) {
121                                 memset (file_share, '\0',
122                                         sizeof(struct _WapiFileShare));
123                         }
124                 }
125
126                 InterlockedIncrement ((gint32 *)&_wapi_shared_layout->collection_count);
127         }
128         
129         _wapi_handle_unlock_shared_handles ();
130
131         LOGDEBUG ("%s: (%d) Collection done", __func__, _wapi_getpid ());
132 }