*
* (C) 2002-2011 Novell, Inc.
* Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/shared.h>
-#include <mono/io-layer/collection.h>
#include <mono/io-layer/process-private.h>
+#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-once.h>
+#include <mono/utils/mono-logger-internals.h>
#undef DEBUG_REFS
-#if 0
-#define DEBUG(...) g_message(__VA_ARGS__)
-#else
-#define DEBUG(...)
-#endif
-
static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer);
static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT] = { (WapiHandleCapability)0 };
struct _WapiHandleSharedLayout *_wapi_shared_layout = NULL;
-/*
- * If SHM is enabled, this will point to shared memory, otherwise it will be NULL.
- */
-struct _WapiFileShareLayout *_wapi_fileshare_layout = NULL;
-
/*
* If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
* it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
gpointer handle = GINT_TO_POINTER (i*_WAPI_HANDLE_INITIAL_COUNT+j);
for(k = handle_data->ref; k > 0; k--) {
- DEBUG ("%s: unreffing %s handle %p", __func__, _wapi_handle_typename[type], handle);
-
_wapi_handle_unref_full (handle, TRUE);
}
}
_wapi_shm_semaphores_remove ();
- _wapi_shm_detach (WAPI_SHM_DATA);
- _wapi_shm_detach (WAPI_SHM_FILESHARE);
+ g_free (_wapi_shared_layout);
if (file_share_hash) {
g_hash_table_destroy (file_share_hash);
} while(_wapi_fd_reserve > _wapi_private_handle_count);
_wapi_shm_semaphores_init ();
-
- _wapi_shared_layout = (_WapiHandleSharedLayout *)_wapi_shm_attach (WAPI_SHM_DATA);
+
+ _wapi_shared_layout = (_WapiHandleSharedLayout *)g_malloc0 (sizeof (_WapiHandleSharedLayout));
g_assert (_wapi_shared_layout != NULL);
-
- if (_wapi_shm_enabled ()) {
- /* This allocates a 4mb array, so do it only if SHM is enabled */
- _wapi_fileshare_layout = (_WapiFileShareLayout *)_wapi_shm_attach (WAPI_SHM_FILESHARE);
- g_assert (_wapi_fileshare_layout != NULL);
- }
-
-#if !defined (DISABLE_SHARED_HANDLES)
- if (_wapi_shm_enabled ())
- _wapi_collection_init ();
-#endif
+
_wapi_io_init ();
mono_os_mutex_init (&scan_mutex);
g_assert (_wapi_has_shut_down == FALSE);
- DEBUG ("%s: Creating new handle of type %s", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
_wapi_handle_typename[type]);
g_assert(!_WAPI_FD_HANDLE(type));
handle = GUINT_TO_POINTER (handle_idx);
- DEBUG ("%s: Allocated new handle %p", __func__, handle);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p", __func__, handle);
if (_WAPI_SHARED_HANDLE(type)) {
/* Add the shared section too */
ref = _wapi_handle_new_shared (type, handle_specific);
if (ref == 0) {
- _wapi_handle_collect ();
ref = _wapi_handle_new_shared (type, handle_specific);
if (ref == 0) {
/* FIXME: grow the arrays */
}
_WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = ref;
- DEBUG ("%s: New shared handle at offset 0x%x", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New shared handle at offset 0x%x", __func__,
ref);
}
g_assert (_wapi_has_shut_down == FALSE);
- DEBUG ("%s: Creating new handle of type %s to offset %d", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s to offset %d", __func__,
_wapi_handle_typename[type], offset);
g_assert(!_WAPI_FD_HANDLE(type));
if (handle != INVALID_HANDLE_VALUE) {
_wapi_handle_ref (handle);
- DEBUG ("%s: Returning old handle %p referencing 0x%x",
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning old handle %p referencing 0x%x",
__func__, handle, offset);
return (handle);
}
if (shared->type == WAPI_HANDLE_UNUSED) {
/* Someone deleted this handle while we were working */
- DEBUG ("%s: Handle at 0x%x unused", __func__, offset);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle at 0x%x unused", __func__, offset);
goto done;
}
if (shared->type != type) {
- DEBUG ("%s: Wrong type at %d 0x%x! Found %s wanted %s",
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Wrong type at %d 0x%x! Found %s wanted %s",
__func__, offset, offset,
_wapi_handle_typename[shared->type],
_wapi_handle_typename[type]);
_WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = offset;
InterlockedIncrement ((gint32 *)&shared->handle_refs);
- DEBUG ("%s: Allocated new handle %p referencing 0x%x (shared refs %d)", __func__, handle, offset, shared->handle_refs);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p referencing 0x%x (shared refs %d)", __func__, handle, offset, shared->handle_refs);
done:
_wapi_handle_unlock_shared_handles ();
g_assert (_wapi_has_shut_down == FALSE);
- DEBUG ("%s: Creating new handle of type %s", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
_wapi_handle_typename[type]);
g_assert(_WAPI_FD_HANDLE(type));
g_assert(!_WAPI_SHARED_HANDLE(type));
if (fd >= _wapi_fd_reserve) {
- DEBUG ("%s: fd %d is too big", __func__, fd);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is too big", __func__, fd);
return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID));
}
handle = &_WAPI_PRIVATE_HANDLES(fd);
if (handle->type != WAPI_HANDLE_UNUSED) {
- DEBUG ("%s: fd %d is already in use!", __func__, fd);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is already in use!", __func__, fd);
/* FIXME: clean up this handle? We can't do anything
* with the fd, cos thats the new one
*/
}
- DEBUG ("%s: Assigning new fd handle %d", __func__, fd);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Assigning new fd handle %d", __func__, fd);
/* Prevent file share entries racing with us, when the file
* handle is only half initialised
if (!found && search_shared && _WAPI_SHARED_HANDLE (type)) {
/* Not found yet, so search the shared memory too */
- DEBUG ("%s: Looking at other shared handles...", __func__);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Looking at other shared handles...", __func__);
for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
shared = &_wapi_shared_layout->handles[i];
continue;
}
- DEBUG ("%s: Opened tmp handle %p (type %s) from offset %d", __func__, ret, _wapi_handle_typename[type], i);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opened tmp handle %p (type %s) from offset %d", __func__, ret, _wapi_handle_typename[type], i);
/* It's possible that the shared part
* of this handle has now been blown
g_assert(_WAPI_SHARED_HANDLE(type));
- DEBUG ("%s: Lookup for handle named [%s] type %s", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s", __func__,
utf8_name, _wapi_handle_typename[type]);
- /* Do a handle collection before starting to look, so that any
- * stale cruft gets removed
- */
- _wapi_handle_collect ();
-
thr_ret = _wapi_handle_lock_shared_handles ();
g_assert (thr_ret == 0);
continue;
}
- DEBUG ("%s: found a shared namespace handle at 0x%x (type %s)", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: found a shared namespace handle at 0x%x (type %s)", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
sharedns=(WapiSharedNamespace *)&shared_handle_data->u;
- DEBUG ("%s: name is [%s]", __func__, sharedns->name);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is [%s]", __func__, sharedns->name);
if (strcmp (sharedns->name, utf8_name) == 0) {
if (shared_handle_data->type != type) {
/* Its the wrong type, so fail now */
- DEBUG ("%s: handle 0x%x matches name but is wrong type: %s", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name but is wrong type: %s", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
ret = -1;
goto done;
} else {
- DEBUG ("%s: handle 0x%x matches name and type", __func__, i);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name and type", __func__, i);
ret = i;
goto done;
}
thr_ret = mono_os_mutex_lock (&scan_mutex);
- DEBUG ("%s: Destroying handle %p", __func__, handle);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Destroying handle %p", __func__, handle);
memcpy (&handle_data, &_WAPI_PRIVATE_HANDLES(idx),
sizeof (struct _WapiHandleUnshared));
type = _WAPI_PRIVATE_HANDLES(idx).type;
- DEBUG ("%s: testing 0x%x against 0x%x (%d)", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing 0x%x against 0x%x (%d)", __func__,
handle_caps[type], caps, handle_caps[type] & caps);
return((handle_caps[type] & caps) != 0);
gpointer handle = handles[i];
guint32 idx = GPOINTER_TO_UINT(handle);
- DEBUG ("%s: attempting to lock %p", __func__, handle);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempting to lock %p", __func__, handle);
type = _WAPI_PRIVATE_HANDLES(idx).type;
if (thr_ret != 0) {
/* Bummer */
- DEBUG ("%s: attempt failed for %p: %s", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt failed for %p: %s", __func__,
handle, strerror (thr_ret));
thr_ret = _wapi_handle_unlock_shared_handles ();
iter=1;
}
- DEBUG ("%s: Backing off for %d ms", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Backing off for %d ms", __func__,
iter*10);
_wapi_handle_spin (10 * iter);
}
}
- DEBUG ("%s: Locked all handles", __func__);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locked all handles", __func__);
count=0;
*lowest=numhandles;
type = _WAPI_PRIVATE_HANDLES(idx).type;
- DEBUG ("%s: Checking handle %p", __func__, handle);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Checking handle %p", __func__, handle);
if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) &&
(_wapi_handle_ops_isowned (handle) == TRUE)) ||
_WAPI_PRIVATE_HANDLES(idx).signalled == TRUE)) {
count++;
- DEBUG ("%s: Handle %p signalled", __func__,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p signalled", __func__,
handle);
if(*lowest>i) {
*lowest=i;
}
}
- DEBUG ("%s: %d event handles signalled", __func__, count);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %d event handles signalled", __func__, count);
if ((waitall == TRUE && count == numhandles) ||
(waitall == FALSE && count > 0)) {
ret=FALSE;
}
- DEBUG ("%s: Returning %d", __func__, ret);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning %d", __func__, ret);
*retcount=count;
for(i=0; i<numhandles; i++) {
gpointer handle = handles[i];
- DEBUG ("%s: unlocking handle %p", __func__, handle);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
thr_ret = _wapi_handle_unlock_handle (handle);
g_assert (thr_ret == 0);
int
_wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean alertable, gboolean poll, gboolean *alerted)
{
- DEBUG ("%s: waiting for %p (type %s)", __func__, handle,
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for %p (type %s)", __func__, handle,
_wapi_handle_typename[_wapi_handle_type (handle)]);
if (alertable)
void
_wapi_free_share_info (_WapiFileShare *share_info)
{
- if (!_wapi_shm_enabled ()) {
- file_share_hash_lock ();
- g_hash_table_remove (file_share_hash, share_info);
- file_share_hash_unlock ();
- /* The hashtable dtor frees share_info */
- } else {
- memset (share_info, '\0', sizeof(struct _WapiFileShare));
- }
+ file_share_hash_lock ();
+ g_hash_table_remove (file_share_hash, share_info);
+ file_share_hash_unlock ();
+ /* The hashtable dtor frees share_info */
}
static gint
struct _WapiFileShare **share_info)
{
struct _WapiFileShare *file_share;
- guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
- int thr_ret, i, first_unused = -1;
+ int thr_ret;
gboolean exists = FALSE;
/* Prevents entries from expiring under us as we search
thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
g_assert (thr_ret == 0);
- if (!_wapi_shm_enabled ()) {
- _WapiFileShare tmp;
-
- /*
- * Instead of allocating a 4MB array, we use a hash table to keep track of this
- * info. This is needed even if SHM is disabled, to track sharing inside
- * the current process.
- */
- if (!file_share_hash) {
- file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
- mono_os_mutex_init_recursive (&file_share_hash_mutex);
- }
-
- tmp.device = device;
- tmp.inode = inode;
+ _WapiFileShare tmp;
- file_share_hash_lock ();
+ /*
+ * Instead of allocating a 4MB array, we use a hash table to keep track of this
+ * info. This is needed even if SHM is disabled, to track sharing inside
+ * the current process.
+ */
+ if (!file_share_hash) {
+ file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
+ mono_os_mutex_init_recursive (&file_share_hash_mutex);
+ }
- file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
- if (file_share) {
- *old_sharemode = file_share->sharemode;
- *old_access = file_share->access;
- *share_info = file_share;
-
- InterlockedIncrement ((gint32 *)&file_share->handle_refs);
- exists = TRUE;
- } else {
- file_share = g_new0 (_WapiFileShare, 1);
+ tmp.device = device;
+ tmp.inode = inode;
- file_share->device = device;
- file_share->inode = inode;
- file_share->opened_by_pid = _wapi_getpid ();
- file_share->sharemode = new_sharemode;
- file_share->access = new_access;
- file_share->handle_refs = 1;
- *share_info = file_share;
+ file_share_hash_lock ();
- g_hash_table_insert (file_share_hash, file_share, file_share);
- }
+ file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
+ if (file_share) {
+ *old_sharemode = file_share->sharemode;
+ *old_access = file_share->access;
+ *share_info = file_share;
- file_share_hash_unlock ();
+ InterlockedIncrement ((gint32 *)&file_share->handle_refs);
+ exists = TRUE;
} else {
- /* If a linear scan gets too slow we'll have to fit a hash
- * table onto the shared mem backing store
- */
- *share_info = NULL;
- for (i = 0; i <= _wapi_fileshare_layout->hwm; i++) {
- file_share = &_wapi_fileshare_layout->share_info[i];
+ file_share = g_new0 (_WapiFileShare, 1);
- /* Make a note of an unused slot, in case we need to
- * store share info
- */
- if (first_unused == -1 && file_share->handle_refs == 0) {
- first_unused = i;
- continue;
- }
-
- if (file_share->handle_refs == 0) {
- continue;
- }
-
- if (file_share->device == device &&
- file_share->inode == inode) {
- *old_sharemode = file_share->sharemode;
- *old_access = file_share->access;
- *share_info = file_share;
-
- /* Increment the reference count while we
- * still have sole access to the shared area.
- * This makes the increment atomic wrt
- * collections
- */
- InterlockedIncrement ((gint32 *)&file_share->handle_refs);
-
- exists = TRUE;
- break;
- }
- }
-
- if (!exists) {
- if (i == _WAPI_FILESHARE_SIZE && first_unused == -1) {
- /* No more space */
- } else {
- if (first_unused == -1) {
- file_share = &_wapi_fileshare_layout->share_info[++i];
- _wapi_fileshare_layout->hwm = i;
- } else {
- file_share = &_wapi_fileshare_layout->share_info[first_unused];
- }
-
- file_share->device = device;
- file_share->inode = inode;
- file_share->opened_by_pid = _wapi_getpid ();
- file_share->sharemode = new_sharemode;
- file_share->access = new_access;
- file_share->handle_refs = 1;
- *share_info = file_share;
- }
- }
+ file_share->device = device;
+ file_share->inode = inode;
+ file_share->opened_by_pid = _wapi_getpid ();
+ file_share->sharemode = new_sharemode;
+ file_share->access = new_access;
+ file_share->handle_refs = 1;
+ *share_info = file_share;
- if (*share_info != NULL) {
- InterlockedExchange ((gint32 *)&(*share_info)->timestamp, now);
- }
+ g_hash_table_insert (file_share_hash, file_share, file_share);
}
+
+ file_share_hash_unlock ();
thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
* owned by someone else) so mark this share info as
* dead
*/
- DEBUG ("%s: Didn't find it, destroying entry", __func__);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't find it, destroying entry", __func__);
_wapi_free_share_info (share_info);
}
struct _WapiHandle_file *file_handle = &handle->u.file;
if (file_handle->share_info == share_info) {
- DEBUG ("%s: handle 0x%x has this file open!",
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x has this file open!",
__func__, i);
goto done;
_wapi_handle_check_share_by_pid (share_info);
} else if (found == FALSE) {
/* Blank out this entry, as it is stale */
- DEBUG ("%s: Didn't find it, destroying entry", __func__);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't find it, destroying entry", __func__);
_wapi_free_share_info (share_info);
}
g_print ("offset: 0x%x", shared->offset);
}
-
-void _wapi_handle_update_refs (void)
-{
- guint32 i, k;
- int thr_ret;
- guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF);
-
- thr_ret = _wapi_handle_lock_shared_handles ();
- g_assert (thr_ret == 0);
-
- /* Prevent file share entries racing with us */
- thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
- g_assert(thr_ret == 0);
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
-
- for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
- if (_wapi_private_handles [i]) {
- for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
- struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
-
- if (_WAPI_SHARED_HANDLE(handle->type)) {
- struct _WapiHandleShared *shared_data;
-
- DEBUG ("%s: (%d) handle 0x%x is SHARED (%s)", __func__, _wapi_getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k, _wapi_handle_typename[handle->type]);
-
- shared_data = &_wapi_shared_layout->handles[handle->u.shared.offset];
-
- DEBUG ("%s: (%d) Updating timestamp of handle 0x%x", __func__, _wapi_getpid (), handle->u.shared.offset);
-
- InterlockedExchange ((gint32 *)&shared_data->timestamp, now);
- } else if (handle->type == WAPI_HANDLE_FILE) {
- struct _WapiHandle_file *file_handle = &handle->u.file;
-
- DEBUG ("%s: (%d) handle 0x%x is FILE", __func__, _wapi_getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k);
-
- g_assert (file_handle->share_info != NULL);
-
- DEBUG ("%s: (%d) Inc refs on fileshare 0x%x", __func__, _wapi_getpid (), (file_handle->share_info - &_wapi_fileshare_layout->share_info[0]) / sizeof(struct _WapiFileShare));
-
- InterlockedExchange ((gint32 *)&file_handle->share_info->timestamp, now);
- }
- }
- }
- }
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
-
- _wapi_handle_unlock_shared_handles ();
-}
-