Take shared file lock before collecting file share_info.
[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 #include <mono/utils/atomic.h>
21
22 #if 0
23 // #define DEBUG(...) g_message(__VA_ARGS__)
24 #else
25 #define DEBUG(...)
26 #endif
27
28 static pthread_t collection_thread_id;
29
30 static gpointer collection_thread (gpointer unused G_GNUC_UNUSED)
31 {
32         struct timespec sleepytime;
33
34         sleepytime.tv_sec = _WAPI_HANDLE_COLLECTION_UPDATE_INTERVAL;
35         sleepytime.tv_nsec = 0;
36
37         while (_wapi_has_shut_down == FALSE) {
38                 nanosleep (&sleepytime, NULL);
39
40                 //_wapi_handle_dump ();
41                 _wapi_handle_update_refs ();
42         }
43
44         pthread_exit (NULL);
45
46         return(NULL);
47 }
48
49 void _wapi_collection_init (void)
50 {
51         pthread_attr_t attr;
52         int ret;
53         int set_stacksize = 0;
54
55  retry:
56         ret = pthread_attr_init (&attr);
57         g_assert (ret == 0);
58
59 #if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
60         if (set_stacksize == 0) {
61                         ret = pthread_attr_setstacksize (&attr, MAX (65536, PTHREAD_STACK_MIN));
62                         g_assert (ret == 0);
63         } else if (set_stacksize == 1) {
64                         ret = pthread_attr_setstacksize (&attr, 131072);
65                         g_assert (ret == 0);
66         }
67 #endif
68
69         ret = pthread_create (&collection_thread_id, &attr, collection_thread,
70                               NULL);
71         if (ret != 0 && set_stacksize < 2) {
72                 set_stacksize++;
73                 goto retry;
74         }
75         if (ret != 0) {
76                 g_error ("%s: Couldn't create handle collection thread: %s",
77                          __func__, g_strerror (ret));
78         }
79 }
80
81 void _wapi_handle_collect (void)
82 {
83         guint32 count = _wapi_shared_layout->collection_count;
84         int i, thr_ret;
85
86         if (!_wapi_shm_enabled ())
87                 return;
88         
89         DEBUG ("%s: (%d) Starting a collection", __func__, _wapi_getpid ());
90
91         /* Become the collection master */
92         thr_ret = _wapi_handle_lock_shared_handles ();
93         g_assert (thr_ret == 0);
94         
95         thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
96         g_assert (thr_ret == 0);
97         
98         DEBUG ("%s: (%d) Master set", __func__, _wapi_getpid ());
99         
100         /* If count has changed, someone else jumped in as master */
101         if (count == _wapi_shared_layout->collection_count) {
102                 guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
103
104                 for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
105                         struct _WapiHandleShared *data;
106                         
107                         data = &_wapi_shared_layout->handles[i];
108                         if (data->timestamp < too_old) {
109                                 DEBUG ("%s: (%d) Deleting handle 0x%x", __func__, _wapi_getpid (), i);
110                                 memset (&_wapi_shared_layout->handles[i], '\0', sizeof(struct _WapiHandleShared));
111                         }
112                 }
113
114                 for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
115                         struct _WapiFileShare *file_share = &_wapi_fileshare_layout->share_info[i];
116                         
117                         if (file_share->timestamp < too_old) {
118                                 memset (file_share, '\0',
119                                         sizeof(struct _WapiFileShare));
120                         }
121                 }
122
123                 InterlockedIncrement ((gint32 *)&_wapi_shared_layout->collection_count);
124         }
125         
126         thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
127         g_assert (thr_ret == 0);
128         
129         _wapi_handle_unlock_shared_handles ();
130
131         DEBUG ("%s: (%d) Collection done", __func__, _wapi_getpid ());
132 }