again:
/* FIXME: expandable array */
- /* FIXME: leave a few slots at the end so that there's always
- * space to move a handle. (Leave the space in the offset
- * table too, so we don't have to keep track of inter-segment
+ /* leave a few slots at the end so that there's always space
+ * to move a handle. (We leave the space in the offset table
+ * too, so we don't have to keep track of inter-segment
* offsets.)
*/
- for(i = last; i <_WAPI_HANDLE_INITIAL_COUNT; i++) {
+ for(i = last; i <_WAPI_HANDLE_INITIAL_COUNT - _WAPI_HEADROOM; i++) {
struct _WapiHandleSharedMetadata *meta = &_wapi_shared_layout->metadata[i];
if(meta->offset == 0) {
/* Leave the first slot empty as a guard */
again:
/* FIXME: expandable array */
- /* FIXME: leave a few slots at the end so that there's always
- * space to move a handle
+ /* Leave a few slots at the end so that there's always space
+ * to move a handle
*/
- for(offset = last; offset <_WAPI_HANDLE_INITIAL_COUNT; offset++) {
+ for(offset = last; offset <_WAPI_HANDLE_INITIAL_COUNT - _WAPI_HEADROOM;
+ offset++) {
struct _WapiHandleShared *handle = &_wapi_shared_layout->handles[offset];
if(handle->type == WAPI_HANDLE_UNUSED) {
handle_data = &_wapi_private_handles[handle_idx];
- if(handle_data->type != type) {
+ if (handle_data->type != type) {
return(FALSE);
}
- if(handle_specific == NULL) {
+ if (handle_specific == NULL) {
return(FALSE);
}
if (_WAPI_SHARED_HANDLE(type)) {
- struct _WapiHandle_shared_ref *ref = &handle_data->u.shared;
+ struct _WapiHandle_shared_ref *ref;
struct _WapiHandleShared *shared_handle_data;
struct _WapiHandleSharedMetadata *shared_meta;
-
- shared_meta = &_wapi_shared_layout->metadata[ref->offset];
- shared_handle_data = &_wapi_shared_layout->handles[shared_meta->offset];
+ guint32 offset;
- g_assert(shared_handle_data->type == type);
+ do {
+ ref = &handle_data->u.shared;
+ shared_meta = &_wapi_shared_layout->metadata[ref->offset];
+ offset = shared_meta->offset;
+ shared_handle_data = &_wapi_shared_layout->handles[offset];
- *handle_specific = &shared_handle_data->u;
+ g_assert(shared_handle_data->type == type);
+
+ *handle_specific = &shared_handle_data->u;
+ } while (offset != shared_meta->offset);
} else {
*handle_specific = &handle_data->u;
}
return(FALSE);
}
- _WAPI_HANDLE_COLLECTION_UNSAFE;
-
do {
ref = &handle_data->u.shared;
shared_meta = &_wapi_shared_layout->metadata[ref->offset];
sizeof(struct _WapiHandleShared));
} while (offset != shared_meta->offset);
- _WAPI_HANDLE_COLLECTION_SAFE;
-
#ifdef DEBUG
g_message ("%s: OK", __func__);
#endif
gpointer *handle_specific)
{
struct _WapiHandleUnshared *handle_data = NULL;
+ gpointer ret = NULL;
guint32 i;
+ /* Unsafe, because we don't want the handle to vanish while
+ * we're checking it
+ */
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
+
for(i = 0; i < _wapi_private_handle_count; i++) {
handle_data = &_wapi_private_handles[i];
if(handle_data->type == type) {
- if(check (GUINT_TO_POINTER (i), user_data) == TRUE) {
+ ret = GUINT_TO_POINTER (i);
+ if(check (ret, user_data) == TRUE) {
break;
}
}
}
if(i == _wapi_private_handle_count) {
- return(GUINT_TO_POINTER (0));
+ goto done;
}
if(handle_specific != NULL) {
if (_WAPI_SHARED_HANDLE(type)) {
- struct _WapiHandle_shared_ref *ref = &handle_data->u.shared;
+ struct _WapiHandle_shared_ref *ref ;
struct _WapiHandleShared *shared_handle_data;
struct _WapiHandleSharedMetadata *shared_meta;
+ guint32 offset, now;
- shared_meta = &_wapi_shared_layout->metadata[ref->offset];
- shared_handle_data = &_wapi_shared_layout->handles[shared_meta->offset];
+ do {
+ ref = &handle_data->u.shared;
+ shared_meta = &_wapi_shared_layout->metadata[ref->offset];
+ offset = shared_meta->offset;
+ shared_handle_data = &_wapi_shared_layout->handles[offset];
- g_assert(shared_handle_data->type == type);
+ g_assert(shared_handle_data->type == type);
- *handle_specific = &shared_handle_data->u;
+ *handle_specific = &shared_handle_data->u;
+ } while (offset != shared_meta->offset);
+
+ /* Make sure this handle doesn't vanish in the
+ * next collection
+ */
+ now = (guint32)(time (NULL) & 0xFFFFFFFF);
+ InterlockedExchange (&shared_meta->timestamp, now);
} else {
*handle_specific = &handle_data->u;
}
}
+
+done:
+ _WAPI_HANDLE_COLLECTION_SAFE;
- return(GUINT_TO_POINTER (i));
+ return(ret);
}
/* This signature makes it easier to use in pthread cleanup handlers */
do {
ret = _wapi_timestamp_exclusion (&_wapi_shared_layout->namespace_check, now);
/* sleep for a bit */
- _wapi_handle_spin (100);
+ if (ret == EBUSY) {
+ _wapi_handle_spin (100);
+ }
} while (ret == EBUSY);
return(ret);
guint32 idx = GPOINTER_TO_UINT(handle);
InterlockedIncrement (&_wapi_private_handles[idx].ref);
- /* Do shared part */
#ifdef DEBUG_REFS
g_message ("%s: handle %p ref now %d", __func__, handle,
void _wapi_handle_register_capabilities (WapiHandleType type,
WapiHandleCapability caps)
{
- handle_caps[type]=caps;
+ handle_caps[type] = caps;
}
gboolean _wapi_handle_test_capabilities (gpointer handle,
*/
gboolean CloseHandle(gpointer handle)
{
- if (handle == NULL) {
- return(FALSE);
- }
-
_wapi_handle_unref (handle);
return(TRUE);
ret = mono_cond_timedwait (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex,
timeout);
+ /* If this times out, it will compare the
+ * shared signal counter and then if that
+ * hasn't increased will fall out of the
+ * do-while loop.
+ */
+ if (ret != ETIMEDOUT) {
+ /* Either a private handle was
+ * signalled, or an error.
+ */
+#ifdef DEBUG
+ g_message ("%s: returning: %d", __func__, ret);
+#endif
+ return (ret);
+ }
} else {
ret = mono_cond_timedwait (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex,
*/
if (ret == ETIMEDOUT) {
ret = 0;
- }
- }
-
- if (ret != ETIMEDOUT) {
- /* Either a private handle was signalled, or
- * an error
- */
+ } else {
+ /* Either a private handle was
+ * signalled, or an error
+ */
#ifdef DEBUG
- g_message ("%s: returning: %d", __func__, ret);
+ g_message ("%s: returning: %d", __func__, ret);
#endif
- return (ret);
+ return (ret);
+ }
}
- /* Check the shared signal counter */
+ /* No private handle was signalled, so check the
+ * shared signal counter
+ */
if (signal_count != _wapi_shared_layout->signal_count) {
#ifdef DEBUG
g_message ("%s: A shared handle was signalled",
_WAPI_HANDLE_COLLECTION_UNSAFE;
/* Prevent new entries racing with us */
- thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ do {
+ now = (guint32)(time(NULL) & 0xFFFFFFFF);
+
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ if (thr_ret == EBUSY) {
+ _wapi_handle_spin (100);
+ }
+ } while (thr_ret == EBUSY);
g_assert (thr_ret == 0);
/* If a linear scan gets too slow we'll have to fit a hash
}
thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now);
- g_assert (thr_ret == 0);
_WAPI_HANDLE_COLLECTION_SAFE;
_WAPI_HANDLE_COLLECTION_UNSAFE;
/* Prevent new entries racing with us */
- thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ do {
+ now = (guint32)(time(NULL) & 0xFFFFFFFF);
+
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ if (thr_ret == EBUSY) {
+ _wapi_handle_spin (100);
+ }
+ } while (thr_ret == EBUSY);
g_assert (thr_ret == 0);
while ((proc_entry = readdir (proc_dir)) != NULL) {
}
thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now);
- g_assert (thr_ret == 0);
_WAPI_HANDLE_COLLECTION_SAFE;
}