2009-05-15 Geoff Norton <gnorton@novell.com>
[mono-project.git] / mono / io-layer / collection.c
blobc3e72f48cfe1385079e1f776bff4e11317d78430
1 /*
2 * collection.c: Garbage collection for handles
4 * Author:
5 * Dick Porter (dick@ximian.com)
7 * (C) 2004-2006 Novell, Inc.
8 */
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>
17 #include <mono/io-layer/wapi.h>
18 #include <mono/io-layer/collection.h>
19 #include <mono/io-layer/handles-private.h>
21 #undef DEBUG
23 static pthread_t collection_thread_id;
25 static gpointer collection_thread (gpointer unused G_GNUC_UNUSED)
27 struct timespec sleepytime;
29 sleepytime.tv_sec = _WAPI_HANDLE_COLLECTION_UPDATE_INTERVAL;
30 sleepytime.tv_nsec = 0;
32 while (_wapi_has_shut_down == FALSE) {
33 nanosleep (&sleepytime, NULL);
35 //_wapi_handle_dump ();
36 _wapi_handle_update_refs ();
38 /* This is an abuse of the collection thread, but it's
39 * better than creating a new thread just for one more
40 * function.
42 _wapi_process_reap ();
45 pthread_exit (NULL);
47 return(NULL);
50 void _wapi_collection_init (void)
52 pthread_attr_t attr;
53 int ret;
55 ret = pthread_attr_init (&attr);
56 g_assert (ret == 0);
58 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
59 #if defined(__FreeBSD__) || defined(__NetBSD__)
60 ret = pthread_attr_setstacksize (&attr, 65536);
61 #else
62 ret = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
63 #endif
64 g_assert (ret == 0);
65 #endif
67 ret = pthread_create (&collection_thread_id, &attr, collection_thread,
68 NULL);
69 if (ret != 0) {
70 g_error ("%s: Couldn't create handle collection thread: %s",
71 __func__, g_strerror (ret));
75 void _wapi_handle_collect (void)
77 guint32 count = _wapi_shared_layout->collection_count;
78 int i, thr_ret;
80 #ifdef DEBUG
81 g_message ("%s: (%d) Starting a collection", __func__,
82 _wapi_getpid ());
83 #endif
85 /* Become the collection master */
86 thr_ret = _wapi_handle_lock_shared_handles ();
87 g_assert (thr_ret == 0);
89 #ifdef DEBUG
90 g_message ("%s: (%d) Master set", __func__, _wapi_getpid ());
91 #endif
93 /* If count has changed, someone else jumped in as master */
94 if (count == _wapi_shared_layout->collection_count) {
95 guint32 too_old = (guint32)(time(NULL) & 0xFFFFFFFF) - _WAPI_HANDLE_COLLECTION_EXPIRED_INTERVAL;
97 for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
98 struct _WapiHandleShared *data;
100 data = &_wapi_shared_layout->handles[i];
101 if (data->timestamp < too_old) {
102 #ifdef DEBUG
103 g_message ("%s: (%d) Deleting handle 0x%x", __func__, _wapi_getpid (), i);
104 #endif
105 memset (&_wapi_shared_layout->handles[i], '\0', sizeof(struct _WapiHandleShared));
109 for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
110 struct _WapiFileShare *file_share = &_wapi_fileshare_layout->share_info[i];
112 if (file_share->timestamp < too_old) {
113 memset (file_share, '\0',
114 sizeof(struct _WapiFileShare));
118 InterlockedIncrement ((gint32 *)&_wapi_shared_layout->collection_count);
121 _wapi_handle_unlock_shared_handles ();
123 #ifdef DEBUG
124 g_message ("%s: (%d) Collection done", __func__, _wapi_getpid ());
125 #endif