X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fio-layer%2Fhandles.c;h=4478bcbd731ee6b02ae56c79f85aba7f12c836a1;hb=bb42ee6c8ee5a1d04c1c962d701da19bfd52637b;hp=6af44cacb41c95140c032e1d943b3e9d24bf7fb0;hpb=42e254f05458e3abf2bd6869e01bc89184d3379c;p=mono.git diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 6af44cacb41..4478bcbd731 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -33,6 +33,8 @@ #undef DEBUG #undef DEBUG_REFS +static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer); + static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT]={0}; static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={ NULL, @@ -100,6 +102,8 @@ guint32 _wapi_fd_reserve; mono_mutex_t _wapi_global_signal_mutex; pthread_cond_t _wapi_global_signal_cond; +int _wapi_sem_id; + static mono_mutex_t scan_mutex = MONO_MUTEX_INITIALIZER; static mono_once_t shared_init_once = MONO_ONCE_INIT; @@ -117,10 +121,12 @@ static void shared_init (void) _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT; } while(_wapi_fd_reserve > _wapi_private_handle_count); - _wapi_shared_layout = _wapi_shm_attach (); + _wapi_shared_layout = _wapi_shm_attach (WAPI_SHM_DATA); g_assert (_wapi_shared_layout != NULL); + + _wapi_shm_semaphores_init (); - _wapi_fileshare_layout = _wapi_fileshare_shm_attach (); + _wapi_fileshare_layout = _wapi_shm_attach (WAPI_SHM_FILESHARE); g_assert (_wapi_fileshare_layout != NULL); _wapi_collection_init (); @@ -136,7 +142,6 @@ static void _wapi_handle_init_shared_metadata (struct _WapiHandleSharedMetadata { meta->timestamp = (guint32)(time (NULL) & 0xFFFFFFFF); meta->signalled = FALSE; - meta->checking = 0; } static void _wapi_handle_init_shared (struct _WapiHandleShared *handle, @@ -368,16 +373,21 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific) _wapi_handle_collect (); offset = _wapi_handle_new_shared (type, handle_specific); - /* FIXME: grow the arrays */ - return (_WAPI_HANDLE_INVALID); + if (offset == 0) { + /* FIXME: grow the arrays */ + return (_WAPI_HANDLE_INVALID); + } } ref = _wapi_handle_new_shared_offset (offset); if (ref == 0) { _wapi_handle_collect (); ref = _wapi_handle_new_shared_offset (offset); - /* FIXME: grow the arrays */ - return (_WAPI_HANDLE_INVALID); + + if (ref == 0) { + /* FIXME: grow the arrays */ + return (_WAPI_HANDLE_INVALID); + } } _WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = ref; @@ -390,9 +400,7 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific) return(handle); } -gpointer _wapi_handle_new_for_existing_ns (WapiHandleType type, - gpointer handle_specific, - guint32 offset) +gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset) { guint32 handle_idx = 0; gpointer handle; @@ -401,8 +409,8 @@ gpointer _wapi_handle_new_for_existing_ns (WapiHandleType type, mono_once (&shared_init_once, shared_init); #ifdef DEBUG - g_message ("%s: Creating new handle of type %s", __func__, - _wapi_handle_typename[type]); + g_message ("%s: Creating new handle of type %s to offset %d", __func__, + _wapi_handle_typename[type], offset); #endif g_assert(!_WAPI_FD_HANDLE(type)); @@ -431,7 +439,7 @@ gpointer _wapi_handle_new_for_existing_ns (WapiHandleType type, thr_ret = mono_mutex_lock (&scan_mutex); g_assert (thr_ret == 0); - while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) { + while ((handle_idx = _wapi_handle_new_internal (type, NULL)) == 0) { /* Try and expand the array, and have another go */ int idx = SLOT_INDEX (_wapi_private_handle_count); _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared, @@ -502,57 +510,6 @@ gpointer _wapi_handle_new_fd (WapiHandleType type, int fd, return(GUINT_TO_POINTER(fd)); } -gpointer _wapi_handle_new_from_offset (WapiHandleType type, int offset) -{ - guint32 handle_idx = 0; - gpointer handle; - int thr_ret; - struct _WapiHandle_shared_ref *ref; - struct _WapiHandleUnshared *handle_data; - - mono_once (&shared_init_once, shared_init); - -#ifdef DEBUG - g_message ("%s: Creating new handle of type %s to offset %d", __func__, - _wapi_handle_typename[type], offset); -#endif - - g_assert(_WAPI_SHARED_HANDLE(type)); - - pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, - (void *)&scan_mutex); - thr_ret = mono_mutex_lock (&scan_mutex); - g_assert(thr_ret == 0); - - while ((handle_idx = _wapi_handle_new_internal (type, NULL)) == 0) { - /* Try and expand the array, and have another go */ - int idx = SLOT_INDEX (_wapi_private_handle_count); - _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared, - _WAPI_HANDLE_INITIAL_COUNT); - - _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT; - } - - thr_ret = mono_mutex_unlock (&scan_mutex); - g_assert (thr_ret == 0); - pthread_cleanup_pop (0); - - /* Make sure we left the space for fd mappings */ - g_assert (handle_idx >= _wapi_fd_reserve); - - handle_data = &_WAPI_PRIVATE_HANDLES(handle_idx); - ref = &handle_data->u.shared; - ref->offset = offset; - - handle = GUINT_TO_POINTER (handle_idx); - -#ifdef DEBUG - g_message ("%s: Allocated new handle %p", __func__, handle); -#endif - - return (handle); -} - gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, gpointer *handle_specific) { @@ -680,8 +637,11 @@ gboolean _wapi_replace_handle (gpointer handle, WapiHandleType type, _wapi_handle_collect (); new_off = _wapi_handle_new_shared (type, handle_specific); - /* FIXME: grow the arrays */ - return (FALSE); + + if (new_off == 0) { + /* FIXME: grow the arrays */ + return (FALSE); + } } shared_handle_data = &_wapi_shared_layout->handles[new_off]; @@ -705,9 +665,44 @@ gboolean _wapi_replace_handle (gpointer handle, WapiHandleType type, return (TRUE); } -/* This will only find shared handles that have already been opened by - * this process. To look up shared handles by name, use - * _wapi_search_handle_namespace +void +_wapi_handle_foreach (WapiHandleType type, + gboolean (*on_each)(gpointer test, gpointer user), + gpointer user_data) +{ + struct _WapiHandleUnshared *handle_data = NULL; + gpointer ret = NULL; + guint32 i, k; + int thr_ret; + + pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, + (void *)&scan_mutex); + thr_ret = mono_mutex_lock (&scan_mutex); + g_assert (thr_ret == 0); + + for (i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) { + for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { + handle_data = &_wapi_private_handles [i][k]; + + if (handle_data->type == type) { + ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k); + if (on_each (ret, user_data) == TRUE) + break; + } + } + } + + thr_ret = mono_mutex_unlock (&scan_mutex); + g_assert (thr_ret == 0); + pthread_cleanup_pop (0); +} + +/* This might list some shared handles twice if they are already + * opened by this process, and the check function returns FALSE the + * first time. Shared handles that are created during the search are + * unreffed if the check function returns FALSE, so callers must not + * rely on the handle persisting (unless the check function returns + * TRUE) */ gpointer _wapi_search_handle (WapiHandleType type, gboolean (*check)(gpointer test, gpointer user), @@ -720,13 +715,13 @@ gpointer _wapi_search_handle (WapiHandleType type, gboolean found = FALSE; - for(i = SLOT_INDEX (0); !found && _wapi_private_handles [i] != NULL; i++) { + for (i = SLOT_INDEX (0); !found && _wapi_private_handles [i] != NULL; i++) { for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) { handle_data = &_wapi_private_handles [i][k]; - if(handle_data->type == type) { + if (handle_data->type == type) { ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k); - if(check (ret, user_data) == TRUE) { + if (check (ret, user_data) == TRUE) { found = TRUE; break; } @@ -734,6 +729,48 @@ gpointer _wapi_search_handle (WapiHandleType type, } } + if (!found) { + /* Not found yet, so search the shared memory too */ +#ifdef DEBUG + g_message ("%s: Looking at other shared handles...", __func__); +#endif + + for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) { + struct _WapiHandleShared *shared; + struct _WapiHandleSharedMetadata *meta; + WapiHandleType shared_type; + + _WAPI_HANDLE_COLLECTION_UNSAFE; + + meta = &_wapi_shared_layout->metadata[i]; + shared = &_wapi_shared_layout->handles[meta->offset]; + shared_type = shared->type; + + _WAPI_HANDLE_COLLECTION_SAFE; + + if (shared_type == type) { + ret = _wapi_handle_new_from_offset (type, i); + +#ifdef DEBUG + g_message ("%s: Opened tmp handle %p (type %s) from offset %d", __func__, ret, _wapi_handle_typename[type], meta->offset); +#endif + + if (check (ret, user_data) == TRUE) { + found = TRUE; + handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(ret)); + + break; + } + + /* This isn't the handle we're looking + * for, so drop the reference we took + * in _wapi_handle_new_from_offset () + */ + _wapi_handle_unref (ret); + } + } + } + if (!found) { goto done; } @@ -777,30 +814,6 @@ done: return(ret); } -/* This signature makes it easier to use in pthread cleanup handlers */ -int _wapi_namespace_timestamp_release (gpointer nowptr) -{ - guint32 now = GPOINTER_TO_UINT(nowptr); - - return (_wapi_timestamp_release (&_wapi_shared_layout->namespace_check, - now)); -} - -int _wapi_namespace_timestamp (guint32 now) -{ - int ret; - - do { - ret = _wapi_timestamp_exclusion (&_wapi_shared_layout->namespace_check, now); - /* sleep for a bit */ - if (ret == EBUSY) { - _wapi_handle_spin (100); - } - } while (ret == EBUSY); - - return(ret); -} - /* Returns the offset of the metadata array, or -1 on error, or 0 for * not found (0 is not a valid offset) */ @@ -813,7 +826,6 @@ gint32 _wapi_search_handle_namespace (WapiHandleType type, gint32 ret = 0; g_assert(_WAPI_SHARED_HANDLE(type)); - g_assert(_wapi_shared_layout->namespace_check != 0); #ifdef DEBUG g_message ("%s: Lookup for handle named [%s] type %s", __func__, @@ -914,13 +926,22 @@ void _wapi_handle_unref (gpointer handle) #endif if(destroy==TRUE) { + /* Need to copy the handle info, reset the slot in the + * array, and _only then_ call the close function to + * avoid race conditions (eg file descriptors being + * closed, and another file being opened getting the + * same fd racing the memset()) + */ + struct _WapiHandleUnshared handle_data; WapiHandleType type = _WAPI_PRIVATE_HANDLES(idx).type; + void (*close_func)(gpointer, gpointer) = _wapi_handle_ops_get_close_func (type); #ifdef DEBUG g_message ("%s: Destroying handle %p", __func__, handle); #endif - _wapi_handle_ops_close (handle); + memcpy (&handle_data, &_WAPI_PRIVATE_HANDLES(idx), + sizeof (struct _WapiHandleUnshared)); memset (&_WAPI_PRIVATE_HANDLES(idx).u, '\0', sizeof(_WAPI_PRIVATE_HANDLES(idx).u)); @@ -943,6 +964,10 @@ void _wapi_handle_unref (gpointer handle) /* The garbage collector will take care of shared data * if this is a shared handle */ + + if (close_func != NULL) { + close_func (handle, &handle_data.u); + } } } @@ -968,7 +993,17 @@ gboolean _wapi_handle_test_capabilities (gpointer handle, return((handle_caps[type] & caps) != 0); } -void _wapi_handle_ops_close (gpointer handle) +static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer) +{ + if (handle_ops[type] != NULL && + handle_ops[type]->close != NULL) { + return (handle_ops[type]->close); + } + + return (NULL); +} + +void _wapi_handle_ops_close (gpointer handle, gpointer data) { guint32 idx = GPOINTER_TO_UINT(handle); WapiHandleType type; @@ -977,7 +1012,7 @@ void _wapi_handle_ops_close (gpointer handle) if (handle_ops[type] != NULL && handle_ops[type]->close != NULL) { - handle_ops[type]->close (handle); + handle_ops[type]->close (handle, data); } } @@ -1059,8 +1094,7 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, gpointer *handles, gboolean waitall, guint32 *retcount, - guint32 *lowest, - guint32 *now) + guint32 *lowest) { guint32 count, i, iter=0; gboolean ret; @@ -1069,6 +1103,9 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, /* Lock all the handles, with backoff */ again: + thr_ret = _wapi_handle_lock_shared_handles (); + g_assert (thr_ret == 0); + for(i=0; i timeout->tv_sec) || + (fake_timeout.tv_sec == timeout->tv_sec && + fake_timeout.tv_nsec > timeout->tv_nsec))) { + /* Real timeout is less than 100ms time */ + ret=mono_cond_timedwait (cond, mutex, timeout); + } else { + ret=mono_cond_timedwait (cond, mutex, &fake_timeout); + + /* Mask the fake timeout, this will cause + * another poll if the cond was not really signaled + */ + if (ret==ETIMEDOUT) { + ret=0; + } + } + + return(ret); +} + int _wapi_handle_wait_signal (void) { - return(mono_cond_wait (&_wapi_global_signal_cond, - &_wapi_global_signal_mutex)); + return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, NULL); } int _wapi_handle_timedwait_signal (struct timespec *timeout) { - return(mono_cond_timedwait (&_wapi_global_signal_cond, - &_wapi_global_signal_mutex, - timeout)); + return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout); } int _wapi_handle_wait_signal_poll_share (void) { - struct timespec fake_timeout; - int ret; - #ifdef DEBUG g_message ("%s: poll private and shared handles", __func__); #endif - - _wapi_calc_timeout (&fake_timeout, 100); - ret = mono_cond_timedwait (&_wapi_global_signal_cond, - &_wapi_global_signal_mutex, &fake_timeout); - - if (ret == ETIMEDOUT) { - /* This will cause the waiting thread to check signal - * status for all handles - */ -#ifdef DEBUG - g_message ("%s: poll timed out, returning success", __func__); -#endif - - return (0); - } else { - /* This will be 0 indicating a private handle was - * signalled, or an error - */ -#ifdef DEBUG - g_message ("%s: returning: %d", __func__, ret); -#endif - - return (ret); - } + return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, NULL); } int _wapi_handle_timedwait_signal_poll_share (struct timespec *timeout) { - struct timespec fake_timeout; - guint32 signal_count = _wapi_shared_layout->signal_count; - int ret; - #ifdef DEBUG g_message ("%s: poll private and shared handles", __func__); #endif - do { - _wapi_calc_timeout (&fake_timeout, 100); - - if ((fake_timeout.tv_sec > timeout->tv_sec) || - (fake_timeout.tv_sec == timeout->tv_sec && - fake_timeout.tv_nsec > timeout->tv_nsec)) { - /* Real timeout is less than 100ms time */ - -#ifdef DEBUG - g_message ("%s: last few ms", __func__); -#endif - - 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, - &fake_timeout); - - /* Mask the fake timeout, this will cause - * another poll if the shared counter hasn't - * changed - */ - if (ret == ETIMEDOUT) { - ret = 0; - } else { - /* Either a private handle was - * signalled, or an error - */ -#ifdef DEBUG - g_message ("%s: returning: %d", __func__, ret); -#endif - return (ret); - } - } - - /* 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", - __func__); -#endif - return (0); - } - } while (ret != ETIMEDOUT); - -#ifdef DEBUG - g_message ("%s: returning ETIMEDOUT", __func__); -#endif - - return (ret); + return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout); } int _wapi_handle_wait_signal_handle (gpointer handle) { - guint32 idx = GPOINTER_TO_UINT(handle); - #ifdef DEBUG g_message ("%s: waiting for %p", __func__, handle); #endif - if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - while(1) { - if (WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) { - return (0); - } - - _wapi_handle_spin (100); - } - } else { - return(mono_cond_wait (&_WAPI_PRIVATE_HANDLES(idx).signal_cond, - &_WAPI_PRIVATE_HANDLES(idx).signal_mutex)); - } + return _wapi_handle_timedwait_signal_handle (handle, NULL); } int _wapi_handle_timedwait_signal_handle (gpointer handle, struct timespec *timeout) { - guint32 idx = GPOINTER_TO_UINT(handle); - #ifdef DEBUG g_message ("%s: waiting for %p (type %s)", __func__, handle, _wapi_handle_typename[_wapi_handle_type (handle)]); #endif if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) { - struct timespec fake_timeout; - - while (1) { - if (WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) { - return (0); - } - + if (WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) { + return (0); + } + if (timeout != NULL) { + struct timespec fake_timeout; _wapi_calc_timeout (&fake_timeout, 100); if ((fake_timeout.tv_sec > timeout->tv_sec) || - (fake_timeout.tv_sec == timeout->tv_sec && - fake_timeout.tv_nsec > timeout->tv_nsec)) { + (fake_timeout.tv_sec == timeout->tv_sec && + fake_timeout.tv_nsec > timeout->tv_nsec)) { /* FIXME: Real timeout is less than * 100ms time, but is it really worth * calculating to the exact ms? */ _wapi_handle_spin (100); - + if (WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) { return (0); } else { return (ETIMEDOUT); } - } else { - _wapi_handle_spin (100); } } + _wapi_handle_spin (100); + return (0); + } else { - return(mono_cond_timedwait (&_WAPI_PRIVATE_HANDLES(idx).signal_cond, &_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout)); + guint32 idx = GPOINTER_TO_UINT(handle); + return timedwait_signal_poll_cond (&_WAPI_PRIVATE_HANDLES(idx).signal_cond, &_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout); } } @@ -1422,14 +1357,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode, _WAPI_HANDLE_COLLECTION_UNSAFE; /* Prevent new entries racing with us */ - 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); + thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_SHARE); g_assert (thr_ret == 0); /* If a linear scan gets too slow we'll have to fit a hash @@ -1482,6 +1410,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode, file_share->device = device; file_share->inode = inode; + file_share->opened_by_pid = getpid (); file_share->sharemode = new_sharemode; file_share->access = new_access; file_share->handle_refs = 1; @@ -1493,13 +1422,34 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode, InterlockedExchange (&(*share_info)->timestamp, now); } - thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now); + thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_SHARE); _WAPI_HANDLE_COLLECTION_SAFE; return(exists); } +/* If we don't have the info in /proc, check if the process that + * opened this share info is still there (it's not a perfect method, + * due to pid reuse) + */ +static void _wapi_handle_check_share_by_pid (struct _WapiFileShare *share_info) +{ + if (kill (share_info->opened_by_pid, 0) == -1 && + (errno == ESRCH || + errno == EPERM)) { + /* It's gone completely (or there's a new process + * owned by someone else) so mark this share info as + * dead + */ +#ifdef DEBUG + g_message ("%s: Didn't find it, destroying entry", __func__); +#endif + + memset (share_info, '\0', sizeof(struct _WapiFileShare)); + } +} + /* Scan /proc//fd/ for open file descriptors to the file in * question. If there are none, reset the share info. * @@ -1509,16 +1459,14 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode, */ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) { - DIR *proc_dir; - struct dirent *proc_entry; gboolean found = FALSE, proc_fds = FALSE; pid_t self = getpid(); int pid; - guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF); - int thr_ret; + int thr_ret, i; - proc_dir = opendir ("/proc"); - if (proc_dir == NULL) { + /* If there is no /proc, there's nothing more we can do here */ + if (access ("/proc", F_OK) == -1) { + _wapi_handle_check_share_by_pid (share_info); return; } @@ -1528,28 +1476,29 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) _WAPI_HANDLE_COLLECTION_UNSAFE; /* Prevent new entries racing with us */ - 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); + thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_SHARE); g_assert (thr_ret == 0); - while ((proc_entry = readdir (proc_dir)) != NULL) { - /* We only care about numerically-named directories */ - pid = atoi (proc_entry->d_name); - if (pid != 0) { + for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) { + struct _WapiHandleShared *shared; + struct _WapiHandleSharedMetadata *meta; + struct _WapiHandle_process *process_handle; + + meta = &_wapi_shared_layout->metadata[i]; + shared = &_wapi_shared_layout->handles[meta->offset]; + + if (shared->type == WAPI_HANDLE_PROCESS) { + DIR *fd_dir; + struct dirent *fd_entry; + char subdir[_POSIX_PATH_MAX]; + + process_handle = &shared->u.process; + pid = process_handle->id; + /* Look in /proc//fd/ but ignore * /proc//fd/, as we have the * file open too */ - DIR *fd_dir; - struct dirent *fd_entry; - char subdir[_POSIX_PATH_MAX]; - g_snprintf (subdir, _POSIX_PATH_MAX, "/proc/%d/fd", pid); @@ -1557,6 +1506,10 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) if (fd_dir == NULL) { continue; } + +#ifdef DEBUG + g_message ("%s: Looking in %s", __func__, subdir); +#endif proc_fds = TRUE; @@ -1590,10 +1543,10 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) closedir (fd_dir); } } - - closedir (proc_dir); - if (found == FALSE && proc_fds == TRUE) { + if (proc_fds == FALSE) { + _wapi_handle_check_share_by_pid (share_info); + } else if (found == FALSE) { /* Blank out this entry, as it is stale */ #ifdef DEBUG g_message ("%s: Didn't find it, destroying entry", __func__); @@ -1602,7 +1555,7 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd) memset (share_info, '\0', sizeof(struct _WapiFileShare)); } - thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now); + thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_SHARE); _WAPI_HANDLE_COLLECTION_SAFE; } @@ -1620,9 +1573,11 @@ void _wapi_handle_dump (void) continue; } - g_print ("%3x [%7s] %s %d ", i, + g_print ("%3x [%7s] %s %d ", + i * _WAPI_HANDLE_INITIAL_COUNT + k, _wapi_handle_typename[handle_data->type], - handle_data->signalled?"Sg":"Un", handle_data->ref); + handle_data->signalled?"Sg":"Un", + handle_data->ref); handle_details[handle_data->type](&handle_data->u); g_print ("\n"); } @@ -1638,21 +1593,13 @@ static void _wapi_shared_details (gpointer handle_info) void _wapi_handle_update_refs (void) { - guint32 i, k, lock_now; + guint32 i, k; int thr_ret; _WAPI_HANDLE_COLLECTION_UNSAFE; /* Prevent file share entries racing with us */ - do { - lock_now = (guint32)(time(NULL) & 0xFFFFFFFF); - - thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, lock_now); - - if (thr_ret == EBUSY) { - _wapi_handle_spin (100); - } - } while (thr_ret == EBUSY); + thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_SHARE); g_assert(thr_ret == 0); for(i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) { @@ -1664,14 +1611,14 @@ void _wapi_handle_update_refs (void) struct _WapiHandleSharedMetadata *shared_meta; #ifdef DEBUG - g_message ("%s: (%d) handle 0x%x is SHARED", __func__, - getpid (), i); + g_message ("%s: (%d) handle 0x%x is SHARED (%s)", __func__, + getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k, _wapi_handle_typename[handle->type]); #endif shared_meta = &_wapi_shared_layout->metadata[handle->u.shared.offset]; #ifdef DEBUG - g_message ("%s: (%d) Updating timstamp of handle 0x%x", + g_message ("%s: (%d) Updating timestamp of handle 0x%x", __func__, getpid(), handle->u.shared.offset); #endif @@ -1682,7 +1629,7 @@ void _wapi_handle_update_refs (void) #ifdef DEBUG g_message ("%s: (%d) handle 0x%x is FILE", __func__, - getpid (), i); + getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k); #endif g_assert (file_handle->share_info != NULL); @@ -1698,6 +1645,7 @@ void _wapi_handle_update_refs (void) } } - thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, lock_now); + thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_SHARE); + _WAPI_HANDLE_COLLECTION_SAFE; }