d4d5313e994c6a72e3be8300d2cc8848723cf378
[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 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 #undef DEBUG
22
23 static pthread_t collection_thread_id;
24
25 static gpointer collection_thread (gpointer args) G_GNUC_NORETURN;
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 (1) {
34                 //_wapi_handle_dump ();
35                 _wapi_handle_update_refs ();
36
37                 /* This is an abuse of the collection thread, but it's
38                  * better than creating a new thread just for one more
39                  * function.
40                  */
41                 _wapi_process_reap ();
42
43                 nanosleep (&sleepytime, NULL);
44         }
45
46 #ifndef __GNUC__
47         /* Even though we tell gcc that this function doesn't return,
48          * other compilers won't see that.
49          */
50         return(NULL);
51 #endif
52 }
53
54 void _wapi_collection_init (void)
55 {
56         pthread_attr_t attr;
57         int ret;
58         
59         ret = pthread_attr_init (&attr);
60         g_assert (ret == 0);
61         
62 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
63 #ifdef __FreeBSD__
64         ret = pthread_attr_setstacksize (&attr, 65536);
65 #else
66         ret = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
67 #endif
68         g_assert (ret == 0);
69 #endif
70
71         ret = pthread_create (&collection_thread_id, &attr, collection_thread,
72                               NULL);
73         if (ret != 0) {
74                 g_error ("%s: Couldn't create handle collection thread: %s",
75                          __func__, g_strerror (ret));
76         }
77 }
78
79 void _wapi_handle_collect (void)
80 {
81         guint32 count = _wapi_shared_layout->collection_count;
82         int i, thr_ret;
83         
84 #ifdef DEBUG
85         g_message ("%s: (%d) Starting a collection", __func__, getpid ());
86 #endif
87
88         /* Become the collection master */
89         thr_ret = _wapi_handle_lock_shared_handles ();
90         g_assert (thr_ret == 0);
91         
92 #ifdef DEBUG
93         g_message ("%s: (%d) Master set", __func__, getpid ());
94 #endif
95         
96         /* If count has changed, someone else jumped in as master */
97         if (count == _wapi_shared_layout->collection_count) {
98                 guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
99
100                 for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
101                         struct _WapiHandleShared *data;
102                         
103                         data = &_wapi_shared_layout->handles[i];
104                         if (data->timestamp < too_old) {
105 #ifdef DEBUG
106                                 g_message ("%s: (%d) Deleting handle 0x%x", __func__, getpid (), i);
107 #endif
108                                 memset (&_wapi_shared_layout->handles[i], '\0', sizeof(struct _WapiHandleShared));
109                         }
110                 }
111
112                 for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
113                         struct _WapiFileShare *file_share = &_wapi_fileshare_layout->share_info[i];
114                         
115                         if (file_share->timestamp < too_old) {
116                                 memset (file_share, '\0',
117                                         sizeof(struct _WapiFileShare));
118                         }
119                 }
120
121                 InterlockedIncrement (&_wapi_shared_layout->collection_count);
122         }
123         
124         _wapi_handle_unlock_shared_handles ();
125
126 #ifdef DEBUG
127         g_message ("%s: (%d) Collection done", __func__, getpid ());
128 #endif
129 }