noinst_LTLIBRARIES = libwapi.la
INCLUDES = \
+ -Werror \
$(GLIB_CFLAGS) \
$(GMODULE_CFLAGS) \
$(LIBGC_CFLAGS) \
OTHER_H = \
access.h \
atomic.h \
+ collection.h \
context.h \
critical-sections.h \
error.h \
access.h \
atomic.c \
atomic.h \
+ collection.c \
+ collection.h \
context.c \
context.h \
critical-sections.c \
critical-sections.h \
- daemon.c \
- daemon-private.h \
- daemon-messages.c \
- daemon-messages.h \
error.c \
error.h \
events.c \
static void spin_init(void)
{
- g_warning("Using non-atomic functions!");
+ g_warning("Using non-atomic functions! Expect race conditions when using process-shared handles!");
}
gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
--- /dev/null
+/*
+ * collection.c: Garbage collection for handles
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * (C) 2004 Novell, Inc.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <mono/io-layer/wapi.h>
+#include <mono/io-layer/collection.h>
+#include <mono/io-layer/handles-private.h>
+
+#undef DEBUG
+
+volatile guint32 _wapi_collection_unsafe = 0;
+volatile guint32 _wapi_collecting = 0;
+
+static void collection_signal (int sig, siginfo_t *info, void *context)
+{
+ union sigval val;
+ sigset_t sig_mask;
+
+#ifdef DEBUG
+ /* This is certainly not reentrant, but as it's just my debug
+ * code it doesn't really matter
+ */
+ g_message ("Collection signal received.");
+ g_message ("signo: %d", info->si_signo);
+ g_message ("errno: %d", info->si_errno);
+ g_message ("code : %d (SI_QUEUE = %d)", info->si_code, SI_QUEUE);
+ g_message ("pid : %d", info->si_pid);
+ g_message ("uid : %d", info->si_uid);
+ g_message ("value: %d", info->si_value.sival_int);
+ g_message ("int : %d", info->si_int);
+#endif
+
+ switch(info->si_int) {
+ case COLLECTION_READY:
+ /* PREPARE, sent by master */
+#ifdef DEBUG
+ g_message ("%s: (%d) Been told to get ready for a collection",
+ __func__, getpid());
+#endif
+
+ /* Set the global flag so that other threads know not
+ * to enter unsafe code
+ */
+ while ((InterlockedCompareExchange (&_wapi_collection_unsafe,
+ 1, 0)) != 0) {
+ /* We can't sleep, we're in a signal handler,
+ * so we'll just have to spin and hope the
+ * unsafe code finishes soon :-(
+ */
+ }
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Ack ready to collect", __func__,
+ getpid());
+#endif
+
+ /* Tell the master process that we're ready */
+ val.sival_int = COLLECTION_ACK;
+ sigqueue (info->si_pid, _WAPI_COLLECTION_SIGNAL, val);
+
+ sigfillset (&sig_mask);
+ sigdelset (&sig_mask, _WAPI_COLLECTION_PREPARE);
+ sigdelset (&sig_mask, _WAPI_COLLECTION_SIGNAL);
+
+ /* Wait for the next signal, which should be START.
+ *
+ * This should really be a timed wait (there's a
+ * window here for the master process to crash and
+ * leave this process stuck waiting), but
+ * sigtimedwait() is not safe to call in a signal
+ * handler. The best way to deal with this (as
+ * recommended by Butenhof) would be to use a
+ * dedicated thread to run all handle GC activities,
+ * then I wouldn't need a signal handler at all - the
+ * combination of pthread_sigmask and
+ * sigwaitinfo()/sigtimedwait() would ensure that the
+ * thread received the signals
+ */
+ sigsuspend (&sig_mask);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Ack suspend done", __func__, getpid());
+#endif
+
+ break;
+
+ case COLLECTION_ACK:
+ /* SIGNAL, sent to master */
+ /* This is only here for completeness and
+ * documentation; the master has this signal masked
+ * globally, and the collection function calls
+ * sigtimedwait() to receive it.
+ */
+ g_error ("%s: _WAPI_COLLECTION_SIGNAL wasn't properly masked!",
+ __func__);
+ break;
+
+ case COLLECTION_START:
+ /* SIGNAL, sent by master */
+#ifdef DEBUG
+ g_message ("%s: (%d) Been told to start a collection",
+ __func__, getpid());
+#endif
+
+ /* Add all our refs */
+ _wapi_handle_update_refs ();
+
+ /* Tell the master process that we've finished */
+ InterlockedDecrement (&_wapi_shared_layout->collection_signal_done);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Refs update done", __func__, getpid());
+#endif
+
+ sigfillset (&sig_mask);
+ sigdelset (&sig_mask, _WAPI_COLLECTION_PREPARE);
+ sigdelset (&sig_mask, _WAPI_COLLECTION_SIGNAL);
+
+ /* Wait for the next signal, which should be DONE */
+ sigsuspend (&sig_mask);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Start suspend done", __func__, getpid());
+#endif
+ break;
+
+ case COLLECTION_DONE:
+ /* SIGNAL, sent by master */
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Collection is complete",
+ __func__, getpid());
+#endif
+
+ /* Clear the global flag so that other threads know
+ * it's now OK to enter unsafe code
+ */
+ InterlockedDecrement (&_wapi_collection_unsafe);
+
+ break;
+
+ case COLLECTION_DUMP:
+ /* Debugging aid */
+#ifdef DEBUG
+ _wapi_handle_dump ();
+#endif
+ break;
+
+ case COLLECTION_FORCE:
+ /* Debugging aid */
+#ifdef DEBUG
+ _wapi_handle_collect ();
+#endif
+ break;
+ }
+}
+
+void _wapi_collection_init (void)
+{
+ struct sigaction act;
+ sigset_t procmask;
+
+ /* Globally block the collection signal, so that it can be
+ * waited for with sigtimedwait() in a particular thread
+ */
+ sigemptyset (&procmask);
+ sigaddset (&procmask, _WAPI_COLLECTION_SIGNAL);
+ sigprocmask (SIG_BLOCK, &procmask, NULL);
+
+ /* And in all threads that we create. ASSUMPTION: this is the
+ * main thread, and all new threads will be ancestors of this
+ * one.
+ */
+ pthread_sigmask (SIG_BLOCK, &procmask, NULL);
+
+ act.sa_sigaction = collection_signal;
+ sigemptyset (&act.sa_mask);
+
+ act.sa_flags = SA_SIGINFO | SA_NODEFER;
+
+ sigaction (_WAPI_COLLECTION_PREPARE, &act, NULL);
+ sigaction (_WAPI_COLLECTION_SIGNAL, &act, NULL);
+}
+
+struct _wapi_collection_pids
+{
+ pid_t pid;
+ gboolean is_mono;
+};
+
+static void wait_for_signals (struct _wapi_collection_pids *pids,
+ guint32 batch_count, guint32 pid_high)
+{
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ sigset_t sig_mask;
+ siginfo_t info;
+ struct timespec timeout;
+ guint32 ack_count = 0;
+ int i;
+
+#ifdef DEBUG
+ g_message ("%s: Checking pids to index %d", __func__, pid_high - 1);
+#endif
+
+ sigemptyset (&sig_mask);
+ sigaddset (&sig_mask, _WAPI_COLLECTION_SIGNAL);
+
+ /* This is a relative timeout, not absolute like some
+ * threading functions. sigtimedwait() doesn't modify the
+ * timeout parameter like select() does, either.
+ */
+ timeout.tv_sec = 2;
+ timeout.tv_nsec = 0;
+
+ do {
+ int ret = sigtimedwait (&sig_mask, &info, &timeout);
+ if (ret == -1 ) {
+#ifdef DEBUG
+ g_message ("%s: (%d) sigtimedwait error: %s", __func__,
+ getpid (), strerror(errno));
+#endif
+ } else if (info.si_int == COLLECTION_ACK) {
+#ifdef DEBUG
+ g_message ("%s: (%d) sigtimedwait ACK signal: %d (%d) from %d", __func__, getpid (), ret, _WAPI_COLLECTION_SIGNAL, info.si_pid);
+#endif
+ for (i = 0; i < pid_high; i++) {
+ if (pids[i].pid == info.si_pid) {
+ pids[i].is_mono = TRUE;
+ break;
+ }
+ }
+
+ ack_count++;
+ } else {
+ /* Bogus response, ignore this process */
+#ifdef DEBUG
+ g_message ("%s: (%d) sigtimedwait bogus (%d) signal: %d (%d) from %d", __func__, getpid (), info.si_int, ret, _WAPI_COLLECTION_SIGNAL, info.si_pid);
+#endif
+ ack_count++;
+ }
+#ifdef DEBUG
+ g_message ("%s: (%d) batch_count: %d ack_count: %d", __func__,
+ getpid (), batch_count, ack_count);
+#endif
+ } while (batch_count > ack_count &&
+ now + 2 > (time(NULL) & 0xFFFFFFFF));
+
+#ifdef DEBUG
+ if (ack_count == batch_count) {
+ g_message ("%s: (%d) All processes ACKed in this batch",
+ __func__, getpid ());
+ } else {
+ g_message ("%s: (%d) %d processes outstanding at ACK in this batch!!", __func__, getpid (), batch_count - ack_count);
+ }
+#endif
+}
+
+static struct _wapi_collection_pids *find_pids (guint32 *proc_count)
+{
+ int i;
+ struct _wapi_collection_pids *pids;
+ guint32 pid_count, batch_count;
+
+ pid_t self = getpid();
+ union sigval val;
+
+ /* Find the upper bound of the process count (some of these
+ * might be dead or non-mono if the pid has been reused)
+ */
+ *proc_count = 0;
+ for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
+ struct _WapiHandleShared *shared;
+
+ shared = &_wapi_shared_layout->handles[i];
+ if (shared->type == WAPI_HANDLE_PROCESS) {
+ (*proc_count)++;
+ }
+ }
+
+ pids = g_new0 (struct _wapi_collection_pids, *proc_count);
+
+#ifdef DEBUG
+ g_message ("%s: Finding pids in %d chunks", __func__,
+ (*proc_count / _POSIX_SIGQUEUE_MAX) + 1);
+#endif
+
+ /* Scan the list for processes to signal. Do this in chunks
+ * of _POSIX_SIGQUEUE_MAX, because the reply signals have to
+ * be queued up by this process.
+ */
+ pid_count = 0;
+ batch_count = 0;
+ for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
+ struct _WapiHandleShared *shared;
+
+ shared = &_wapi_shared_layout->handles[i];
+ if (shared->type == WAPI_HANDLE_PROCESS) {
+ struct _WapiHandle_process *proc = &shared->u.process;
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Found process %d", __func__, self,
+ proc->id);
+#endif
+
+ if (proc->id == self) {
+ /* Don't signal ourselves! */
+ continue;
+ }
+
+ if (kill (proc->id, 0) == -1) {
+ /* This process no longer exists, or
+ * we can't signal it anyway, so don't
+ * bother.
+ */
+ continue;
+ }
+
+ pids[pid_count].pid = proc->id;
+
+ val.sival_int = COLLECTION_READY;
+ sigqueue (proc->id, _WAPI_COLLECTION_PREPARE, val);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Signalled %d", __func__, self,
+ proc->id);
+#endif
+
+ batch_count++;
+
+ if (++pid_count % _POSIX_SIGQUEUE_MAX == 0) {
+ /* Wait for this batch to check in */
+ wait_for_signals (pids, batch_count,
+ pid_count);
+ batch_count = 0;
+ }
+ }
+ }
+
+ if (batch_count > 0) {
+ wait_for_signals (pids, batch_count, pid_count);
+ }
+
+ return(pids);
+}
+
+void _wapi_handle_collect (void)
+{
+ guint32 now;
+ guint32 count = _wapi_shared_layout->collection_count;
+ union sigval val;
+ int thr_ret, i;
+ guint32 proc_count;
+ struct _wapi_collection_pids *pids;
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Starting a collection", __func__, getpid ());
+#endif
+
+ do {
+ /* Become the collection master */
+ now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_shared_layout->master, now);
+ if (thr_ret == EBUSY) {
+ /* we will eventually usurp the master role,
+ * if the previous one is taking too long.
+ */
+ _wapi_handle_spin (100);
+ }
+ } while (thr_ret == EBUSY);
+ g_assert(thr_ret == 0);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Master set", __func__, getpid ());
+#endif
+
+ _wapi_shared_layout->collection_signal_done = 0;
+
+ pids = find_pids(&proc_count);
+
+ /* From here on we know exactly which other processes are
+ * really mono, because they've told us.
+ */
+
+ /* Zero every shared refcount */
+ for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
+ struct _WapiHandleSharedMetadata *meta;
+
+ meta = &_wapi_shared_layout->metadata[i];
+ meta->ref = 0;
+ }
+
+ /* And every file share refcount */
+ for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
+ struct _WapiFileShare *share;
+
+ share = &_wapi_fileshare_layout->share_info[i];
+ share->handle_refs = 0;
+ }
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Zerod all refs", __func__, getpid ());
+#endif
+
+ /* Scan the list for processes to signal to start updating
+ */
+ val.sival_int = COLLECTION_START;
+ for (i = 0; i < proc_count; i++) {
+ if (pids[i].is_mono) {
+ sigqueue (pids[i].pid, _WAPI_COLLECTION_SIGNAL, val);
+ InterlockedIncrement (&_wapi_shared_layout->collection_signal_done);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Signalled %d", __func__,
+ getpid (), pids[i].pid);
+#endif
+ }
+ }
+
+ /* Add our own refs */
+ _wapi_handle_update_refs ();
+
+ /* And wait for the other processes to signal that they've
+ * updated theirs
+ */
+ do {
+ /* Sleep for a bit, and then break out. 2 seconds
+ * ought to be major overkill
+ */
+ _wapi_handle_spin (100);
+ } while (_wapi_shared_layout->collection_signal_done > 0 &&
+ now + 2 > (time(NULL) & 0xFFFFFFFF));
+
+#ifdef DEBUG
+ if (_wapi_shared_layout->collection_signal_done == 0) {
+ g_message ("%s: (%d) All processes reported in", __func__,
+ getpid ());
+ } else {
+ g_message ("%s: (%d) %d processes outstanding!!", __func__,
+ getpid (),
+ _wapi_shared_layout->collection_signal_done);
+ }
+#endif
+
+ if (count == _wapi_shared_layout->collection_count) {
+ for (i = 0; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
+ struct _WapiHandleShared *shared;
+ struct _WapiHandleSharedMetadata *meta;
+
+ meta = &_wapi_shared_layout->metadata[i];
+ if (meta->ref == 0 && meta->offset != 0) {
+#ifdef DEBUG
+ g_message ("%s: (%d) Deleting metadata slot 0x%x handle 0x%x", __func__, getpid (), i, meta->offset);
+#endif
+ memset (&_wapi_shared_layout->handles[meta->offset], '\0', sizeof(struct _WapiHandleShared));
+ memset (&_wapi_shared_layout->metadata[i], '\0', sizeof(struct _WapiHandleSharedMetadata));
+ }
+
+ /* Need to blank any handles data that is no
+ * longer pointed to by a metadata entry too
+ */
+ shared = &_wapi_shared_layout->handles[i];
+ if (shared->stale == TRUE) {
+#ifdef DEBUG
+ g_message ("%s: (%d) Deleting stale handle 0x%x", __func__, getpid (), i);
+#endif
+ memset (&_wapi_shared_layout->handles[i], '\0',
+ sizeof(struct _WapiHandleShared));
+ }
+ }
+
+ for (i = 0; i < _wapi_fileshare_layout->hwm; i++) {
+ struct _WapiFileShare *file_share = &_wapi_fileshare_layout->share_info[i];
+
+ if (file_share->handle_refs == 0) {
+ memset (file_share, '\0',
+ sizeof(struct _WapiFileShare));
+ }
+ }
+
+ InterlockedIncrement (&_wapi_shared_layout->collection_count);
+ }
+
+ /* Scan the list for processes to signal that collection is
+ * done. Signal everyone, not just mono processes (with the
+ * _PREPARE signal) just in case a mono process failed to
+ * check in in time, and is now stuck suspended waiting for
+ * the _START signal. (If this does happen it probably wont
+ * survive much longer - chances are its handles were blown
+ * away cos it didn't get told to add the ref counts...)
+ */
+ val.sival_int = COLLECTION_DONE;
+ for (i = 0; i < proc_count; i++) {
+ /* Some entries might have pid == 0, as the array
+ * length is the total number of entries in the shared
+ * memory, not just the valid processes.
+ */
+ if (pids[i].pid) {
+ sigqueue (pids[i].pid, _WAPI_COLLECTION_PREPARE, val);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Signalled %d", __func__,
+ getpid (), pids[i].pid);
+#endif
+ }
+ }
+
+ g_free (pids);
+
+ thr_ret = _wapi_timestamp_release (&_wapi_shared_layout->master, now);
+ g_assert (thr_ret == 0);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Collection done", __func__, getpid ());
+#endif
+}
--- /dev/null
+/*
+ * collection.h: Garbage collection for handles
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ *
+ * (C) 2004 Novell, Inc.
+ */
+
+#ifndef _WAPI_COLLECTION_H_
+#define _WAPI_COLLECTION_H_
+
+#include <glib.h>
+#include <signal.h>
+
+/* This needs to be a signal that is ignored by default, as we might
+ * be sending it accidentally to non-mono processes
+ */
+#define _WAPI_COLLECTION_PREPARE SIGWINCH
+
+/* This needs to be a real-time signal, because several will be queued
+ * up
+ */
+#define _WAPI_COLLECTION_SIGNAL SIGRTMIN+4 /* LinuxThreads uses the first 3 */
+
+/* The collection protocol:
+ *
+ * 1) A process decides that a handle collection is necessary, and
+ * atomically assigns the master slot in the shared memory. If it
+ * can't get the master slot, it saves the current collection count
+ * and retries until it can, or until n seconds have elapsed (to cope
+ * with a master that crashed.) If the collection count hasn't
+ * increased, it goes ahead. Otherwise it returns, as someone else
+ * has done a collection.
+ *
+ * 2) It sends every process with a Process handle entry a
+ * WAPI_COLLECTION_PREPARE signal with COLLECTION_START in the
+ * siginfo_t intval. Other processes that are in unsafe code will
+ * have the signal delayed until it is safe to respond. Processes
+ * respond by sending back a WAPI_COLLECTION_SIGNAL signal with
+ * COLLECTION_ACK in the siginfo_t intval.
+ *
+ * 3) The master waits for the ACK signals, or times out after n
+ * seconds. It then zeros every shared handle refcount and every
+ * fileshare refcount and signals every process that responded (now
+ * known to be capable of receiving the signal) with COLLECTION_START
+ * in the siginfo_t intval.
+ *
+ * 4) All processes (including the master) atomically add their own
+ * ref count to each referenced shared handle
+ *
+ * 5) All other processes inform the master that they have finished by
+ * decrementing the "signal_done" field in the shared memory
+ * structure. The master will time out after n seconds, to cope with
+ * other processes quitting mid-process. Other processes that are in
+ * unsafe code will have the START signal delayed until it is safe to
+ * respond, so unsafe areas should be kept small.
+ *
+ * 6) If the collection count hasn't increased (someone else might
+ * have decided the master took too long and assumed control), the
+ * master deletes all shared slots with zero refs, and atomically
+ * increments the collection count slot. The master then signals
+ * every process with COLLECTION_DONE.
+ */
+
+typedef enum {
+ COLLECTION_READY = 1,
+ COLLECTION_ACK = 2,
+ COLLECTION_START = 3,
+ COLLECTION_DONE = 4,
+ COLLECTION_DUMP = 5,
+ COLLECTION_FORCE = 6
+} _wapi_collection_command;
+
+extern volatile guint32 _wapi_collection_unsafe;
+
+/* Prevent a handle collection from happening in unsafe code **in this
+ * thread**. Another thread will get this signal, if it happens. The
+ * collection code will wait for the unsafe flag to be 0 before
+ * starting a collection.
+ *
+ * Using just one flag for "unsafe code" and "collecting" means that
+ * unsafe sections are serialised, and therefore a bottleneck, but it
+ * avoids the race condition between checking two flags.
+ */
+
+#define _WAPI_HANDLE_BLOCK_IF_COLLECTING \
+ if (_wapi_collection_unsafe) { \
+ do { \
+ _wapi_handle_spin (100); \
+ } while (_wapi_collection_unsafe); \
+ }
+
+#define _WAPI_HANDLE_COLLECTION_UNSAFE \
+ { \
+ sigset_t _wapi_new_procmask; \
+ sigset_t _wapi_old_procmask; \
+ guint32 _wapi_save_start; \
+ \
+ _WAPI_HANDLE_BLOCK_IF_COLLECTING; \
+ \
+ _wapi_save_start = (guint32)(time(NULL) & 0xFFFFFFFF); \
+ \
+ sigemptyset (&_wapi_new_procmask); \
+ sigaddset (&_wapi_new_procmask, _WAPI_COLLECTION_PREPARE); \
+ pthread_sigmask (SIG_BLOCK, &_wapi_new_procmask, \
+ &_wapi_old_procmask); \
+ \
+ while ((InterlockedCompareExchange (&_wapi_collection_unsafe, 1, 0)) != 0) { \
+ _wapi_handle_spin (10); \
+ }
+
+
+#define _WAPI_HANDLE_COLLECTION_SAFE \
+ InterlockedDecrement (&_wapi_collection_unsafe); \
+ pthread_sigmask (SIG_SETMASK, &_wapi_old_procmask, NULL); \
+ \
+ if (_wapi_save_start + 2 < (time(NULL) & 0xFFFFFFFF)) { \
+ g_warning ("%s: Took more than 2 seconds in unsafe code, shared handle collection might break", __func__); \
+ } \
+ }
+
+
+extern void _wapi_collection_init (void);
+extern void _wapi_handle_collect (void);
+
+#endif /* _WAPI_COLLECTION_H_ */
int stat;
if ((stat = mono_mutex_lock(§ion->mutex)) != 0) {
- g_error (G_GNUC_PRETTY_FUNCTION
- ": EnterCriticalSection failed: %s", g_strerror(stat));
+ g_error ("%s: EnterCriticalSection failed: %s", __func__,
+ g_strerror(stat));
}
}
sys_error = strerror (code);
msg = g_locale_to_utf8 (sys_error, strlen (sys_error), NULL, NULL, NULL);
if (function_name == NULL)
- function_name = G_GNUC_PRETTY_FUNCTION;
+ function_name = __func__;
g_warning ("%s: Need to translate %d [%s] into winsock error",
function_name, code, msg);
extern struct _WapiHandleOps _wapi_event_ops;
+extern void _wapi_event_details (gpointer handle_info);
+
struct _WapiHandle_event
{
gboolean manual;
guint32 set_count;
};
-struct _WapiHandlePrivate_event
-{
- int dummy;
-};
-
#endif /* _WAPI_EVENT_PRIVATE_H_ */
#undef DEBUG
-static void event_close_shared (gpointer handle);
static void event_signal(gpointer handle);
-static void event_own (gpointer handle);
+static gboolean event_own (gpointer handle);
struct _WapiHandleOps _wapi_event_ops = {
- event_close_shared, /* close_shared */
- NULL, /* close_private */
+ NULL, /* close */
event_signal, /* signal */
event_own, /* own */
NULL, /* is_owned */
};
+void _wapi_event_details (gpointer handle_info)
+{
+ struct _WapiHandle_event *event = (struct _WapiHandle_event *)handle_info;
+
+ g_print ("manual: %s", event->manual?"TRUE":"FALSE");
+}
+
static mono_once_t event_ops_once=MONO_ONCE_INIT;
static void event_ops_init (void)
WAPI_HANDLE_CAP_SIGNAL);
}
-static void event_close_shared(gpointer handle)
-{
- struct _WapiHandle_event *event_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
- return;
- }
-
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing event handle %p", handle);
-#endif
-}
-
static void event_signal(gpointer handle)
{
ResetEvent(handle);
}
-static void event_own (gpointer handle)
+static gboolean event_own (gpointer handle)
{
struct _WapiHandle_event *event_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
+ (gpointer *)&event_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
- return;
+ g_warning ("%s: error looking up event handle %p", __func__,
+ handle);
+ return (FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": owning event handle %p", handle);
+ g_message("%s: owning event handle %p", __func__, handle);
#endif
if(event_handle->manual==FALSE) {
_wapi_handle_set_signal_state (handle, FALSE, FALSE);
}
}
+
+ return(TRUE);
}
/**
gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean manual,
gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
{
- struct _WapiHandle_event *event_handle;
+ struct _WapiHandle_event event_handle = {0};
gpointer handle;
- gboolean ok;
- gpointer ret = NULL;
int thr_ret;
mono_once (&event_ops_once, event_ops_init);
+
+ event_handle.manual = manual;
+ event_handle.set_count = 0;
- handle=_wapi_handle_new (WAPI_HANDLE_EVENT);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating event handle");
- return(NULL);
+ if (initial == TRUE) {
+ if (manual == FALSE) {
+ event_handle.set_count = 1;
+ }
}
+ handle = _wapi_handle_new (WAPI_HANDLE_EVENT, &event_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating event handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
+ return(NULL);
+ }
+
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
handle);
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
- goto cleanup;
- }
- ret = handle;
-
- event_handle->manual=manual;
- event_handle->set_count = 0;
-
- if(initial==TRUE) {
- if (manual == FALSE) {
- event_handle->set_count = 1;
- }
-
+ if (initial == TRUE) {
_wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": created new event handle %p",
- handle);
+ g_message("%s: created new event handle %p", __func__, handle);
#endif
-cleanup:
thr_ret = _wapi_handle_unlock_handle (handle);
g_assert (thr_ret == 0);
-
pthread_cleanup_pop (0);
- return(ret);
+ return(handle);
}
/**
int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
+ (gpointer *)&event_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
+ g_warning ("%s: error looking up event handle %p", __func__,
+ handle);
return(FALSE);
}
g_assert (thr_ret == 0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Pulsing event handle %p", handle);
+ g_message("%s: Pulsing event handle %p", __func__, handle);
#endif
if(event_handle->manual==TRUE) {
* a condition.
*/
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Obtained write lock on event handle %p", handle);
+ g_message("%s: Obtained write lock on event handle %p",
+ __func__, handle);
#endif
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
+ (gpointer *)&event_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
+ g_warning ("%s: error looking up event handle %p",
+ __func__, handle);
return(FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Resetting event handle %p",
- handle);
+ g_message("%s: Resetting event handle %p", __func__, handle);
#endif
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
if(_wapi_handle_issignalled (handle)==FALSE) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": No need to reset event handle %p", handle);
+ g_message("%s: No need to reset event handle %p", __func__,
+ handle);
#endif
} else {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Obtained write lock on event handle %p", handle);
+ g_message("%s: Obtained write lock on event handle %p",
+ __func__, handle);
#endif
_wapi_handle_set_signal_state (handle, FALSE, FALSE);
int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
- (gpointer *)&event_handle, NULL);
+ (gpointer *)&event_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up event handle %p", handle);
+ g_warning ("%s: error looking up event handle %p", __func__,
+ handle);
return(FALSE);
}
g_assert (thr_ret == 0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Setting event handle %p", handle);
+ g_message("%s: Setting event handle %p", __func__, handle);
#endif
if(event_handle->manual==TRUE) {
#include <config.h>
#include <glib.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/shared.h>
#include <mono/io-layer/misc-private.h>
+#include <mono/io-layer/collection.h>
#undef DEBUG
-/* Shared threads dont seem to work yet */
-#undef _POSIX_THREAD_PROCESS_SHARED
-
-extern struct _WapiHandleShared_list **_wapi_shared_data;
-extern struct _WapiHandleScratch *_wapi_shared_scratch;
-extern struct _WapiHandlePrivate_list **_wapi_private_data;
-extern pthread_mutex_t _wapi_shared_mutex;
-extern guint32 _wapi_shm_mapped_segments;
-
-extern guint32 _wapi_fd_offset_table_size;
-extern gpointer *_wapi_fd_offset_table;
-
-extern guint32 _wapi_handle_new_internal (WapiHandleType type);
-extern gpointer _wapi_handle_new (WapiHandleType type);
+extern struct _WapiHandleUnshared *_wapi_private_handles;
+extern struct _WapiHandleSharedLayout *_wapi_shared_layout;
+extern struct _WapiFileShareLayout *_wapi_fileshare_layout;
+
+extern guint32 _wapi_fd_reserve;
+extern mono_mutex_t _wapi_global_signal_mutex;
+extern pthread_cond_t _wapi_global_signal_cond;
+
+extern gpointer _wapi_handle_new (WapiHandleType type,
+ gpointer handle_specific);
+extern gpointer _wapi_handle_new_for_existing_ns (WapiHandleType type,
+ gpointer handle_specific,
+ guint32 offset);
+extern gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
+ gpointer handle_specific);
extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
- gpointer *shared, gpointer *private);
+ gpointer *handle_specific);
+extern gboolean _wapi_copy_handle (gpointer handle, WapiHandleType type,
+ struct _WapiHandleShared *handle_specific);
+extern void _wapi_replace_handle (gpointer handle, WapiHandleType type,
+ struct _WapiHandleShared *handle_specific);
+extern gboolean _wapi_try_replace_handle (gpointer handle, WapiHandleType type, struct _WapiHandleShared *handle_specific);
extern gpointer _wapi_search_handle (WapiHandleType type,
gboolean (*check)(gpointer, gpointer),
gpointer user_data,
- gpointer *shared, gpointer *private);
-extern gpointer _wapi_search_handle_namespace (WapiHandleType type,
- gchar *utf8_name,
- gpointer *shared,
- gpointer *private);
+ gpointer *handle_specific);
+extern int _wapi_namespace_timestamp_release (gpointer nowptr);
+extern int _wapi_namespace_timestamp (guint32 now);
+extern gint32 _wapi_search_handle_namespace (WapiHandleType type,
+ gchar *utf8_name);
extern void _wapi_handle_ref (gpointer handle);
extern void _wapi_handle_unref (gpointer handle);
-extern guint32 _wapi_handle_scratch_store_internal (guint32 bytes,
- gboolean *remap);
-extern guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes);
-extern guint32 _wapi_handle_scratch_store_string_array (gchar **data);
-extern gpointer _wapi_handle_scratch_lookup (guint32 idx);
-extern gchar **_wapi_handle_scratch_lookup_string_array (guint32 idx);
-extern void _wapi_handle_scratch_delete_internal (guint32 idx);
-extern void _wapi_handle_scratch_delete (guint32 idx);
-extern void _wapi_handle_scratch_delete_string_array (guint32 idx);
extern void _wapi_handle_register_capabilities (WapiHandleType type,
WapiHandleCapability caps);
extern gboolean _wapi_handle_test_capabilities (gpointer handle,
WapiHandleCapability caps);
-extern void _wapi_handle_ops_close_shared (gpointer handle);
-extern void _wapi_handle_ops_close_private (gpointer handle);
+extern void _wapi_handle_ops_close (gpointer handle);
extern void _wapi_handle_ops_signal (gpointer handle);
-extern void _wapi_handle_ops_own (gpointer handle);
+extern gboolean _wapi_handle_ops_own (gpointer handle);
extern gboolean _wapi_handle_ops_isowned (gpointer handle);
extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
gpointer *handles);
extern int _wapi_handle_wait_signal (void);
extern int _wapi_handle_timedwait_signal (struct timespec *timeout);
+extern int _wapi_handle_wait_signal_poll_share (void);
+extern int _wapi_handle_timedwait_signal_poll_share (struct timespec *timeout);
extern int _wapi_handle_wait_signal_handle (gpointer handle);
extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
struct timespec *timeout);
guint32 new_sharemode,
guint32 new_access,
guint32 *old_sharemode,
- guint32 *old_access);
-extern void _wapi_handle_set_share (dev_t device, ino_t inode,
- guint32 sharemode, guint32 access);
-
-static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
-{
- struct _WapiHandleShared_list *shared;
- int thr_ret;
-
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_shared_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
-
- shared=_wapi_shared_data[segment];
-
- thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- return(shared);
-}
-
-static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
-{
- struct _WapiHandlePrivate_list *priv;
- int thr_ret;
-
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_shared_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
-
- priv=_wapi_private_data[segment];
-
- thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- return(priv);
-}
-
-static inline void _wapi_handle_ensure_mapped (guint32 segment)
-{
- int thr_ret;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
- segment);
- g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_shm_mapped_segments: %d",
- _wapi_shm_mapped_segments);
- if(segment<_wapi_shm_mapped_segments) {
- g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_handle_get_shared_segment(segment): %p", _wapi_handle_get_shared_segment (segment));
- }
-#endif
-
- if(segment<_wapi_shm_mapped_segments &&
- _wapi_handle_get_shared_segment (segment)!=NULL) {
- /* Got it already */
- return;
- }
-
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_shared_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
-
- if(segment>=_wapi_shm_mapped_segments) {
- /* Need to extend the arrays. We can't use g_renew
- * here, because the unmapped segments must be NULL,
- * and g_renew doesn't initialise the memory it
- * returns
- */
- gulong old_len, new_len;
-
- old_len=_wapi_shm_mapped_segments;
- new_len=segment+1;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": extending shared array: mapped_segments is %d",
- _wapi_shm_mapped_segments);
-#endif
-
- _wapi_shared_data=_wapi_g_renew0 (_wapi_shared_data, sizeof(struct _WapiHandleShared_list *) * old_len, sizeof(struct _WapiHandleShared_list *) * new_len);
-
- if(_wapi_private_data!=NULL) {
- /* the daemon doesn't deal with private data */
- _wapi_private_data=_wapi_g_renew0 (_wapi_private_data, sizeof(struct _WapiHandlePrivate_list *) * old_len, sizeof(struct _WapiHandlePrivate_list *) * new_len);
- }
-
- _wapi_shm_mapped_segments=segment+1;
- }
-
- if(_wapi_shared_data[segment]==NULL) {
- /* Need to map it too */
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": mapping segment %d",
- segment);
-#endif
-
- _wapi_shared_data[segment]=_wapi_shm_file_map (WAPI_SHM_DATA,
- segment, NULL,
- NULL);
- if(_wapi_private_data!=NULL) {
- /* the daemon doesn't deal with private data */
- _wapi_private_data[segment]=g_new0 (struct _WapiHandlePrivate_list, 1);
- }
- }
-
- thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-}
-
-static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
- guint32 *idx)
-{
- guint32 h=GPOINTER_TO_UINT (handle);
- div_t divvy;
-
- divvy=div (h, _WAPI_HANDLES_PER_SEGMENT);
- *segment=divvy.quot;
- *idx=divvy.rem;
-}
-
-static inline guint32 _wapi_handle_index (guint32 segment, guint32 idx)
-{
- return((segment*_WAPI_HANDLES_PER_SEGMENT)+idx);
-}
-
-static inline gpointer _wapi_handle_fd_offset_to_handle (gpointer fd_handle)
-{
- int fd = GPOINTER_TO_INT (fd_handle);
- gpointer handle;
-
- if (fd >= _wapi_fd_offset_table_size) {
- return(NULL);
- }
-
- handle = _wapi_fd_offset_table[fd];
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- return(NULL);
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Returning fd offset %d of %p", fd,
- handle);
-#endif
+ guint32 *old_access,
+ struct _WapiFileShare **info);
+extern void _wapi_handle_check_share (struct _WapiFileShare *share_info);
+extern void _wapi_handle_dump (void);
+extern void _wapi_handle_update_refs (void);
+
+/* This is OK to use for atomic writes of individual struct members, as they
+ * are independent
+ */
+#define WAPI_SHARED_HANDLE_METADATA(handle) _wapi_shared_layout->metadata[_wapi_private_handles[GPOINTER_TO_UINT((handle))].u.shared.offset]
- return(handle);
-}
+/* Use this for read-only accesses to shared handle structs, so that
+ * if a handle is updated we always look at the latest copy. For
+ * write access, use handle_copy/handle_replace so that all the
+ * handle-type-specific data is updated atomically.
+ */
+#define WAPI_SHARED_HANDLE_TYPED_DATA(handle, type) _wapi_shared_layout->handles[_wapi_shared_layout->metadata[_wapi_private_handles[GPOINTER_TO_UINT((handle))].u.shared.offset].offset].u.type
static inline WapiHandleType _wapi_handle_type (gpointer handle)
{
- guint32 idx;
- guint32 segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- if(segment>=_wapi_shm_mapped_segments)
- return WAPI_HANDLE_UNUSED;
-
- return(_wapi_handle_get_shared_segment (segment)->handles[idx].type);
-}
-
-static inline void _wapi_handle_fd_offset_store (int fd, gpointer handle)
-{
- g_assert (fd < _wapi_fd_offset_table_size);
-
- if (_wapi_fd_offset_table[fd] != NULL && handle != NULL) {
- gpointer oldhandle = _wapi_fd_offset_table[fd];
- struct _WapiHandlePrivate *private_handle;
- guint32 idx;
- guint32 segment;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Reassigning fd offset %d from %p", fd,
- oldhandle);
-#endif
-
- /* The WapiFDMapped struct at the head of the private
- * handle data means we don't need to do a full
- * lookup, and we don't need to know the handle type.
- */
- g_assert (_wapi_handle_type (oldhandle) == WAPI_HANDLE_FILE ||
- _wapi_handle_type (oldhandle) == WAPI_HANDLE_CONSOLE ||
- _wapi_handle_type (oldhandle) == WAPI_HANDLE_PIPE ||
- _wapi_handle_type (oldhandle) == WAPI_HANDLE_SOCKET);
-
- _wapi_handle_segment (oldhandle, &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
-
- private_handle=&_wapi_handle_get_private_segment(segment)->handles[idx];
- ((WapiFDMapped *)(&private_handle->u))->assigned = FALSE;
- }
-
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size || handle==NULL);
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Assigning fd offset %d to %p", fd,
- handle);
-#endif
-
- _wapi_fd_offset_table[fd]=handle;
+ return(_wapi_private_handles[idx].type);
}
static inline void _wapi_handle_set_signal_state (gpointer handle,
gboolean state,
gboolean broadcast)
{
- guint32 idx;
- guint32 segment;
- struct _WapiHandleShared *shared_handle;
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ struct _WapiHandleUnshared *handle_data;
int thr_ret;
+
+ g_assert (!_WAPI_SHARED_HANDLE(_wapi_handle_type (handle)));
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
-
- _wapi_handle_segment (handle, &segment, &idx);
- shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
+ handle_data = &_wapi_private_handles[idx];
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": setting state of %p to %s (broadcast %s)", handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
+ g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
+ handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
#endif
- if(state==TRUE) {
+ if (state == TRUE) {
/* Tell everyone blocking on a single handle */
/* This function _must_ be called with
* handle->signal_mutex locked
*/
- shared_handle->signalled=state;
+ handle_data->signalled=state;
- if(broadcast==TRUE) {
- thr_ret = pthread_cond_broadcast (&shared_handle->signal_cond);
+ if (broadcast == TRUE) {
+ thr_ret = pthread_cond_broadcast (&handle_data->signal_cond);
g_assert (thr_ret == 0);
} else {
- thr_ret = pthread_cond_signal (&shared_handle->signal_cond);
+ thr_ret = pthread_cond_signal (&handle_data->signal_cond);
g_assert (thr_ret == 0);
}
/* Tell everyone blocking on multiple handles that something
* was signalled
*/
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- {
- struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
-
- pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
- thr_ret = mono_mutex_lock (&segment0->signal_mutex);
- g_assert (thr_ret == 0);
-
- thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
- g_assert (thr_ret == 0);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&_wapi_global_signal_mutex);
+ thr_ret = mono_mutex_lock (&_wapi_global_signal_mutex);
+ g_assert (thr_ret == 0);
- thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
- }
-#else
- {
- struct _WapiHandlePrivate_list *segment0=_wapi_handle_get_private_segment (0);
+ thr_ret = pthread_cond_broadcast (&_wapi_global_signal_cond);
+ g_assert (thr_ret == 0);
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
-#endif
+ thr_ret = mono_mutex_unlock (&_wapi_global_signal_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+ } else {
+ handle_data->signalled=state;
+ }
+}
- pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
- thr_ret = mono_mutex_lock (&segment0->signal_mutex);
- g_assert (thr_ret == 0);
-
- thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
- g_assert (thr_ret == 0);
+static inline void _wapi_shared_handle_set_signal_state (gpointer handle,
+ gboolean state)
+{
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ struct _WapiHandleUnshared *handle_data;
+ struct _WapiHandle_shared_ref *ref;
+ struct _WapiHandleSharedMetadata *shared_meta;
+
+ g_assert (_WAPI_SHARED_HANDLE(_wapi_handle_type (handle)));
+
+ handle_data = &_wapi_private_handles[idx];
+
+ ref = &handle_data->u.shared;
+ shared_meta = &_wapi_shared_layout->metadata[ref->offset];
+ shared_meta->signalled = state;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
+ g_message ("%s: signalled shared handle offset 0x%x", __func__,
+ ref->offset);
#endif
- thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
- }
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
- } else {
- shared_handle->signalled=state;
- }
+ InterlockedIncrement (&_wapi_shared_layout->signal_count);
}
static inline gboolean _wapi_handle_issignalled (gpointer handle)
{
- guint32 idx;
- guint32 segment;
-
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
+ guint32 idx = GPOINTER_TO_UINT(handle);
- _wapi_handle_segment (handle, &segment, &idx);
-
- return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled);
+ if (_WAPI_SHARED_HANDLE(_wapi_handle_type (handle))) {
+ return(WAPI_SHARED_HANDLE_METADATA(handle).signalled);
+ } else {
+ return(_wapi_private_handles[idx].signalled);
+ }
}
static inline int _wapi_handle_lock_signal_mutex (void)
{
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
+ g_message ("%s: lock global signal mutex", __func__);
#endif
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- return(mono_mutex_lock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
-#else
- return(mono_mutex_lock (&_wapi_handle_get_private_segment (0)->signal_mutex));
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ return(mono_mutex_lock (&_wapi_global_signal_mutex));
}
/* the parameter makes it easier to call from a pthread cleanup handler */
static inline int _wapi_handle_unlock_signal_mutex (void *unused)
{
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
+ g_message ("%s: unlock global signal mutex", __func__);
#endif
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
-#else
- return(mono_mutex_unlock (&_wapi_handle_get_private_segment (0)->signal_mutex));
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ return(mono_mutex_unlock (&_wapi_global_signal_mutex));
}
static inline int _wapi_handle_lock_handle (gpointer handle)
{
- guint32 idx;
- guint32 segment;
-
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
+ guint32 idx = GPOINTER_TO_UINT(handle);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
+ g_message ("%s: locking handle %p", __func__, handle);
#endif
_wapi_handle_ref (handle);
- _wapi_handle_segment (handle, &segment, &idx);
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
+ return(0);
+ }
+
+ return(mono_mutex_lock (&_wapi_private_handles[idx].signal_mutex));
+}
+
+static inline int _wapi_handle_trylock_handle (gpointer handle)
+{
+ guint32 idx = GPOINTER_TO_UINT(handle);
+
+#ifdef DEBUG
+ g_message ("%s: locking handle %p", __func__, handle);
+#endif
+
+ _wapi_handle_ref (handle);
- return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
+ return(0);
+ }
+
+ return(mono_mutex_trylock (&_wapi_private_handles[idx].signal_mutex));
}
static inline int _wapi_handle_unlock_handle (gpointer handle)
{
- guint32 idx;
- guint32 segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
int ret;
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
-
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
+ g_message ("%s: unlocking handle %p", __func__, handle);
#endif
-
- _wapi_handle_segment (handle, &segment, &idx);
- ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
+ _wapi_handle_unref (handle);
+ return(0);
+ }
+
+ ret = mono_mutex_unlock (&_wapi_private_handles[idx].signal_mutex);
_wapi_handle_unref (handle);
return(ret);
}
+static inline int _wapi_timestamp_exclusion (volatile gint32 *timestamp,
+ guint32 now)
+{
+ guint32 then;
+ int ret;
+
+ then = InterlockedCompareExchange (timestamp, now, 0);
+ if (then == 0) {
+ ret = 0;
+ } else if (now - then > 10) {
+ /* Try to overwrite the previous
+ * attempt, but make sure noone else
+ * got in first
+ */
+ g_warning ("%s: Breaking a previous timestamp", __func__);
+
+ ret = InterlockedCompareExchange (timestamp, now,
+ then) == then?0:EBUSY;
+ } else {
+ /* Someone else is working on this one */
+ ret = EBUSY;
+ }
+
+ return(ret);
+}
+
+static inline int _wapi_timestamp_release (volatile gint32 *timestamp,
+ guint32 now)
+{
+ /* The timestamp can be either: now, in which case we reset
+ * it; 0, in which case we don't do anything; any other value,
+ * in which case we don't do anything because someone else is
+ * in charge of resetting it.
+ */
+ return(InterlockedCompareExchange (timestamp, 0, now) != now);
+}
+
+static inline void _wapi_handle_spin (guint32 ms)
+{
+ struct timespec sleepytime;
+
+ sleepytime.tv_sec = 0;
+ sleepytime.tv_nsec = ms * 1000000;
+
+ nanosleep (&sleepytime, NULL);
+}
+
+static inline void _wapi_handle_share_release (struct _WapiFileShare *info)
+{
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ int thr_ret;
+
+ g_assert (info->handle_refs > 0);
+
+ /* Marking this as COLLECTION_UNSAFE prevents entries from
+ * expiring under us if we remove this one
+ */
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
+
+ /* Prevent new entries racing with us */
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ g_assert (thr_ret == 0);
+
+ if (InterlockedDecrement (&info->handle_refs) == 0) {
+ memset (info, '\0', sizeof(struct _WapiFileShare));
+ }
+
+ thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now);
+ g_assert (thr_ret == 0);
+
+ _WAPI_HANDLE_COLLECTION_SAFE;
+}
+
#endif /* _WAPI_HANDLES_PRIVATE_H_ */
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mman.h>
+#include <dirent.h>
+#include <sys/stat.h>
#include <mono/os/gc_wrapper.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/mono-mutex.h>
-#include <mono/io-layer/shared.h>
#include <mono/io-layer/misc-private.h>
-#include <mono/io-layer/daemon-messages.h>
+#include <mono/io-layer/shared.h>
+#include <mono/io-layer/collection.h>
#undef DEBUG
-#undef HEAVY_DEBUG /* This will print handle counts on every handle created */
-
-/* Shared threads don't seem to work yet */
-#undef _POSIX_THREAD_PROCESS_SHARED
-
-/*
- * This flag _MUST_ remain set to FALSE in the daemon process. When
- * we exec()d a standalone daemon, that happened because shared_init()
- * didnt get called in the daemon process. Now we just fork() without
- * exec(), we need to ensure that the fork() happens when shared is
- * still FALSE.
- *
- * This is further complicated by the second attempt to start the
- * daemon if the connect() fails.
- */
-static gboolean shared=FALSE;
+#undef DEBUG_REFS
static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT]={0};
static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
&_wapi_find_ops,
&_wapi_process_ops,
&_wapi_pipe_ops,
+ &_wapi_namedmutex_ops,
+};
+
+static void _wapi_shared_details (gpointer handle_info);
+
+static void (*handle_details[WAPI_HANDLE_COUNT])(gpointer) = {
+ NULL,
+ _wapi_file_details,
+ _wapi_console_details,
+ _wapi_shared_details, /* thread */
+ _wapi_sem_details,
+ _wapi_mutex_details,
+ _wapi_event_details,
+ NULL, /* Nothing useful to see in a socket handle */
+ NULL, /* Nothing useful to see in a find handle */
+ _wapi_shared_details, /* process */
+ _wapi_pipe_details,
+ _wapi_shared_details, /* namedmutex */
};
-static int daemon_sock;
+const char *_wapi_handle_typename[] = {
+ "Unused",
+ "File",
+ "Console",
+ "Thread",
+ "Sem",
+ "Mutex",
+ "Event",
+ "Socket",
+ "Find",
+ "Process",
+ "Pipe",
+ "N.Mutex",
+ "Error!!"
+};
-static pthread_mutexattr_t mutex_shared_attr;
-static pthread_condattr_t cond_shared_attr;
+struct _WapiHandleUnshared *_wapi_private_handles = NULL;
+static guint32 _wapi_private_handle_count = 0;
-struct _WapiHandleShared_list **_wapi_shared_data=NULL;
-struct _WapiHandleScratch *_wapi_shared_scratch=NULL;
-struct _WapiHandlePrivate_list **_wapi_private_data=NULL;
-pthread_mutex_t _wapi_shared_mutex=PTHREAD_MUTEX_INITIALIZER;
+struct _WapiHandleSharedLayout *_wapi_shared_layout = NULL;
+struct _WapiFileShareLayout *_wapi_fileshare_layout = NULL;
-/* This holds the length of the _wapi_shared_data and
- * _wapi_private_data arrays, so we know if a segment is off the end
- * of the array, requiring a realloc
- */
-guint32 _wapi_shm_mapped_segments;
+guint32 _wapi_fd_reserve;
-guint32 _wapi_fd_offset_table_size;
-gpointer *_wapi_fd_offset_table=NULL;
+mono_mutex_t _wapi_global_signal_mutex;
+pthread_cond_t _wapi_global_signal_cond;
+static mono_once_t shared_init_once = MONO_ONCE_INIT;
static void shared_init (void)
{
- struct sockaddr_un shared_socket_address;
- gboolean tried_once=FALSE;
- int ret;
int thr_ret;
- _wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1);
- _wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1);
+ _wapi_fd_reserve = getdtablesize();
-attach_again:
-
-#ifndef DISABLE_SHARED_HANDLES
- if(getenv ("MONO_DISABLE_SHM"))
-#endif
- {
- shared=FALSE;
-#ifndef DISABLE_SHARED_HANDLES
- } else {
- /* Ensure that shared==FALSE while _wapi_shm_attach()
- * calls fork()
- */
- shared=FALSE;
-
- shared=_wapi_shm_attach (&_wapi_shared_data[0],
- &_wapi_shared_scratch);
- if(shared==FALSE) {
- g_warning (
- "Failed to attach shared memory! "
- "Falling back to non-shared handles\n"
- "See: http://www.go-mono.com/issues.html#wapi for details");
- }
-#endif /* DISABLE_SHARED_HANDLES */
- }
+ _wapi_private_handle_count = _WAPI_HANDLE_INITIAL_COUNT;
-
- if(shared==TRUE) {
- daemon_sock=socket (PF_UNIX, SOCK_STREAM, 0);
- shared_socket_address.sun_family=AF_UNIX;
- memcpy (shared_socket_address.sun_path,
- _wapi_shared_data[0]->daemon, MONO_SIZEOF_SUNPATH);
- ret=connect (daemon_sock,
- (struct sockaddr *)&shared_socket_address,
- sizeof(struct sockaddr_un));
- if(ret==-1) {
- if(tried_once==TRUE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": connect to daemon failed: %s",
- g_strerror (errno));
- /* Fall back to private handles */
- shared=FALSE;
- } else {
- /* It's possible that the daemon
- * crashed without destroying the
- * shared memory segment (thus fooling
- * subsequent processes into thinking
- * the daemon is still active).
- *
- * Destroy the shared memory segment
- * and try once more. This won't
- * break running apps, but no new apps
- * will be able to see the current
- * shared memory segment.
- */
- tried_once=TRUE;
- _wapi_shm_destroy ();
-
- goto attach_again;
- }
- } else {
- _wapi_fd_offset_table_size = _wapi_shared_data[0]->fd_offset_table_size;
- _wapi_fd_offset_table=g_new0 (gpointer, _wapi_fd_offset_table_size);
- }
+ while(_wapi_fd_reserve > _wapi_private_handle_count) {
+ _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
}
+
+ _wapi_private_handles = g_new0 (struct _WapiHandleUnshared,
+ _wapi_private_handle_count);
- if(shared==FALSE) {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Using process-private handles");
-#endif
- _wapi_shared_data[0]=g_new0 (struct _WapiHandleShared_list, 1);
- _wapi_shared_data[0]->num_segments=1;
-
- _wapi_shared_scratch=g_new0 (struct _WapiHandleScratch, 1);
-
- _wapi_fd_offset_table_size=getdtablesize ();
- _wapi_fd_offset_table=g_new0 (gpointer,
- _wapi_fd_offset_table_size);
- }
- _wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1);
- _wapi_shm_mapped_segments=1;
- thr_ret = pthread_mutexattr_init (&mutex_shared_attr);
- g_assert (thr_ret == 0);
+ _wapi_shared_layout = _wapi_shm_attach ();
+ g_assert (_wapi_shared_layout != NULL);
- thr_ret = pthread_condattr_init (&cond_shared_attr);
- g_assert (thr_ret == 0);
+ _wapi_fileshare_layout = _wapi_fileshare_shm_attach ();
+ g_assert (_wapi_fileshare_layout != NULL);
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- thr_ret = pthread_mutexattr_setpshared (&mutex_shared_attr,
- PTHREAD_PROCESS_SHARED);
- g_assert (thr_ret == 0);
+ _wapi_collection_init ();
- thr_ret = pthread_condattr_setpshared (&cond_shared_attr,
- PTHREAD_PROCESS_SHARED);
- g_assert (thr_ret == 0);
-#else
- thr_ret = pthread_cond_init(&_wapi_private_data[0]->signal_cond, NULL);
+ thr_ret = pthread_cond_init(&_wapi_global_signal_cond, NULL);
g_assert (thr_ret == 0);
- thr_ret = mono_mutex_init(&_wapi_private_data[0]->signal_mutex, NULL);
+ thr_ret = mono_mutex_init(&_wapi_global_signal_mutex, NULL);
g_assert (thr_ret == 0);
-#endif
}
-#ifdef HEAVY_DEBUG
-static void
-print_handle_count (gint mask)
+static void _wapi_handle_init_shared_metadata (struct _WapiHandleSharedMetadata *meta)
{
- gint *count, num_handles;
- gint i;
- static const gchar *names [] = {"WAPI_HANDLE_UNUSED",
- "WAPI_HANDLE_FILE",
- "WAPI_HANDLE_CONSOLE",
- "WAPI_HANDLE_THREAD",
- "WAPI_HANDLE_SEM",
- "WAPI_HANDLE_MUTEX",
- "WAPI_HANDLE_EVENT",
- "WAPI_HANDLE_SOCKET",
- "WAPI_HANDLE_FIND",
- "WAPI_HANDLE_PROCESS",
- "WAPI_HANDLE_PIPE"
- };
-
-
- num_handles=_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT;
- count=g_new0 (gint, num_handles);
-
- for (i = 1; i < num_handles; i++) {
- struct _WapiHandleShared *shared;
- guint32 segment, idx;
-
- _wapi_handle_segment (GUINT_TO_POINTER (i), &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
-
- shared = &_wapi_handle_get_shared_segment (segment)->handles[idx];
- count [shared->type]++;
+ meta->ref = 1;
+ meta->signalled = FALSE;
+}
+
+static void _wapi_handle_init_shared (struct _WapiHandleShared *handle,
+ WapiHandleType type,
+ gpointer handle_specific)
+{
+ handle->type = type;
+ handle->stale = FALSE;
+
+ if (handle_specific != NULL) {
+ memcpy (&handle->u, handle_specific, sizeof (handle->u));
}
+}
- for (i = 0; i < num_handles; i++)
- if ((i & mask) == i) /* Always prints the UNUSED count */
- g_print ("%s: %d\n", names [i], count [i]);
+static void _wapi_handle_init (struct _WapiHandleUnshared *handle,
+ WapiHandleType type, gpointer handle_specific)
+{
+ int thr_ret;
+
+ handle->type = type;
+ handle->signalled = FALSE;
+ handle->ref = 1;
+
+ if (!_WAPI_SHARED_HANDLE(type)) {
+ thr_ret = pthread_cond_init (&handle->signal_cond, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_init (&handle->signal_mutex, NULL);
+ g_assert (thr_ret == 0);
- g_free (count);
+ if (handle_specific != NULL) {
+ memcpy (&handle->u, handle_specific,
+ sizeof (handle->u));
+ }
+ }
}
-#endif /* HEAVY_DEBUG */
-/*
- * _wapi_handle_new_internal:
- * @type: Init handle to this type
- *
- * Search for a free handle and initialize it. Return the handle on
- * success and 0 on failure.
- */
-guint32 _wapi_handle_new_internal (WapiHandleType type)
+static guint32 _wapi_handle_new_shared_offset (guint32 offset)
{
- guint32 segment, idx;
- guint32 i, j;
- static guint32 last=1;
- int thr_ret;
- guint32 num_segments = _wapi_handle_get_shared_segment (0)->num_segments;
+ guint32 i;
+ static guint32 last = 1;
- /* A linear scan should be fast enough. Start from the last
- * allocation, assuming that handles are allocated more often
- * than they're freed. Leave 0 (NULL) as a guard
- */
-#ifdef HEAVY_DEBUG
- print_handle_count (0xFFF);
-#endif
again:
- _wapi_handle_segment (GUINT_TO_POINTER (last), &segment, &idx);
- for(i=segment; i < num_segments; i++) {
- if(i!=segment) {
- idx=0;
- }
-
- for(j=idx; j<_WAPI_HANDLES_PER_SEGMENT; j++) {
- struct _WapiHandleShared *shared;
+ /* 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
+ * offsets.)
+ */
+ for(i = last; i <_WAPI_HANDLE_INITIAL_COUNT; i++) {
+ struct _WapiHandleSharedMetadata *meta = &_wapi_shared_layout->metadata[i];
- /* Make sure we dont try and assign the
- * handles that would clash with fds
- */
- if ((i * _WAPI_HANDLES_PER_SEGMENT + j) < _wapi_fd_offset_table_size) {
- i = _wapi_fd_offset_table_size / _WAPI_HANDLES_PER_SEGMENT;
- j = _wapi_fd_offset_table_size - (i * _WAPI_HANDLES_PER_SEGMENT);
-
- if (i >= num_segments) {
- /* Need to get the caller to
- * add more shared segments
- */
- return(0);
- }
-
- continue;
- }
+ if(meta->offset == 0) {
+ if (InterlockedCompareExchange (&meta->offset, offset,
+ 0) == 0) {
+ last = i + 1;
- shared=&_wapi_handle_get_shared_segment (i)->handles[j];
-
- if(shared->type==WAPI_HANDLE_UNUSED) {
- last=(_wapi_handle_index (i, j)+1) % (_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT);
- shared->type=type;
- shared->signalled=FALSE;
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- thr_ret = mono_mutex_init (&shared->signal_mutex, &mutex_shared_attr);
- g_assert (thr_ret == 0);
-
- thr_ret = pthread_cond_init (&shared->signal_cond, &cond_shared_attr);
- g_assert (thr_ret == 0);
-#else
- thr_ret = pthread_cond_init(&shared->signal_cond, NULL);
- g_assert (thr_ret == 0);
-
- thr_ret = mono_mutex_init(&shared->signal_mutex, NULL);
- g_assert (thr_ret == 0);
-#endif
-
- return(_wapi_handle_index (i, j));
+ _wapi_handle_init_shared_metadata (meta);
+ return(i);
+ } else {
+ /* Someone else beat us to it, just
+ * continue looking
+ */
}
}
}
- if(last>1) {
+ if(last > 1) {
/* Try again from the beginning */
- last=1;
+ last = 1;
goto again;
}
- /* Will need a new segment. The caller will sort it out */
+ /* Will need to expand the array. The caller will sort it out */
return(0);
}
-gpointer _wapi_handle_new (WapiHandleType type)
+static guint32 _wapi_handle_new_shared (WapiHandleType type,
+ gpointer handle_specific)
{
- static mono_once_t shared_init_once = MONO_ONCE_INIT;
- static pthread_mutex_t scan_mutex=PTHREAD_MUTEX_INITIALIZER;
- guint32 handle_idx = 0, idx, segment;
- gpointer handle;
- WapiHandleRequest new={0};
- WapiHandleResponse new_resp={0};
-#if HAVE_BOEHM_GC
- gboolean tried_collect=FALSE;
-#endif
- int thr_ret;
-
- mono_once (&shared_init_once, shared_init);
+ guint32 offset;
+ static guint32 last = 1;
+ /* The shared memory holds an offset to the real data, so we
+ * can update the handle RCU-style without taking a lock.
+ * This function just allocates the next available data slot,
+ * use _wapi_handle_new_shared_offset to get the offset entry.
+ */
+
+ /* Leave the first slot empty as a guard */
again:
- if(shared==TRUE) {
- new.type=WapiHandleRequestType_New;
- new.u.new.type=type;
-
- _wapi_daemon_request_response (daemon_sock, &new, &new_resp);
-
- if (new_resp.type==WapiHandleResponseType_New) {
- handle_idx=new_resp.u.new.handle;
- } else {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
- new_resp.type);
- g_assert_not_reached ();
- }
- } else {
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&scan_mutex);
- thr_ret = pthread_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
+ /* FIXME: expandable array */
+ /* FIXME: 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++) {
+ struct _WapiHandleShared *handle = &_wapi_shared_layout->handles[offset];
- while ((handle_idx = _wapi_handle_new_internal (type)) == 0) {
- /* Try and get a new segment, and have another go */
- segment=_wapi_handle_get_shared_segment (0)->num_segments;
- _wapi_handle_ensure_mapped (segment);
+ if(handle->type == WAPI_HANDLE_UNUSED) {
+ if (InterlockedCompareExchange ((gint32 *)&handle->type, type, WAPI_HANDLE_UNUSED) == WAPI_HANDLE_UNUSED) {
+ last = offset + 1;
- if(_wapi_handle_get_shared_segment (segment)!=NULL) {
- /* Got a new segment */
- _wapi_handle_get_shared_segment (0)->num_segments++;
+ _wapi_handle_init_shared (handle, type,
+ handle_specific);
+ return(offset);
} else {
- /* Map failed. Just return 0 meaning
- * "out of handles"
+ /* Someone else beat us to it, just
+ * continue looking
*/
}
}
-
- _wapi_handle_segment (GUINT_TO_POINTER (handle_idx), &segment, &idx);
- _wapi_handle_get_shared_segment (segment)->handles[idx].ref++;
-
- thr_ret = pthread_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_offset_table_size);
-
- if(handle_idx==0) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": Ran out of handles!");
-#if HAVE_BOEHM_GC
- /* See if we can reclaim some handles by forcing a GC
- * collection
- */
- if(tried_collect==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": Seeing if GC collection helps...");
- GC_gcollect (); /* FIXME: we should wait for finalizers to be called */
- tried_collect=TRUE;
- goto again;
- } else {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": didn't help, returning error");
- }
-#endif
-
- return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID));
+ if(last > 1) {
+ /* Try again from the beginning */
+ last = 1;
+ goto again;
}
- _wapi_handle_segment (GUINT_TO_POINTER (handle_idx), &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
-
- if(_wapi_private_data!=NULL) {
- _wapi_handle_get_private_segment (segment)->handles[idx].type=type;
- }
-
-#if !defined(_POSIX_THREAD_PROCESS_SHARED) || _POSIX_THREAD_PROCESS_SHARED == -1
- thr_ret = mono_mutex_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex, &mutex_shared_attr);
- g_assert (thr_ret == 0);
-
- thr_ret = pthread_cond_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, &cond_shared_attr);
- g_assert (thr_ret == 0);
-#endif
- handle=GUINT_TO_POINTER (handle_idx);
+ /* Will need to expand the array. The caller will sort it out */
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Allocated new handle %p", handle);
-#endif
-
- return(handle);
+ return(0);
}
-gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
- gpointer *shared, gpointer *private)
+/*
+ * _wapi_handle_new_internal:
+ * @type: Init handle to this type
+ *
+ * Search for a free handle and initialize it. Return the handle on
+ * success and 0 on failure. This is only called from
+ * _wapi_handle_new, and scan_mutex must be held.
+ */
+static guint32 _wapi_handle_new_internal (WapiHandleType type,
+ gpointer handle_specific)
{
- struct _WapiHandleShared *shared_handle_data;
- struct _WapiHandlePrivate *private_handle_data = NULL;
- guint32 idx;
- guint32 segment;
-
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
-
- _wapi_handle_segment (handle, &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
+ guint32 i;
+ static guint32 last = 0;
- shared_handle_data=&_wapi_handle_get_shared_segment (segment)->handles[idx];
-
- if(shared!=NULL) {
- *shared=&shared_handle_data->u;
- }
+ /* A linear scan should be fast enough. Start from the last
+ * allocation, assuming that handles are allocated more often
+ * than they're freed. Leave the space reserved for file
+ * descriptors
+ */
- if(private!=NULL) {
- private_handle_data=&_wapi_handle_get_private_segment (segment)->handles[idx];
-
- *private=&private_handle_data->u;
- }
-
- if(shared_handle_data->type!=type) {
- /* If shared type is UNUSED, see if the private type
- * matches what we are looking for - this can happen
- * when the handle is being destroyed and the
- * close_private function is looking up the private
- * data
- */
- if(shared_handle_data->type==WAPI_HANDLE_UNUSED &&
- (private!=NULL && private_handle_data->type==type)) {
- return(TRUE);
- } else {
- return(FALSE);
- }
+ if (last < _wapi_fd_reserve) {
+ last = _wapi_fd_reserve;
}
- return(TRUE);
-}
-
-gpointer _wapi_search_handle (WapiHandleType type,
- gboolean (*check)(gpointer test, gpointer user),
- gpointer user_data,
- gpointer *shared, gpointer *private)
-{
- struct _WapiHandleShared *shared_handle_data;
- struct _WapiHandlePrivate *private_handle_data;
- guint32 i, segment, idx;
-
- for(i=1; i<_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT; i++) {
- struct _WapiHandleShared *shared;
-
- _wapi_handle_segment (GUINT_TO_POINTER (i), &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
-
- shared=&_wapi_handle_get_shared_segment (segment)->handles[idx];
+again:
+ for(i = last; i <_wapi_private_handle_count; i++) {
+ struct _WapiHandleUnshared *handle = &_wapi_private_handles[i];
- if(shared->type==type) {
- if(check (GUINT_TO_POINTER (i), user_data)==TRUE) {
- break;
- }
+ if(handle->type == WAPI_HANDLE_UNUSED) {
+ last = i + 1;
+
+ _wapi_handle_init (handle, type, handle_specific);
+ return(i);
}
}
- if(i==_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT) {
- return(GUINT_TO_POINTER (0));
+ if(last > _wapi_fd_reserve) {
+ /* Try again from the beginning */
+ last = _wapi_fd_reserve;
+ goto again;
}
-
- if(shared!=NULL) {
- shared_handle_data=&_wapi_handle_get_shared_segment (segment)->handles[idx];
- *shared=&shared_handle_data->u;
- }
-
- if(private!=NULL) {
- private_handle_data=&_wapi_handle_get_private_segment (segment)->handles[idx];
+ /* Will need to expand the array. The caller will sort it out */
- *private=&private_handle_data->u;
- }
-
- return(GUINT_TO_POINTER (i));
+ return(0);
}
-gpointer _wapi_search_handle_namespace (WapiHandleType type,
- gchar *utf8_name, gpointer *shared,
- gpointer *private)
+gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
{
- struct _WapiHandleShared *shared_handle_data;
- struct _WapiHandlePrivate *private_handle_data;
- guint32 i, segment, idx;
-
+ static pthread_mutex_t scan_mutex=PTHREAD_MUTEX_INITIALIZER;
+ guint32 handle_idx = 0;
+ gpointer handle;
+ int thr_ret;
+
+ mono_once (&shared_init_once, shared_init);
+
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Lookup for handle named [%s] type %d", utf8_name, type);
+ g_message ("%s: Creating new handle of type %s", __func__,
+ _wapi_handle_typename[type]);
#endif
- for(i=1; i<_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT; i++) {
- struct _WapiHandleShared *shared;
+ g_assert(!_WAPI_FD_HANDLE(type));
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&scan_mutex);
+ thr_ret = pthread_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) {
+ /* Try and expand the array, and have another go */
+ _wapi_private_handles = g_renew (struct _WapiHandleUnshared,
+ _wapi_private_handles,
+ _wapi_private_handle_count +
+ _WAPI_HANDLE_INITIAL_COUNT);
+ memset (_wapi_private_handles +
+ (_wapi_private_handle_count *
+ sizeof(struct _WapiHandleUnshared)), '\0',
+ (_WAPI_HANDLE_INITIAL_COUNT *
+ sizeof(struct _WapiHandleUnshared)));
- _wapi_handle_segment (GUINT_TO_POINTER (i), &segment, &idx);
- _wapi_handle_ensure_mapped (segment);
+ _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
+ }
- shared=&_wapi_handle_get_shared_segment (segment)->handles[idx];
+ thr_ret = pthread_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- /* Check mutex, event, semaphore, timer, job and file-mapping
- * object names. So far only mutex is implemented.
- */
- if(_WAPI_SHARED_NAMESPACE (shared->type)) {
- gchar *lookup_name;
- WapiSharedNamespace *sharedns;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": found a shared namespace handle at 0x%x (type %d)", i, shared->type);
-#endif
-
- shared_handle_data=&_wapi_handle_get_shared_segment (segment)->handles[idx];
- sharedns=(WapiSharedNamespace *)&shared_handle_data->u;
-
-
- if(sharedns->name) {
- lookup_name=_wapi_handle_scratch_lookup (
- sharedns->name);
- } else {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle 0x%x is unnamed", i);
-#endif
- continue;
- }
-
- if(lookup_name==NULL) {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": couldn't find handle 0x%x name",
- i);
-#endif
- continue;
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": name is [%s]",
- lookup_name);
-#endif
+ /* Make sure we left the space for fd mappings */
+ g_assert (handle_idx >= _wapi_fd_reserve);
+
+ handle = GUINT_TO_POINTER (handle_idx);
- if(strcmp (lookup_name, utf8_name)==0) {
- if(shared->type!=type) {
- /* Its the wrong type, so fail now */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle 0x%x matches name but is wrong type: %d", i, shared->type);
+ g_message ("%s: Allocated new handle %p", __func__, handle);
#endif
- return(_WAPI_HANDLE_INVALID);
- } else {
- /* fall through so we can fill
- * in the data
- */
+
+ if (_WAPI_SHARED_HANDLE(type)) {
+ /* Add the shared section too */
+ guint32 offset, ref;
+
+ offset = _wapi_handle_new_shared (type, handle_specific);
+ if (offset == 0) {
+ _wapi_handle_collect ();
+ offset = _wapi_handle_new_shared (type,
+ handle_specific);
+ /* FIXME: grow the arrays */
+ g_assert (offset != 0);
+ }
+
+ ref = _wapi_handle_new_shared_offset (offset);
+ if (ref == 0) {
+ _wapi_handle_collect ();
+ ref = _wapi_handle_new_shared_offset (offset);
+ /* FIXME: grow the arrays */
+ g_assert (ref != 0);
+ }
+
+ _wapi_private_handles[handle_idx].u.shared.offset = ref;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle 0x%x matches name and type", i);
+ g_message ("%s: New shared handle at offset 0x%x", __func__,
+ ref);
#endif
- break;
- }
- }
- }
- }
-
- if(i==_wapi_handle_get_shared_segment (0)->num_segments * _WAPI_HANDLES_PER_SEGMENT) {
- return(GUINT_TO_POINTER (0));
}
- if(shared!=NULL) {
- shared_handle_data=&_wapi_handle_get_shared_segment (segment)->handles[idx];
-
- *shared=&shared_handle_data->u;
- }
-
- if(private!=NULL) {
- private_handle_data=&_wapi_handle_get_private_segment (segment)->handles[idx];
-
- *private=&private_handle_data->u;
- }
-
- return(GUINT_TO_POINTER (i));
+ return(handle);
}
-void _wapi_handle_ref (gpointer handle)
+gpointer _wapi_handle_new_for_existing_ns (WapiHandleType type,
+ gpointer handle_specific,
+ guint32 offset)
{
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
-
- if(shared==TRUE) {
- WapiHandleRequest req={0};
- WapiHandleResponse resp={0};
+ static pthread_mutex_t scan_mutex=PTHREAD_MUTEX_INITIALIZER;
+ guint32 handle_idx = 0;
+ gpointer handle;
+ int thr_ret;
- req.type=WapiHandleRequestType_Open;
- req.u.open.handle=GPOINTER_TO_UINT (handle);
+ mono_once (&shared_init_once, shared_init);
- _wapi_daemon_request_response (daemon_sock, &req, &resp);
- if(resp.type!=WapiHandleResponseType_Open) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
- resp.type);
- g_assert_not_reached ();
- }
- } else {
- guint32 idx, segment;
+#ifdef DEBUG
+ g_message ("%s: Creating new handle of type %s", __func__,
+ _wapi_handle_typename[type]);
+#endif
- _wapi_handle_segment (handle, &segment, &idx);
+ g_assert(!_WAPI_FD_HANDLE(type));
+ g_assert(_WAPI_SHARED_HANDLE(type));
+ g_assert(offset != 0);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&scan_mutex);
+ thr_ret = pthread_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) {
+ /* Try and expand the array, and have another go */
+ _wapi_private_handles = g_renew (struct _WapiHandleUnshared,
+ _wapi_private_handles,
+ _wapi_private_handle_count +
+ _WAPI_HANDLE_INITIAL_COUNT);
+ memset (_wapi_private_handles +
+ (_wapi_private_handle_count *
+ sizeof(struct _WapiHandleUnshared)), '\0',
+ (_WAPI_HANDLE_INITIAL_COUNT *
+ sizeof(struct _WapiHandleUnshared)));
+
+ _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
+ }
- _wapi_handle_get_shared_segment (segment)->handles[idx].ref++;
+ thr_ret = pthread_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 = GUINT_TO_POINTER (handle_idx);
+
+ _wapi_private_handles[handle_idx].u.shared.offset = offset;
+
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p ref now %d",
- handle,
- _wapi_handle_get_shared_segment (segment)->handles[idx].ref);
+ g_message ("%s: Allocated new handle %p referencing 0x%x", __func__,
+ handle, offset);
#endif
- }
+
+ return(handle);
}
-/* The handle must not be locked on entry to this function */
-void _wapi_handle_unref (gpointer handle)
+gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
+ gpointer handle_specific)
{
- guint32 idx, segment;
- gboolean destroy = FALSE;
- int thr_ret;
-
- g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
+ struct _WapiHandleUnshared *handle;
- _wapi_handle_segment (handle, &segment, &idx);
-
- if(shared==TRUE) {
- WapiHandleRequest req={0};
- WapiHandleResponse resp={0};
+ mono_once (&shared_init_once, shared_init);
- req.type=WapiHandleRequestType_Close;
- req.u.close.handle=GPOINTER_TO_UINT (handle);
+#ifdef DEBUG
+ g_message ("%s: Creating new handle of type %s", __func__,
+ _wapi_handle_typename[type]);
+#endif
- _wapi_daemon_request_response (daemon_sock, &req, &resp);
- if(resp.type!=WapiHandleResponseType_Close) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
- resp.type);
- g_assert_not_reached ();
- } else {
- destroy=resp.u.close.destroy;
- }
- } else {
- _wapi_handle_get_shared_segment (segment)->handles[idx].ref--;
+ g_assert(_WAPI_FD_HANDLE(type));
+ g_assert(!_WAPI_SHARED_HANDLE(type));
+ if (fd >= _wapi_fd_reserve) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p ref now %d", handle, _wapi_handle_get_shared_segment (segment)->handles[idx].ref);
+ g_message ("%s: fd %d is too big", __func__, fd);
#endif
- /* Possible race condition here if another thread refs
- * the handle between here and setting the type to
- * UNUSED. I could lock a mutex, but I'm not sure
- * that allowing a handle reference to reach 0 isn't
- * an application bug anyway.
+ return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID));
+ }
+
+ handle = &_wapi_private_handles[fd];
+
+ if (handle->type != WAPI_HANDLE_UNUSED) {
+#ifdef DEBUG
+ g_message ("%s: fd %d is already in use!", __func__, fd);
+#endif
+ /* FIXME: clean up this handle? We can't do anything
+ * with the fd, cos thats the new one
*/
- destroy=(_wapi_handle_get_shared_segment (segment)->handles[idx].ref==0);
}
- if(destroy==TRUE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Destroying handle %p",
- handle);
+ g_message ("%s: Assigning new fd handle %d", __func__, fd);
#endif
-
- if(shared==FALSE) {
- _wapi_handle_ops_close_shared (handle);
- memset (&_wapi_handle_get_shared_segment (segment)->handles[idx].u, '\0', sizeof(_wapi_handle_get_shared_segment (segment)->handles[idx].u));
- }
+ _wapi_handle_init (handle, type, handle_specific);
- _wapi_handle_ops_close_private (handle);
- _wapi_handle_get_shared_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
- _wapi_handle_get_private_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
-
- /* Destroy the mutex and cond var. We hope nobody
- * tried to grab them between the handle unlock and
- * now, but pthreads doesn't have a
- * "unlock_and_destroy" atomic function.
- */
- thr_ret = mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
- g_assert (thr_ret == 0);
-
- thr_ret = pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
- g_assert (thr_ret == 0);
- }
+ return(GUINT_TO_POINTER(fd));
}
-#define HDRSIZE sizeof(struct _WapiScratchHeader)
+gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
+ gpointer *handle_specific)
+{
+ struct _WapiHandleUnshared *handle_data;
+ guint32 handle_idx = GPOINTER_TO_UINT(handle);
-static pthread_mutex_t _wapi_scratch_mutex=PTHREAD_MUTEX_INITIALIZER;
+ handle_data = &_wapi_private_handles[handle_idx];
+
+ if(handle_data->type != type) {
+ return(FALSE);
+ }
-/* _wapi_scratch_mutex must be held when this function is called in
- * the non-shared case
- */
-static void _wapi_handle_scratch_expand (void)
-{
- guint32 old_len, new_len;
+ if(handle_specific == NULL) {
+ return(FALSE);
+ }
+
+ if (_WAPI_SHARED_HANDLE(type)) {
+ struct _WapiHandle_shared_ref *ref = &handle_data->u.shared;
+ 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];
- old_len=sizeof(struct _WapiHandleScratch) +
- _wapi_shared_scratch->data_len;
- new_len=old_len+_WAPI_SHM_SCRATCH_SIZE;
+ g_assert(shared_handle_data->type == type);
- if(_wapi_shared_scratch->is_shared==TRUE) {
- /* expand via mmap() */
- _wapi_shared_scratch=_wapi_shm_file_expand (_wapi_shared_scratch, WAPI_SHM_SCRATCH, 0, old_len, new_len);
+ *handle_specific = &shared_handle_data->u;
} else {
- _wapi_shared_scratch=_wapi_g_renew0 (_wapi_shared_scratch, old_len, new_len);
+ *handle_specific = &handle_data->u;
}
- _wapi_shared_scratch->data_len+=_WAPI_SHM_SCRATCH_SIZE;
+
+ return(TRUE);
}
-/* _wapi_scratch_mutex must be held when this function is called in
- * the non-shared case
- */
-static guint32 _wapi_handle_scratch_locate_space (guint32 bytes)
+gboolean _wapi_copy_handle (gpointer handle, WapiHandleType type,
+ struct _WapiHandleShared *handle_specific)
{
- guint32 idx=0, last_idx=0;
- struct _WapiScratchHeader *hdr, *last_hdr = NULL;
- gboolean last_was_free=FALSE;
- guchar *storage=_wapi_shared_scratch->scratch_data;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": looking for %d bytes of scratch space (%d bytes total)",
- bytes, _wapi_shared_scratch->data_len);
-#endif
+ struct _WapiHandleUnshared *handle_data;
+ guint32 handle_idx = GPOINTER_TO_UINT(handle);
+ struct _WapiHandle_shared_ref *ref;
+ struct _WapiHandleShared *shared_handle_data;
+ struct _WapiHandleSharedMetadata *shared_meta;
+ guint32 offset;
- while(idx< _wapi_shared_scratch->data_len) {
- hdr=(struct _WapiScratchHeader *)&storage[idx];
-
- /* Do a simple first-fit allocation, coalescing
- * adjacent free blocks as we progress through the
- * scratch space
- */
- if(hdr->flags & WAPI_SHM_SCRATCH_FREE &&
- hdr->length >= bytes + HDRSIZE) {
- /* found space */
- guint32 old_length=hdr->length;
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": found suitable free size at %d, length %d", idx, hdr->length);
-#endif
-
- hdr->flags &= ~WAPI_SHM_SCRATCH_FREE;
- hdr->length=bytes;
- idx += HDRSIZE;
-
- /* Put a new header in at the end of the used
- * space
- */
- hdr=(struct _WapiScratchHeader *)&storage[idx+bytes];
- hdr->flags |= WAPI_SHM_SCRATCH_FREE;
- hdr->length = old_length-bytes-HDRSIZE;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": new header at %d, length %d", idx+bytes, hdr->length);
-#endif
-
- /*
- * It was memset(0..) when free/made so no need to do it here
- */
+ g_assert(_WAPI_SHARED_HANDLE(type));
- return(idx);
- } else if(hdr->flags & WAPI_SHM_SCRATCH_FREE &&
- last_was_free == FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": found too-small free block at %d, length %d (previous used)", idx, hdr->length);
+ g_message ("%s: copying handle %p type %s", __func__, handle,
+ _wapi_handle_typename[type]);
#endif
- /* save this point in case we can coalesce it with
- * the next block, if that is free.
- */
- last_was_free=TRUE;
- last_idx=idx;
- last_hdr=hdr;
- idx+=(hdr->length+HDRSIZE);
- } else if (hdr->flags & WAPI_SHM_SCRATCH_FREE &&
- last_was_free == TRUE) {
+ handle_data = &_wapi_private_handles[handle_idx];
+
+ if(handle_data->type != type) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": found too-small free block at %d, length %d (previous free)", idx, hdr->length);
+ g_message ("%s: incorrect type, %p has type %s", __func__,
+ handle, _wapi_handle_typename[handle_data->type]);
#endif
- /* This block and the previous are both free,
- * so coalesce them
- */
- last_hdr->length += (hdr->length + HDRSIZE);
+ return(FALSE);
+ }
- /* If the new block is now big enough, use it
- * (next time round the loop)
- */
- if(last_hdr->length >= bytes + HDRSIZE) {
- idx=last_idx;
- } else {
- /* leave the last free info as it is,
- * in case the next block is also free
- * and can be coalesced too
- */
- idx=last_idx+last_hdr->length+HDRSIZE;
- }
- } else {
+ if(handle_specific == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": found used block at %d, length %d", idx,
- hdr->length);
+ g_message ("%s: Nowhere to store data", __func__);
#endif
- /* must be used, try next chunk */
- idx+=(hdr->length+HDRSIZE);
-
- /* Don't let the coalescing blow away this block */
- last_was_free=FALSE;
-
- /* But remember where the last block started */
- last_idx=idx;
- }
+ return(FALSE);
}
-
- /* Not enough free space. last_idx points to the last block.
- * If it's free, just tack on more space and update the
- * length. If it's allocated, it must have fit right into the
- * available space, so add more space and add a new header
- * after this block.
- */
- _wapi_handle_scratch_expand ();
- storage=_wapi_shared_scratch->scratch_data;
- hdr=(struct _WapiScratchHeader *)&storage[last_idx];
- if(hdr->flags & WAPI_SHM_SCRATCH_FREE) {
- hdr->length+=_WAPI_SHM_SCRATCH_SIZE;
- } else {
- idx=(hdr->length+HDRSIZE);
- hdr=(struct _WapiScratchHeader *)&storage[idx];
- hdr->flags |= WAPI_SHM_SCRATCH_FREE;
- hdr->length = _WAPI_SHM_SCRATCH_SIZE-HDRSIZE;
- }
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
+
+ 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);
+
+ memcpy(handle_specific, shared_handle_data,
+ sizeof(struct _WapiHandleShared));
+ } while (offset != shared_meta->offset);
+
+ _WAPI_HANDLE_COLLECTION_SAFE;
+
+#ifdef DEBUG
+ g_message ("%s: OK", __func__);
+#endif
- /* The caller will try again */
- return(0);
+ return(TRUE);
}
-/*
- * _wapi_handle_scratch_store_internal:
- * @bytes: Allocate no. bytes
- *
- * Like malloc(3) except its for the shared memory segment's scratch
- * part. Memory block returned is zeroed out.
- */
-guint32 _wapi_handle_scratch_store_internal (guint32 bytes, gboolean *remap)
+void _wapi_replace_handle (gpointer handle, WapiHandleType type,
+ struct _WapiHandleShared *handle_specific)
{
- guchar *storage;
- guint32 idx;
- struct _WapiScratchHeader *hdr;
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": storing %d bytes", bytes);
-#endif
-
- *remap=FALSE;
+ struct _WapiHandleShared *shared_handle_data;
+ struct _WapiHandleSharedMetadata *shared_meta;
+ guint32 handle_idx = GPOINTER_TO_UINT(handle);
+ guint32 old_off, new_off, ref;
- if(_wapi_shared_scratch->data_len==0) {
- /* Need to expand the data array for the first use */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": setting up scratch space");
+ g_message ("%s: Replacing handle %p of type %s", __func__, handle,
+ _wapi_handle_typename[type]);
#endif
- _wapi_handle_scratch_expand ();
- *remap=TRUE;
- }
+ g_assert(_WAPI_SHARED_HANDLE(type));
+ g_assert(_wapi_private_handles[handle_idx].type == type);
+
+ ref = _wapi_private_handles[handle_idx].u.shared.offset;
+ shared_meta = &_wapi_shared_layout->metadata[ref];
+
+ do {
+ old_off = shared_meta->offset;
+ new_off = _wapi_handle_new_shared (type, handle_specific);
+ if (new_off == 0) {
+ _wapi_handle_collect ();
+ new_off = _wapi_handle_new_shared (type,
+ handle_specific);
+ /* FIXME: grow the arrays */
+ g_assert (new_off != 0);
+ }
+
+ shared_handle_data = &_wapi_shared_layout->handles[new_off];
- storage=_wapi_shared_scratch->scratch_data;
- hdr=(struct _WapiScratchHeader *)&storage[0];
- if(hdr->flags==0 && hdr->length==0) {
- /* Need to initialise scratch data */
- hdr->flags |= WAPI_SHM_SCRATCH_FREE;
- hdr->length = _wapi_shared_scratch->data_len - HDRSIZE;
- }
+ memcpy (shared_handle_data, handle_specific,
+ sizeof(struct _WapiHandleShared));
+
+ /* An entry can't become fresh again (its going to be
+ * collected eventually), so no need for atomic ops
+ * here.
+ */
+ _wapi_shared_layout->handles[old_off].stale = TRUE;
+ } while(InterlockedCompareExchange (&shared_meta->offset, new_off,
+ old_off) != old_off);
- idx=_wapi_handle_scratch_locate_space (bytes);
- if(idx==0) {
- /* Some more space will have been allocated, so try again */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": trying again");
+ g_message ("%s: handle at 0x%x is now found at 0x%x", __func__, ref,
+ new_off);
#endif
-
- idx=_wapi_handle_scratch_locate_space (bytes);
- *remap=TRUE;
- }
-
- return(idx);
}
-guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
+gboolean _wapi_try_replace_handle (gpointer handle, WapiHandleType type,
+ struct _WapiHandleShared *handle_specific)
{
- guint32 idx = 0, store_bytes;
- gboolean remap;
- int thr_ret;
- guint32 ret = 0;
+ struct _WapiHandleShared *shared_handle_data;
+ struct _WapiHandleSharedMetadata *shared_meta;
+ guint32 handle_idx = GPOINTER_TO_UINT(handle);
+ guint32 old_off, new_off, ref;
+ gboolean ret;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": storing %d bytes", bytes);
+ g_message ("%s: Trying to replace handle %p of type %s", __func__,
+ handle, _wapi_handle_typename[type]);
#endif
- /* No point storing no data */
- if(bytes==0) {
- return(0);
- }
-
- /* Align bytes to 32 bits (needed for sparc at least) */
- store_bytes = (((bytes) + 3) & (~3));
-
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_scratch_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
-
- if(shared==TRUE) {
- WapiHandleRequest scratch={0};
- WapiHandleResponse scratch_resp={0};
- guint32 old_len=sizeof(struct _WapiHandleScratch) +
- _wapi_shared_scratch->data_len;
-
- scratch.type=WapiHandleRequestType_Scratch;
- scratch.u.scratch.length=store_bytes;
+ g_assert(_WAPI_SHARED_HANDLE(type));
+ g_assert(_wapi_private_handles[handle_idx].type == type);
- _wapi_daemon_request_response (daemon_sock, &scratch,
- &scratch_resp);
+ ref = _wapi_private_handles[handle_idx].u.shared.offset;
+ shared_meta = &_wapi_shared_layout->metadata[ref];
- if(scratch_resp.type==WapiHandleResponseType_Scratch) {
- idx=scratch_resp.u.scratch.idx;
- remap=scratch_resp.u.scratch.remap;
- } else {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
- scratch_resp.type);
- g_assert_not_reached ();
- }
+ old_off = shared_meta->offset;
+ new_off = _wapi_handle_new_shared (type, handle_specific);
+
+ if (new_off == 0) {
+ _wapi_handle_collect ();
+ new_off = _wapi_handle_new_shared (type, handle_specific);
- if(remap==TRUE) {
- munmap (_wapi_shared_scratch, old_len);
- _wapi_shared_scratch=_wapi_shm_file_map (WAPI_SHM_SCRATCH, 0, NULL, NULL);
- }
- } else {
- idx=_wapi_handle_scratch_store_internal (store_bytes, &remap);
- if(idx==0) {
- /* Failed to allocate space */
- goto cleanup;
- }
+ /* FIXME: grow the arrays */
+ g_assert (new_off != 0);
}
- ret = idx;
+ shared_handle_data = &_wapi_shared_layout->handles[new_off];
+
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": stored [%s] at %d (len %d, aligned len %d)",
- (char *)data, idx, bytes, store_bytes);
+ g_message ("%s: Old offset: 0x%x, trying to move to 0x%x", __func__,
+ old_off, new_off);
#endif
-
- memcpy (&_wapi_shared_scratch->scratch_data[idx], data, bytes);
-cleanup:
- thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
+ memcpy (shared_handle_data, handle_specific,
+ sizeof(struct _WapiHandleShared));
- return(ret);
-}
+ ret = (InterlockedCompareExchange (&shared_meta->offset, new_off,
+ old_off) == old_off);
-guint32 _wapi_handle_scratch_store_string_array (gchar **data)
-{
- guint32 *stored_strings, count=0, i, idx;
- gchar **strings;
-
- /* No point storing no data */
- if(data==NULL) {
- return(0);
+ if (ret) {
+ /* An entry can't become fresh again (its going to be
+ * collected eventually), so no need for atomic ops
+ * here.
+ */
+ _wapi_shared_layout->handles[old_off].stale = TRUE;
}
- strings=data;
- while(*strings!=NULL) {
- count++;
- strings++;
- }
-
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": %d strings to store", count);
+ if (ret) {
+ g_message ("%s: handle at 0x%x is now found at 0x%x", __func__,
+ ref, new_off);
+ } else {
+ g_message ("%s: handle at 0x%x already updated", __func__,
+ ref);
+ }
#endif
-
- if(count==0) {
- return(0);
+
+ return(ret);
+}
+
+/* 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
+ */
+gpointer _wapi_search_handle (WapiHandleType type,
+ gboolean (*check)(gpointer test, gpointer user),
+ gpointer user_data,
+ gpointer *handle_specific)
+{
+ struct _WapiHandleUnshared *handle_data = NULL;
+ guint32 i;
+
+ 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) {
+ break;
+ }
+ }
}
- /* stored_strings[0] is the count */
- stored_strings=g_new0 (guint32, count+1);
- stored_strings[0]=count;
+ if(i == _wapi_private_handle_count) {
+ return(GUINT_TO_POINTER (0));
+ }
- strings=data;
- for(i=0; i<count; i++) {
- stored_strings[i+1]=_wapi_handle_scratch_store (strings[i], strlen (strings[i]));
+ if(handle_specific != NULL) {
+ if (_WAPI_SHARED_HANDLE(type)) {
+ struct _WapiHandle_shared_ref *ref = &handle_data->u.shared;
+ 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];
+
+ g_assert(shared_handle_data->type == type);
+
+ *handle_specific = &shared_handle_data->u;
+ } else {
+ *handle_specific = &handle_data->u;
+ }
}
-
- idx=_wapi_handle_scratch_store (stored_strings,
- sizeof(guint32)*(count+1));
- return(idx);
+ return(GUINT_TO_POINTER (i));
}
-gpointer _wapi_handle_scratch_lookup (guint32 idx)
+/* This signature makes it easier to use in pthread cleanup handlers */
+int _wapi_namespace_timestamp_release (gpointer nowptr)
{
- struct _WapiScratchHeader *hdr;
- gpointer ret;
- guchar *storage;
- int thr_ret;
+ guint32 now = GPOINTER_TO_UINT(nowptr);
- if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
- return(NULL);
- }
+ return (_wapi_timestamp_release (&_wapi_shared_layout->namespace_check,
+ now));
+}
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_scratch_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
+int _wapi_namespace_timestamp (guint32 now)
+{
+ int ret;
- storage=_wapi_shared_scratch->scratch_data;
+ do {
+ ret = _wapi_timestamp_exclusion (&_wapi_shared_layout->namespace_check, now);
+ /* sleep for a bit */
+ _wapi_handle_spin (100);
+ } while (ret == EBUSY);
- hdr=(struct _WapiScratchHeader *)&storage[idx - HDRSIZE];
- ret=g_malloc0 (hdr->length+1);
- memcpy (ret, &storage[idx], hdr->length);
-
- thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
return(ret);
}
-gchar **_wapi_handle_scratch_lookup_string_array (guint32 idx)
+/* Returns the offset of the metadata array, or -1 on error, or 0 for
+ * not found (0 is not a valid offset)
+ */
+gint32 _wapi_search_handle_namespace (WapiHandleType type,
+ gchar *utf8_name)
{
- gchar **strings;
- guint32 *stored_strings;
- guint32 count, i;
-
- if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
- return(NULL);
- }
-
- stored_strings=_wapi_handle_scratch_lookup (idx);
- if(stored_strings==NULL) {
- return(NULL);
- }
+ struct _WapiHandleShared *shared_handle_data;
+ struct _WapiHandleSharedMetadata *shared_meta;
+ guint32 i;
+ gint32 ret = 0;
- /* stored_strings[0] is the number of strings, the index of
- * each string follows
- */
- count=stored_strings[0];
+ g_assert(_WAPI_SHARED_HANDLE(type));
+ g_assert(_wapi_shared_layout->namespace_check != 0);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": looking up an array of %d strings", count);
+ g_message ("%s: Lookup for handle named [%s] type %s", __func__,
+ utf8_name, _wapi_handle_typename[type]);
#endif
+
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
- /* NULL-terminate the array */
- strings=g_new0 (gchar *, count+1);
-
- for(i=0; i<count; i++) {
- strings[i]=_wapi_handle_scratch_lookup (stored_strings[i+1]);
+ for(i = 1; i < _WAPI_HANDLE_INITIAL_COUNT; i++) {
+ WapiSharedNamespace *sharedns;
+
+ shared_meta = &_wapi_shared_layout->metadata[i];
+ shared_handle_data = &_wapi_shared_layout->handles[shared_meta->offset];
+
+ /* Check mutex, event, semaphore, timer, job and file-mapping
+ * object names. So far only mutex is implemented.
+ */
+ if (!_WAPI_SHARED_NAMESPACE (shared_handle_data->type)) {
+ continue;
+ }
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": string %d is [%s]", i,
- strings[i]);
+ g_message ("%s: found a shared namespace handle at 0x%x (type %s)", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
#endif
- }
- g_free (stored_strings);
-
- return(strings);
-}
+ sharedns=(WapiSharedNamespace *)&shared_handle_data->u;
+
+#ifdef DEBUG
+ g_message ("%s: name is [%s]", __func__, sharedns->name);
+#endif
-/*
- * _wapi_handle_scratch_delete_internal:
- * @idx: Index to free block
- *
- * Like free(3) except its for the shared memory segment's scratch
- * part.
- */
-void _wapi_handle_scratch_delete_internal (guint32 idx)
-{
- struct _WapiScratchHeader *hdr;
- guchar *storage;
- int thr_ret;
-
- if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
- return;
+ if (strcmp (sharedns->name, utf8_name) == 0) {
+ if (shared_handle_data->type != type) {
+ /* Its the wrong type, so fail now */
+#ifdef DEBUG
+ g_message ("%s: handle 0x%x matches name but is wrong type: %s", __func__, i, _wapi_handle_typename[shared_handle_data->type]);
+#endif
+ ret = -1;
+ goto done;
+ } else {
+#ifdef DEBUG
+ g_message ("%s: handle 0x%x matches name and type", __func__, i);
+#endif
+ ret = i;
+ goto done;
+ }
+ }
}
- pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
- (void *)&_wapi_scratch_mutex);
- thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
-
- storage=_wapi_shared_scratch->scratch_data;
+done:
+ _WAPI_HANDLE_COLLECTION_SAFE;
- hdr=(struct _WapiScratchHeader *)&storage[idx - HDRSIZE];
- memset (&storage[idx], '\0', hdr->length);
- hdr->flags |= WAPI_SHM_SCRATCH_FREE;
-
- /* We could coalesce forwards here if the next block is also
- * free, but the _store() function will do that anyway.
- */
-
- thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
+ return(ret);
}
-void _wapi_handle_scratch_delete (guint32 idx)
+void _wapi_handle_ref (gpointer handle)
{
- if(shared==TRUE) {
- WapiHandleRequest scratch_free={0};
- WapiHandleResponse scratch_free_resp={0};
-
- scratch_free.type=WapiHandleRequestType_ScratchFree;
- scratch_free.u.scratch_free.idx=idx;
+ guint32 idx = GPOINTER_TO_UINT(handle);
- _wapi_daemon_request_response (daemon_sock, &scratch_free,
- &scratch_free_resp);
+ InterlockedIncrement (&_wapi_private_handles[idx].ref);
+ /* Do shared part */
- if(scratch_free_resp.type!=WapiHandleResponseType_ScratchFree) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
- scratch_free_resp.type);
- g_assert_not_reached ();
- }
- } else {
- _wapi_handle_scratch_delete_internal (idx);
- }
+#ifdef DEBUG_REFS
+ g_message ("%s: handle %p ref now %d", __func__, handle,
+ _wapi_private_handles[idx].ref);
+#endif
}
-void _wapi_handle_scratch_delete_string_array (guint32 idx)
+/* The handle must not be locked on entry to this function */
+void _wapi_handle_unref (gpointer handle)
{
- guint32 *stored_strings;
- guint32 count, i;
-
- stored_strings=_wapi_handle_scratch_lookup (idx);
- if(stored_strings==NULL) {
- return;
- }
-
- /* stored_strings[0] is the number of strings, the index of
- * each string follows
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ gboolean destroy = FALSE;
+ int thr_ret;
+
+ /* Possible race condition here if another thread refs the
+ * handle between here and setting the type to UNUSED. I
+ * could lock a mutex, but I'm not sure that allowing a handle
+ * reference to reach 0 isn't an application bug anyway.
*/
- count=stored_strings[0];
+ destroy = (InterlockedDecrement (&_wapi_private_handles[idx].ref) ==0);
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": deleting an array of %d strings",
- count);
+#ifdef DEBUG_REFS
+ g_message ("%s: handle %p ref now %d (destroy %s)", __func__, handle,
+ _wapi_private_handles[idx].ref, destroy?"TRUE":"FALSE");
#endif
- for(i=1; i<count; i++) {
- _wapi_handle_scratch_delete (stored_strings[i]);
- }
-
- _wapi_handle_scratch_delete (idx);
+ if(destroy==TRUE) {
+#ifdef DEBUG
+ g_message ("%s: Destroying handle %p", __func__, handle);
+#endif
+
+ _wapi_handle_ops_close (handle);
+
+ memset (&_wapi_private_handles[idx].u, '\0',
+ sizeof(_wapi_private_handles[idx].u));
+
+ _wapi_private_handles[idx].type = WAPI_HANDLE_UNUSED;
+
+ /* Destroy the mutex and cond var. We hope nobody
+ * tried to grab them between the handle unlock and
+ * now, but pthreads doesn't have a
+ * "unlock_and_destroy" atomic function.
+ */
+ thr_ret = mono_mutex_destroy (&_wapi_private_handles[idx].signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_destroy (&_wapi_private_handles[idx].signal_cond);
+ g_assert (thr_ret == 0);
- g_free (stored_strings);
+ /* The garbage collector will take care of shared data
+ * if this is a shared handle
+ */
+ }
}
void _wapi_handle_register_capabilities (WapiHandleType type,
gboolean _wapi_handle_test_capabilities (gpointer handle,
WapiHandleCapability caps)
{
- guint32 idx, segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
WapiHandleType type;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
+ type = _wapi_private_handles[idx].type;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": testing 0x%x against 0x%x (%d)",
+ g_message ("%s: testing 0x%x against 0x%x (%d)", __func__,
handle_caps[type], caps, handle_caps[type] & caps);
#endif
- return((handle_caps[type] & caps)!=0);
-}
-
-void _wapi_handle_ops_close_shared (gpointer handle)
-{
- guint32 idx, segment;
- WapiHandleType type;
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
-
- if(handle_ops[type]!=NULL && handle_ops[type]->close_shared!=NULL) {
- handle_ops[type]->close_shared (handle);
- }
+ return((handle_caps[type] & caps) != 0);
}
-void _wapi_handle_ops_close_private (gpointer handle)
+void _wapi_handle_ops_close (gpointer handle)
{
- guint32 idx, segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
WapiHandleType type;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
+ type = _wapi_private_handles[idx].type;
- /* When a handle in the process of being destroyed the shared
- * type has already been set to UNUSED
- */
- if(type==WAPI_HANDLE_UNUSED && _wapi_private_data!=NULL) {
- type=_wapi_handle_get_private_segment (segment)->handles[idx].type;
- }
-
- if(handle_ops[type]!=NULL && handle_ops[type]->close_private!=NULL) {
- handle_ops[type]->close_private (handle);
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->close != NULL) {
+ handle_ops[type]->close (handle);
}
}
void _wapi_handle_ops_signal (gpointer handle)
{
- guint32 idx, segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
WapiHandleType type;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
+ type = _wapi_private_handles[idx].type;
- if(handle_ops[type]!=NULL && handle_ops[type]->signal!=NULL) {
+ if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
handle_ops[type]->signal (handle);
}
}
-void _wapi_handle_ops_own (gpointer handle)
+gboolean _wapi_handle_ops_own (gpointer handle)
{
- guint32 idx, segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
WapiHandleType type;
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
+ type = _wapi_private_handles[idx].type;
- if(handle_ops[type]!=NULL && handle_ops[type]->own_handle!=NULL) {
- handle_ops[type]->own_handle (handle);
+ if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
+ return(handle_ops[type]->own_handle (handle));
+ } else {
+ return(FALSE);
}
}
gboolean _wapi_handle_ops_isowned (gpointer handle)
{
- guint32 idx, segment;
+ guint32 idx = GPOINTER_TO_UINT(handle);
WapiHandleType type;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
- type=_wapi_handle_get_shared_segment (segment)->handles[idx].type;
+ type = _wapi_private_handles[idx].type;
- if(handle_ops[type]!=NULL && handle_ops[type]->is_owned!=NULL) {
+ if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
return(handle_ops[type]->is_owned (handle));
} else {
return(FALSE);
*/
gboolean CloseHandle(gpointer handle)
{
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
if (handle == NULL) {
return(FALSE);
}
guint32 count, i, iter=0;
gboolean ret;
int thr_ret;
+ WapiHandleType type;
/* Lock all the handles, with backoff */
again:
for(i=0; i<numhandles; i++) {
- guint32 idx, segment;
gpointer handle = handles[i];
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": attempting to lock %p",
- handle);
+ g_message ("%s: attempting to lock %p", __func__, handle);
#endif
- ret=mono_mutex_trylock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
- if(ret!=0) {
+ type = _wapi_private_handles[idx].type;
+
+ if (_WAPI_SHARED_HANDLE(type)) {
+ /* We don't lock shared handles, but we need
+ * to be able to simultaneously check the
+ * signal state of all handles in the array
+ *
+ * We do this by atomically putting the
+ * least-significant 32 bits of time(2) into
+ * the 'checking' field if it is zero. If it
+ * isn't zero, then it means that either
+ * another thread is looking at this handle
+ * right now, or someone crashed here. Assume
+ * that if the time value is more than 10
+ * seconds old, its a crash and override it.
+ * 10 seconds should be enough for anyone...
+ *
+ * If the time value is within 10 seconds,
+ * back off and try again as per the
+ * non-shared case.
+ */
+ thr_ret = _wapi_timestamp_exclusion (&WAPI_SHARED_HANDLE_METADATA(handle).checking, now);
+ } else {
+ thr_ret = _wapi_handle_trylock_handle (handle);
+ }
+
+ if (thr_ret != 0) {
/* Bummer */
- struct timespec sleepytime;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p: %s", handle, strerror (ret));
+ g_message ("%s: attempt failed for %p: %s", __func__,
+ handle, strerror (thr_ret));
#endif
- while(i--) {
+ while (i--) {
handle = handles[i];
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
+ idx = GPOINTER_TO_UINT(handle);
- _wapi_handle_segment (handle, &segment, &idx);
- thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ if (_WAPI_SHARED_HANDLE(type)) {
+ /* Reset the checking field */
+ thr_ret = _wapi_timestamp_release (&WAPI_SHARED_HANDLE_METADATA(handle).checking, now);
+ } else{
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ }
g_assert (thr_ret == 0);
}
*/
iter++;
if(iter==100) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": iteration overflow!");
+ g_warning ("%s: iteration overflow!",
+ __func__);
iter=1;
}
- sleepytime.tv_sec=0;
- sleepytime.tv_nsec=10000000 * iter; /* 10ms*iter */
-
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Backing off for %d ms", iter*10);
+ g_message ("%s: Backing off for %d ms", __func__,
+ iter*10);
#endif
- nanosleep (&sleepytime, NULL);
+ _wapi_handle_spin (10 * iter);
goto again;
}
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Locked all handles");
+ g_message ("%s: Locked all handles", __func__);
#endif
count=0;
*lowest=numhandles;
for(i=0; i<numhandles; i++) {
- guint32 idx, segment;
gpointer handle = handles[i];
+ guint32 idx = GPOINTER_TO_UINT(handle);
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
+ type = _wapi_private_handles[idx].type;
+
_wapi_handle_ref (handle);
- _wapi_handle_segment (handle, &segment, &idx);
-
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Checking handle %p",
- handle);
+ g_message ("%s: Checking handle %p", __func__, handle);
#endif
if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) &&
- (_wapi_handle_ops_isowned (handle)==TRUE)) ||
- (_wapi_handle_get_shared_segment (segment)->handles[idx].signalled==TRUE)) {
+ (_wapi_handle_ops_isowned (handle) == TRUE)) ||
+ (_WAPI_SHARED_HANDLE(type) &&
+ WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) ||
+ (!_WAPI_SHARED_HANDLE(type) &&
+ _wapi_private_handles[idx].signalled == TRUE)) {
count++;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Handle %p signalled", handle);
+ g_message ("%s: Handle %p signalled", __func__,
+ handle);
#endif
if(*lowest>i) {
*lowest=i;
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": %d event handles signalled",
- count);
+ g_message ("%s: %d event handles signalled", __func__, count);
#endif
- if((waitall==TRUE && count==numhandles) ||
- (waitall==FALSE && count>0)) {
+ if ((waitall == TRUE && count == numhandles) ||
+ (waitall == FALSE && count > 0)) {
ret=TRUE;
} else {
ret=FALSE;
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Returning %d", ret);
+ g_message ("%s: Returning %d", __func__, ret);
#endif
*retcount=count;
int thr_ret;
for(i=0; i<numhandles; i++) {
- guint32 idx, segment;
gpointer handle = handles[i];
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ WapiHandleType type = _wapi_private_handles[idx].type;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
-
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p",
- handle);
+ g_message ("%s: unlocking handle %p", __func__, handle);
#endif
- thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
- g_assert (thr_ret == 0);
+ if (_WAPI_SHARED_HANDLE(type)) {
+ WAPI_SHARED_HANDLE_METADATA(handle).checking = 0;
+ } else {
+ thr_ret = mono_mutex_unlock (&_wapi_private_handles[idx].signal_mutex);
+ g_assert (thr_ret == 0);
+ }
_wapi_handle_unref (handle);
}
}
-/* Process-shared handles (currently only process and thread handles
- * are allowed, and they only work because once signalled they can't
- * become unsignalled) are waited for by one process and signalled by
- * another. Without process-shared conditions, the waiting process
- * will block forever. To get around this, the four handle waiting
- * functions use a short timeout when _POSIX_THREAD_PROCESS_SHARED is
- * not available. They also return "success" if the fake timeout
- * expired, and let the caller check signal status.
- */
int _wapi_handle_wait_signal (void)
{
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- return(mono_cond_wait (&_wapi_handle_get_shared_segment (0)->signal_cond,
- &_wapi_handle_get_shared_segment (0)->signal_mutex));
-#else
- struct timespec fake_timeout;
- int ret;
-
- _wapi_calc_timeout (&fake_timeout, 100);
-
- ret=mono_cond_timedwait (&_wapi_handle_get_private_segment (0)->signal_cond,
- &_wapi_handle_get_private_segment (0)->signal_mutex,
- &fake_timeout);
- if(ret==ETIMEDOUT) {
- ret=0;
- }
-
- return(ret);
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
+ return(mono_cond_wait (&_wapi_global_signal_cond,
+ &_wapi_global_signal_mutex));
}
int _wapi_handle_timedwait_signal (struct timespec *timeout)
{
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- return(mono_cond_timedwait (&_wapi_handle_get_shared_segment (0)->signal_cond,
- &_wapi_handle_get_shared_segment (0)->signal_mutex,
+ return(mono_cond_timedwait (&_wapi_global_signal_cond,
+ &_wapi_global_signal_mutex,
timeout));
-#else
+}
+
+int _wapi_handle_wait_signal_poll_share (void)
+{
struct timespec fake_timeout;
+ guint32 signal_count = _wapi_shared_layout->signal_count;
int ret;
- _wapi_calc_timeout (&fake_timeout, 100);
+#ifdef DEBUG
+ g_message ("%s: poll private and shared handles", __func__);
+#endif
+
+ while(1) {
+ _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 */
- ret=mono_cond_timedwait (&_wapi_handle_get_private_segment (0)->signal_cond,
- &_wapi_handle_get_private_segment (0)->signal_mutex,
- timeout);
- } else {
- ret=mono_cond_timedwait (&_wapi_handle_get_private_segment (0)->signal_cond,
- &_wapi_handle_get_private_segment (0)->signal_mutex,
- &fake_timeout);
- if(ret==ETIMEDOUT) {
- ret=0;
- }
- }
+ ret = mono_cond_timedwait (&_wapi_global_signal_cond,
+ &_wapi_global_signal_mutex,
+ &fake_timeout);
- return(ret);
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-}
+ /* Check the shared signal counter */
+ if (ret == ETIMEDOUT) {
+ if (signal_count != _wapi_shared_layout->signal_count) {
+#ifdef DEBUG
+ g_message ("%s: A shared handle was signalled",
+ __func__);
+#endif
-int _wapi_handle_wait_signal_handle (gpointer handle)
-{
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- guint32 idx, segment;
+ 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);
+ }
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
+ /* If timeout and no shared handle was signalled, go
+ * round again
+ */
}
+}
- _wapi_handle_segment (handle, &segment, &idx);
-
- return(mono_cond_wait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond,
- &_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
-#else
- guint32 idx, segment;
+int _wapi_handle_timedwait_signal_poll_share (struct timespec *timeout)
+{
struct timespec fake_timeout;
+ guint32 signal_count = _wapi_shared_layout->signal_count;
int ret;
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
+#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);
+ } 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;
+ }
+ }
+
+ if (ret != ETIMEDOUT) {
+ /* Either a private handle was signalled, or
+ * an error
+ */
+#ifdef DEBUG
+ g_message ("%s: returning: %d", __func__, ret);
+#endif
+ return (ret);
+ }
+
+ /* 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);
- _wapi_handle_segment (handle, &segment, &idx);
- _wapi_calc_timeout (&fake_timeout, 100);
+#ifdef DEBUG
+ g_message ("%s: returning ETIMEDOUT", __func__);
+#endif
+
+ return (ret);
+}
+
+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
- ret=mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond,
- &_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex,
- &fake_timeout);
- if(ret==ETIMEDOUT) {
- ret=0;
+ 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(ret);
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
}
int _wapi_handle_timedwait_signal_handle (gpointer handle,
struct timespec *timeout)
{
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- guint32 idx, segment;
-
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
-
- _wapi_handle_segment (handle, &segment, &idx);
+ guint32 idx = GPOINTER_TO_UINT(handle);
- return(mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond,
- &_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex,
- timeout));
-#else
- guint32 idx, segment;
- struct timespec fake_timeout;
- int ret;
+#ifdef DEBUG
+ g_message ("%s: waiting for %p (type %s)", __func__, handle,
+ _wapi_handle_typename[_wapi_handle_type (handle)]);
+#endif
- if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
- handle = _wapi_handle_fd_offset_to_handle (handle);
- }
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
+ struct timespec fake_timeout;
- _wapi_handle_segment (handle, &segment, &idx);
- _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 */
- ret=mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond,
- &_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex,
- timeout);
- } else {
- ret=mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond,
- &_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex,
- &fake_timeout);
- if(ret==ETIMEDOUT) {
- ret=0;
+ while (1) {
+ if (WAPI_SHARED_HANDLE_METADATA(handle).signalled == TRUE) {
+ return (0);
+ }
+
+ _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)) {
+ /* 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);
+ }
}
+ } else {
+ return(mono_cond_timedwait (&_wapi_private_handles[idx].signal_cond, &_wapi_private_handles[idx].signal_mutex, timeout));
}
-
- return(ret);
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
}
gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir,
gpointer *thread_handle, guint32 *pid,
guint32 *tid)
{
+#if 0
WapiHandleRequest fork_proc={0};
WapiHandleResponse fork_proc_resp={0};
int in_fd, out_fd, err_fd;
fork_proc.u.process_fork.inherit=inherit;
fork_proc.u.process_fork.flags=flags;
- in_fd=_wapi_file_handle_to_fd (stdin_handle);
- out_fd=_wapi_file_handle_to_fd (stdout_handle);
- err_fd=_wapi_file_handle_to_fd (stderr_handle);
+ in_fd = GPOINTER_TO_UINT (stdin_handle);
+ out_fd = GPOINTER_TO_UINT (stdout_handle);
+ err_fd = GPOINTER_TO_UINT (stderr_handle);
if(in_fd==-1 || out_fd==-1 || err_fd==-1) {
/* We were given duff handles */
return(TRUE);
}
} else {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
+ g_warning ("%s: bogus daemon response, type %d", __func__,
fork_proc_resp.type);
g_assert_not_reached ();
}
return(FALSE);
+#else
+ return(FALSE);
+#endif
}
gboolean
_wapi_handle_process_kill (pid_t process, guint32 signo, gint *errnum)
{
+#if 0
WapiHandleRequest killproc = {0};
WapiHandleResponse killprocresp = {0};
gint result;
_wapi_daemon_request_response (daemon_sock, &killproc, &killprocresp);
if (killprocresp.type != WapiHandleResponseType_ProcessKill) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d",
+ g_warning ("%s: bogus daemon response, type %d", __func__,
killprocresp.type);
g_assert_not_reached ();
}
*errnum = (result == FALSE) ? result : 0;
return (result == 0);
+#else
+ return(FALSE);
+#endif
}
gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
guint32 new_sharemode,
guint32 new_access,
guint32 *old_sharemode,
- guint32 *old_access)
+ guint32 *old_access,
+ struct _WapiFileShare **share_info)
{
- WapiHandleRequest req = {0};
- WapiHandleResponse resp = {0};
-
- if(shared != TRUE) {
- /* No daemon means we don't know if a file is sharable.
- * We're running in our own little world if this is
- * the case, so there's no point in pretending that
- * the file isn't sharable.
+ struct _WapiFileShare *file_share;
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ int thr_ret, i, first_unused = -1;
+ gboolean exists = FALSE;
+
+ /* Marking this as COLLECTION_UNSAFE prevents entries from
+ * expiring under us as we search
+ */
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
+
+ /* Prevent new entries racing with us */
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ g_assert (thr_ret == 0);
+
+ /* 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];
+
+ /* Make a note of an unused slot, in case we need to
+ * store share info
*/
- return(FALSE);
+ 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 (&file_share->handle_refs);
+
+ exists = TRUE;
+ break;
+ }
}
- req.type = WapiHandleRequestType_GetOrSetShare;
- req.u.get_or_set_share.device = device;
- req.u.get_or_set_share.inode = inode;
- req.u.get_or_set_share.new_sharemode = new_sharemode;
- req.u.get_or_set_share.new_access = new_access;
-
- _wapi_daemon_request_response (daemon_sock, &req, &resp);
- if (resp.type != WapiHandleResponseType_GetOrSetShare) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d", resp.type);
- g_assert_not_reached ();
+ 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->sharemode = new_sharemode;
+ file_share->access = new_access;
+ file_share->handle_refs = 1;
+ *share_info = file_share;
+ }
}
- *old_sharemode = resp.u.get_or_set_share.sharemode;
- *old_access = resp.u.get_or_set_share.access;
+ thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now);
+ g_assert (thr_ret == 0);
- return(resp.u.get_or_set_share.exists);
+ _WAPI_HANDLE_COLLECTION_SAFE;
+
+ return(exists);
}
-void _wapi_handle_set_share (dev_t device, ino_t inode, guint32 sharemode,
- guint32 access)
+/* Scan /proc/<pids>/fd/ for open file descriptors to the file in
+ * question. If there are none, reset the share info.
+ *
+ * This implementation is Linux-specific; legacy systems will have to
+ * implement their own ways of finding out if a particular file is
+ * open by a process.
+ */
+void _wapi_handle_check_share (struct _WapiFileShare *share_info)
{
- WapiHandleRequest req = {0};
- WapiHandleResponse resp = {0};
+ DIR *proc_dir;
+ struct dirent *proc_entry;
+ gboolean found = FALSE;
+ pid_t self = getpid();
+ int pid;
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ int thr_ret;
- if(shared != TRUE) {
- /* No daemon, so there's no one else to tell about
- * file sharing.
- */
+ proc_dir = opendir ("/proc");
+ if (proc_dir == NULL) {
return;
}
+
+ /* Marking this as COLLECTION_UNSAFE prevents entries from
+ * expiring under us if we remove this one
+ */
+ _WAPI_HANDLE_COLLECTION_UNSAFE;
+
+ /* Prevent new entries racing with us */
+ thr_ret = _wapi_timestamp_exclusion (&_wapi_fileshare_layout->share_check, now);
+ 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 && pid != self) {
+ /* Look in /proc/<pid>/fd/ but ignore
+ * ourselves, 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);
+
+ fd_dir = opendir (subdir);
+ if (fd_dir == NULL) {
+ continue;
+ }
+
+ while ((fd_entry = readdir (fd_dir)) != NULL) {
+ char path[_POSIX_PATH_MAX];
+ struct stat link_stat;
+
+ if (!strcmp (fd_entry->d_name, ".") ||
+ !strcmp (fd_entry->d_name, "..")) {
+ continue;
+ }
- req.type = WapiHandleRequestType_SetShare;
- req.u.set_share.device = device;
- req.u.set_share.inode = inode;
- req.u.set_share.sharemode = sharemode;
- req.u.set_share.access = access;
+ g_snprintf (path, _POSIX_PATH_MAX,
+ "/proc/%d/fd/%s", pid,
+ fd_entry->d_name);
+
+ stat (path, &link_stat);
+ if (link_stat.st_dev == share_info->device &&
+ link_stat.st_ino == share_info->inode) {
+#ifdef DEBUG
+ g_message ("%s: Found it at %s",
+ __func__, path);
+#endif
+
+ found = TRUE;
+ }
+ }
+
+ closedir (fd_dir);
+ }
+ }
- _wapi_daemon_request_response (daemon_sock, &req, &resp);
- if (resp.type != WapiHandleResponseType_SetShare) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": bogus daemon response, type %d", resp.type);
- g_assert_not_reached ();
+ closedir (proc_dir);
+
+ if (found == FALSE) {
+ /* Blank out this entry, as it is stale */
+#ifdef DEBUG
+ g_message ("%s: Didn't find it, destroying entry", __func__);
+#endif
+
+ memset (share_info, '\0', sizeof(struct _WapiFileShare));
+ }
+
+ thr_ret = _wapi_timestamp_release (&_wapi_fileshare_layout->share_check, now);
+ g_assert (thr_ret == 0);
+
+ _WAPI_HANDLE_COLLECTION_SAFE;
+}
+
+void _wapi_handle_dump (void)
+{
+ struct _WapiHandleUnshared *handle_data;
+ guint32 i;
+
+ for (i = 0; i < _wapi_private_handle_count; i++) {
+ handle_data = &_wapi_private_handles[i];
+
+ if (handle_data->type == WAPI_HANDLE_UNUSED) {
+ continue;
+ }
+
+ g_print ("%3x [%7s] %s %d ", i,
+ _wapi_handle_typename[handle_data->type],
+ handle_data->signalled?"Sg":"Un", handle_data->ref);
+ handle_details[handle_data->type](&handle_data->u);
+ g_print ("\n");
+ }
+}
+
+static void _wapi_shared_details (gpointer handle_info)
+{
+ struct _WapiHandle_shared_ref *shared = (struct _WapiHandle_shared_ref *)handle_info;
+
+ g_print ("offset: 0x%x", shared->offset);
+}
+
+void _wapi_handle_update_refs (void)
+{
+ guint32 i;
+
+ for (i = 0; i < _wapi_private_handle_count; i++) {
+ struct _WapiHandleUnshared *handle = &_wapi_private_handles[i];
+
+ if (_WAPI_SHARED_HANDLE(handle->type)) {
+ struct _WapiHandleSharedMetadata *shared_meta;
+
+ shared_meta = &_wapi_shared_layout->metadata[handle->u.shared.offset];
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Adding %d refs to handle 0x%x",
+ __func__, getpid(), handle->ref,
+ handle->u.shared.offset);
+#endif
+
+ InterlockedExchangeAdd (&shared_meta->ref, handle->ref);
+ } else if (handle->type == WAPI_HANDLE_FILE) {
+ struct _WapiHandle_file *file_handle = &handle->u.file;
+
+ g_assert (file_handle->share_info != NULL);
+
+#ifdef DEBUG
+ g_message ("%s: (%d) Inc refs on fileshare 0x%x",
+ __func__, getpid(),
+ (file_handle->share_info - &_wapi_fileshare_layout->share_info[0]) / sizeof(struct _WapiFileShare));
+#endif
+
+ InterlockedIncrement (&file_handle->share_info->handle_refs);
+ }
}
}
#include <glib.h>
#include <dirent.h>
#include <mono/io-layer/io.h>
+#include <mono/io-layer/wapi-private.h>
extern struct _WapiHandleOps _wapi_file_ops;
extern struct _WapiHandleOps _wapi_console_ops;
extern struct _WapiHandleOps _wapi_find_ops;
extern struct _WapiHandleOps _wapi_pipe_ops;
+extern void _wapi_file_details (gpointer handle_info);
+extern void _wapi_console_details (gpointer handle_info);
+extern void _wapi_pipe_details (gpointer handle_info);
+
/* Currently used for both FILE, CONSOLE and PIPE handle types. This may
* have to change in future.
*/
struct _WapiHandle_file
{
- guint32 filename;
+ gchar *filename;
+ struct _WapiFileShare *share_info; /* Pointer into shared mem */
guint32 security_attributes;
guint32 fileaccess;
guint32 sharemode;
guint32 attrs;
- dev_t device;
- ino_t inode;
-};
-
-struct _WapiHandlePrivate_file
-{
- WapiFDMapped fd_mapped;
gboolean async;
WapiOverlappedCB callback;
};
struct _WapiHandle_find
-{
- int dummy;
-};
-
-struct _WapiHandlePrivate_find
{
gchar **namelist;
gchar *dir_part;
};
G_BEGIN_DECLS
-int _wapi_file_handle_to_fd (gpointer handle);
-gboolean _wapi_io_add_callback (gpointer handle,
- WapiOverlappedCB callback,
- guint64 flags);
+extern gboolean _wapi_io_add_callback (gpointer handle,
+ WapiOverlappedCB callback,
+ guint64 flags);
G_END_DECLS
#endif /* _WAPI_IO_PRIVATE_H_ */
static gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length);
static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length);
-static void file_close_shared (gpointer handle);
-static void file_close_private (gpointer handle);
+static void file_close (gpointer handle);
static WapiFileType file_getfiletype(void);
static gboolean file_read(gpointer handle, gpointer buffer,
guint32 numbytes, guint32 *bytesread,
/* File handle is only signalled for overlapped IO */
struct _WapiHandleOps _wapi_file_ops = {
- file_close_shared, /* close_shared */
- file_close_private, /* close_private */
+ file_close, /* close */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
};
-static void console_close_shared (gpointer handle);
-static void console_close_private (gpointer handle);
+void _wapi_file_details (gpointer handle_info)
+{
+ struct _WapiHandle_file *file = (struct _WapiHandle_file *)handle_info;
+
+ g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
+ file->filename,
+ file->fileaccess&GENERIC_READ?'R':'.',
+ file->fileaccess&GENERIC_WRITE?'W':'.',
+ file->fileaccess&GENERIC_EXECUTE?'X':'.',
+ file->sharemode&FILE_SHARE_READ?'R':'.',
+ file->sharemode&FILE_SHARE_WRITE?'W':'.',
+ file->sharemode&FILE_SHARE_DELETE?'D':'.',
+ file->attrs);
+}
+
+static void console_close (gpointer handle);
static WapiFileType console_getfiletype(void);
static gboolean console_read(gpointer handle, gpointer buffer,
guint32 numbytes, guint32 *bytesread,
* input or output
*/
struct _WapiHandleOps _wapi_console_ops = {
- console_close_shared, /* close_shared */
- console_close_private, /* close_private */
+ console_close, /* close */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
};
+void _wapi_console_details (gpointer handle_info)
+{
+ _wapi_file_details (handle_info);
+}
+
/* Find handle has no ops.
*/
struct _WapiHandleOps _wapi_find_ops = {
- NULL, /* close_shared */
- NULL, /* close_private */
+ NULL, /* close */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
};
-static void pipe_close_shared (gpointer handle);
-static void pipe_close_private (gpointer handle);
+static void pipe_close (gpointer handle);
static WapiFileType pipe_getfiletype (void);
static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes,
guint32 *bytesread, WapiOverlapped *overlapped);
/* Pipe handles
*/
struct _WapiHandleOps _wapi_pipe_ops = {
- pipe_close_shared, /* close_shared */
- pipe_close_private, /* close_private */
+ pipe_close, /* close */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
};
+void _wapi_pipe_details (gpointer handle_info)
+{
+ _wapi_file_details (handle_info);
+}
+
static const struct {
/* File, console and pipe handles */
WapiFileType (*getfiletype)(void);
/* Handle ops.
*/
-static void file_close_shared (gpointer handle)
+static void file_close (gpointer handle)
{
struct _WapiHandle_file *file_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle, NULL);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return;
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p", handle);
+ g_message("%s: closing file handle %p", __func__, handle);
#endif
-
- if(file_handle->filename!=0) {
- _wapi_handle_scratch_delete (file_handle->filename);
- file_handle->filename=0;
- }
- if(file_handle->security_attributes!=0) {
- _wapi_handle_scratch_delete (file_handle->security_attributes);
- file_handle->security_attributes=0;
- }
-}
-static void file_close_private (gpointer handle)
-{
- struct _WapiHandlePrivate_file *file_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return;
- }
-
- if (file_private_handle->fd_mapped.assigned) {
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p with fd %d",
- handle, file_private_handle->fd_mapped.fd);
-#endif
+ g_free (file_handle->filename);
- /* Blank out the mapping, to make catching errors easier */
- _wapi_handle_fd_offset_store (file_private_handle->fd_mapped.fd, NULL);
+ _wapi_handle_share_release (file_handle->share_info);
- close(file_private_handle->fd_mapped.fd);
- }
+ close (GPOINTER_TO_UINT(handle));
}
static WapiFileType file_getfiletype(void)
WapiOverlapped *overlapped)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
+ int fd = GPOINTER_TO_UINT(handle);
int ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
- if (file_private_handle->fd_mapped.assigned == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
if(bytesread!=NULL) {
*bytesread=0;
}
- if(!(file_handle->fileaccess&GENERIC_READ) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
}
- if (file_private_handle->async == FALSE) {
+ if (file_handle->async == FALSE) {
do {
- ret=read(file_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=read(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR &&
+ !_wapi_thread_cur_apc_pending());
if(ret==-1) {
gint err = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": read of handle %p fd %d error: %s", handle,
- file_private_handle->fd_mapped.fd,
- strerror(err));
+ g_message("%s: read of handle %p error: %s", __func__,
+ handle, strerror(err));
#endif
SetLastError (_wapi_get_win32_file_error (err));
return(FALSE);
SetLastError (ERROR_NOT_SUPPORTED);
return FALSE;
#else
- if (overlapped == NULL || file_private_handle->callback == NULL) {
+ if (overlapped == NULL || file_handle->callback == NULL) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
{
- int fd = file_private_handle->fd_mapped.fd;
struct aiocb *aio;
int result;
notifier_data_t *ndata;
aio = g_new0 (struct aiocb, 1);
ndata->overlapped = overlapped;
ndata->aio = aio;
- ndata->callback = file_private_handle->callback;
+ ndata->callback = file_handle->callback;
aio->aio_fildes = fd;
aio->aio_lio_opcode = LIO_READ;
WapiOverlapped *overlapped G_GNUC_UNUSED)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*byteswritten=0;
}
- if(!(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
}
- if (file_private_handle->async == FALSE) {
+ if (file_handle->async == FALSE) {
off_t current_pos;
/* Need to lock the region we're about to write to,
* because we only do advisory locking on POSIX
* systems
*/
- current_pos = lseek (file_private_handle->fd_mapped.fd,
- (off_t)0, SEEK_CUR);
+ current_pos = lseek (fd, (off_t)0, SEEK_CUR);
if (current_pos == -1) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd_mapped.fd, strerror (errno));
+ g_message ("%s: handle %p lseek failed: %s", __func__,
+ handle, strerror (errno));
#endif
_wapi_set_last_error_from_errno ();
return(FALSE);
}
- if (_wapi_lock_file_region (file_private_handle->fd_mapped.fd,
- current_pos, numbytes) == FALSE) {
+ if (_wapi_lock_file_region (fd, current_pos,
+ numbytes) == FALSE) {
/* The error has already been set */
return(FALSE);
}
do {
- ret=write(file_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=write(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR &&
+ !_wapi_thread_cur_apc_pending());
- _wapi_unlock_file_region (file_private_handle->fd_mapped.fd,
- current_pos, numbytes);
+ _wapi_unlock_file_region (fd, current_pos, numbytes);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": write of handle %p fd %d error: %s", handle,
- file_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message("%s: write of handle %p error: %s",
+ __func__, handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
SetLastError (ERROR_NOT_SUPPORTED);
return FALSE;
#else
- if (overlapped == NULL || file_private_handle->callback == NULL) {
+ if (overlapped == NULL || file_handle->callback == NULL) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
{
- int fd = file_private_handle->fd_mapped.fd;
struct aiocb *aio;
int result;
notifier_data_t *ndata;
aio = g_new0 (struct aiocb, 1);
ndata->overlapped = overlapped;
ndata->aio = aio;
- ndata->callback = file_private_handle->callback;
+ ndata->callback = file_handle->callback;
aio->aio_fildes = fd;
aio->aio_lio_opcode = LIO_WRITE;
static gboolean file_flush(gpointer handle)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
- if(!(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
}
- ret=fsync(file_private_handle->fd_mapped.fd);
+ ret=fsync(fd);
if (ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": fsync of handle %p fd %d error: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: fsync of handle %p error: %s", __func__, handle,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
gint32 *highmovedistance, WapiSeekMethod method)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
off_t offset, newpos;
int whence;
guint32 ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(INVALID_SET_FILE_POINTER);
}
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- if(!(file_handle->fileaccess&GENERIC_READ) &&
- !(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
break;
default:
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": invalid seek type %d",
- method);
+ g_message("%s: invalid seek type %d", __func__, method);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
if(highmovedistance==NULL) {
offset=movedistance;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": setting offset to %lld (low %d)", offset,
- movedistance);
+ g_message("%s: setting offset to %lld (low %d)", __func__,
+ offset, movedistance);
#endif
} else {
offset=((gint64) *highmovedistance << 32) | (unsigned long)movedistance;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
+ g_message("%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
#endif
}
#else
#ifdef DEBUG
#ifdef HAVE_LARGE_FILE_SUPPORT
- g_message(G_GNUC_PRETTY_FUNCTION
- ": moving handle %p fd %d by %lld bytes from %d", handle,
- file_private_handle->fd_mapped.fd, offset, whence);
+ g_message("%s: moving handle %p by %lld bytes from %d", __func__,
+ handle, offset, whence);
#else
- g_message(G_GNUC_PRETTY_FUNCTION
- ": moving handle %p fd %d by %ld bytes from %d", handle,
- file_private_handle->fd_mapped.fd, offset, whence);
+ g_message("%s: moving handle %p fd %d by %ld bytes from %d", __func__,
+ handle, offset, whence);
#endif
#endif
- newpos=lseek(file_private_handle->fd_mapped.fd, offset, whence);
+ newpos=lseek(fd, offset, whence);
if(newpos==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": lseek on handle %p fd %d returned error %s",
- handle, file_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message("%s: lseek on handle %p returned error %s",
+ __func__, handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
#ifdef DEBUG
#ifdef HAVE_LARGE_FILE_SUPPORT
- g_message(G_GNUC_PRETTY_FUNCTION ": lseek returns %lld", newpos);
+ g_message("%s: lseek returns %lld", __func__, newpos);
#else
- g_message(G_GNUC_PRETTY_FUNCTION ": lseek returns %ld", newpos);
+ g_message ("%s: lseek returns %ld", __func__, newpos);
#endif
#endif
#endif
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": move of handle %p fd %d returning %d/%d", handle,
- file_private_handle->fd_mapped.fd, ret,
- highmovedistance==NULL?0:*highmovedistance);
+ g_message ("%s: move of handle %p returning %d/%d", __func__,
+ handle, ret, highmovedistance==NULL?0:*highmovedistance);
#endif
return(ret);
static gboolean file_setendoffile(gpointer handle)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
struct stat statbuf;
off_t size, pos;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
- if(!(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
* than the length, truncate the file.
*/
- ret=fstat(file_private_handle->fd_mapped.fd, &statbuf);
+ ret=fstat(fd, &statbuf);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d fstat failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message ("%s: handle %p fstat failed: %s", __func__,
+ handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
}
size=statbuf.st_size;
- pos=lseek(file_private_handle->fd_mapped.fd, (off_t)0, SEEK_CUR);
+ pos=lseek(fd, (off_t)0, SEEK_CUR);
if(pos==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d lseek failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: handle %p lseek failed: %s", __func__,
+ handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
if(pos>size) {
/* extend */
do {
- ret=write(file_private_handle->fd_mapped.fd, "", 1);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=write(fd, "", 1);
+ } while (ret==-1 && errno==EINTR &&
+ !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d extend write failed: %s",
- handle, file_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message("%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
* byte to the end of the file
*/
do {
- ret=ftruncate(file_private_handle->fd_mapped.fd, pos);
+ ret=ftruncate(fd, pos);
}
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
-
+ while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d ftruncate failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: handle %p ftruncate failed: %s", __func__,
+ handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
struct stat statbuf;
guint32 size;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(INVALID_FILE_SIZE);
}
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- if(!(file_handle->fileaccess&GENERIC_READ) &&
- !(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(INVALID_FILE_SIZE);
}
- ret=fstat(file_private_handle->fd_mapped.fd, &statbuf);
+ ret=fstat(fd, &statbuf);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d fstat failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: handle %p fstat failed: %s", __func__,
+ handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
#endif
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Returning size %d/%d", size,
- *highsize);
+ g_message("%s: Returning size %d/%d", __func__, size, *highsize);
#endif
return(size);
WapiFileTime *last_write)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
struct stat statbuf;
guint64 create_ticks, access_ticks, write_ticks;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
- if (file_private_handle->fd_mapped.assigned == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if(!(file_handle->fileaccess&GENERIC_READ) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
}
- ret=fstat(file_private_handle->fd_mapped.fd, &statbuf);
+ ret=fstat(fd, &statbuf);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d fstat failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: handle %p fstat failed: %s", __func__, handle,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": atime: %ld ctime: %ld mtime: %ld",
+ g_message("%s: atime: %ld ctime: %ld mtime: %ld", __func__,
statbuf.st_atime, statbuf.st_ctime,
statbuf.st_mtime);
#endif
write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": aticks: %llu cticks: %llu wticks: %llu",
- access_ticks, create_ticks, write_ticks);
+ g_message("%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+ access_ticks, create_ticks, write_ticks);
#endif
if(create_time!=NULL) {
const WapiFileTime *last_write)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
- guchar *name;
struct utimbuf utbuf;
struct stat statbuf;
guint64 access_ticks, write_ticks;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
- if(!(file_handle->fileaccess&GENERIC_WRITE) &&
- !(file_handle->fileaccess&GENERIC_ALL)) {
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
}
- if(file_handle->filename==0) {
+ if(file_handle->filename == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d unknown filename", handle,
- file_private_handle->fd_mapped.fd);
+ g_message("%s: handle %p unknown filename", __func__, handle);
#endif
SetLastError (ERROR_INVALID_HANDLE);
/* Get the current times, so we can put the same times back in
* the event that one of the FileTime structs is NULL
*/
- ret=fstat(file_private_handle->fd_mapped.fd, &statbuf);
+ ret=fstat (fd, &statbuf);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p fd %d fstat failed: %s", handle,
- file_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: handle %p fstat failed: %s", __func__, handle,
+ strerror(errno));
#endif
SetLastError (ERROR_INVALID_PARAMETER);
*/
if (access_ticks < 116444736000000000ULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": attempt to set access time too early");
+ g_message ("%s: attempt to set access time too early",
+ __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
return(FALSE);
*/
if (write_ticks < 116444736000000000ULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": attempt to set write time too early");
+ g_message ("%s: attempt to set write time too early",
+ __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
return(FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": setting handle %p access %ld write %ld", handle,
- utbuf.actime, utbuf.modtime);
+ g_message("%s: setting handle %p access %ld write %ld", __func__,
+ handle, utbuf.actime, utbuf.modtime);
#endif
- name=_wapi_handle_scratch_lookup (file_handle->filename);
-
- ret=utime(name, &utbuf);
+ ret=utime(file_handle->filename, &utbuf);
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": handle %p [%s] fd %d utime failed: %s", handle,
- name, file_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message("%s: handle %p [%s] utime failed: %s", __func__,
+ handle, file_handle->filename, strerror(errno));
#endif
- g_free (name);
SetLastError (ERROR_INVALID_PARAMETER);
return(FALSE);
}
-
- g_free (name);
return(TRUE);
}
-static void console_close_shared (gpointer handle)
+static void console_close (gpointer handle)
{
struct _WapiHandle_file *console_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
- (gpointer *)&console_handle, NULL);
+ (gpointer *)&console_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up console handle %p", handle);
+ g_warning ("%s: error looking up console handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return;
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing console handle %p", handle);
+ g_message("%s: closing console handle %p", __func__, handle);
#endif
-
- if(console_handle->filename!=0) {
- _wapi_handle_scratch_delete (console_handle->filename);
- console_handle->filename=0;
- }
- if(console_handle->security_attributes!=0) {
- _wapi_handle_scratch_delete (console_handle->security_attributes);
- console_handle->security_attributes=0;
- }
-}
-static void console_close_private (gpointer handle)
-{
- struct _WapiHandlePrivate_file *console_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE, NULL,
- (gpointer *)&console_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up console handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return;
- }
-
- if (console_private_handle->fd_mapped.assigned == TRUE) {
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": closing console handle %p with fd %d", handle,
- console_private_handle->fd_mapped.fd);
-#endif
+ g_free (console_handle->filename);
- /* Blank out the mapping, to make catching errors easier */
- _wapi_handle_fd_offset_store (console_private_handle->fd_mapped.fd, NULL);
-
- close(console_private_handle->fd_mapped.fd);
- }
+ close (GPOINTER_TO_UINT(handle));
}
static WapiFileType console_getfiletype(void)
WapiOverlapped *overlapped G_GNUC_UNUSED)
{
struct _WapiHandle_file *console_handle;
- struct _WapiHandlePrivate_file *console_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
- (gpointer *)&console_handle,
- (gpointer *)&console_private_handle);
+ (gpointer *)&console_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up console handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (console_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up console handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*bytesread=0;
}
- if(!(console_handle->fileaccess&GENERIC_READ) &&
- !(console_handle->fileaccess&GENERIC_ALL)) {
+ if(!(console_handle->fileaccess & GENERIC_READ) &&
+ !(console_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, console_private_handle->fd_mapped.fd, console_handle->fileaccess);
+ g_message ("%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, console_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
}
do {
- ret=read(console_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=read(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": read of handle %p fd %d error: %s", handle,
- console_private_handle->fd_mapped.fd,
+ g_message("%s: read of handle %p error: %s", __func__, handle,
strerror(errno));
#endif
WapiOverlapped *overlapped G_GNUC_UNUSED)
{
struct _WapiHandle_file *console_handle;
- struct _WapiHandlePrivate_file *console_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
- (gpointer *)&console_handle,
- (gpointer *)&console_private_handle);
+ (gpointer *)&console_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up console handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (console_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up console handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*byteswritten=0;
}
- if(!(console_handle->fileaccess&GENERIC_WRITE) &&
- !(console_handle->fileaccess&GENERIC_ALL)) {
+ if(!(console_handle->fileaccess & GENERIC_WRITE) &&
+ !(console_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, console_private_handle->fd_mapped.fd, console_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
}
do {
- ret=write(console_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=write(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": write of handle %p fd %d error: %s", handle,
- console_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message ("%s: write of handle %p error: %s", __func__,
+ handle, strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
return(TRUE);
}
-static void pipe_close_shared (gpointer handle)
+static void pipe_close (gpointer handle)
{
struct _WapiHandle_file *pipe_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
- (gpointer *)&pipe_handle, NULL);
+ (gpointer *)&pipe_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up pipe handle %p", handle);
+ g_warning ("%s: error looking up pipe handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return;
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing pipe handle %p", handle);
+ g_message("%s: closing pipe handle %p", __func__, handle);
#endif
-
- if(pipe_handle->filename!=0) {
- _wapi_handle_scratch_delete (pipe_handle->filename);
- pipe_handle->filename=0;
- }
- if(pipe_handle->security_attributes!=0) {
- _wapi_handle_scratch_delete (pipe_handle->security_attributes);
- pipe_handle->security_attributes=0;
- }
-}
-static void pipe_close_private (gpointer handle)
-{
- struct _WapiHandlePrivate_file *pipe_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL,
- (gpointer *)&pipe_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up pipe handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return;
- }
-
- if (pipe_private_handle->fd_mapped.assigned == TRUE) {
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": closing pipe handle %p with fd %d", handle,
- pipe_private_handle->fd_mapped.fd);
-#endif
-
- /* Blank out the mapping, to make catching errors easier */
- _wapi_handle_fd_offset_store (pipe_private_handle->fd_mapped.fd, NULL);
-
- close(pipe_private_handle->fd_mapped.fd);
- }
+ /* No filename with pipe handles */
+
+ close(GPOINTER_TO_UINT(handle));
}
static WapiFileType pipe_getfiletype(void)
WapiOverlapped *overlapped G_GNUC_UNUSED)
{
struct _WapiHandle_file *pipe_handle;
- struct _WapiHandlePrivate_file *pipe_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
- (gpointer *)&pipe_handle,
- (gpointer *)&pipe_private_handle);
+ (gpointer *)&pipe_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up pipe handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (pipe_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up pipe handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*bytesread=0;
}
- if(!(pipe_handle->fileaccess&GENERIC_READ) &&
- !(pipe_handle->fileaccess&GENERIC_ALL)) {
+ if(!(pipe_handle->fileaccess & GENERIC_READ) &&
+ !(pipe_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, pipe_private_handle->fd_mapped.fd, pipe_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, pipe_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": reading up to %d bytes from pipe %p (fd %d)", numbytes,
- handle, pipe_private_handle->fd_mapped.fd);
+ g_message ("%s: reading up to %d bytes from pipe %p", __func__,
+ numbytes, handle);
#endif
do {
- ret=read(pipe_private_handle->fd_mapped.fd, buffer, numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=read(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": read of handle %p fd %d error: %s", handle,
- pipe_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: read of handle %p error: %s", __func__, handle,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": read %d bytes from pipe", ret);
+ g_message ("%s: read %d bytes from pipe", __func__, ret);
#endif
if(bytesread!=NULL) {
WapiOverlapped *overlapped G_GNUC_UNUSED)
{
struct _WapiHandle_file *pipe_handle;
- struct _WapiHandlePrivate_file *pipe_private_handle;
gboolean ok;
int ret;
+ int fd = GPOINTER_TO_UINT(handle);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
- (gpointer *)&pipe_handle,
- (gpointer *)&pipe_private_handle);
+ (gpointer *)&pipe_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up pipe handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (pipe_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up pipe handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*byteswritten=0;
}
- if(!(pipe_handle->fileaccess&GENERIC_WRITE) &&
- !(pipe_handle->fileaccess&GENERIC_ALL)) {
+ if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
+ !(pipe_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, pipe_private_handle->fd_mapped.fd, pipe_handle->fileaccess);
+ g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": writing up to %d bytes to pipe %p (fd %d)", numbytes,
- handle, pipe_private_handle->fd_mapped.fd);
+ g_message ("%s: writing up to %d bytes to pipe %p", __func__, numbytes,
+ handle);
#endif
do {
- ret=write(pipe_private_handle->fd_mapped.fd, buffer, numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret=write(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(ret==-1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": write of handle %p fd %d error: %s", handle,
- pipe_private_handle->fd_mapped.fd, strerror(errno));
+ g_message("%s: write of handle %p error: %s", __func__, handle,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
break;
default:
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Unknown access type 0x%x",
+ g_message("%s: Unknown access type 0x%x", __func__,
fileaccess);
#endif
break;
break;
default:
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Unknown create mode 0x%x",
+ g_message("%s: Unknown create mode 0x%x", __func__,
createmode);
#endif
break;
fileaccess=GENERIC_READ|GENERIC_WRITE;
} else {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Can't figure out flags 0x%x", flags);
+ g_message("%s: Can't figure out flags 0x%x", __func__, flags);
#endif
}
return(fileaccess);
}
+#if 0 /* unused */
static mode_t convert_perms(guint32 sharemode)
{
mode_t perms=0600;
return(perms);
}
+#endif
+static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
+ guint32 fileaccess,
+ struct _WapiFileShare **share_info)
+{
+ gboolean file_already_shared;
+ guint32 file_existing_share, file_existing_access;
+
+ file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
+
+ if (file_already_shared) {
+ /* The reference to this share info was incremented
+ * when we looked it up, so be careful to put it back
+ * if we conclude we can't use this file.
+ */
+ if (file_existing_share == 0) {
+ /* Quick and easy, no possibility to share */
+#ifdef DEBUG
+ g_message ("%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+#endif
+
+ _wapi_handle_share_release (*share_info);
+
+ return(FALSE);
+ }
+
+ if (((file_existing_share == FILE_SHARE_READ) &&
+ (fileaccess != GENERIC_READ)) ||
+ ((file_existing_share == FILE_SHARE_WRITE) &&
+ (fileaccess != GENERIC_WRITE))) {
+ /* New access mode doesn't match up */
+#ifdef DEBUG
+ g_message ("%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+#endif
+
+ _wapi_handle_share_release (*share_info);
+
+ return(FALSE);
+ }
+
+ if (((file_existing_access & GENERIC_READ) &&
+ !(sharemode & FILE_SHARE_READ)) ||
+ ((file_existing_access & GENERIC_WRITE) &&
+ !(sharemode & FILE_SHARE_WRITE))) {
+ /* New share mode doesn't match up */
+#ifdef DEBUG
+ g_message ("%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+#endif
+
+ _wapi_handle_share_release (*share_info);
+
+ return(FALSE);
+ }
+ } else {
+#ifdef DEBUG
+ g_message ("%s: New file!", __func__);
+#endif
+ }
+
+ return(TRUE);
+}
+
+static gboolean share_check (struct stat *statbuf, guint32 sharemode,
+ guint32 fileaccess,
+ struct _WapiFileShare **share_info)
+{
+ if (share_allows_open (statbuf, sharemode, fileaccess,
+ share_info) == TRUE) {
+ return (TRUE);
+ }
+
+ /* Got a share violation. Double check that the file is still
+ * open by someone, in case a process crashed while still
+ * holding a file handle. This will also cope with someone
+ * using Mono.Posix to close the file. This is cheaper and
+ * less intrusive to other processes than initiating a handle
+ * collection.
+ */
+
+ _wapi_handle_check_share (*share_info);
+ if (share_allows_open (statbuf, sharemode, fileaccess,
+ share_info) == TRUE) {
+ return (TRUE);
+ }
+
+ /* Still violating. It's possible that a process crashed
+ * while still holding a file handle, and that a non-mono
+ * process has the file open. (For example, C-c mcs while
+ * editing a source file.) As a last resort, run a handle
+ * collection, which will remove stale share entries.
+ */
+ _wapi_handle_collect ();
+
+ return(share_allows_open (statbuf, sharemode, fileaccess, share_info));
+}
/**
* CreateFile:
guint32 createmode, guint32 attrs,
gpointer template G_GNUC_UNUSED)
{
- struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
+ struct _WapiHandle_file file_handle = {0};
gpointer handle;
- gboolean ok;
int flags=convert_flags(fileaccess, createmode);
/*mode_t perms=convert_perms(sharemode);*/
/* we don't use sharemode, because that relates to sharing of the file
mode_t perms=0644;
gchar *filename;
int fd, ret;
- int thr_ret;
- gpointer cf_ret = INVALID_HANDLE_VALUE;
struct stat statbuf;
- gboolean file_already_shared;
- guint32 file_existing_share, file_existing_access;
mono_once (&io_ops_once, io_ops_init);
- if(name==NULL) {
+ if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message ("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
return(INVALID_HANDLE_VALUE);
}
- filename=mono_unicode_to_external (name);
- if(filename==NULL) {
+ filename = mono_unicode_to_external (name);
+ if (filename == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": unicode conversion returned NULL");
+ g_message("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Opening %s with share 0x%x and access 0x%x", filename, sharemode, fileaccess);
+ g_message ("%s: Opening %s with share 0x%x and access 0x%x", __func__,
+ filename, sharemode, fileaccess);
#endif
fd = open(filename, flags, perms);
if (fd == -1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Error opening file %s: %s",
- filename, strerror(errno));
+ g_message("%s: Error opening file %s: %s", __func__, filename,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
g_free (filename);
return(INVALID_HANDLE_VALUE);
}
- if (fd >= _wapi_fd_offset_table_size) {
+ if (fd >= _wapi_fd_reserve) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
+ g_message ("%s: File descriptor is too big", __func__);
#endif
SetLastError (ERROR_TOO_MANY_OPEN_FILES);
ret = fstat (fd, &statbuf);
if (ret == -1) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": fstat error of file %s: %s", filename, strerror (errno));
+ g_message ("%s: fstat error of file %s: %s", __func__,
+ filename, strerror (errno));
#endif
_wapi_set_last_error_from_errno ();
g_free (filename);
return(INVALID_HANDLE_VALUE);
}
- file_already_shared = _wapi_handle_get_or_set_share (statbuf.st_dev, statbuf.st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access);
-
- if (file_already_shared) {
- if (file_existing_share == 0) {
- /* Quick and easy, no possibility to share */
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Share mode prevents open: requested access: 0x%x, file has sharing = NONE", fileaccess);
-#endif
- SetLastError (ERROR_SHARING_VIOLATION);
- g_free (filename);
- close (fd);
+ if (share_check (&statbuf, sharemode, fileaccess,
+ &file_handle.share_info) == FALSE) {
+ SetLastError (ERROR_SHARING_VIOLATION);
+ g_free (filename);
+ close (fd);
- return(INVALID_HANDLE_VALUE);
- }
-
- if (((file_existing_share == FILE_SHARE_READ) &&
- (fileaccess != GENERIC_READ)) ||
- ((file_existing_share == FILE_SHARE_WRITE) &&
- (fileaccess != GENERIC_WRITE))) {
- /* New access mode doesn't match up */
+ return (INVALID_HANDLE_VALUE);
+ }
+ if (file_handle.share_info == NULL) {
+ /* No space, so no more files can be opened */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", fileaccess, file_existing_share);
+ g_message ("%s: No space in the share table", __func__);
#endif
- SetLastError (ERROR_SHARING_VIOLATION);
- g_free (filename);
- close (fd);
-
- return(INVALID_HANDLE_VALUE);
- }
- if (((file_existing_access & GENERIC_READ) &&
- !(sharemode & FILE_SHARE_READ)) ||
- ((file_existing_access & GENERIC_WRITE) &&
- !(sharemode & FILE_SHARE_WRITE))) {
- /* New share mode doesn't match up */
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Access mode prevents open: requested share: 0x%x, file has access: 0x%x", sharemode, file_existing_access);
-#endif
- SetLastError (ERROR_SHARING_VIOLATION);
- g_free (filename);
- close (fd);
-
- return(INVALID_HANDLE_VALUE);
- }
- } else {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": New file!");
-#endif
- }
-
- handle=_wapi_handle_new (WAPI_HANDLE_FILE);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating file handle");
- g_free (filename);
+ SetLastError (ERROR_TOO_MANY_OPEN_FILES);
close (fd);
+ g_free (filename);
- SetLastError (ERROR_GEN_FAILURE);
return(INVALID_HANDLE_VALUE);
}
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- close (fd);
- goto cleanup;
- }
-
- _wapi_handle_fd_offset_store (fd, handle);
- cf_ret = GINT_TO_POINTER (fd);
+ file_handle.async = ((attrs & FILE_FLAG_OVERLAPPED) != 0);
+ file_handle.filename = filename;
- file_private_handle->fd_mapped.fd=fd;
- file_private_handle->fd_mapped.assigned=TRUE;
- file_private_handle->async = ((attrs & FILE_FLAG_OVERLAPPED) != 0);
- file_handle->filename=_wapi_handle_scratch_store (filename,
- strlen (filename));
if(security!=NULL) {
- file_handle->security_attributes=_wapi_handle_scratch_store (
- security, sizeof(WapiSecurityAttributes));
+ //file_handle->security_attributes=_wapi_handle_scratch_store (
+ //security, sizeof(WapiSecurityAttributes));
}
- file_handle->fileaccess=fileaccess;
- file_handle->sharemode=sharemode;
- file_handle->attrs=attrs;
- file_handle->device = statbuf.st_dev;
- file_handle->inode = statbuf.st_ino;
+ file_handle.fileaccess=fileaccess;
+ file_handle.sharemode=sharemode;
+ file_handle.attrs=attrs;
+
+ handle = _wapi_handle_new_fd (WAPI_HANDLE_FILE, fd, &file_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating file handle", __func__);
+ g_free (filename);
+ close (fd);
+
+ SetLastError (ERROR_GEN_FAILURE);
+ return(INVALID_HANDLE_VALUE);
+ }
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": returning handle %p with fd %d", handle,
- file_private_handle->fd_mapped.fd);
+ g_message("%s: returning handle %p", __func__, handle);
#endif
-
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
- g_free (filename);
-
- return(cf_ret);
+ return(handle);
}
/**
if(name==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
filename=mono_unicode_to_external(name);
if(filename==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": unicode conversion returned NULL");
+ g_message("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
if(name==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
if(dest_name==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
g_free (utf8_name);
utf8_dest_name = mono_unicode_to_external (dest_name);
if (utf8_dest_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
g_free (utf8_name);
if(name==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_src = mono_unicode_to_external (name);
if (utf8_src == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion of source returned NULL");
+ g_message ("%s: unicode conversion of source returned NULL",
+ __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
if(dest_name==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
g_free (utf8_src);
utf8_dest = mono_unicode_to_external (dest_name);
if (utf8_dest == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion of dest returned NULL");
+ g_message ("%s: unicode conversion of dest returned NULL",
+ __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
_wapi_set_last_error_from_errno ();
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": write failed.");
+ g_message ("%s: write failed.", __func__);
#endif
g_free (utf8_src);
static gpointer stdhandle_create (int fd, const guchar *name)
{
- struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
- gboolean ok;
- gpointer handle, ret = INVALID_HANDLE_VALUE;
+ struct _WapiHandle_file file_handle = {0};
+ gpointer handle;
int flags;
- int thr_ret;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": creating standard handle type %s",
- name);
+ g_message("%s: creating standard handle type %s, fd %d", __func__,
+ name, fd);
#endif
/* Check if fd is valid */
do {
flags=fcntl(fd, F_GETFL);
- }
- while (flags==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ } while (flags==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
if(flags==-1) {
/* Invalid fd. Not really much point checking for EBADF
* specifically
*/
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": fcntl error on fd %d: %s",
- fd, strerror(errno));
+ g_message("%s: fcntl error on fd %d: %s", __func__, fd,
+ strerror(errno));
#endif
_wapi_set_last_error_from_errno ();
return(INVALID_HANDLE_VALUE);
}
- handle=_wapi_handle_new (WAPI_HANDLE_CONSOLE);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating file handle");
+ file_handle.filename = g_strdup(name);
+ /* some default security attributes might be needed */
+ file_handle.security_attributes=0;
+ file_handle.fileaccess=convert_from_flags(flags);
+ file_handle.sharemode=0;
+ file_handle.attrs=0;
+
+ handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating file handle", __func__);
SetLastError (ERROR_GEN_FAILURE);
return(INVALID_HANDLE_VALUE);
}
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up console handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- }
-
- /* We know this is fd 0, 1 or 2 */
- _wapi_handle_fd_offset_store (fd, handle);
- ret = GINT_TO_POINTER (fd);
-
- file_private_handle->fd_mapped.fd=fd;
- file_private_handle->fd_mapped.assigned=TRUE;
- file_handle->filename=_wapi_handle_scratch_store (name, strlen (name));
- /* some default security attributes might be needed */
- file_handle->security_attributes=0;
- file_handle->fileaccess=convert_from_flags(flags);
- file_handle->sharemode=0;
- file_handle->attrs=0;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": returning handle %p with fd %d",
- handle, file_private_handle->fd_mapped.fd);
+ g_message("%s: returning handle %p", __func__, handle);
#endif
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- return(ret);
+ return(handle);
}
static void stdhandle_init (void)
default:
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": unknown standard handle type");
+ g_message("%s: unknown standard handle type", __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
}
/* Add a reference to this handle */
- _wapi_handle_ref (_wapi_handle_fd_offset_to_handle (handle));
+ _wapi_handle_ref (handle);
return(handle);
}
* read due to an attempt to read past the end of the file), %FALSE on
* error.
*/
-gboolean ReadFile(gpointer fd_handle, gpointer buffer, guint32 numbytes,
+gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
guint32 *bytesread, WapiOverlapped *overlapped)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
if(io_ops[type].readfile==NULL) {
*
* Return value: %TRUE if the write succeeds, %FALSE on error.
*/
-gboolean WriteFile(gpointer fd_handle, gconstpointer buffer, guint32 numbytes,
+gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
guint32 *byteswritten, WapiOverlapped *overlapped)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
if(io_ops[type].writefile==NULL) {
*
* Return value: %TRUE on success, %FALSE otherwise.
*/
-gboolean FlushFileBuffers(gpointer fd_handle)
+gboolean FlushFileBuffers(gpointer handle)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
if(io_ops[type].flushfile==NULL) {
*
* Return value: %TRUE on success, %FALSE otherwise.
*/
-gboolean SetEndOfFile(gpointer fd_handle)
+gboolean SetEndOfFile(gpointer handle)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].setendoffile==NULL) {
+ if (io_ops[type].setendoffile == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
* If @highmovedistance is not %NULL, the high 32 bits of the new file
* pointer are stored there. On failure, %INVALID_SET_FILE_POINTER.
*/
-guint32 SetFilePointer(gpointer fd_handle, gint32 movedistance,
+guint32 SetFilePointer(gpointer handle, gint32 movedistance,
gint32 *highmovedistance, WapiSeekMethod method)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_SET_FILE_POINTER);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].seek==NULL) {
+ if (io_ops[type].seek == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(INVALID_SET_FILE_POINTER);
}
* %FILE_TYPE_CHAR - @handle is a character device, such as a console.
* %FILE_TYPE_PIPE - @handle is a named or anonymous pipe.
*/
-WapiFileType GetFileType(gpointer fd_handle)
+WapiFileType GetFileType(gpointer handle)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FILE_TYPE_UNKNOWN);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].getfiletype==NULL) {
+ if (io_ops[type].getfiletype == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(FILE_TYPE_UNKNOWN);
}
* @highsize is non-%NULL then the high 32 bits of the file size are
* stored here. On failure %INVALID_FILE_SIZE is returned.
*/
-guint32 GetFileSize(gpointer fd_handle, guint32 *highsize)
+guint32 GetFileSize(gpointer handle, guint32 *highsize)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_FILE_SIZE);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].getfilesize==NULL) {
+ if (io_ops[type].getfilesize == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(INVALID_FILE_SIZE);
}
*
* Return value: %TRUE on success, %FALSE otherwise.
*/
-gboolean GetFileTime(gpointer fd_handle, WapiFileTime *create_time,
+gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
WapiFileTime *last_access, WapiFileTime *last_write)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].getfiletime==NULL) {
+ if (io_ops[type].getfiletime == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*
* Return value: %TRUE on success, %FALSE otherwise.
*/
-gboolean SetFileTime(gpointer fd_handle, const WapiFileTime *create_time,
+gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
const WapiFileTime *last_access,
const WapiFileTime *last_write)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
WapiHandleType type;
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
type = _wapi_handle_type (handle);
- if(io_ops[type].setfiletime==NULL) {
+ if (io_ops[type].setfiletime == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
if(system_time==NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": system_time NULL");
+ g_message("%s: system_time NULL", __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
*/
if(file_ticks<0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": file_time too big");
+ g_message("%s: file_time too big", __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
totaldays=(file_ticks / TICKS_PER_DAY);
rem = file_ticks % TICKS_PER_DAY;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld rem: %lld",
- totaldays, rem);
+ g_message("%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
#endif
system_time->wHour=rem/TICKS_PER_HOUR;
rem %= TICKS_PER_HOUR;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Hour: %d rem: %lld",
- system_time->wHour, rem);
+ g_message("%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
#endif
system_time->wMinute = rem / TICKS_PER_MINUTE;
rem %= TICKS_PER_MINUTE;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Minute: %d rem: %lld",
- system_time->wMinute, rem);
+ g_message("%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
+ rem);
#endif
system_time->wSecond = rem / TICKS_PER_SECOND;
rem %= TICKS_PER_SECOND;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Second: %d rem: %lld",
- system_time->wSecond, rem);
+ g_message("%s: Second: %d rem: %lld", __func__, system_time->wSecond,
+ rem);
#endif
system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Milliseconds: %d",
+ g_message("%s: Milliseconds: %d", __func__,
system_time->wMilliseconds);
#endif
/* January 1, 1601 was a Monday, according to Emacs calendar */
system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Day of week: %d",
- system_time->wDayOfWeek);
+ g_message("%s: Day of week: %d", __func__, system_time->wDayOfWeek);
#endif
/* This algorithm to find year and month given days from epoch
/* Guess a corrected year, assuming 365 days per year */
gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": totaldays: %lld yg: %lld y: %lld", totaldays, yg,
+ g_message("%s: totaldays: %lld yg: %lld y: %lld", __func__,
+ totaldays, yg,
y);
- g_message(G_GNUC_PRETTY_FUNCTION
- ": LEAPS(yg): %lld LEAPS(y): %lld",
+ g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
#endif
+ LEAPS_THRU_END_OF (yg - 1)
- LEAPS_THRU_END_OF (y - 1));
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld",
- totaldays);
+ g_message("%s: totaldays: %lld", __func__, totaldays);
#endif
y = yg;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": y: %lld", y);
+ g_message("%s: y: %lld", __func__, y);
#endif
}
system_time->wYear = y;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Year: %d", system_time->wYear);
+ g_message("%s: Year: %d", __func__, system_time->wYear);
#endif
ip = mon_yday[isleap(y)];
}
totaldays-=ip[y];
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld", totaldays);
+ g_message("%s: totaldays: %lld", __func__, totaldays);
#endif
system_time->wMonth = y + 1;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Month: %d", system_time->wMonth);
+ g_message("%s: Month: %d", __func__, system_time->wMonth);
#endif
system_time->wDay = totaldays + 1;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Day: %d", system_time->wDay);
+ g_message("%s: Day: %d", __func__, system_time->wDay);
#endif
return(TRUE);
gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
{
- struct _WapiHandlePrivate_find *find_handle;
+ struct _WapiHandle_find find_handle = {0};
gpointer handle, find_ret = INVALID_HANDLE_VALUE;
- gboolean ok;
gchar *utf8_pattern = NULL, *dir_part, *entry_part;
int result;
- int thr_ret;
- gboolean unref = FALSE;
if (pattern == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": pattern is NULL");
+ g_message ("%s: pattern is NULL", __func__);
#endif
SetLastError (ERROR_PATH_NOT_FOUND);
utf8_pattern = mono_unicode_to_external (pattern);
if (utf8_pattern == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": looking for [%s]",
- utf8_pattern);
+ g_message ("%s: looking for [%s]", __func__, utf8_pattern);
#endif
/* Figure out which bit of the pattern is the directory */
- dir_part=g_path_get_dirname (utf8_pattern);
- entry_part=g_path_get_basename (utf8_pattern);
+ dir_part = g_path_get_dirname (utf8_pattern);
+ entry_part = g_path_get_basename (utf8_pattern);
#if 0
/* Don't do this check for now, it breaks if directories
return(INVALID_HANDLE_VALUE);
}
#endif
-
- handle=_wapi_handle_new (WAPI_HANDLE_FIND);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": error creating find handle");
- g_free (dir_part);
- g_free (entry_part);
- g_free (utf8_pattern);
- SetLastError (ERROR_GEN_FAILURE);
-
- return(INVALID_HANDLE_VALUE);
- }
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
- (gpointer *)&find_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up find handle %p", handle);
- g_free (dir_part);
- dir_part = NULL;
- g_free (entry_part);
- entry_part = NULL;
- g_free (utf8_pattern);
- utf8_pattern = NULL;
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- }
/* The pattern can specify a directory or a set of files.
*
* than mess around with regexes.
*/
- find_handle->namelist = NULL;
- result = mono_io_scandir (dir_part, entry_part, &find_handle->namelist);
+ find_handle.namelist = NULL;
+ result = mono_io_scandir (dir_part, entry_part, &find_handle.namelist);
if (result < 0) {
#ifdef DEBUG
#endif
_wapi_set_last_error_from_errno ();
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": scandir error: %s", g_strerror (errnum));
+ g_message ("%s: scandir error: %s", __func__,
+ g_strerror (errnum));
#endif
g_free (utf8_pattern);
g_free (entry_part);
g_free (dir_part);
- unref = TRUE;
- goto cleanup;
+ SetLastError (ERROR_GEN_FAILURE);
+ return (INVALID_HANDLE_VALUE);
}
g_free (utf8_pattern);
g_free (entry_part);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Got %d matches", result);
+ g_message ("%s: Got %d matches", __func__, result);
#endif
- find_handle->dir_part = dir_part;
- find_handle->num = result;
- find_handle->count = 0;
-
- find_ret = handle;
-
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
+ find_handle.dir_part = dir_part;
+ find_handle.num = result;
+ find_handle.count = 0;
+
+ handle = _wapi_handle_new (WAPI_HANDLE_FIND, &find_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating find handle", __func__);
+ g_free (dir_part);
+ g_free (entry_part);
+ g_free (utf8_pattern);
+ SetLastError (ERROR_GEN_FAILURE);
+
+ return(INVALID_HANDLE_VALUE);
+ }
- /* FindNextFile has to be called after unlocking the handle,
- * because it wants to lock the handle itself
- */
- if (find_ret != INVALID_HANDLE_VALUE &&
+ if (handle != INVALID_HANDLE_VALUE &&
!FindNextFile (handle, find_data)) {
FindClose (handle);
SetLastError (ERROR_NO_MORE_FILES);
find_ret = INVALID_HANDLE_VALUE;
}
- /* Must not call _wapi_handle_unref() with the handle already
- * locked
- */
- if (unref) {
- _wapi_handle_unref (handle);
- }
-
- return (find_ret);
+ return (handle);
}
gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
{
- struct _WapiHandlePrivate_find *find_handle;
+ struct _WapiHandle_find *find_handle;
gboolean ok;
struct stat buf;
gchar *filename;
int thr_ret;
gboolean ret = FALSE;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
(gpointer *)&find_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up find handle %p", handle);
+ g_warning ("%s: error looking up find handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
if (lstat (filename, &buf) != 0) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": stat failed: %s", filename);
+ g_message ("%s: stat failed: %s", __func__, filename);
#endif
g_free (filename);
}
}
- utf8_filename=mono_utf8_from_external (filename);
- if(utf8_filename==NULL) {
+ utf8_filename = mono_utf8_from_external (filename);
+ if (utf8_filename == NULL) {
/* We couldn't turn this filename into utf8 (eg the
* encoding of the name wasn't convertible), so just
* ignore it.
g_free (filename);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Found [%s]", utf8_filename);
+ g_message ("%s: Found [%s]", __func__, utf8_filename);
#endif
/* fill data block */
if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
find_data->nFileSizeHigh = 0;
find_data->nFileSizeLow = 0;
- }
- else {
+ } else {
find_data->nFileSizeHigh = buf.st_size >> 32;
find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
}
*/
gboolean FindClose (gpointer handle)
{
- struct _WapiHandlePrivate_find *find_handle;
+ struct _WapiHandle_find *find_handle;
gboolean ok;
int thr_ret;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
(gpointer *)&find_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up find handle %p", handle);
+ g_warning ("%s: error looking up find handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
*
* Return value: %TRUE on success, %FALSE otherwise.
*/
-gboolean CreateDirectory (const gunichar2 *name, WapiSecurityAttributes *security)
+gboolean CreateDirectory (const gunichar2 *name,
+ WapiSecurityAttributes *security)
{
gchar *utf8_name;
int result;
if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
if (level != GetFileExInfoStandard) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": info level %d not supported.", level);
+ g_message ("%s: info level %d not supported.", __func__,
+ level);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_PARAMETER);
if (name == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+ g_message("%s: name is NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
utf8_name = mono_unicode_to_external (name);
if (utf8_name == NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError (ERROR_INVALID_NAME);
return result;
}
-/* When we're confident there are no more bugs in the fd->handle
- * mapping, this can be replaced as a no-op: GPOINTER_TO_INT(fd_handle) == fd
- */
-int _wapi_file_handle_to_fd (gpointer fd_handle)
-{
- struct _WapiHandlePrivate_file *file_private_handle;
- gboolean ok;
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": looking up fd for %p", handle);
-#endif
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE, NULL,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL,
- (gpointer *)&file_private_handle);
- if(ok==FALSE) {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": returning -1");
-#endif
- SetLastError (ERROR_INVALID_HANDLE);
- return(-1);
- }
- }
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(-1);
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning %d",
- file_private_handle->fd_mapped.fd);
-#endif
-
- g_assert (file_private_handle->fd_mapped.fd == GPOINTER_TO_INT (fd_handle));
-
- return(file_private_handle->fd_mapped.fd);
-}
-
gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 size)
{
- struct _WapiHandle_file *pipe_read_handle;
- struct _WapiHandle_file *pipe_write_handle;
- struct _WapiHandlePrivate_file *pipe_read_private_handle;
- struct _WapiHandlePrivate_file *pipe_write_private_handle;
+ struct _WapiHandle_file pipe_read_handle = {0};
+ struct _WapiHandle_file pipe_write_handle = {0};
gpointer read_handle;
gpointer write_handle;
- gboolean ok;
int filedes[2];
int ret;
- int thr_ret;
- gboolean unref_read = FALSE, unref_write = FALSE;
- gboolean cp_ret = FALSE;
mono_once (&io_ops_once, io_ops_init);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Creating pipe");
+ g_message ("%s: Creating pipe", __func__);
#endif
ret=pipe (filedes);
if(ret==-1) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Error creating pipe: %s",
+ g_message ("%s: Error creating pipe: %s", __func__,
strerror (errno));
#endif
return(FALSE);
}
- if (filedes[0] >= _wapi_fd_offset_table_size ||
- filedes[1] >= _wapi_fd_offset_table_size) {
+ if (filedes[0] >= _wapi_fd_reserve ||
+ filedes[1] >= _wapi_fd_reserve) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
+ g_message ("%s: File descriptor is too big", __func__);
#endif
SetLastError (ERROR_TOO_MANY_OPEN_FILES);
/* filedes[0] is open for reading, filedes[1] for writing */
- read_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
- if(read_handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating pipe read handle");
+ pipe_read_handle.fileaccess = GENERIC_READ;
+ read_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[0],
+ &pipe_read_handle);
+ if (read_handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating pipe read handle", __func__);
close (filedes[0]);
close (filedes[1]);
SetLastError (ERROR_GEN_FAILURE);
return(FALSE);
}
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- read_handle);
- thr_ret = _wapi_handle_lock_handle (read_handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (read_handle, WAPI_HANDLE_PIPE,
- (gpointer *)&pipe_read_handle,
- (gpointer *)&pipe_read_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
- close (filedes[0]);
- close (filedes[1]);
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- }
-
- write_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
- if(write_handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating pipe write handle");
- unref_read = TRUE;
+ pipe_write_handle.fileaccess = GENERIC_WRITE;
+ write_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[1],
+ &pipe_write_handle);
+ if (write_handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating pipe write handle", __func__);
+ _wapi_handle_unref (read_handle);
close (filedes[0]);
close (filedes[1]);
SetLastError (ERROR_GEN_FAILURE);
- goto cleanup;
- }
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- write_handle);
- thr_ret = _wapi_handle_lock_handle (write_handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (write_handle, WAPI_HANDLE_PIPE,
- (gpointer *)&pipe_write_handle,
- (gpointer *)&pipe_write_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
- unref_read = TRUE;
- unref_write = TRUE;
-
- close (filedes[0]);
- close (filedes[1]);
- SetLastError (ERROR_INVALID_HANDLE);
- goto write_cleanup;
+ return(FALSE);
}
- cp_ret = TRUE;
-
- pipe_read_private_handle->fd_mapped.fd=filedes[0];
- pipe_read_private_handle->fd_mapped.assigned=TRUE;
- pipe_read_handle->fileaccess=GENERIC_READ;
-
- _wapi_handle_fd_offset_store (filedes[0], read_handle);
- *readpipe=GINT_TO_POINTER (filedes[0]);
-
- pipe_write_private_handle->fd_mapped.fd=filedes[1];
- pipe_write_private_handle->fd_mapped.assigned=TRUE;
- pipe_write_handle->fileaccess=GENERIC_WRITE;
- _wapi_handle_fd_offset_store (filedes[1], write_handle);
- *writepipe=GINT_TO_POINTER (filedes[1]);
+ *readpipe = read_handle;
+ *writepipe = write_handle;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Returning pipe: read handle %p (fd %d), write handle %p (fd %d)", read_handle, filedes[0], write_handle, filedes[1]);
+ g_message ("%s: Returning pipe: read handle %p, write handle %p",
+ __func__, read_handle, write_handle);
#endif
-write_cleanup:
- thr_ret =_wapi_handle_unlock_handle (write_handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- if (unref_write) {
- _wapi_handle_unref (write_handle);
- }
-
-cleanup:
- thr_ret =_wapi_handle_unlock_handle (read_handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- /* Must not call _wapi_handle_unref() with the handle already
- * locked
- */
- if (unref_read) {
- _wapi_handle_unref (read_handle);
- }
-
- return(cp_ret);
+ return(TRUE);
}
guint32 GetTempPath (guint32 len, gunichar2 *buf)
if(dirlen+1>len) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Size %d smaller than needed (%ld)", len,
- dirlen+1);
+ g_message ("%s: Size %d smaller than needed (%ld)",
+ __func__, len, dirlen+1);
#endif
ret=dirlen+1;
}
gboolean
-_wapi_io_add_callback (gpointer fd_handle,
+_wapi_io_add_callback (gpointer handle,
WapiOverlappedCB callback,
guint64 flags G_GNUC_UNUSED)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
int thr_ret;
gboolean ret = FALSE;
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *) &file_handle,
- (gpointer *) &file_private_handle);
+ (gpointer *) &file_handle);
if (ok == FALSE) {
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
- (gpointer *) &file_handle,
- (gpointer *) &file_private_handle);
+ (gpointer *) &file_handle);
}
- if (ok == FALSE || file_private_handle->async == FALSE) {
+ if (ok == FALSE || file_handle->async == FALSE) {
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
- if (file_private_handle->callback != NULL) {
+ if (file_handle->callback != NULL) {
SetLastError (ERROR_INVALID_PARAMETER);
goto cleanup;
}
ret = TRUE;
- file_private_handle->callback = callback;
+ file_handle->callback = callback;
cleanup:
thr_ret = _wapi_handle_unlock_handle (handle);
while(ret == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": fcntl returns %d", ret);
+ g_message ("%s: fcntl returns %d", __func__, ret);
#endif
if (ret == -1) {
while(ret == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": fcntl returns %d", ret);
+ g_message ("%s: fcntl returns %d", __func__, ret);
#endif
if (ret == -1) {
return(TRUE);
}
-gboolean LockFile (gpointer fd_handle, guint32 offset_low, guint32 offset_high,
+gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
guint32 length_low, guint32 length_high)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
off_t offset, length;
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
+ int fd = GPOINTER_TO_UINT(handle);
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if (ok == FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
!(file_handle->fileaccess & GENERIC_WRITE) &&
!(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
length = ((gint64)length_high << 32) | length_low;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Locking handle %p fd %d, offset %lld, length %lld",
- handle, file_private_handle->fd_mapped.fd, offset, length);
+ g_message ("%s: Locking handle %p, offset %lld, length %lld", __func__,
+ handle, offset, length);
#endif
#else
offset = offset_low;
length = length_low;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Locking handle %p fd %d, offset %ld, length %ld",
- handle, file_private_handle->fd_mapped.fd, offset, length);
+ g_message ("%s: Locking handle %p, offset %ld, length %ld", __func__,
+ handle, offset, length);
#endif
#endif
- return(_wapi_lock_file_region (file_private_handle->fd_mapped.fd,
- offset, length));
+ return(_wapi_lock_file_region (fd, offset, length));
}
-gboolean UnlockFile (gpointer fd_handle, guint32 offset_low,
+gboolean UnlockFile (gpointer handle, guint32 offset_low,
guint32 offset_high, guint32 length_low,
guint32 length_high)
{
struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
off_t offset, length;
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
+ int fd = GPOINTER_TO_UINT(handle);
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *)&file_handle,
- (gpointer *)&file_private_handle);
+ (gpointer *)&file_handle);
if (ok == FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up file handle %p", handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (file_private_handle->fd_mapped.assigned == FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
!(file_handle->fileaccess & GENERIC_WRITE) &&
!(file_handle->fileaccess & GENERIC_ALL)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd_mapped.fd, file_handle->fileaccess);
+ g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
#endif
SetLastError (ERROR_ACCESS_DENIED);
return(FALSE);
length = ((gint64)length_high << 32) | length_low;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Unlocking handle %p fd %d, offset %lld, length %lld",
- handle, file_private_handle->fd_mapped.fd, offset, length);
+ g_message ("%s: Unlocking handle %p, offset %lld, length %lld",
+ __func__, handle, offset, length);
#endif
#else
offset = offset_low;
length = length_low;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Unlocking handle %p fd %d, offset %ld, length %ld",
- handle, file_private_handle->fd_mapped.fd, offset, length);
+ g_message ("%s: Unlocking handle %p, offset %ld, length %ld", __func__,
+ handle, offset, length);
#endif
#endif
- return(_wapi_unlock_file_region (file_private_handle->fd_mapped.fd,
- offset, length));
+ return(_wapi_unlock_file_region (fd, offset, length));
}
#include <sys/time.h>
extern void _wapi_calc_timeout(struct timespec *timeout, guint32 ms);
-extern gpointer _wapi_g_renew0 (gpointer mem, gulong old_len, gulong new_len);
#endif /* _WAPI_MISC_PRIVATE_H_ */
timeout->tv_sec = now.tv_sec + ms_divvy.quot + overflow_divvy.quot;
timeout->tv_nsec = overflow_divvy.rem * 1000000;
}
-
-/* This is used instead of g_renew when we need to keep unused
- * elements NULL, because g_renew doesn't initialize the memory it
- * returns.
- */
-gpointer _wapi_g_renew0 (gpointer mem, gulong old_len, gulong new_len)
-{
- gpointer new_mem=g_malloc0 (new_len);
- memcpy (new_mem, mem, old_len);
- g_free (mem);
- return(new_mem);
-}
#include <sys/types.h>
extern struct _WapiHandleOps _wapi_mutex_ops;
+extern struct _WapiHandleOps _wapi_namedmutex_ops;
+
+extern void _wapi_mutex_details (gpointer handle_info);
struct _WapiHandle_mutex
{
- WapiSharedNamespace sharedns;
pid_t pid;
pthread_t tid;
guint32 recursion;
};
-struct _WapiHandlePrivate_mutex
+struct _WapiHandle_namedmutex
{
- int dummy;
+ WapiSharedNamespace sharedns;
+ guint32 is_owned;
+ pid_t pid;
+ pthread_t tid;
+ guint32 recursion;
};
extern void _wapi_mutex_check_abandoned (pid_t pid, pthread_t tid);
#undef DEBUG
-/* This is used to serialise mutex creation when names are given
- */
-static mono_mutex_t named_mutex_mutex;
-
-static void mutex_close_shared (gpointer handle);
+static void mutex_close (gpointer handle);
static void mutex_signal(gpointer handle);
-static void mutex_own (gpointer handle);
+static gboolean mutex_own (gpointer handle);
static gboolean mutex_is_owned (gpointer handle);
+static void namedmutex_close (gpointer handle);
+static void namedmutex_signal (gpointer handle);
+static gboolean namedmutex_own (gpointer handle);
+static gboolean namedmutex_is_owned (gpointer handle);
+
struct _WapiHandleOps _wapi_mutex_ops = {
- mutex_close_shared, /* close_shared */
- NULL, /* close_private */
+ mutex_close, /* close */
mutex_signal, /* signal */
mutex_own, /* own */
mutex_is_owned, /* is_owned */
};
-static mono_once_t mutex_ops_once=MONO_ONCE_INIT;
-
-static void mutex_ops_init (void)
+void _wapi_mutex_details (gpointer handle_info)
{
- int thr_ret;
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- pthread_mutexattr_t mutex_shared_attr;
+ struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)handle_info;
+
+ g_print ("own: %5d:%5ld, count: %5u", mut->pid, mut->tid,
+ mut->recursion);
+}
- thr_ret = mono_mutexattr_init (&mutex_shared_attr);
- g_assert (thr_ret == 0);
+struct _WapiHandleOps _wapi_namedmutex_ops = {
+ namedmutex_close, /* close */
+ namedmutex_signal, /* signal */
+ namedmutex_own, /* own */
+ namedmutex_is_owned, /* is_owned */
+};
- thr_ret = mono_mutexattr_setpshared (&mutex_shared_attr,
- PTHREAD_PROCESS_SHARED);
- g_assert (thr_ret == 0);
+static gboolean mutex_release (gpointer handle);
+static gboolean namedmutex_release (gpointer handle);
- thr_ret = mono_mutex_init (&named_mutex_mutex, &mutex_shared_attr);
- g_assert (thr_ret == 0);
-#else
- thr_ret = mono_mutex_init (&named_mutex_mutex, NULL);
-#endif
+static struct
+{
+ gboolean (*release)(gpointer handle);
+} mutex_ops[WAPI_HANDLE_COUNT] = {
+ {NULL},
+ {NULL},
+ {NULL},
+ {NULL},
+ {NULL},
+ {mutex_release},
+ {NULL},
+ {NULL},
+ {NULL},
+ {NULL},
+ {NULL},
+ {namedmutex_release},
+};
+
+static mono_once_t mutex_ops_once=MONO_ONCE_INIT;
+static void mutex_ops_init (void)
+{
_wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX,
WAPI_HANDLE_CAP_WAIT |
WAPI_HANDLE_CAP_SIGNAL |
WAPI_HANDLE_CAP_OWN);
+ _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDMUTEX,
+ WAPI_HANDLE_CAP_WAIT |
+ WAPI_HANDLE_CAP_SIGNAL |
+ WAPI_HANDLE_CAP_OWN);
}
-static void mutex_close_shared (gpointer handle)
+static void mutex_close (gpointer handle)
{
struct _WapiHandle_mutex *mutex_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
+ (gpointer *)&mutex_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
return;
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing mutex handle %p", handle);
+ g_message("%s: closing mutex handle %p", __func__, handle);
#endif
- if(mutex_handle->sharedns.name!=0) {
- _wapi_handle_scratch_delete (mutex_handle->sharedns.name);
- mutex_handle->sharedns.name=0;
- }
+ /* If its a shared one, clear the name */
}
static void mutex_signal(gpointer handle)
ReleaseMutex(handle);
}
-static void mutex_own (gpointer handle)
+static gboolean mutex_own (gpointer handle)
{
struct _WapiHandle_mutex *mutex_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
+ (gpointer *)&mutex_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
- return;
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
+ return(FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": owning mutex handle %p", handle);
+ g_message("%s: owning mutex handle %p", __func__, handle);
#endif
_wapi_handle_set_signal_state (handle, FALSE, FALSE);
mutex_handle->recursion++;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": mutex handle %p locked %d times by %d:%ld", handle,
- mutex_handle->recursion, mutex_handle->pid,
+ g_message ("%s: mutex handle %p locked %d times by %d:%ld", __func__,
+ handle, mutex_handle->recursion, mutex_handle->pid,
mutex_handle->tid);
#endif
+
+ return(TRUE);
}
static gboolean mutex_is_owned (gpointer handle)
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
+ (gpointer *)&mutex_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
return(FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": testing ownership mutex handle %p", handle);
+ g_message("%s: testing ownership mutex handle %p", __func__, handle);
#endif
if(mutex_handle->recursion>0 &&
mutex_handle->pid==getpid () &&
mutex_handle->tid==pthread_self ()) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": mutex handle %p owned by %d:%ld", handle,
- getpid (), pthread_self ());
+ g_message ("%s: mutex handle %p owned by %d:%ld", __func__,
+ handle, getpid (), pthread_self ());
#endif
return(TRUE);
} else {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", handle, getpid (), pthread_self (), mutex_handle->recursion, mutex_handle->pid, mutex_handle->tid);
+ g_message ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, getpid (), pthread_self (), mutex_handle->recursion, mutex_handle->pid, mutex_handle->tid);
+#endif
+
+ return(FALSE);
+ }
+}
+
+static void namedmutex_close (gpointer handle)
+{
+ /**/
+}
+
+static void namedmutex_signal (gpointer handle)
+{
+ /**/
+}
+
+static gboolean namedmutex_own (gpointer handle)
+{
+ struct _WapiHandleShared shared_handle;
+ struct _WapiHandle_namedmutex *namedmutex_handle;
+ gboolean ok;
+
+#ifdef DEBUG
+ g_message("%s: owning named mutex handle %p", __func__, handle);
+#endif
+
+ ok = _wapi_copy_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
+ &shared_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error looking up named mutex handle %p",
+ __func__, handle);
+ return(FALSE);
+ }
+ namedmutex_handle = &shared_handle.u.namedmutex;
+
+ namedmutex_handle->pid = getpid ();
+ namedmutex_handle->tid = pthread_self ();
+ namedmutex_handle->recursion++;
+
+ /* If try_replace returns FALSE, it means someone else updated
+ * this handle, so we failed to own it
+ */
+ ok = _wapi_try_replace_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
+ &shared_handle);
+ if (ok) {
+ _wapi_shared_handle_set_signal_state (handle, FALSE);
+
+#ifdef DEBUG
+ g_message ("%s: mutex handle %p locked %d times by %d:%ld",
+ __func__, handle, namedmutex_handle->recursion,
+ namedmutex_handle->pid, namedmutex_handle->tid);
+#endif
+ } else {
+#ifdef DEBUG
+ g_message ("%s: failed to own mutex handle %p", __func__,
+ handle);
+#endif
+ }
+
+ return(ok);
+}
+
+static gboolean namedmutex_is_owned (gpointer handle)
+{
+ struct _WapiHandle_namedmutex *namedmutex_handle;
+ gboolean ok;
+
+ ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
+ (gpointer *)&namedmutex_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
+ return(FALSE);
+ }
+
+#ifdef DEBUG
+ g_message ("%s: testing ownership mutex handle %p", __func__, handle);
+#endif
+
+ if (namedmutex_handle->recursion > 0 &&
+ namedmutex_handle->pid == getpid () &&
+ namedmutex_handle->tid == pthread_self ()) {
+#ifdef DEBUG
+ g_message ("%s: mutex handle %p owned by %d:%ld", __func__,
+ handle, getpid (), pthread_self ());
+#endif
+
+ return(TRUE);
+ } else {
+#ifdef DEBUG
+ g_message ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, getpid (), pthread_self (), namedmutex_handle->recursion, namedmutex_handle->pid, namedmutex_handle->tid);
#endif
return(FALSE);
int thr_ret;
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
+ (gpointer *)&mutex_handle);
if (ok == FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
return(FALSE);
}
if (mutex_handle->pid == data->pid &&
mutex_handle->tid == data->tid) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Mutex handle %p abandoned!", handle);
+ g_message ("%s: Mutex handle %p abandoned!", __func__, handle);
#endif
mutex_handle->recursion = 0;
return(FALSE);
}
+static gboolean namedmutex_check (gpointer handle, gpointer user_data)
+{
+ struct _WapiHandle_namedmutex *mutex_handle;
+ gboolean ok;
+ struct mutex_check_data *data = (struct mutex_check_data *)user_data;
+ int thr_ret;
+
+ ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
+ (gpointer *)&mutex_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error looking up named mutex handle %p",
+ __func__, handle);
+ return(FALSE);
+ }
+
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (mutex_handle->pid == data->pid &&
+ mutex_handle->tid == data->tid) {
+#ifdef DEBUG
+ g_message ("%s: Mutex handle %p abandoned!", __func__, handle);
+#endif
+
+ mutex_handle->recursion = 0;
+ mutex_handle->pid = 0;
+ mutex_handle->tid = 0;
+
+ _wapi_shared_handle_set_signal_state (handle, TRUE);
+ }
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ /* Return false to keep searching */
+ return(FALSE);
+}
+
/* When a thread exits, any mutexes it still holds need to be signalled */
void _wapi_mutex_check_abandoned (pid_t pid, pthread_t tid)
{
data.pid = pid;
data.tid = tid;
- _wapi_search_handle (WAPI_HANDLE_MUTEX, mutex_check, &data, NULL,
+ _wapi_search_handle (WAPI_HANDLE_MUTEX, mutex_check, &data, NULL);
+ _wapi_search_handle (WAPI_HANDLE_NAMEDMUTEX, namedmutex_check, &data,
NULL);
}
+static gpointer mutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED,
+ gboolean owned)
+{
+ struct _WapiHandle_mutex mutex_handle = {0};
+ gpointer handle;
+ int thr_ret;
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
+ * was freshly created
+ */
+ SetLastError (ERROR_SUCCESS);
+
+#ifdef DEBUG
+ g_message ("%s: Creating unnamed mutex", __func__);
+#endif
+
+ handle = _wapi_handle_new (WAPI_HANDLE_MUTEX, &mutex_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating mutex handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
+ return(NULL);
+ }
+
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if(owned==TRUE) {
+ mutex_own (handle);
+ } else {
+ _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ }
+
+#ifdef DEBUG
+ g_message ("%s: returning mutex handle %p", __func__, handle);
+#endif
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(handle);
+}
+
+static gpointer namedmutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
+ const gunichar2 *name)
+{
+ struct _WapiHandle_namedmutex namedmutex_handle = {{{0}}, 0};
+ gpointer handle;
+ gchar *utf8_name;
+ int thr_ret;
+ gpointer ret = NULL;
+ guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
+ guint32 namelen;
+ gint32 offset;
+
+ /* w32 seems to guarantee that opening named mutexes can't
+ * race each other
+ */
+ pthread_cleanup_push ((void(*)(void *))_wapi_namespace_timestamp_release, GUINT_TO_POINTER(now));
+ thr_ret = _wapi_namespace_timestamp (now);
+ g_assert (thr_ret == 0);
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
+ * was freshly created
+ */
+ SetLastError (ERROR_SUCCESS);
+
+ utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+#ifdef DEBUG
+ g_message ("%s: Creating named mutex [%s]", __func__, utf8_name);
+#endif
+
+ offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX,
+ utf8_name);
+ if (offset == -1) {
+ /* The name has already been used for a different
+ * object.
+ */
+ SetLastError (ERROR_INVALID_HANDLE);
+ goto cleanup;
+ } else if (offset != 0) {
+ /* Not an error, but this is how the caller is
+ * informed that the mutex wasn't freshly created
+ */
+ SetLastError (ERROR_ALREADY_EXISTS);
+ }
+ /* Fall through to create the mutex handle. */
+
+ if (strlen (utf8_name) < MAX_PATH) {
+ namelen = strlen (utf8_name);
+ } else {
+ namelen = MAX_PATH;
+ }
+
+ memcpy (&namedmutex_handle.sharedns.name, utf8_name, namelen);
+
+ if (offset == 0) {
+ /* A new named mutex, so create both the private and
+ * shared parts
+ */
+ handle = _wapi_handle_new (WAPI_HANDLE_NAMEDMUTEX,
+ &namedmutex_handle);
+ } else {
+ /* A new reference to an existing named mutex, so just
+ * create the private part
+ */
+ handle = _wapi_handle_new_for_existing_ns (WAPI_HANDLE_NAMEDMUTEX, &namedmutex_handle, offset);
+ }
+
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating mutex handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ ret = handle;
+
+ if (offset == 0) {
+ /* Set the initial state, as this is a completely new
+ * handle
+ */
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (owned == TRUE) {
+ namedmutex_own (handle);
+ } else {
+ _wapi_shared_handle_set_signal_state (handle, TRUE);
+ }
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+ }
+
+#ifdef DEBUG
+ g_message ("%s: returning mutex handle %p", __func__, handle);
+#endif
+
+cleanup:
+ g_free (utf8_name);
+ /* Releases the timestamp */
+ pthread_cleanup_pop (1);
+
+ return(ret);
+}
+
/**
* CreateMutex:
* @security: Ignored for now.
gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
const gunichar2 *name)
{
- struct _WapiHandle_mutex *mutex_handle;
- gpointer handle;
- gboolean ok;
- gchar *utf8_name;
- int thr_ret;
- gpointer ret = NULL;
-
mono_once (&mutex_ops_once, mutex_ops_init);
- /* w32 seems to guarantee that opening named mutexes can't
- * race each other
- */
- pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
- (void *)&named_mutex_mutex);
- thr_ret = mono_mutex_lock (&named_mutex_mutex);
- g_assert (thr_ret == 0);
-
- /* Need to blow away any old errors here, because code tests
- * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
- * was freshly created
- */
- SetLastError (ERROR_SUCCESS);
-
- if(name!=NULL) {
- utf8_name=g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+ if (name == NULL) {
+ return(mutex_create (security, owned));
} else {
- utf8_name=NULL;
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Creating mutex (name [%s])",
- utf8_name==NULL?"<unnamed>":utf8_name);
-#endif
-
- if(name!=NULL) {
- handle=_wapi_search_handle_namespace (
- WAPI_HANDLE_MUTEX, utf8_name,
- (gpointer *)&mutex_handle, NULL);
- if(handle==_WAPI_HANDLE_INVALID) {
- /* The name has already been used for a different
- * object.
- */
- g_free (utf8_name);
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- } else if (handle!=NULL) {
- g_free (utf8_name);
- _wapi_handle_ref (handle);
- ret = handle;
-
- /* Not an error, but this is how the caller is
- * informed that the mutex wasn't freshly
- * created
- */
- SetLastError (ERROR_ALREADY_EXISTS);
- goto cleanup;
- }
- /* Otherwise fall through to create the mutex. */
+ return(namedmutex_create (security, owned, name));
}
+}
+
+static gboolean mutex_release (gpointer handle)
+{
+ struct _WapiHandle_mutex *mutex_handle;
+ gboolean ok;
+ pthread_t tid=pthread_self();
+ pid_t pid=getpid ();
+ int thr_ret;
+ gboolean ret = FALSE;
- handle=_wapi_handle_new (WAPI_HANDLE_MUTEX);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating mutex handle");
- if(utf8_name!=NULL) {
- g_free (utf8_name);
- }
- goto cleanup;
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
+ (gpointer *)&mutex_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up mutex handle %p", __func__,
+ handle);
+ return(FALSE);
}
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
- if(utf8_name!=NULL) {
- g_free (utf8_name);
- }
-
- goto handle_cleanup;
- }
- ret = handle;
-
- if(utf8_name!=NULL) {
- mutex_handle->sharedns.name=_wapi_handle_scratch_store (
- utf8_name, strlen (utf8_name));
+#ifdef DEBUG
+ g_message("%s: Releasing mutex handle %p", __func__, handle);
+#endif
+
+ if(mutex_handle->tid!=tid || mutex_handle->pid!=pid) {
+#ifdef DEBUG
+ g_message("%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
+#endif
+
+ goto cleanup;
}
+ ret = TRUE;
- if(owned==TRUE) {
- mutex_own (handle);
- } else {
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
- }
+ /* OK, we own this mutex */
+ mutex_handle->recursion--;
+ if(mutex_handle->recursion==0) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning mutex handle %p",
- handle);
+ g_message("%s: Unlocking mutex handle %p", __func__, handle);
#endif
- if(utf8_name!=NULL) {
- g_free (utf8_name);
+ mutex_handle->pid=0;
+ mutex_handle->tid=0;
+ _wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
-handle_cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
cleanup:
- thr_ret = mono_mutex_unlock (&named_mutex_mutex);
+ thr_ret = _wapi_handle_unlock_handle (handle);
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
return(ret);
}
-/**
- * ReleaseMutex:
- * @handle: The mutex handle.
- *
- * Releases ownership if the mutex handle @handle.
- *
- * Return value: %TRUE on success, %FALSE otherwise. This function
- * fails if the calling thread does not own the mutex @handle.
- */
-gboolean ReleaseMutex(gpointer handle)
+static gboolean namedmutex_release (gpointer handle)
{
- struct _WapiHandle_mutex *mutex_handle;
+ struct _WapiHandle_namedmutex *mutex_handle;
gboolean ok;
pthread_t tid=pthread_self();
pid_t pid=getpid ();
int thr_ret;
gboolean ret = FALSE;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
- (gpointer *)&mutex_handle, NULL);
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
+ (gpointer *)&mutex_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up mutex handle %p", handle);
+ g_warning ("%s: error looking up named mutex handle %p",
+ __func__, handle);
return(FALSE);
}
g_assert (thr_ret == 0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex handle %p",
- handle);
+ g_message("%s: Releasing mutex handle %p", __func__, handle);
#endif
if(mutex_handle->tid!=tid || mutex_handle->pid!=pid) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
+ g_message("%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
#endif
goto cleanup;
if(mutex_handle->recursion==0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Unlocking mutex handle %p",
- handle);
+ g_message("%s: Unlocking mutex handle %p", __func__, handle);
#endif
mutex_handle->pid=0;
mutex_handle->tid=0;
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ _wapi_shared_handle_set_signal_state (handle, TRUE);
}
cleanup:
return(ret);
}
+
+/**
+ * ReleaseMutex:
+ * @handle: The mutex handle.
+ *
+ * Releases ownership if the mutex handle @handle.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise. This function
+ * fails if the calling thread does not own the mutex @handle.
+ */
+gboolean ReleaseMutex(gpointer handle)
+{
+ WapiHandleType type;
+
+ if (handle == NULL) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ type = _wapi_handle_type (handle);
+
+ if (mutex_ops[type].release == NULL) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(mutex_ops[type].release (handle));
+}
guint32 env;
WapiFileTime create_time;
WapiFileTime exit_time;
- guint32 proc_name;
+ gchar proc_name[_POSIX_PATH_MAX];
size_t min_working_set;
size_t max_working_set;
};
-struct _WapiHandlePrivate_process
-{
- int dummy;
-};
-
#endif /* _WAPI_PROCESS_PRIVATE_H_ */
#undef DEBUG
-static void process_close_shared (gpointer handle);
-
struct _WapiHandleOps _wapi_process_ops = {
- process_close_shared, /* close_shared */
- NULL, /* close_private */
+ NULL, /* close_shared */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
WAPI_HANDLE_CAP_WAIT);
}
-static void process_close_shared (gpointer handle G_GNUC_UNUSED)
-{
- struct _WapiHandle_process *process_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up process handle %p", handle);
- return;
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": closing process handle %p with id %d", handle,
- process_handle->id);
-#endif
-
- if(process_handle->proc_name!=0) {
- _wapi_handle_scratch_delete (process_handle->proc_name);
- process_handle->proc_name=0;
- }
-}
-
gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
WapiSecurityAttributes *process_attrs G_GNUC_UNUSED,
WapiSecurityAttributes *thread_attrs G_GNUC_UNUSED,
cmd=mono_unicode_to_external (appname);
if(cmd==NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL",
+ __func__);
#endif
SetLastError(ERROR_PATH_NOT_FOUND);
args=mono_unicode_to_external (cmdline);
if(args==NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError(ERROR_PATH_NOT_FOUND);
dir=mono_unicode_to_external (cwd);
if(dir==NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": unicode conversion returned NULL");
+ g_message ("%s: unicode conversion returned NULL", __func__);
#endif
SetLastError(ERROR_PATH_NOT_FOUND);
} else {
dir=g_get_current_dir ();
}
- stored_dir=_wapi_handle_scratch_store (dir, strlen (dir));
+ //stored_dir=_wapi_handle_scratch_store (dir, strlen (dir));
/* new_environ is a block of NULL-terminated strings, which
}
}
- env=_wapi_handle_scratch_store_string_array (strings);
+ //env=_wapi_handle_scratch_store_string_array (strings);
g_strfreev (strings);
} else {
/* Use the existing environment */
- env=_wapi_handle_scratch_store_string_array (environ);
+ //env=_wapi_handle_scratch_store_string_array (environ);
}
/* We can't put off locating the executable any longer :-( */
/* Executable existing ? */
if(access (prog, X_OK)!=0) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Couldn't find executable %s", prog);
+ g_message ("%s: Couldn't find executable %s",
+ __func__, prog);
#endif
g_free (prog);
g_free (unquoted);
if(token==NULL) {
/* Give up */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Couldn't find what to exec");
+ g_message ("%s: Couldn't find what to exec", __func__);
#endif
SetLastError(ERROR_PATH_NOT_FOUND);
if(access (prog, X_OK)!=0) {
g_free (prog);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Couldn't find executable %s", token);
+ g_message ("%s: Couldn't find executable %s",
+ __func__, token);
#endif
g_free (token);
SetLastError (ERROR_FILE_NOT_FOUND);
prog=g_find_program_in_path (token);
if(prog==NULL) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Couldn't find executable %s", token);
+ g_message ("%s: Couldn't find executable %s", __func__, token);
#endif
g_free (token);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Exec prog [%s] args [%s]", prog,
+ g_message ("%s: Exec prog [%s] args [%s]", __func__, prog,
args_after_prog);
#endif
full_prog=g_shell_quote (prog);
}
- stored_prog=_wapi_handle_scratch_store (full_prog, strlen (full_prog));
+ //stored_prog=_wapi_handle_scratch_store (full_prog, strlen (full_prog));
if(startup!=NULL && startup->dwFlags & STARTF_USESTDHANDLES) {
stdin_handle=startup->hStdInput;
if (WaitForSingleObjectEx (process_handle, 500, FALSE) != WAIT_TIMEOUT) {
_wapi_lookup_handle (GUINT_TO_POINTER (process_handle),
WAPI_HANDLE_PROCESS,
- (gpointer *) &process_handle_data,
- NULL);
+ (gpointer *) &process_handle_data);
if (process_handle_data && process_handle_data->exec_errno != 0) {
ret = FALSE;
if(full_prog!=NULL) {
g_free (prog);
}
- if(stored_prog!=0) {
- _wapi_handle_scratch_delete (stored_prog);
- }
+// if(stored_prog!=0) {
+// _wapi_handle_scratch_delete (stored_prog);
+// }
if(args!=NULL) {
g_free (args);
}
if(dir!=NULL) {
g_free (dir);
}
- if(stored_dir!=0) {
- _wapi_handle_scratch_delete (stored_dir);
- }
- if(env!=0) {
- _wapi_handle_scratch_delete_string_array (env);
- }
+// if(stored_dir!=0) {
+// _wapi_handle_scratch_delete (stored_dir);
+// }
+// if(env!=0) {
+// _wapi_handle_scratch_delete_string_array (env);
+// }
return(ret);
}
utf8_progname=mono_utf8_from_external (progname);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": using [%s] as prog name",
- progname);
+ g_message ("%s: using [%s] as prog name", __func__, progname);
#endif
if(utf8_progname!=NULL) {
slash=strrchr (utf8_progname, '/');
if(slash!=NULL) {
- process_handle->proc_name=_wapi_handle_scratch_store (slash+1, strlen (slash+1));
+ g_strlcpy (process_handle->proc_name, slash+1,
+ sizeof(process_handle->proc_name));
} else {
- process_handle->proc_name=_wapi_handle_scratch_store (utf8_progname, strlen (utf8_progname));
+ g_strlcpy (process_handle->proc_name, utf8_progname,
+ sizeof(process_handle->proc_name));
}
g_free (utf8_progname);
static void process_set_current (void)
{
- struct _WapiHandle_process *process_handle;
- gboolean ok;
pid_t pid=getpid ();
char *handle_env;
handle_env=getenv ("_WAPI_PROCESS_HANDLE");
if(handle_env==NULL) {
+ struct _WapiHandle_process process_handle = {0};
+
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Need to create my own process handle");
+ g_message ("%s: Need to create my own process handle",
+ __func__);
#endif
- current_process=_wapi_handle_new (WAPI_HANDLE_PROCESS);
- if(current_process==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating process handle");
- return;
- }
-
- ok=_wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up process handle %p",
- current_process);
- return;
- }
-
- process_handle->id=pid;
+ process_handle.id = pid;
/* These seem to be the defaults on w2k */
- process_handle->min_working_set=204800;
- process_handle->max_working_set=1413120;
+ process_handle.min_working_set = 204800;
+ process_handle.max_working_set = 1413120;
+
+ _wapi_time_t_to_filetime (time (NULL),
+ &process_handle.create_time);
- _wapi_time_t_to_filetime (time (NULL), &process_handle->create_time);
+ process_set_name (&process_handle);
- process_set_name (process_handle);
+ current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS,
+ &process_handle);
+ if (current_process == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating process handle",
+ __func__);
+ return;
+ }
/* Make sure the new handle has a reference so it wont go away
* until this process exits
*/
_wapi_handle_ref (current_process);
} else {
- guchar *procname;
+ struct _WapiHandle_process *process_handle;
+ guchar *procname = NULL;
+ gboolean ok;
- current_process=GUINT_TO_POINTER (atoi (handle_env));
+ current_process = GUINT_TO_POINTER (atoi (handle_env));
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Found my process handle: %p", current_process);
+ g_message ("%s: Found my process handle: %p", __func__,
+ current_process);
#endif
ok=_wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up process handle %p",
- current_process);
+ g_warning ("%s: error looking up process handle %p",
+ __func__, current_process);
return;
}
- procname=_wapi_handle_scratch_lookup (process_handle->proc_name);
- if(procname!=NULL) {
- if(!strcmp (procname, "mono")) {
- /* Set a better process name */
+ procname = process_handle->proc_name;
+ if(!strcmp (procname, "mono")) {
+ /* Set a better process name */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Setting better process name");
+ g_message ("%s: Setting better process name",
+ __func__);
#endif
- _wapi_handle_scratch_delete (process_handle->proc_name);
- process_set_name (process_handle);
- } else {
+ process_set_name (process_handle);
+ } else {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Leaving process name: %s",
- procname);
+ g_message ("%s: Leaving process name: %s", __func__,
+ procname);
#endif
- }
-
- g_free (procname);
}
}
}
mono_once (&process_current_once, process_set_current);
ok=_wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
- (gpointer *)¤t_process_handle, NULL);
+ (gpointer *)¤t_process_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up current process handle %p",
- current_process);
+ g_warning ("%s: error looking up current process handle %p",
+ __func__, current_process);
/* No failure return is defined. PID 0 is invalid.
* This should only be reached when something else has
* gone badly wrong anyway.
gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
{
GPtrArray *processes=g_ptr_array_new ();
- guint32 fit, i;
+ guint32 fit, i, j;
mono_once (&process_current_once, process_set_current);
_wapi_search_handle (WAPI_HANDLE_PROCESS, process_enum, processes,
- NULL, NULL);
+ NULL);
fit=len/sizeof(guint32);
- for(i=0; i<fit && i<processes->len; i++) {
+ for (i = 0, j = 0; j < fit && i < processes->len; i++) {
struct _WapiHandle_process *process_handle;
gboolean ok;
ok=_wapi_lookup_handle (g_ptr_array_index (processes, i),
WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up process handle %p", g_ptr_array_index (processes, i));
- g_ptr_array_free (processes, FALSE);
- return(FALSE);
+ (gpointer *)&process_handle);
+ if (ok == TRUE) {
+ pids[j++] = process_handle->id;
+ } else {
+ /* Handle must have been deleted while we were
+ * looking through the list
+ */
}
-
- pids[i]=process_handle->id;
}
g_ptr_array_free (processes, FALSE);
- *needed=i*sizeof(guint32);
+ *needed = j * sizeof(guint32);
return(TRUE);
}
pid_t pid;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up process handle %p", handle);
+ g_warning ("%s: error looking up process handle %p", __func__,
+ handle);
return(FALSE);
}
mono_once (&process_current_once, process_set_current);
handle=_wapi_search_handle (WAPI_HANDLE_PROCESS, process_open_compare,
- GUINT_TO_POINTER (pid), NULL, NULL);
+ GUINT_TO_POINTER (pid), NULL);
if(handle==0) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find pid %d", pid);
+ g_message ("%s: Can't find pid %d", __func__, pid);
#endif
/* Set an error code */
}
ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
return(FALSE);
}
ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
return(FALSE);
mono_once (&process_current_once, process_set_current);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Getting module base name, process handle %p module %p",
- process, module);
+ g_message ("%s: Getting module base name, process handle %p module %p",
+ __func__, process, module);
#endif
if(basename==NULL || size==0) {
}
ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
return(FALSE);
*/
pid_t pid;
gunichar2 *procname;
- guchar *procname_utf8;
+ guchar *procname_utf8 = NULL;
glong len, bytes;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Returning main module name");
+ g_message ("%s: Returning main module name", __func__);
#endif
pid=process_handle->id;
- procname_utf8=_wapi_handle_scratch_lookup (process_handle->proc_name);
+ procname_utf8 = process_handle->proc_name;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Process name is [%s]",
+ g_message ("%s: Process name is [%s]", __func__,
procname_utf8);
#endif
- procname=g_utf8_to_utf16 (procname_utf8, -1, NULL, &len, NULL);
- if(procname==NULL) {
+ procname = g_utf8_to_utf16 (procname_utf8, -1, NULL, &len,
+ NULL);
+ if (procname == NULL) {
/* bugger */
- g_free (procname_utf8);
return(0);
}
/* Add the terminator, and convert chars to bytes */
- bytes=(len+1)*2;
+ bytes = (len + 1) * 2;
- if(size<bytes) {
+ if (size < bytes) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Size %d smaller than needed (%ld); truncating", size, bytes);
+ g_message ("%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
#endif
memcpy (basename, procname, size);
} else {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Size %d larger than needed (%ld)",
- size, bytes);
+ g_message ("%s: Size %d larger than needed (%ld)",
+ __func__, size, bytes);
#endif
memcpy (basename, procname, bytes);
}
- g_free (procname_utf8);
g_free (procname);
return(len);
}
ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
return(FALSE);
mono_once (&process_current_once, process_set_current);
ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *)&process_handle, NULL);
+ (gpointer *)&process_handle);
if(ok==FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
return(FALSE);
gint err;
ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
- (gpointer *) &process_handle, NULL);
+ (gpointer *) &process_handle);
if (ok == FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Can't find process %p",
- process);
+ g_message ("%s: Can't find process %p", __func__, process);
#endif
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
extern struct _WapiHandleOps _wapi_sem_ops;
+extern void _wapi_sem_details (gpointer handle_info);
+
/* emulate sem_t, so that we can prod the internal state more easily */
struct _WapiHandle_sem
{
gint32 max;
};
-struct _WapiHandlePrivate_sem
-{
- int dummy;
-};
-
#endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */
#undef DEBUG
-static void sema_close_shared (gpointer handle);
static void sema_signal(gpointer handle);
-static void sema_own (gpointer handle);
+static gboolean sema_own (gpointer handle);
struct _WapiHandleOps _wapi_sem_ops = {
- sema_close_shared, /* close_shared */
- NULL, /* close_private */
+ NULL, /* close */
sema_signal, /* signal */
sema_own, /* own */
NULL, /* is_owned */
};
+void _wapi_sem_details (gpointer handle_info)
+{
+ struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)handle_info;
+
+ g_print ("val: %5u, max: %5d", sem->val, sem->max);
+}
+
static mono_once_t sem_ops_once=MONO_ONCE_INIT;
static void sem_ops_init (void)
WAPI_HANDLE_CAP_SIGNAL);
}
-static void sema_close_shared (gpointer handle G_GNUC_UNUSED)
-{
- /* Not really much to do here */
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing sem handle %p", handle);
-#endif
-}
-
static void sema_signal(gpointer handle)
{
ReleaseSemaphore(handle, 1, NULL);
}
-static void sema_own (gpointer handle)
+static gboolean sema_own (gpointer handle)
{
struct _WapiHandle_sem *sem_handle;
gboolean ok;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
- (gpointer *)&sem_handle, NULL);
+ (gpointer *)&sem_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up sem handle %p", handle);
- return;
+ g_warning ("%s: error looking up sem handle %p", __func__,
+ handle);
+ return(FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": owning sem handle %p", handle);
+ g_message("%s: owning sem handle %p", __func__, handle);
#endif
sem_handle->val--;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": sem %p val now %d", handle,
- sem_handle->val);
+ g_message ("%s: sem %p val now %d", __func__, handle, sem_handle->val);
#endif
if(sem_handle->val==0) {
_wapi_handle_set_signal_state (handle, FALSE, FALSE);
}
+
+ return(TRUE);
}
*/
gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name G_GNUC_UNUSED)
{
- struct _WapiHandle_sem *sem_handle;
+ struct _WapiHandle_sem sem_handle = {0};
gpointer handle;
- gboolean ok;
int thr_ret;
- gpointer ret = NULL;
mono_once (&sem_ops_once, sem_ops_init);
if(max<=0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": max <= 0");
+ g_message("%s: max <= 0", __func__);
#endif
+ SetLastError (ERROR_INVALID_PARAMETER);
return(NULL);
}
if(initial>max || initial<0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": initial>max or < 0");
+ g_message("%s: initial>max or < 0", __func__);
#endif
+ SetLastError (ERROR_INVALID_PARAMETER);
return(NULL);
}
- handle=_wapi_handle_new (WAPI_HANDLE_SEM);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating semaphore handle");
+ sem_handle.val = initial;
+ sem_handle.max = max;
+
+ handle = _wapi_handle_new (WAPI_HANDLE_SEM, &sem_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating semaphore handle", __func__);
+ SetLastError (ERROR_GEN_FAILURE);
return(NULL);
}
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
- (gpointer *)&sem_handle, NULL);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error lookup up semaphore handle %p", handle);
- goto cleanup;
- }
- ret = handle;
-
- sem_handle->val=initial;
- sem_handle->max=max;
-
- if(initial!=0) {
+ if (initial != 0) {
_wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Created semaphore handle %p initial %d max %d", handle,
- initial, max);
+ g_message ("%s: Created semaphore handle %p initial %d max %d",
+ __func__, handle, initial, max);
#endif
-cleanup:
thr_ret = _wapi_handle_unlock_handle (handle);
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
-
- return(ret);
+
+ return(handle);
}
/**
int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
- (gpointer *)&sem_handle, NULL);
+ (gpointer *)&sem_handle);
if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up sem handle %p", handle);
+ g_warning ("%s: error looking up sem handle %p", __func__,
+ handle);
return(FALSE);
}
g_assert (thr_ret == 0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val %d count %d",
- handle, sem_handle->val, count);
+ g_message("%s: sem %p val %d count %d", __func__, handle,
+ sem_handle->val, count);
#endif
/* Do this before checking for count overflow, because overflowing max
/* No idea why max is signed, but thats the spec :-( */
if(sem_handle->val+count > (guint32)sem_handle->max) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": sem %p max value would be exceeded: max %d current %d count %d",
- handle, sem_handle->max, sem_handle->val, count);
+ g_message("%s: sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count);
#endif
goto end;
ret=TRUE;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val now %d", handle,
- sem_handle->val);
+ g_message("%s: sem %p val now %d", __func__, handle, sem_handle->val);
#endif
end:
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/shared.h>
-#include <mono/io-layer/daemon-private.h>
#undef DEBUG
-/* Define this to make it easier to run valgrind on the daemon. Then
- * the first process to start will turn into a daemon without forking
- * (the debug utility mono/handles/hps is ideal for this.)
- */
-#undef VALGRINDING
-
-guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment)
+static guchar *_wapi_shm_file (void)
{
static guchar file[_POSIX_PATH_MAX];
guchar *name = NULL, *filename, *dir, *wapi_dir;
/* Change the filename whenever the format of the contents
* changes
*/
- if(type==WAPI_SHM_DATA) {
- name=g_strdup_printf ("shared_data-%s-%d-%d",
- machine_name, _WAPI_HANDLE_VERSION, segment);
- } else if (type==WAPI_SHM_SCRATCH) {
- name=g_strdup_printf ("shared_scratch-%s-%d-%d",
- machine_name, _WAPI_HANDLE_VERSION, segment);
- } else {
- g_assert_not_reached ();
- }
+ name = g_strdup_printf ("shared_data-%s-%d-%d",
+ machine_name, _WAPI_HANDLE_VERSION, 0);
/* I don't know how nfs affects mmap. If mmap() of files on
* nfs mounts breaks, then there should be an option to set
* the directory.
*/
- wapi_dir=getenv ("MONO_SHARED_DIR");
- if(wapi_dir==NULL) {
- filename=g_build_filename (g_get_home_dir (), ".wapi", name,
- NULL);
+ wapi_dir = getenv ("MONO_SHARED_DIR");
+ if (wapi_dir == NULL) {
+ filename = g_build_filename (g_get_home_dir (), ".wapi", name,
+ NULL);
} else {
- filename=g_build_filename (wapi_dir, ".wapi", name, NULL);
+ filename = g_build_filename (wapi_dir, ".wapi", name, NULL);
}
g_free (name);
* mkdir() errors, because on any error the open() call will
* report the problem.
*/
- dir=g_path_get_dirname (file);
+ dir = g_path_get_dirname (file);
mkdir (dir, 0755);
g_free (dir);
return(file);
}
-gpointer _wapi_shm_file_expand (gpointer mem, _wapi_shm_t type,
- guint32 segment, guint32 old_len,
- guint32 new_len)
+static guchar *_wapi_fileshare_shm_file (void)
{
- int fd;
- gpointer new_mem;
- guchar *filename=_wapi_shm_file (type, segment);
- int ret;
-
- if(old_len>=new_len) {
- return(mem);
- }
-
- munmap (mem, old_len);
-
- fd=open (filename, O_RDWR, 0600);
- if(fd==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] open error: %s", filename,
- g_strerror (errno));
- return(NULL);
- }
+ static guchar file[_POSIX_PATH_MAX];
+ guchar *name = NULL, *filename, *dir, *wapi_dir;
+ gchar machine_name[256];
- if(lseek (fd, new_len-1, SEEK_SET)==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] lseek error: %s", filename,
- g_strerror (errno));
- return(NULL);
- }
+ if (gethostname(machine_name, sizeof(machine_name)) != 0)
+ machine_name[0] = '\0';
- do {
- ret=write (fd, "", 1);
- }
- while (ret==-1 && errno==EINTR);
+ /* Change the filename whenever the format of the contents
+ * changes
+ */
+ name = g_strdup_printf ("shared_fileshare-%s-%d-%d",
+ machine_name, _WAPI_HANDLE_VERSION, 0);
- if(ret==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] write error: %s", filename,
- g_strerror (errno));
- return(NULL);
+ /* I don't know how nfs affects mmap. If mmap() of files on
+ * nfs mounts breaks, then there should be an option to set
+ * the directory.
+ */
+ wapi_dir = getenv ("MONO_SHARED_DIR");
+ if (wapi_dir == NULL) {
+ filename = g_build_filename (g_get_home_dir (), ".wapi", name,
+ NULL);
+ } else {
+ filename = g_build_filename (wapi_dir, ".wapi", name, NULL);
}
+ g_free (name);
- close (fd);
-
- new_mem=_wapi_shm_file_map (type, segment, NULL, NULL);
+ g_snprintf (file, _POSIX_PATH_MAX, "%s", filename);
+ g_free (filename);
+
+ /* No need to check if the dir already exists or check
+ * mkdir() errors, because on any error the open() call will
+ * report the problem.
+ */
+ dir = g_path_get_dirname (file);
+ mkdir (dir, 0755);
+ g_free (dir);
- return(new_mem);
+ return(file);
}
-static int _wapi_shm_file_open (const guchar *filename, _wapi_shm_t type,
- gboolean *created)
+static int _wapi_shm_file_open (const guchar *filename, guint32 wanted_size)
{
int fd;
struct stat statbuf;
- guint32 wanted_size = 0;
int ret;
-
- if(created) {
- *created=FALSE;
- }
-
- if(type==WAPI_SHM_DATA) {
- wanted_size=sizeof(struct _WapiHandleShared_list);
- } else if (type==WAPI_SHM_SCRATCH) {
- wanted_size=sizeof(struct _WapiHandleScratch) +
- (_WAPI_SHM_SCRATCH_SIZE - MONO_ZERO_ARRAY_LENGTH);
- } else {
- g_assert_not_reached ();
- }
+ gboolean created = FALSE;
try_again:
/* No O_CREAT yet, because we need to initialise the file if
* we have to create it.
*/
- fd=open (filename, O_RDWR, 0600);
- if(fd==-1 && errno==ENOENT) {
+ fd = open (filename, O_RDWR, 0600);
+ if (fd == -1 && errno == ENOENT) {
/* OK, its up to us to create it. O_EXCL to avoid a
* race condition where two processes can
* simultaneously try and create the file
*/
- fd=open (filename, O_CREAT|O_EXCL|O_RDWR, 0600);
- if(fd==-1 && errno==EEXIST) {
+ fd = open (filename, O_CREAT|O_EXCL|O_RDWR, 0600);
+ if (fd == -1 && errno == EEXIST) {
/* It's possible that the file was created in
* between finding it didn't exist, and trying
* to create it. Just try opening it again
*/
goto try_again;
- } else if (fd==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] open error: %s",
- filename, g_strerror (errno));
+ } else if (fd == -1) {
+ g_critical ("%s: shared file [%s] open error: %s",
+ __func__, filename, g_strerror (errno));
return(-1);
} else {
/* We created the file, so we need to expand
- * the file and inform the caller so it can
- * fork the handle daemon too.
+ * the file.
*
* (wanted_size-1, because we're about to
* write the other byte to actually expand the
* file.)
*/
- if(lseek (fd, wanted_size-1, SEEK_SET)==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": shared file [%s] lseek error: %s", filename, g_strerror (errno));
+ if (lseek (fd, wanted_size-1, SEEK_SET) == -1) {
+ g_critical ("%s: shared file [%s] lseek error: %s", __func__, filename, g_strerror (errno));
close (fd);
unlink (filename);
return(-1);
}
do {
- ret=write (fd, "", 1);
- }
- while (ret==-1 && errno==EINTR);
+ ret = write (fd, "", 1);
+ } while (ret == -1 && errno == EINTR);
- if(ret==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": shared file [%s] write error: %s", filename, g_strerror (errno));
+ if (ret == -1) {
+ g_critical ("%s: shared file [%s] write error: %s", __func__, filename, g_strerror (errno));
close (fd);
unlink (filename);
return(-1);
}
- if(created) {
- *created=TRUE;
- }
+ created = TRUE;
/* The contents of the file is set to all
* zero, because it is opened up with lseek,
* initialisation here
*/
}
- } else if(fd==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] open error: %s", filename,
- g_strerror (errno));
+ } else if (fd == -1) {
+ g_critical ("%s: shared file [%s] open error: %s", __func__,
+ filename, g_strerror (errno));
return(-1);
}
- /* From now on, we need to delete the file before exiting on
- * error if we created it (ie, if *created==TRUE)
- */
-
/* Use stat to find the file size (instead of hard coding it)
* because we can expand the file later if needed (for more
* handles or scratch space.)
*/
- if(fstat (fd, &statbuf)==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": fstat error: %s",
+ if (fstat (fd, &statbuf) == -1) {
+ g_critical ("%s: fstat error: %s", __func__,
g_strerror (errno));
- if(created && *created==TRUE) {
+ if (created == TRUE) {
unlink (filename);
}
close (fd);
return(-1);
}
- if(statbuf.st_size < wanted_size) {
+ if (statbuf.st_size < wanted_size) {
close (fd);
- if(created && *created==TRUE) {
+ if (created == TRUE) {
#ifdef HAVE_LARGE_FILE_SUPPORT
/* Keep gcc quiet... */
- g_critical (G_GNUC_PRETTY_FUNCTION ": shared file [%s] is not big enough! (found %lld, need %d bytes)", filename, statbuf.st_size, wanted_size);
+ g_critical ("%s: shared file [%s] is not big enough! (found %lld, need %d bytes)", __func__, filename, statbuf.st_size, wanted_size);
#else
- g_critical (G_GNUC_PRETTY_FUNCTION ": shared file [%s] is not big enough! (found %ld, need %d bytes)", filename, statbuf.st_size, wanted_size);
+ g_critical ("%s: shared file [%s] is not big enough! (found %ld, need %d bytes)", __func__, filename, statbuf.st_size, wanted_size);
#endif
unlink (filename);
return(-1);
return(fd);
}
-gpointer _wapi_shm_file_map (_wapi_shm_t type, guint32 segment,
- gboolean *created, off_t *size)
+/*
+ * _wapi_shm_attach:
+ * @success: Was it a success
+ *
+ * Attach to the shared memory file or create it if it did not exist.
+ * Returns the memory area the file was mmapped to.
+ */
+gpointer _wapi_shm_attach (void)
{
gpointer shm_seg;
int fd;
struct stat statbuf;
- guchar *filename=_wapi_shm_file (type, segment);
+ guchar *filename=_wapi_shm_file ();
- fd=_wapi_shm_file_open (filename, type, created);
+ fd=_wapi_shm_file_open (filename,
+ sizeof(struct _WapiHandleSharedLayout));
if(fd==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION
- ": shared file [%s] open error", filename);
+ g_critical ("%s: shared file [%s] open error", __func__,
+ filename);
return(NULL);
}
if(fstat (fd, &statbuf)==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": fstat error: %s",
+ g_critical ("%s: fstat error: %s", __func__,
g_strerror (errno));
close (fd);
return(NULL);
}
- if(size) {
- *size=statbuf.st_size;
- }
shm_seg=mmap (NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, 0);
if(shm_seg==MAP_FAILED) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": mmap error: %s",
+ g_critical ("%s: mmap error: %s", __func__,
g_strerror (errno));
close (fd);
return(NULL);
return(shm_seg);
}
-/*
- * _wapi_shm_attach:
- * @success: Was it a success
- *
- * Attach to the shared memory file or create it if it did not
- * exist. If it was created and daemon was FALSE a new daemon is
- * forked into existence. Returns the memory area the file was mmapped
- * to.
- */
-gboolean _wapi_shm_attach (struct _WapiHandleShared_list **data,
- struct _WapiHandleScratch **scratch)
+gpointer _wapi_fileshare_shm_attach (void)
{
- gboolean data_created=FALSE, scratch_created=FALSE;
- off_t data_size, scratch_size;
- int tries, closing_tries=0;
-
-map_again:
- *data=_wapi_shm_file_map (WAPI_SHM_DATA, 0, &data_created, &data_size);
- if(*data==NULL) {
- return(FALSE);
- }
+ gpointer shm_seg;
+ int fd;
+ struct stat statbuf;
+ guchar *filename=_wapi_fileshare_shm_file ();
- *scratch=_wapi_shm_file_map (WAPI_SHM_SCRATCH, 0, &scratch_created,
- &scratch_size);
- if(*scratch==NULL) {
- if(data_created) {
- _wapi_shm_destroy ();
- }
- return(FALSE);
- }
-
- if(scratch_created)
- (*scratch)->data_len = scratch_size -
- (sizeof(struct _WapiHandleScratch) - MONO_ZERO_ARRAY_LENGTH);
-
- if(data_created==FALSE && (*data)->daemon_running==DAEMON_CLOSING) {
- /* Daemon is closing down, give it a few ms and try
- * again.
- */
-
- struct timespec sleepytime;
-
- /* Something must have gone wrong, so delete the
- * shared segments and try again.
- */
- _wapi_shm_destroy ();
-
- munmap (*data, data_size);
- munmap (*scratch, scratch_size);
-
- if(closing_tries++ == 5) {
- /* Still can't get going, so bail out */
- g_warning ("The handle daemon is stuck closing");
- return(FALSE);
- }
-
- sleepytime.tv_sec=0;
- sleepytime.tv_nsec=10000000; /* 10ms */
-
- nanosleep (&sleepytime, NULL);
- goto map_again;
+ fd=_wapi_shm_file_open (filename, sizeof(struct _WapiFileShareLayout));
+ if(fd==-1) {
+ g_critical ("%s: shared file [%s] open error", __func__,
+ filename);
+ return(NULL);
}
- if(data_created==TRUE) {
-#ifdef VALGRINDING
- /* _wapi_daemon_main() does not return */
- _wapi_daemon_main (*data, *scratch);
-
- /* But just in case... */
- (*data)->daemon_running=DAEMON_DIED_AT_STARTUP;
- exit (-1);
-#else
- pid_t pid;
-
- pid=fork ();
- if(pid==-1) {
- g_critical (G_GNUC_PRETTY_FUNCTION ": fork error: %s",
- strerror (errno));
- _wapi_shm_destroy ();
- return(FALSE);
- } else if (pid==0) {
- int i;
-
- /* child */
- setsid ();
-
- /* FIXME: Set process title to something
- * informative
- */
-
- /* Start the daemon with a clean sheet of file
- * descriptors
- */
- for(i=3; i<getdtablesize (); i++) {
- close (i);
- }
-
- /* _wapi_daemon_main() does not return */
- _wapi_daemon_main (*data, *scratch);
-
- /* But just in case... */
- (*data)->daemon_running=DAEMON_DIED_AT_STARTUP;
- exit (-1);
- }
- /* parent carries on */
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": Daemon pid %d", pid);
-#endif
-#endif /* !VALGRINDING */
- }
-
- for(tries=0; (*data)->daemon_running==DAEMON_STARTING && tries < 100;
- tries++) {
- /* wait for the daemon to sort itself out. To be
- * completely safe, we should have a timeout before
- * giving up.
- */
- struct timespec sleepytime;
-
- sleepytime.tv_sec=0;
- sleepytime.tv_nsec=10000000; /* 10ms */
-
- nanosleep (&sleepytime, NULL);
- }
- if(tries==100 && (*data)->daemon_running==DAEMON_STARTING) {
- /* Daemon didnt get going */
- struct timespec sleepytime;
-
- /* Something must have gone wrong, so delete the
- * shared segments and try again.
- */
- _wapi_shm_destroy ();
-
- /* Daemon didn't get going, give it a few ms and try
- * again.
- */
-
- munmap (*data, data_size);
- munmap (*scratch, scratch_size);
-
- if(closing_tries++ == 5) {
- /* Still can't get going, so bail out */
- g_warning ("The handle daemon didnt start up properly");
- return(FALSE);
- }
-
- sleepytime.tv_sec=0;
- sleepytime.tv_nsec=10000000; /* 10ms */
-
- nanosleep (&sleepytime, NULL);
- goto map_again;
+ if(fstat (fd, &statbuf)==-1) {
+ g_critical ("%s: fstat error: %s", __func__,
+ g_strerror (errno));
+ close (fd);
+ return(NULL);
}
- if((*data)->daemon_running==DAEMON_DIED_AT_STARTUP) {
- /* Oh dear, the daemon had an error starting up */
- if(data_created==TRUE) {
- _wapi_shm_destroy ();
- }
- g_warning ("Handle daemon failed to start");
- return(FALSE);
- }
-
- /* Do some sanity checking on the shared memory we
- * attached
- */
- if(((*data)->daemon_running!=DAEMON_RUNNING) ||
-#ifdef NEED_LINK_UNLINK
- (strncmp ((*data)->daemon, "/tmp/mono-handle-daemon-",
- 24)!=0)) {
-#else
- (strncmp ((*data)->daemon+1, "mono-handle-daemon-", 19)!=0)) {
-#endif
- g_warning ("Shared memory sanity check failed.");
- g_warning("status: %d", (*data)->daemon_running);
-#ifdef NEED_LINK_UNLINK
- g_warning("daemon: [%s]", (*data)->daemon);
-#else
- g_warning("daemon: [%s]", (*data)->daemon+1);
-#endif
- return(FALSE);
+ shm_seg=mmap (NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ fd, 0);
+ if(shm_seg==MAP_FAILED) {
+ g_critical ("%s: mmap error: %s", __func__,
+ g_strerror (errno));
+ close (fd);
+ return(NULL);
}
- /* From now on, it's up to the daemon to delete the shared
- * memory segment
- */
-
- return(TRUE);
-}
-
-void _wapi_shm_destroy (void)
-{
-#ifndef DISABLE_SHARED_HANDLES
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlinking shared data");
-#endif
- /* Only delete the first segments. The daemon will destroy
- * any others when it exits
- */
- unlink (_wapi_shm_file (WAPI_SHM_DATA, 0));
- unlink (_wapi_shm_file (WAPI_SHM_SCRATCH, 0));
-#endif /* DISABLE_SHARED_HANDLES */
+ close (fd);
+ return(shm_seg);
}
-
#include <mono/io-layer/wapi-private.h>
-struct _WapiScratchHeader
-{
- /* These two can be merged */
- guint32 flags;
- guint32 length;
-};
-
-enum {
- WAPI_SHM_SCRATCH_FREE=0x1
-};
-
-typedef enum {
- WAPI_SHM_DATA,
- WAPI_SHM_SCRATCH
-} _wapi_shm_t;
-
-extern guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment);
-extern gpointer _wapi_shm_file_map (_wapi_shm_t type, guint32 segment,
- gboolean *created, off_t *size);
-extern gpointer _wapi_shm_file_expand (gpointer mem, _wapi_shm_t type,
- guint32 segment, guint32 old_len,
- guint32 new_len);
-extern gboolean _wapi_shm_attach (struct _WapiHandleShared_list **data,
- struct _WapiHandleScratch **scratch);
-extern void _wapi_shm_destroy (void);
+extern gpointer _wapi_shm_attach (void);
+extern gpointer _wapi_fileshare_shm_attach (void);
#endif /* _WAPI_SHARED_H_ */
int dummy;
};
-struct _WapiHandlePrivate_socket
-{
- WapiFDMapped fd_mapped;
-};
-
#endif /* _WAPI_SOCKET_PRIVATE_H_ */
static pthread_key_t error_key;
static mono_once_t error_key_once=MONO_ONCE_INIT;
-static void socket_close_private (gpointer handle);
+static void socket_close (gpointer handle);
struct _WapiHandleOps _wapi_socket_ops = {
- NULL, /* close_shared */
- socket_close_private, /* close_private */
+ socket_close, /* close */
NULL, /* signal */
NULL, /* own */
NULL, /* is_owned */
/* No capabilities to register */
}
-static void socket_close_private (gpointer handle)
+static void socket_close (gpointer handle)
{
- struct _WapiHandlePrivate_socket *socket_private_handle;
- gboolean ok;
int ret;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": closing socket handle %p",
- handle);
+ g_message ("%s: closing socket handle %p", __func__, handle);
#endif
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return;
}
- ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
- NULL, (gpointer *)&socket_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up socket handle %p", handle);
- WSASetLastError(WSAENOTSOCK);
- return;
- }
-
- g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle));
-
- if (socket_private_handle->fd_mapped.assigned == TRUE) {
- /* Blank out the mapping, to make catching errors easier */
- _wapi_handle_fd_offset_store (socket_private_handle->fd_mapped.fd, NULL);
+ g_ptr_array_remove_fast (sockets, handle);
- do {
- ret=close(socket_private_handle->fd_mapped.fd);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ do {
+ ret = close (GPOINTER_TO_UINT(handle));
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
- if(ret==-1) {
- gint errnum = errno;
+ if (ret == -1) {
+ gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
- strerror(errno));
+ g_message ("%s: close error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
- WSASetLastError (errnum);
-
- return;
- }
- } else {
- WSASetLastError(WSAENOTSOCK);
+ errnum = errno_to_WSA (errnum, __func__);
+ WSASetLastError (errnum);
}
}
int WSAStartup(guint32 requested, WapiWSAData *data)
{
- if(data==NULL) {
+ if (data == NULL) {
return(WSAEFAULT);
}
/* Insist on v2.0+ */
- if(requested < MAKEWORD(2,0)) {
+ if (requested < MAKEWORD(2,0)) {
return(WSAVERNOTSUPPORTED);
}
- if(startup_count==0) {
- sockets=g_ptr_array_new();
+ if (startup_count == 0) {
+ sockets = g_ptr_array_new();
}
startup_count++;
/* I've no idea what is the minor version of the spec I read */
- data->wHighVersion=MAKEWORD(2,0);
+ data->wHighVersion = MAKEWORD(2,0);
- data->wVersion=requested < data->wHighVersion? requested:
+ data->wVersion = requested < data->wHighVersion? requested:
data->wHighVersion;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
- data->wHighVersion);
+ g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
#endif
- strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
- strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
+ strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
+ strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
return(0);
}
guint32 i;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
+ g_message ("%s: cleaning up", __func__);
#endif
- if(--startup_count) {
+ if (--startup_count) {
/* Do nothing */
return(0);
}
/* Close down all sockets */
- for(i=0; i<sockets->len; i++) {
+ for (i = 0; i < sockets->len; i++) {
gpointer handle;
- handle=g_ptr_array_index(sockets, i);
- _wapi_handle_ops_close_private (handle);
+ handle = g_ptr_array_index (sockets, i);
+ _wapi_handle_ops_close (handle);
}
- g_ptr_array_free(sockets, FALSE);
- sockets=NULL;
+ g_ptr_array_free (sockets, FALSE);
+ sockets = NULL;
return(0);
}
{
int ret;
- ret = pthread_key_create(&error_key, NULL);
+ ret = pthread_key_create (&error_key, NULL);
g_assert (ret == 0);
}
{
int ret;
- mono_once(&error_key_once, error_init);
- ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
+ mono_once (&error_key_once, error_init);
+ ret = pthread_setspecific (error_key, GINT_TO_POINTER(error));
g_assert (ret == 0);
}
int err;
void *errptr;
- mono_once(&error_key_once, error_init);
- errptr=pthread_getspecific(error_key);
- err=GPOINTER_TO_INT(errptr);
+ mono_once (&error_key_once, error_init);
+ errptr = pthread_getspecific (error_key);
+ err = GPOINTER_TO_INT(errptr);
return(err);
}
-int closesocket(guint32 fd_handle)
+int closesocket(guint32 fd)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd_handle));
+ gpointer handle = GUINT_TO_POINTER (fd);
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(0);
}
guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
{
- struct _WapiHandlePrivate_socket *new_socket_private_handle;
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
gpointer new_handle;
- gboolean ok;
int new_fd;
- int thr_ret;
- guint32 ret = INVALID_SOCKET;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(INVALID_SOCKET);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(INVALID_SOCKET);
}
do {
- new_fd=accept(fd, addr, addrlen);
- }
- while (new_fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ new_fd = accept (fd, addr, addrlen);
+ } while (new_fd == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending());
- if(new_fd==-1) {
+ if (new_fd == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
- strerror(errno));
+ g_message ("%s: accept error: %s", __func__, strerror(errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(INVALID_SOCKET);
}
- if (new_fd >= _wapi_fd_offset_table_size) {
+ if (new_fd >= _wapi_fd_reserve) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
+ g_message ("%s: File descriptor is too big", __func__);
#endif
WSASetLastError (WSASYSCALLFAILURE);
return(INVALID_SOCKET);
}
- new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
- if(new_handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating socket handle");
+ new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, NULL);
+ if(new_handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating socket handle", __func__);
WSASetLastError (ERROR_GEN_FAILURE);
return(INVALID_SOCKET);
}
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- new_handle);
- thr_ret = _wapi_handle_lock_handle (new_handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
- (gpointer *)&new_socket_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up new socket handle %p",
- new_handle);
- goto cleanup;
- }
-
- _wapi_handle_fd_offset_store (new_fd, new_handle);
- ret = new_fd;
-
- new_socket_private_handle->fd_mapped.fd = new_fd;
- new_socket_private_handle->fd_mapped.assigned = TRUE;
+ g_ptr_array_add (sockets, new_handle);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": returning newly accepted socket handle %p with fd %d",
- new_handle, new_socket_private_handle->fd_mapped.fd);
+ g_message ("%s: returning newly accepted socket handle %p with",
+ __func__, new_handle);
#endif
-
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (new_handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
- return(ret);
+ return(new_fd);
}
int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=bind(fd, my_addr, addrlen);
- if(ret==-1) {
+ ret = bind (fd, my_addr, addrlen);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
- strerror(errno));
+ g_message ("%s: bind error: %s", __func__, strerror(errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
socklen_t addrlen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
gint errnum;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
do {
- ret=connect(fd, serv_addr, addrlen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = connect (fd, serv_addr, addrlen);
+ } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
- if(ret==-1 && errno==EACCES) {
+ if (ret == -1 && errno == EACCES) {
/* Try setting SO_BROADCAST and connecting again, but
* keep the original errno
*/
errnum = errno;
- ret=setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
- sizeof(true));
- if(ret==0) {
+ ret = setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
+ sizeof(true));
+ if (ret == 0) {
do {
- ret=connect (fd, serv_addr, addrlen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = connect (fd, serv_addr, addrlen);
+ } while (ret==-1 && errno==EINTR &&
+ !_wapi_thread_cur_apc_pending());
}
- } else if (ret==-1) {
+ } else if (ret == -1) {
errnum = errno;
}
- if(ret==-1) {
+ if (ret == -1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
- strerror(errnum));
+ g_message ("%s: connect error: %s", __func__,
+ strerror (errnum));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=getpeername(fd, name, namelen);
- if(ret==-1) {
+ ret = getpeername (fd, name, namelen);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
- strerror(errno));
+ g_message ("%s: getpeername error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=getsockname(fd, name, namelen);
- if(ret==-1) {
+ ret = getsockname (fd, name, namelen);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
- strerror(errno));
+ g_message ("%s: getsockname error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
socklen_t *optlen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=getsockopt(fd, level, optname, optval, optlen);
- if(ret==-1) {
+ ret = getsockopt (fd, level, optname, optval, optlen);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
- strerror(errno));
+ g_message ("%s: getsockopt error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_listen(guint32 fd, int backlog)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=listen(fd, backlog);
- if(ret==-1) {
+ ret = listen (fd, backlog);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
- strerror(errno));
+ g_message ("%s: listen error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
{
- return(_wapi_recvfrom(fd, buf, len, recv_flags, NULL, 0));
+ return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
}
int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
#ifndef HAVE_MSG_NOSIGNAL
void (*old_sigpipe)(int); // old SIGPIPE handler
#endif
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
#ifdef HAVE_MSG_NOSIGNAL
do {
- ret=recvfrom(fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
- fromlen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = recvfrom (fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
+ fromlen);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
#else
- old_sigpipe = signal(SIGPIPE, SIG_IGN);
+ old_sigpipe = signal (SIGPIPE, SIG_IGN);
do {
- ret=recvfrom(fd, buf, len, recv_flags, from, fromlen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
- signal(SIGPIPE, old_sigpipe);
+ ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
+ signal (SIGPIPE, old_sigpipe);
#endif
- if(ret==-1) {
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
- strerror(errno));
+ g_message ("%s: recv error: %s", __func__, strerror(errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
#ifndef HAVE_MSG_NOSIGNAL
void (*old_sigpipe)(int); // old SIGPIPE handler
#endif
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
#ifdef HAVE_MSG_NOSIGNAL
do {
- ret=send(fd, msg, len, send_flags | MSG_NOSIGNAL);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = send (fd, msg, len, send_flags | MSG_NOSIGNAL);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
#else
- old_sigpipe = signal(SIGPIPE, SIG_IGN);
+ old_sigpipe = signal (SIGPIPE, SIG_IGN);
do {
- ret=send(fd, msg, len, send_flags);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
- signal(SIGPIPE, old_sigpipe);
+ ret = send (fd, msg, len, send_flags);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
+ signal (SIGPIPE, old_sigpipe);
#endif
- if(ret==-1) {
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
- strerror(errno));
+ g_message ("%s: send error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
#ifndef HAVE_MSG_NOSIGNAL
void (*old_sigpipe)(int); // old SIGPIPE handler
#endif
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
#ifdef HAVE_MSG_NOSIGNAL
do {
- ret=sendto(fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = sendto (fd, msg, len, send_flags | MSG_NOSIGNAL, to,
+ tolen);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
#else
- old_sigpipe = signal(SIGPIPE, SIG_IGN);
+ old_sigpipe = signal (SIGPIPE, SIG_IGN);
do {
- ret=sendto(fd, msg, len, send_flags, to, tolen);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
- signal(SIGPIPE, old_sigpipe);
+ ret = sendto (fd, msg, len, send_flags, to, tolen);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
+ signal (SIGPIPE, old_sigpipe);
#endif
- if(ret==-1) {
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
- strerror(errno));
+ g_message ("%s: send error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_setsockopt(guint32 fd, int level, int optname,
const void *optval, socklen_t optlen)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=setsockopt(fd, level, optname, optval, optlen);
- if(ret==-1) {
+ ret = setsockopt (fd, level, optname, optval, optlen);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
- strerror(errno));
+ g_message ("%s: setsockopt error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
int _wapi_shutdown(guint32 fd, int how)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- ret=shutdown(fd, how);
- if(ret==-1) {
+ ret = shutdown (fd, how);
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
- strerror(errno));
+ g_message ("%s: shutdown error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
return(ret);
}
-guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
+guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
+ guint32 unused2, guint32 unused3)
{
- struct _WapiHandlePrivate_socket *socket_private_handle;
gpointer handle;
- gboolean ok;
int fd;
- int thr_ret;
- guint32 ret = INVALID_SOCKET;
- fd=socket(domain, type, protocol);
- if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
+ fd = socket (domain, type, protocol);
+ if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
+ protocol == 0) {
/* Retry with protocol == 4 (see bug #54565) */
fd = socket (AF_INET, SOCK_RAW, 4);
}
if (fd == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
+ g_message ("%s: socket error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(INVALID_SOCKET);
}
- if (fd >= _wapi_fd_offset_table_size) {
+ if (fd >= _wapi_fd_reserve) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big");
+ g_message ("%s: File descriptor is too big", __func__);
#endif
WSASetLastError (WSASYSCALLFAILURE);
mono_once (&socket_ops_once, socket_ops_init);
- handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating socket handle");
+ handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, NULL);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating socket handle", __func__);
return(INVALID_SOCKET);
}
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
- (gpointer *)&socket_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up socket handle %p", handle);
- goto cleanup;
- }
+ g_ptr_array_add (sockets, handle);
- _wapi_handle_fd_offset_store (fd, handle);
- ret = fd;
-
- socket_private_handle->fd_mapped.fd = fd;
- socket_private_handle->fd_mapped.assigned = TRUE;
-
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": returning socket handle %p with fd %d", handle,
- socket_private_handle->fd_mapped.fd);
+ g_message ("%s: returning socket handle %p", __func__, handle);
#endif
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- return(ret);
+ return(fd);
}
struct hostent *_wapi_gethostbyname(const char *hostname)
{
struct hostent *he;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(NULL);
}
- he=gethostbyname(hostname);
- if(he==NULL) {
+ he = gethostbyname (hostname);
+ if (he == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
- strerror(h_errno));
+ g_message ("%s: gethostbyname error: %s", __func__,
+ strerror (h_errno));
#endif
switch(h_errno) {
case HOST_NOT_FOUND:
- WSASetLastError(WSAHOST_NOT_FOUND);
+ WSASetLastError (WSAHOST_NOT_FOUND);
break;
#if NO_ADDRESS != NO_DATA
case NO_ADDRESS:
#endif
case NO_DATA:
- WSASetLastError(WSANO_DATA);
+ WSASetLastError (WSANO_DATA);
break;
case NO_RECOVERY:
- WSASetLastError(WSANO_RECOVERY);
+ WSASetLastError (WSANO_RECOVERY);
break;
case TRY_AGAIN:
- WSASetLastError(WSATRY_AGAIN);
+ WSASetLastError (WSATRY_AGAIN);
break;
default:
- g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
+ g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
break;
}
}
gchar *output, gint o_len, glong *written,
void *unused1, void *unused2)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
gchar *buffer = NULL;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return SOCKET_ERROR;
}
- if (i_len > 0)
+ if (i_len > 0) {
buffer = g_memdup (input, i_len);
+ }
ret = ioctl (fd, command, buffer);
if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
- strerror(errno));
+ g_message("%s: WSAIoctl error: %s", __func__,
+ strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
g_free (buffer);
- return SOCKET_ERROR;
+ return(SOCKET_ERROR);
}
if (buffer == NULL) {
*written = 0;
} else {
/* We just copy the buffer to the output. Some ioctls
- * don't even output any data, but, well... */
+ * don't even output any data, but, well...
+ */
i_len = (i_len > o_len) ? o_len : i_len;
memcpy (output, buffer, i_len);
g_free (buffer);
*written = i_len;
}
- return 0;
+ return(0);
}
int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
- if(command!=FIONBIO &&
- command!=FIONREAD &&
- command!=SIOCATMARK) {
+ if (command != FIONBIO &&
+ command != FIONREAD &&
+ command != SIOCATMARK) {
/* Not listed in the MSDN specs, but ioctl(2) returns
* this if command is invalid
*/
- WSASetLastError(WSAEINVAL);
+ WSASetLastError (WSAEINVAL);
return(SOCKET_ERROR);
}
/* This works better than ioctl(...FIONBIO...) on Linux (it causes
* connect to return EINPROGRESS, but the ioctl doesn't seem to)
*/
- if(command==FIONBIO) {
- ret=fcntl(fd, F_GETFL, 0);
- if(ret!=-1) {
- if(*(gboolean *)arg) {
+ if (command == FIONBIO) {
+ ret = fcntl (fd, F_GETFL, 0);
+ if (ret != -1) {
+ if (*(gboolean *)arg) {
ret &= ~O_NONBLOCK;
} else {
ret |= O_NONBLOCK;
}
- ret=fcntl(fd, F_SETFL, ret);
+ ret = fcntl (fd, F_SETFL, ret);
}
} else
#endif /* O_NONBLOCK */
{
- ret=ioctl(fd, command, arg);
+ ret = ioctl (fd, command, arg);
}
- if(ret==-1) {
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
- strerror(errno));
+ g_message ("%s: ioctl error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
{
int ret;
- if(startup_count==0) {
- WSASetLastError(WSANOTINITIALISED);
+ if (startup_count == 0) {
+ WSASetLastError (WSANOTINITIALISED);
return(SOCKET_ERROR);
}
do {
- ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+ ret = select(getdtablesize (), readfds, writefds, exceptfds,
+ timeout);
+ } while (ret == -1 && errno == EINTR &&
+ !_wapi_thread_cur_apc_pending ());
- if(ret==-1) {
+ if (ret == -1) {
gint errnum = errno;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
- strerror(errno));
+ g_message ("%s: select error: %s", __func__, strerror (errno));
#endif
- errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+ errnum = errno_to_WSA (errnum, __func__);
WSASetLastError (errnum);
return(SOCKET_ERROR);
void _wapi_FD_CLR(guint32 fd, fd_set *set)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return;
}
- FD_CLR(fd, set);
+ FD_CLR (fd, set);
}
int _wapi_FD_ISSET(guint32 fd, fd_set *set)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return(0);
}
- return(FD_ISSET(fd, set));
+ return(FD_ISSET (fd, set));
}
void _wapi_FD_SET(guint32 fd, fd_set *set)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd));
+ gpointer handle = GUINT_TO_POINTER (fd);
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError(WSAENOTSOCK);
+ if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ WSASetLastError (WSAENOTSOCK);
return;
}
- FD_SET(fd, set);
+ FD_SET (fd, set);
}
#ifdef USE_AIO
}
static gboolean
-do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer,
+do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
guint32 numbytes, guint32 *out_bytes,
gpointer ares,
SocketAsyncCB callback)
{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
- int fd = GPOINTER_TO_UINT (fd_handle);
+ int fd = GPOINTER_TO_UINT (handle);
struct aiocb *aio;
int result;
notifier_data_t *ndata;
{
WapiThreadState state;
guint32 exitstatus;
- gpointer process_handle;
-};
-
-struct _WapiHandlePrivate_thread
-{
+ pid_t owner_pid;
TimedThread *thread;
gboolean joined;
};
-gboolean _wapi_thread_apc_pending (gpointer handle);
-gboolean _wapi_thread_cur_apc_pending (void);
-gboolean _wapi_thread_dispatch_apc_queue (gpointer handle);
+extern gboolean _wapi_thread_apc_pending (gpointer handle);
+extern gboolean _wapi_thread_cur_apc_pending (void);
+extern gboolean _wapi_thread_dispatch_apc_queue (gpointer handle);
#endif /* _WAPI_THREAD_PRIVATE_H_ */
static MonoGHashTable *tls_gc_hash = NULL;
#endif
-static void thread_close_private (gpointer handle);
-static void thread_own (gpointer handle);
+static gboolean thread_own (gpointer handle);
struct _WapiHandleOps _wapi_thread_ops = {
NULL, /* close_shared */
- thread_close_private, /* close_private */
NULL, /* signal */
thread_own, /* own */
NULL, /* is_owned */
#endif
}
-static void thread_close_private (gpointer handle)
+static gboolean thread_own (gpointer handle)
{
- struct _WapiHandlePrivate_thread *thread_handle;
+ struct _WapiHandleShared shared_handle;
+ struct _WapiHandle_thread *thread_handle;
gboolean ok;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, NULL,
- (gpointer *)&thread_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return;
- }
-
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": closing thread handle %p with thread %p id %ld",
- handle, thread_handle->thread,
- thread_handle->thread->id);
+ g_message ("%s: owning thread handle %p", __func__, handle);
#endif
- thread_handle->thread=NULL;
-}
+ ok = _wapi_copy_handle (handle, WAPI_HANDLE_THREAD,
+ &shared_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error copying thread handle %p", __func__,
+ handle);
+ return(FALSE);
+ }
+ thread_handle = &shared_handle.u.thread;
-static void thread_own (gpointer handle)
-{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return;
+ if (thread_handle->owner_pid != getpid()) {
+#ifdef DEBUG
+ g_message ("%s: can't join thread, %d not owner process %d",
+ __func__, getpid(), thread_handle->owner_pid);
+#endif
+ /* FIXME: might need to return TRUE here so that other
+ * processes can WaitFor thread handles
+ */
+ return(FALSE);
}
+
+ if (thread_handle->joined == FALSE) {
+ _wapi_timed_thread_join (thread_handle->thread, NULL, NULL);
+ thread_handle->joined = TRUE;
- if(thread_private_handle->joined==FALSE) {
- _wapi_timed_thread_join (thread_private_handle->thread, NULL,
- NULL);
- thread_private_handle->joined=TRUE;
+ _wapi_replace_handle (handle, WAPI_HANDLE_THREAD,
+ &shared_handle);
}
+
+ return(TRUE);
}
static void thread_exit(guint32 exitstatus, gpointer handle)
{
+ struct _WapiHandleShared shared_handle;
struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
gboolean ok;
int thr_ret;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return;
- }
-
- _wapi_mutex_check_abandoned (getpid (),
- thread_private_handle->thread->id);
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
handle);
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
+
+ ok = _wapi_copy_handle (handle, WAPI_HANDLE_THREAD,
+ &shared_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error copying thread handle %p", __func__,
+ handle);
+ return;
+ }
+ thread_handle = &shared_handle.u.thread;
+
+ _wapi_mutex_check_abandoned (getpid (), thread_handle->thread->id);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Recording thread handle %p exit status", handle);
+ g_message ("%s: Recording thread handle %p exit status", __func__,
+ handle);
#endif
- thread_handle->exitstatus=exitstatus;
- thread_handle->state=THREAD_STATE_EXITED;
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ thread_handle->exitstatus = exitstatus;
+ thread_handle->state = THREAD_STATE_EXITED;
+
+ _wapi_replace_handle (handle, WAPI_HANDLE_THREAD, &shared_handle);
+
+ _wapi_shared_handle_set_signal_state (handle, TRUE);
thr_ret = _wapi_handle_unlock_handle (handle);
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Recording thread handle %p id %ld status as %d",
- handle, thread_private_handle->thread->id, exitstatus);
+ g_message("%s: Recording thread handle %p id %ld status as %d",
+ __func__, handle, thread_handle->thread->id, exitstatus);
#endif
/* Remove this thread from the hash */
thr_ret = mono_mutex_lock(&thread_hash_mutex);
g_assert (thr_ret == 0);
- g_hash_table_remove(thread_hash, &thread_private_handle->thread->id);
+ g_hash_table_remove(thread_hash, &thread_handle->thread->id);
thr_ret = mono_mutex_unlock(&thread_hash_mutex);
g_assert (thr_ret == 0);
static void thread_hash_init(void)
{
- thread_hash=g_hash_table_new(g_int_hash, g_int_equal);
+ thread_hash = g_hash_table_new(g_int_hash, g_int_equal);
}
/**
WapiThreadStart start, gpointer param, guint32 create,
guint32 *tid)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
+ struct _WapiHandleShared shared_handle;
+ struct _WapiHandle_thread thread_handle = {0};
pthread_attr_t attr;
gpointer handle;
gboolean ok;
int ret;
int thr_ret;
- int i, unrefs = 0;
gpointer ct_ret = NULL;
- mono_once(&thread_hash_once, thread_hash_init);
+ mono_once (&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
- if(start==NULL) {
- return(NULL);
- }
-
- handle=_wapi_handle_new (WAPI_HANDLE_THREAD);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating thread handle");
+ if (start == NULL) {
return(NULL);
}
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- goto cleanup;
- }
-
- /* Hold a reference while the thread is active, because we use
- * the handle to store thread exit information
- */
- _wapi_handle_ref (handle);
-
- thread_handle->state=THREAD_STATE_START;
-
- /* Lock around the thread create, so that the new thread cant
- * race us to look up the thread handle in GetCurrentThread()
- */
- pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
- (void *)&thread_hash_mutex);
- thr_ret = mono_mutex_lock(&thread_hash_mutex);
- g_assert (thr_ret == 0);
+ thread_handle.state = THREAD_STATE_START;
+ thread_handle.owner_pid = getpid();
/* Set a 2M stack size. This is the default on Linux, but BSD
* needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
/* defaults of 2Mb for 32bits and 4Mb for 64bits */
if (stacksize == 0){
#if HAVE_VALGRIND_MEMCHECK_H
- if (RUNNING_ON_VALGRIND)
+ if (RUNNING_ON_VALGRIND) {
stacksize = 1 << 20;
- else
+ } else {
stacksize = (SIZEOF_VOID_P / 2) * 1024 * 1024;
+ }
#else
stacksize = (SIZEOF_VOID_P / 2) * 1024 * 1024;
#endif
thr_ret = pthread_attr_setstacksize(&attr, stacksize);
g_assert (thr_ret == 0);
#endif
+
+ /* Lock around the thread create, so that the new thread cant
+ * race us to look up the thread handle in GetCurrentThread()
+ */
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+
+ handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating thread handle", __func__);
+ goto thread_hash_cleanup;
+ }
+ ct_ret = handle;
- ret=_wapi_timed_thread_create(&thread_private_handle->thread, &attr,
- create, start, thread_exit, param,
- handle);
- if(ret!=0) {
+ ret = _wapi_timed_thread_create (&thread_handle.thread, &attr,
+ create, start, thread_exit, param,
+ handle);
+ if (ret != 0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Thread create error: %s",
- strerror(ret));
+ g_message ("%s: Thread create error: %s", __func__,
+ strerror(ret));
#endif
- /* Two, because of the reference we took above */
- unrefs = 2;
+ _wapi_handle_unref (handle);
goto thread_hash_cleanup;
}
- ct_ret = handle;
+
+ /* Need to update the handle with the state info that
+ * _wapi_timed_thread_create created, after the initial handle
+ * info was copied into shared memory
+ */
+ ok = _wapi_copy_handle (handle, WAPI_HANDLE_THREAD, &shared_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error copying thread handle %p", __func__,
+ handle);
+ _wapi_handle_unref (handle);
+ goto thread_hash_cleanup;
+ }
+ shared_handle.u.thread.thread = thread_handle.thread;
+ _wapi_replace_handle (handle, WAPI_HANDLE_THREAD, &shared_handle);
- g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
- handle);
+ /* Hold a reference while the thread is active, because we use
+ * the handle to store thread exit information
+ */
+ _wapi_handle_ref (handle);
+
+ g_hash_table_insert (thread_hash, &thread_handle.thread->id, handle);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Started thread handle %p thread %p ID %ld", handle,
- thread_private_handle->thread,
- thread_private_handle->thread->id);
+ g_message("%s: Started thread handle %p thread %p ID %ld", __func__,
+ handle, thread_handle.thread, thread_handle.thread->id);
#endif
- if(tid!=NULL) {
+ if (tid != NULL) {
#ifdef PTHREAD_POINTER_ID
- *tid=GPOINTER_TO_UINT(thread_private_handle->thread->id);
+ *tid = GPOINTER_TO_UINT (thread_handle.thread->id);
#else
- *tid=thread_private_handle->thread->id;
+ *tid = thread_handle.thread->id;
#endif
}
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- /* Must not call _wapi_handle_unref() with the handle already
- * locked
- */
- for (i = 0; i < unrefs; i++) {
- _wapi_handle_unref (handle);
- }
-
return(ct_ret);
}
mono_once (&thread_ops_once, thread_ops_init);
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": looking up thread %d", tid);
+ g_message ("%s: looking up thread %d", __func__, tid);
#endif
pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning thread handle %p", ret);
+ g_message ("%s: returning thread handle %p", __func__, ret);
#endif
return(ret);
*/
gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(FALSE);
- }
-
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Finding exit status for thread handle %p id %ld", handle,
- thread_private_handle->thread->id);
+ g_message ("%s: Finding exit status for thread handle %p id %ld",
+ __func__, handle,
+ WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread->id);
#endif
- if(exitcode==NULL) {
+ if (exitcode == NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Nowhere to store exit code");
+ g_message ("%s: Nowhere to store exit code", __func__);
#endif
return(FALSE);
}
- if(thread_handle->state!=THREAD_STATE_EXITED) {
+ if (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).state != THREAD_STATE_EXITED) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Thread still active (state %d, exited is %d)",
- thread_handle->state, THREAD_STATE_EXITED);
+ g_message ("%s: Thread still active (state %d, exited is %d)",
+ __func__,
+ WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).state,
+ THREAD_STATE_EXITED);
#endif
- *exitcode=STILL_ACTIVE;
+ *exitcode = STILL_ACTIVE;
return(TRUE);
}
- *exitcode=thread_handle->exitstatus;
+ *exitcode = WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).exitstatus;
return(TRUE);
}
*/
guint32 GetCurrentThreadId(void)
{
- pthread_t tid=pthread_self();
+ pthread_t tid = pthread_self();
#ifdef PTHREAD_POINTER_ID
return(GPOINTER_TO_UINT(tid));
static gpointer thread_attach(guint32 *tid)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
+ struct _WapiHandleShared shared_handle;
+ struct _WapiHandle_thread thread_handle = {0};
gpointer handle;
gboolean ok;
int ret;
int thr_ret;
- int i, unrefs = 0;
gpointer ta_ret = NULL;
- mono_once(&thread_hash_once, thread_hash_init);
+ mono_once (&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
- handle=_wapi_handle_new (WAPI_HANDLE_THREAD);
- if(handle==_WAPI_HANDLE_INVALID) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error creating thread handle");
- return(NULL);
- }
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- goto cleanup;
- }
-
- /* Hold a reference while the thread is active, because we use
- * the handle to store thread exit information
- */
- _wapi_handle_ref (handle);
-
- thread_handle->state=THREAD_STATE_START;
+ thread_handle.state = THREAD_STATE_START;
+ thread_handle.owner_pid = getpid();
/* Lock around the thread create, so that the new thread cant
* race us to look up the thread handle in GetCurrentThread()
thr_ret = mono_mutex_lock(&thread_hash_mutex);
g_assert (thr_ret == 0);
- ret=_wapi_timed_thread_attach(&thread_private_handle->thread,
- thread_exit, handle);
- if(ret!=0) {
+ handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
+ if (handle == _WAPI_HANDLE_INVALID) {
+ g_warning ("%s: error creating thread handle", __func__);
+ goto thread_hash_cleanup;
+ }
+ ta_ret = handle;
+
+ ret = _wapi_timed_thread_attach (&thread_handle.thread, thread_exit,
+ handle);
+ if (ret != 0) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Thread attach error: %s",
- strerror(ret));
+ g_message ("%s: Thread attach error: %s", __func__,
+ strerror(ret));
#endif
- /* Two, because of the reference we took above */
- unrefs = 2;
+ _wapi_handle_unref (handle);
goto thread_hash_cleanup;
}
- ta_ret = handle;
+
+ /* Need to update the handle with the state info that
+ * _wapi_timed_thread_create created, after the initial handle
+ * info was copied into shared memory
+ */
+ ok = _wapi_copy_handle (handle, WAPI_HANDLE_THREAD, &shared_handle);
+ if (ok == FALSE) {
+ g_warning ("%s: error copying thread handle %p", __func__,
+ handle);
+ _wapi_handle_unref (handle);
+ goto thread_hash_cleanup;
+ }
+ shared_handle.u.thread.thread = thread_handle.thread;
+ _wapi_replace_handle (handle, WAPI_HANDLE_THREAD, &shared_handle);
+
+ /* Hold a reference while the thread is active, because we use
+ * the handle to store thread exit information
+ */
+ _wapi_handle_ref (handle);
- g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
- handle);
+ g_hash_table_insert (thread_hash, &thread_handle.thread->id, handle);
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Attached thread handle %p thread %p ID %ld", handle,
- thread_private_handle->thread,
- thread_private_handle->thread->id);
+ g_message("%s: Attached thread handle %p thread %p ID %ld", __func__,
+ handle, thread_handle.thread, thread_handle.thread->id);
#endif
- if(tid!=NULL) {
+ if (tid != NULL) {
#ifdef PTHREAD_POINTER_ID
- *tid=GPOINTER_TO_UINT(thread_private_handle->thread->id);
+ *tid = GPOINTER_TO_UINT(thread_handle.thread->id);
#else
- *tid=thread_private_handle->thread->id;
+ *tid = thread_handle.thread->id;
#endif
}
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- /* Must not call _wapi_handle_unref() with the handle already
- * locked
- */
- for (i = 0; i < unrefs; i++) {
- _wapi_handle_unref (handle);
- }
-
return(ta_ret);
}
*/
guint32 ResumeThread(gpointer handle)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(0xFFFFFFFF);
- }
-
- if (thread_private_handle->thread == NULL) {
+ if (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread == NULL) {
return(0xFFFFFFFF);
}
#ifdef WITH_INCLUDED_LIBGC
- if (thread_private_handle->thread->suspend_count <= 1)
- _wapi_timed_thread_resume (thread_private_handle->thread);
+ if (WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspend_count <= 1)
+ _wapi_timed_thread_resume (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread);
- return --thread_private_handle->thread->suspend_count;
+ return (--(WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread->suspend_count));
#else
/* This is still a kludge that only copes with starting a
* thread that was suspended on create, so don't bother with
* the suspend count crap yet
*/
- _wapi_timed_thread_resume (thread_private_handle->thread);
+ _wapi_timed_thread_resume (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread);
return(0xFFFFFFFF);
#endif
}
guint32 SuspendThread(gpointer handle)
{
#ifdef WITH_INCLUDED_LIBGC
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
gpointer current;
- gboolean ok;
current = GetCurrentThread ();
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(0xFFFFFFFF);
- }
- if (thread_private_handle->thread == NULL) {
+ if (WAPI_SHARED_HANDLE_DATA(handle, thread).thread == NULL) {
return(0xFFFFFFFF);
}
- if (!thread_private_handle->thread->suspend_count) {
+ if (!WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspend_count) {
if (handle == current)
- _wapi_timed_thread_suspend (thread_private_handle->thread);
+ _wapi_timed_thread_suspend (WAPI_SHARED_HANDLE_DATA(handle, thread).thread);
else {
- pthread_kill (thread_private_handle->thread->id, SIGPWR);
- while (MONO_SEM_WAIT (&thread_private_handle->thread->suspended_sem) != 0) {
+ pthread_kill (WAPI_SHARED_HANDLE_DATA(handle, thread).thread->id, SIGPWR);
+ while (MONO_SEM_WAIT (&WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspended_sem) != 0) {
if (errno != EINTR) {
return(0xFFFFFFFF);
}
}
}
- return thread_private_handle->thread->suspend_count++;
+ return (WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspend_count++);
#else
return(0xFFFFFFFF);
#endif
MONO_SPIN_UNLOCK (TLS_spinlock);
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning key %d",
- i);
+ g_message ("%s: returning key %d", __func__, i);
#endif
return(i);
MONO_SPIN_UNLOCK (TLS_spinlock);
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": out of indices");
+ g_message ("%s: out of indices", __func__);
#endif
int thr_ret;
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": freeing key %d", idx);
+ g_message ("%s: freeing key %d", __func__, idx);
#endif
MONO_SPIN_LOCK (TLS_spinlock);
gpointer ret;
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": looking up key %d", idx);
+ g_message ("%s: looking up key %d", __func__, idx);
#endif
ret=pthread_getspecific(TLS_keys[idx]);
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning %p", ret);
+ g_message ("%s: returning %p", __func__, ret);
#endif
return(ret);
int ret;
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": setting key %d to %p", idx,
- value);
+ g_message ("%s: setting key %d to %p", __func__, idx, value);
#endif
MONO_SPIN_LOCK (TLS_spinlock);
if(TLS_used[idx]==FALSE) {
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": key %d unused", idx);
+ g_message ("%s: key %d unused", __func__, idx);
#endif
MONO_SPIN_UNLOCK (TLS_spinlock);
ret=pthread_setspecific(TLS_keys[idx], value);
if(ret!=0) {
#ifdef TLS_DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": pthread_setspecific error: %s", strerror (ret));
+ g_message ("%s: pthread_setspecific error: %s", __func__,
+ strerror (ret));
#endif
MONO_SPIN_UNLOCK (TLS_spinlock);
gpointer current_thread = NULL;
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Sleeping for %d ms", ms);
+ g_message("%s: Sleeping for %d ms", __func__, ms);
#endif
if (alertable) {
#ifdef DEBUG
guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
- g_message(G_GNUC_PRETTY_FUNCTION ": Still got %d ms to go",
- rems);
+ g_message("%s: Still got %d ms to go", __func__, rems);
#endif
req=rem;
goto again;
guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
gpointer param)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(0);
- }
-
- _wapi_timed_thread_queue_apc (thread_private_handle->thread,
- apc_callback, param);
+ _wapi_timed_thread_queue_apc (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread, apc_callback, param);
return(1);
}
gboolean _wapi_thread_cur_apc_pending (void)
{
- return _wapi_thread_apc_pending (GetCurrentThread ());
+ return(_wapi_thread_apc_pending (GetCurrentThread ()));
}
gboolean _wapi_thread_apc_pending (gpointer handle)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(FALSE);
- }
-
- return _wapi_timed_thread_apc_pending (thread_private_handle->thread);
+ return(_wapi_timed_thread_apc_pending (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread));
}
gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return(0);
- }
-
- _wapi_timed_thread_dispatch_apc_queue (thread_private_handle->thread);
+ _wapi_timed_thread_dispatch_apc_queue (WAPI_SHARED_HANDLE_TYPED_DATA(handle, thread).thread);
return(1);
}
static void GC_suspend_handler (int sig)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
gpointer handle;
- gboolean ok;
handle = GetCurrentThread ();
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return;
- }
- thread_private_handle->thread->stack_ptr = &ok;
- MONO_SEM_POST (&thread_private_handle->thread->suspended_sem);
+ WAPI_SHARED_HANDLE_DATA(handle, thread).thread->stack_ptr = &ok;
+ MONO_SEM_POST (&WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspended_sem);
- _wapi_timed_thread_suspend (thread_private_handle->thread);
+ _wapi_timed_thread_suspend (WAPI_SHARED_HANDLE_DATA(handle, thread).thread);
- thread_private_handle->thread->stack_ptr = NULL;
+ WAPI_SHARED_HANDLE_DATA(handle, thread).thread->stack_ptr = NULL;
}
static void gc_init (void)
void mono_wapi_push_thread_stack (gpointer handle, gpointer stack_ptr)
{
- struct _WapiHandle_thread *thread_handle;
- struct _WapiHandlePrivate_thread *thread_private_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
- (gpointer *)&thread_handle,
- (gpointer *)&thread_private_handle);
- if(ok==FALSE) {
- g_warning (G_GNUC_PRETTY_FUNCTION
- ": error looking up thread handle %p", handle);
- return;
- }
-
- GC_push_all_stack (thread_private_handle->thread->stack_ptr, stack_ptr);
+ GC_push_all_stack (WAPI_SHARED_HANDLE_DATA(handle, thread).thread->stack_ptr, stack_ptr);
}
#endif /* WITH_INCLUDED_LIBGC */
/* Tell a joiner that we're exiting.
*/
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Setting thread %p id %ld exit status to %d",
+ g_message("%s: Setting thread %p id %ld exit status to %d", __func__,
thread, thread->id, exitstatus);
#endif
void *specific;
if((specific = pthread_getspecific (timed_thread_key))==NULL) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": thread lookup failed");
+ g_warning ("%s: thread lookup failed", __func__);
return;
}
self=(TimedThread *)specific;
if(thread != self) {
- g_error (G_GNUC_PRETTY_FUNCTION
- ": attempt to suspend a different thread!");
+ g_error ("%s: attempt to suspend a different thread!",
+ __func__);
exit (-1);
}
ret=(guint32)((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": returning %d", ret);
+ g_message ("%s: returning %d", __func__, ret);
#endif
return(ret);
gboolean apc_pending = FALSE;
gpointer current_thread = GetCurrentThread ();
- if(_wapi_handle_test_capabilities (handle,
- WAPI_HANDLE_CAP_WAIT)==FALSE) {
+ if (_wapi_handle_test_capabilities (handle,
+ WAPI_HANDLE_CAP_WAIT) == FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p can't be waited for", handle);
+ g_message ("%s: handle %p can't be waited for", __func__,
+ handle);
#endif
return(WAIT_FAILED);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
+ g_message ("%s: locking handle %p", __func__, handle);
#endif
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
thr_ret = _wapi_handle_lock_handle (handle);
g_assert (thr_ret == 0);
- if(_wapi_handle_test_capabilities (handle,
- WAPI_HANDLE_CAP_OWN)==TRUE) {
- if(_wapi_handle_ops_isowned (handle)==TRUE) {
+ if (_wapi_handle_test_capabilities (handle,
+ WAPI_HANDLE_CAP_OWN) == TRUE) {
+ if (_wapi_handle_ops_isowned (handle)==TRUE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p already owned", handle);
+ g_message ("%s: handle %p already owned", __func__,
+ handle);
#endif
_wapi_handle_ops_own (handle);
- ret=WAIT_OBJECT_0;
+ ret = WAIT_OBJECT_0;
goto done;
}
}
goto done;
}
- if(_wapi_handle_issignalled (handle)) {
+ if (_wapi_handle_issignalled (handle)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p already signalled", handle);
+ g_message ("%s: handle %p already signalled", __func__,
+ handle);
#endif
_wapi_handle_ops_own (handle);
}
/* Have to wait for it */
- if(timeout!=INFINITE) {
+ if (timeout != INFINITE) {
_wapi_calc_timeout (&abstime, timeout);
}
do {
- if(timeout==INFINITE) {
- waited=_wapi_handle_wait_signal_handle (handle);
+ if (timeout == INFINITE) {
+ waited = _wapi_handle_wait_signal_handle (handle);
} else {
- waited=_wapi_handle_timedwait_signal_handle (handle,
- &abstime);
+ waited = _wapi_handle_timedwait_signal_handle (handle, &abstime);
}
if (alertable)
*/
if(_wapi_handle_issignalled (handle)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p signalled", handle);
+ g_message ("%s: handle %p signalled", __func__,
+ handle);
#endif
- _wapi_handle_ops_own (handle);
- ret=WAIT_OBJECT_0;
- goto done;
+ /* This might fail if a shared handle
+ * was grabbed before we got it (we
+ * can't lock those.)
+ */
+ if (_wapi_handle_ops_own (handle) == TRUE) {
+ ret=WAIT_OBJECT_0;
+ goto done;
+ }
}
/* Better luck next time */
}
- } while(waited==0 && !apc_pending);
+ } while(waited == 0 && !apc_pending);
/* Timeout or other error */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": wait on handle %p error: %s",
- handle, strerror (ret));
+ g_message ("%s: wait on handle %p error: %s", __func__, handle,
+ strerror (waited));
#endif
- ret=WAIT_TIMEOUT;
+ ret = WAIT_TIMEOUT;
done:
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
+ g_message ("%s: unlocking handle %p", __func__, handle);
#endif
thr_ret = _wapi_handle_unlock_handle (handle);
gboolean apc_pending = FALSE;
gpointer current_thread = GetCurrentThread ();
- if(_wapi_handle_test_capabilities (signal_handle,
- WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
+ if (_wapi_handle_test_capabilities (signal_handle,
+ WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
return(WAIT_FAILED);
}
- if(_wapi_handle_test_capabilities (wait,
- WAPI_HANDLE_CAP_WAIT)==FALSE) {
+ if (_wapi_handle_test_capabilities (wait,
+ WAPI_HANDLE_CAP_WAIT)==FALSE) {
return(WAIT_FAILED);
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", wait);
+ g_message ("%s: locking handle %p", __func__, wait);
#endif
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
_wapi_handle_ops_signal (signal_handle);
- if(_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) {
- if(_wapi_handle_ops_isowned (wait)==TRUE) {
+ if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) {
+ if (_wapi_handle_ops_isowned (wait)==TRUE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p already owned", wait);
+ g_message ("%s: handle %p already owned", __func__,
+ wait);
#endif
_wapi_handle_ops_own (wait);
- ret=WAIT_OBJECT_0;
+ ret = WAIT_OBJECT_0;
goto done;
}
}
if(_wapi_handle_issignalled (wait)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p already signalled", wait);
+ g_message ("%s: handle %p already signalled", __func__, wait);
#endif
_wapi_handle_ops_own (wait);
&abstime);
}
- if (alertable)
+ if (alertable) {
apc_pending = _wapi_thread_apc_pending (current_thread);
+ }
- if(waited==0 && !apc_pending) {
+ if (waited==0 && !apc_pending) {
/* Condition was signalled, so hopefully
* handle is signalled now. (It might not be
* if someone else got in before us.)
*/
if(_wapi_handle_issignalled (wait)) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": handle %p signalled", wait);
+ g_message ("%s: handle %p signalled", __func__,
+ wait);
#endif
- _wapi_handle_ops_own (wait);
- ret=WAIT_OBJECT_0;
- goto done;
+ /* This might fail if a shared handle
+ * was grabbed before we got it (we
+ * can't lock those.)
+ */
+ if (_wapi_handle_ops_own (wait) == TRUE) {
+ ret = WAIT_OBJECT_0;
+ goto done;
+ }
}
/* Better luck next time */
}
- } while(waited==0 && !apc_pending);
+ } while(waited == 0 && !apc_pending);
/* Timeout or other error */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": wait on handle %p error: %s",
- wait, strerror (ret));
+ g_message ("%s: wait on handle %p error: %s", __func__, wait,
+ strerror (ret));
#endif
- ret=WAIT_TIMEOUT;
+ ret = WAIT_TIMEOUT;
done:
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", wait);
+ g_message ("%s: unlocking handle %p", __func__, wait);
#endif
thr_ret = _wapi_handle_unlock_handle (wait);
int i;
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking handles");
+ g_message ("%s: locking handles", __func__);
#endif
cleanup_data.numobjects = numobjects;
cleanup_data.handles = handles;
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
+ g_message ("%s: unlocking handles", __func__);
#endif
/* calls the unlock function */
* %WAIT_IO_COMPLETION - the wait was ended by an APC.
*/
guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
- gboolean waitall, guint32 timeout, gboolean alertable)
+ gboolean waitall, guint32 timeout,
+ gboolean alertable)
{
GHashTable *dups;
- gboolean duplicate=FALSE, bogustype=FALSE, done;
+ gboolean duplicate = FALSE, bogustype = FALSE, done;
+ gboolean shared_wait = FALSE;
guint32 count, lowest;
struct timespec abstime;
guint i;
int thr_ret;
gpointer current_thread = GetCurrentThread ();
- if(numobjects>MAXIMUM_WAIT_OBJECTS) {
+ if (numobjects > MAXIMUM_WAIT_OBJECTS) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": Too many handles: %d",
- numobjects);
+ g_message ("%s: Too many handles: %d", __func__, numobjects);
#endif
return(WAIT_FAILED);
}
/* Check for duplicates */
- dups=g_hash_table_new(g_direct_hash, g_direct_equal);
- for(i=0; i<numobjects; i++) {
- gpointer exists=g_hash_table_lookup(dups, handles[i]);
- if(exists!=NULL) {
+ dups = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (i = 0; i < numobjects; i++) {
+ gpointer exists = g_hash_table_lookup (dups, handles[i]);
+ if (exists != NULL) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Handle %p duplicated", handles[i]);
+ g_message ("%s: Handle %p duplicated", __func__,
+ handles[i]);
#endif
- duplicate=TRUE;
+ duplicate = TRUE;
break;
}
- if(_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT)==FALSE) {
+ if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT) == FALSE) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION
- ": Handle %p can't be waited for",
- handles[i]);
+ g_message ("%s: Handle %p can't be waited for",
+ __func__, handles[i]);
#endif
- bogustype=TRUE;
+ bogustype = TRUE;
+ }
+
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) {
+ shared_wait = TRUE;
}
- g_hash_table_insert(dups, handles[i], handles[i]);
+ g_hash_table_insert (dups, handles[i], handles[i]);
}
- g_hash_table_destroy(dups);
+ g_hash_table_destroy (dups);
- if(duplicate==TRUE) {
+ if (duplicate == TRUE) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Returning due to duplicates");
+ g_message ("%s: Returning due to duplicates", __func__);
#endif
return(WAIT_FAILED);
}
- if(bogustype==TRUE) {
+ if (bogustype == TRUE) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Returning due to bogus type");
+ g_message ("%s: Returning due to bogus type", __func__);
#endif
return(WAIT_FAILED);
}
- done=test_and_own (numobjects, handles, waitall, &count, &lowest);
- if(done==TRUE) {
+ done = test_and_own (numobjects, handles, waitall, &count, &lowest);
+ if (done == TRUE) {
return(WAIT_OBJECT_0+lowest);
}
while(1) {
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking signal mutex");
+ g_message ("%s: locking signal mutex", __func__);
#endif
pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_signal_mutex, NULL);
thr_ret = _wapi_handle_lock_signal_mutex ();
g_assert (thr_ret == 0);
- if(timeout==INFINITE) {
- ret=_wapi_handle_wait_signal ();
+ if (shared_wait == TRUE) {
+ if (timeout == INFINITE) {
+ ret = _wapi_handle_wait_signal_poll_share ();
+ } else {
+ ret = _wapi_handle_timedwait_signal_poll_share (&abstime);
+ }
} else {
- ret=_wapi_handle_timedwait_signal (&abstime);
+ if (timeout == INFINITE) {
+ ret = _wapi_handle_wait_signal ();
+ } else {
+ ret = _wapi_handle_timedwait_signal (&abstime);
+ }
}
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking signal mutex");
+ g_message ("%s: unlocking signal mutex", __func__);
#endif
thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
} else {
/* Timeout or other error */
#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": wait returned error: %s", strerror (ret));
+ g_message ("%s: wait returned error: %s", __func__,
+ strerror (ret));
#endif
if(ret==ETIMEDOUT) {
#include <mono/io-layer/io.h>
#include <mono/io-layer/daemon-private.h>
-/* for non-GCC compilers where Glib gives an empty pretty function
- * macro create one that gives file & line number instead
- */
-#ifndef __GNUC__
-#undef G_GNUC_PRETTY_FUNCTION
-#define STRINGIZE_HELPER(exp) #exp
-#define STRINGIZE(exp) STRINGIZE_HELPER(exp)
-#define G_GNUC_PRETTY_FUNCTION __FILE__ "(" STRINGIZE(__LINE__) ")"
-#endif
-
/* Catch this here rather than corrupt the shared data at runtime */
#if MONO_SIZEOF_SUNPATH==0
#error configure failed to discover size of unix socket path
/* Increment this whenever an incompatible change is made to the
* shared handle structure.
*/
-#define _WAPI_HANDLE_VERSION 3
+#define _WAPI_HANDLE_VERSION 4
typedef enum {
WAPI_HANDLE_UNUSED=0,
WAPI_HANDLE_FIND,
WAPI_HANDLE_PROCESS,
WAPI_HANDLE_PIPE,
+ WAPI_HANDLE_NAMEDMUTEX,
WAPI_HANDLE_COUNT
} WapiHandleType;
-#define _WAPI_SHARED_NAMESPACE(type) (type==WAPI_HANDLE_MUTEX)
+extern const char *_wapi_handle_typename[];
-typedef struct
-{
- guint32 name;
-} WapiSharedNamespace;
+#define _WAPI_SHARED_HANDLE(type) (type == WAPI_HANDLE_THREAD || \
+ type == WAPI_HANDLE_PROCESS || \
+ type == WAPI_HANDLE_NAMEDMUTEX)
+
+#define _WAPI_FD_HANDLE(type) (type == WAPI_HANDLE_FILE || \
+ type == WAPI_HANDLE_CONSOLE || \
+ type == WAPI_HANDLE_SOCKET || \
+ type == WAPI_HANDLE_PIPE)
+
+#define _WAPI_SHARED_NAMESPACE(type) (type == WAPI_HANDLE_NAMEDMUTEX)
-/* The boolean is for distinguishing between a zeroed struct being not
- * as yet assigned, and one containing a valid fd 0. It's also used
- * to signal that a previously-good fd has been reused behind our
- * back, so we need to invalidate the handle that thought it owned the
- * fd.
- */
typedef struct
{
- int fd;
- gboolean assigned;
-} WapiFDMapped;
-
+ gchar name[MAX_PATH + 1];
+} WapiSharedNamespace;
typedef enum {
WAPI_HANDLE_CAP_WAIT=0x01,
struct _WapiHandleOps
{
- void (*close_shared)(gpointer handle);
- void (*close_private)(gpointer handle);
+ void (*close)(gpointer handle);
/* SignalObjectAndWait */
void (*signal)(gpointer signal);
/* Called by WaitForSingleObject and WaitForMultipleObjects,
- * with the handle locked
+ * with the handle locked (shared handles aren't locked.)
+ * Returns TRUE if ownership was established, false otherwise.
*/
- void (*own_handle)(gpointer handle);
+ gboolean (*own_handle)(gpointer handle);
/* Called by WaitForSingleObject and WaitForMultipleObjects, if the
* handle in question is "ownable" (ie mutexes), to see if the current
#include <mono/io-layer/thread-private.h>
#include <mono/io-layer/process-private.h>
-/* Shared threads don't seem to work yet */
-#undef _POSIX_THREAD_PROCESS_SHARED
+struct _WapiHandle_shared_ref
+{
+ /* This will be split 16:16 with the shared file segment in
+ * the top half, when I implement space increases
+ */
+ guint32 offset;
+};
-struct _WapiHandleShared
+#define _WAPI_HANDLE_INITIAL_COUNT 4096
+
+struct _WapiHandleUnshared
{
WapiHandleType type;
guint ref;
struct _WapiHandle_mutex mutex;
struct _WapiHandle_sem sem;
struct _WapiHandle_socket sock;
- struct _WapiHandle_thread thread;
- struct _WapiHandle_process process;
+ struct _WapiHandle_shared_ref shared;
} u;
};
-#define _WAPI_HANDLES_PER_SEGMENT 4096
-#define _WAPI_HANDLE_INVALID (gpointer)-1
-
-#define _WAPI_SHM_SCRATCH_SIZE 512000
-
-/*
- * This is the layout of the shared scratch data. When the data array
- * is filled, it will be expanded by _WAPI_SHM_SCRATCH_SIZE
- * bytes. (scratch data is always copied out of the shared memory, so
- * it doesn't matter that the mapping will move around.)
- */
-struct _WapiHandleScratch
+struct _WapiHandleSharedMetadata
{
- guint32 data_len;
-
- /* This is set to TRUE by the daemon. It determines whether a
- * resize will go via mremap() or just realloc().
- */
- gboolean is_shared;
- guchar scratch_data[MONO_ZERO_ARRAY_LENGTH];
+ volatile guint32 offset;
+ guint32 ref;
+ volatile gboolean signalled;
+ volatile guint32 checking;
};
-/*
- * This is the layout of the shared memory segments. When the handles
- * array is filled, another shared memory segment will be allocated
- * with the same structure. This is to avoid having the shared memory
- * potentially move if it is resized and remapped.
- *
- * Note that the additional segments have the same structure, but only
- * the handle array is used.
- */
-struct _WapiHandleShared_list
+struct _WapiHandleShared
{
- guchar daemon[MONO_SIZEOF_SUNPATH];
- _wapi_daemon_status daemon_running;
- guint32 fd_offset_table_size;
+ WapiHandleType type;
+ gboolean stale;
-#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- mono_mutex_t signal_mutex;
- pthread_cond_t signal_cond;
-#endif
-
- /* This holds the number of segments */
- guint32 num_segments;
- struct _WapiHandleShared handles[_WAPI_HANDLES_PER_SEGMENT];
+ union
+ {
+ struct _WapiHandle_thread thread;
+ struct _WapiHandle_process process;
+ struct _WapiHandle_namedmutex namedmutex;
+ } u;
};
-struct _WapiHandlePrivate
+struct _WapiHandleSharedLayout
{
- WapiHandleType type;
+ guint32 master;
+ guint32 namespace_check;
+ volatile guint32 signal_count;
+ volatile guint32 collection_signal_done;
+ volatile guint32 collection_count;
+
+ struct _WapiHandleSharedMetadata metadata[_WAPI_HANDLE_INITIAL_COUNT];
+ struct _WapiHandleShared handles[_WAPI_HANDLE_INITIAL_COUNT];
+};
- union
- {
- struct _WapiHandlePrivate_event event;
- struct _WapiHandlePrivate_file file;
- struct _WapiHandlePrivate_find find;
- struct _WapiHandlePrivate_mutex mutex;
- struct _WapiHandlePrivate_sem sem;
- struct _WapiHandlePrivate_socket sock;
- struct _WapiHandlePrivate_thread thread;
- struct _WapiHandlePrivate_process process;
- } u;
+#define _WAPI_FILESHARE_SIZE 102400
+
+struct _WapiFileShare
+{
+ dev_t device;
+ ino_t inode;
+ guint32 sharemode;
+ guint32 access;
+ guint32 handle_refs;
};
-/* Per-process handle info. For lookup convenience, each segment and
- * index matches the corresponding shared data.
- *
- * Note that the additional segments have the same structure, but only
- * the handle array is used.
- */
-struct _WapiHandlePrivate_list
+struct _WapiFileShareLayout
{
-#if !defined(_POSIX_THREAD_PROCESS_SHARED) || _POSIX_THREAD_PROCESS_SHARED == -1
- mono_mutex_t signal_mutex;
- pthread_cond_t signal_cond;
-#endif
+ guint32 share_check;
+ guint32 hwm;
- struct _WapiHandlePrivate handles[_WAPI_HANDLES_PER_SEGMENT];
+ struct _WapiFileShare share_info[_WAPI_FILESHARE_SIZE];
};
+
+#define _WAPI_HANDLE_INVALID (gpointer)-1
+
#endif /* _WAPI_PRIVATE_H_ */