2 * collection.c: Garbage collection for handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2004-2006 Novell, Inc.
14 #include <sys/types.h>
17 #include <mono/io-layer/wapi.h>
18 #include <mono/io-layer/collection.h>
19 #include <mono/io-layer/handles-private.h>
22 // #define LOGDEBUG(...) g_message(__VA_ARGS__)
24 static pthread_t collection_thread_id
;
26 static gpointer
collection_thread (gpointer unused G_GNUC_UNUSED
)
28 struct timespec sleepytime
;
30 sleepytime
.tv_sec
= _WAPI_HANDLE_COLLECTION_UPDATE_INTERVAL
;
31 sleepytime
.tv_nsec
= 0;
33 while (_wapi_has_shut_down
== FALSE
) {
34 nanosleep (&sleepytime
, NULL
);
36 //_wapi_handle_dump ();
37 _wapi_handle_update_refs ();
39 /* This is an abuse of the collection thread, but it's
40 * better than creating a new thread just for one more
43 _wapi_process_reap ();
51 void _wapi_collection_init (void)
55 int set_stacksize
= 0;
58 ret
= pthread_attr_init (&attr
);
61 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
62 if (set_stacksize
== 0) {
63 #if defined(__FreeBSD__) || defined(__NetBSD__)
64 ret
= pthread_attr_setstacksize (&attr
, 65536);
66 ret
= pthread_attr_setstacksize (&attr
, PTHREAD_STACK_MIN
);
69 } else if (set_stacksize
== 1) {
70 ret
= pthread_attr_setstacksize (&attr
, 131072);
75 ret
= pthread_create (&collection_thread_id
, &attr
, collection_thread
,
77 if (ret
!= 0 && set_stacksize
< 2) {
82 g_error ("%s: Couldn't create handle collection thread: %s",
83 __func__
, g_strerror (ret
));
87 void _wapi_handle_collect (void)
89 guint32 count
= _wapi_shared_layout
->collection_count
;
92 LOGDEBUG ("%s: (%d) Starting a collection", __func__
, _wapi_getpid ());
94 /* Become the collection master */
95 thr_ret
= _wapi_handle_lock_shared_handles ();
96 g_assert (thr_ret
== 0);
98 LOGDEBUG ("%s: (%d) Master set", __func__
, _wapi_getpid ());
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
;
104 for (i
= 0; i
< _WAPI_HANDLE_INITIAL_COUNT
; i
++) {
105 struct _WapiHandleShared
*data
;
107 data
= &_wapi_shared_layout
->handles
[i
];
108 if (data
->timestamp
< too_old
) {
109 LOGDEBUG ("%s: (%d) Deleting handle 0x%x", __func__
, _wapi_getpid (), i
);
110 memset (&_wapi_shared_layout
->handles
[i
], '\0', sizeof(struct _WapiHandleShared
));
114 for (i
= 0; i
< _wapi_fileshare_layout
->hwm
; i
++) {
115 struct _WapiFileShare
*file_share
= &_wapi_fileshare_layout
->share_info
[i
];
117 if (file_share
->timestamp
< too_old
) {
118 memset (file_share
, '\0',
119 sizeof(struct _WapiFileShare
));
123 InterlockedIncrement ((gint32
*)&_wapi_shared_layout
->collection_count
);
126 _wapi_handle_unlock_shared_handles ();
128 LOGDEBUG ("%s: (%d) Collection done", __func__
, _wapi_getpid ());