2005-05-13 Zoltan Varga <vargaz@freemail.hu>
[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                 nanosleep (&sleepytime, NULL);
37         }
38
39 #ifndef __GNUC__
40         /* Even though we tell gcc that this function doesn't return,
41          * other compilers won't see that.
42          */
43         return(NULL);
44 #endif
45 }
46
47 void _wapi_collection_init (void)
48 {
49         pthread_attr_t attr;
50         int ret;
51         
52         ret = pthread_attr_init (&attr);
53         g_assert (ret == 0);
54         
55 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
56 #ifdef __FreeBSD__
57         ret = pthread_attr_setstacksize (&attr, 65536);
58 #else
59         ret = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
60 #endif
61         g_assert (ret == 0);
62 #endif
63
64         ret = pthread_create (&collection_thread_id, &attr, collection_thread,
65                               NULL);
66         if (ret != 0) {
67                 g_error ("%s: Couldn't create handle collection thread: %s",
68                          __func__, g_strerror (ret));
69         }
70 }
71
72 void _wapi_handle_collect (void)
73 {
74         guint32 count = _wapi_shared_layout->collection_count;
75         int i;
76         
77 #ifdef DEBUG
78         g_message ("%s: (%d) Starting a collection", __func__, getpid ());
79 #endif
80
81         /* Become the collection master */
82         _WAPI_HANDLE_COLLECTION_UNSAFE;
83         
84 #ifdef DEBUG
85         g_message ("%s: (%d) Master set", __func__, getpid ());
86 #endif
87         
88         /* If count has changed, someone else jumped in as master */
89         if (count == _wapi_shared_layout->collection_count) {
90                 for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
91                         struct _WapiHandleShared *shared;
92                         struct _WapiHandleSharedMetadata *meta;
93                         guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
94                         
95                         meta = &_wapi_shared_layout->metadata[i];
96                         if (meta->timestamp < too_old && meta->offset != 0) {
97 #ifdef DEBUG
98                                 g_message ("%s: (%d) Deleting metadata slot 0x%x handle 0x%x", __func__, getpid (), i, meta->offset);
99 #endif
100                                 memset (&_wapi_shared_layout->handles[meta->offset], '\0', sizeof(struct _WapiHandleShared));
101                                 memset (&_wapi_shared_layout->metadata[i], '\0', sizeof(struct _WapiHandleSharedMetadata));
102                         }
103
104                         /* Need to blank any handles data that is no
105                          * longer pointed to by a metadata entry too
106                          */
107                         shared = &_wapi_shared_layout->handles[i];
108                         if (shared->stale == TRUE) {
109 #ifdef DEBUG
110                                 g_message ("%s: (%d) Deleting stale handle 0x%x", __func__, getpid (), i);
111 #endif
112                                 memset (&_wapi_shared_layout->handles[i], '\0',
113                                         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                         guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
120                         
121                         if (file_share->timestamp < too_old) {
122                                 memset (file_share, '\0',
123                                         sizeof(struct _WapiFileShare));
124                         }
125                 }
126
127                 InterlockedIncrement (&_wapi_shared_layout->collection_count);
128         }
129         
130         _WAPI_HANDLE_COLLECTION_SAFE;
131
132 #ifdef DEBUG
133         g_message ("%s: (%d) Collection done", __func__, getpid ());
134 #endif
135 }