Daemon-less io-layer code dump.
authorDick Porter <dick@acm.org>
Mon, 31 Jan 2005 14:25:32 +0000 (14:25 -0000)
committerDick Porter <dick@acm.org>
Mon, 31 Jan 2005 14:25:32 +0000 (14:25 -0000)
svn path=/branches/dick/io-layer-no-daemon/; revision=39846

30 files changed:
mono/io-layer/Makefile.am
mono/io-layer/atomic.c
mono/io-layer/collection.c [new file with mode: 0644]
mono/io-layer/collection.h [new file with mode: 0644]
mono/io-layer/critical-sections.c
mono/io-layer/error.c
mono/io-layer/event-private.h
mono/io-layer/events.c
mono/io-layer/handles-private.h
mono/io-layer/handles.c
mono/io-layer/io-private.h
mono/io-layer/io.c
mono/io-layer/misc-private.h
mono/io-layer/misc.c
mono/io-layer/mutex-private.h
mono/io-layer/mutexes.c
mono/io-layer/process-private.h
mono/io-layer/processes.c
mono/io-layer/semaphore-private.h
mono/io-layer/semaphores.c
mono/io-layer/shared.c
mono/io-layer/shared.h
mono/io-layer/socket-private.h
mono/io-layer/sockets.c
mono/io-layer/thread-private.h
mono/io-layer/threads.c
mono/io-layer/timed-thread.c
mono/io-layer/timefuncs.c
mono/io-layer/wait.c
mono/io-layer/wapi-private.h

index a9625478458f685eb8e84b990d9e4dde97a8d056..2dd273cd5b37b67728cb6ec3bb49b45cafeb636b 100644 (file)
@@ -1,6 +1,7 @@
 noinst_LTLIBRARIES = libwapi.la
 
 INCLUDES = \
+       -Werror                 \
        $(GLIB_CFLAGS)          \
        $(GMODULE_CFLAGS)       \
        $(LIBGC_CFLAGS)         \
@@ -12,6 +13,7 @@ libwapiincludedir = $(includedir)/mono/io-layer
 OTHER_H = \
        access.h        \
        atomic.h        \
+       collection.h    \
        context.h       \
        critical-sections.h     \
        error.h         \
@@ -40,14 +42,12 @@ OTHER_SRC = \
        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                \
index 1721edadea1c452cfe5fcdc790bccc95c7164779..8a7bebea1a8cf1ab95773bbcde73c115f27c9a1c 100644 (file)
@@ -25,7 +25,7 @@ static mono_once_t spin_once=MONO_ONCE_INIT;
 
 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,
diff --git a/mono/io-layer/collection.c b/mono/io-layer/collection.c
new file mode 100644 (file)
index 0000000..19c56ee
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * 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
+}
diff --git a/mono/io-layer/collection.h b/mono/io-layer/collection.h
new file mode 100644 (file)
index 0000000..5cccdf7
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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_ */
index 7f8553ce5285a829d61cfde7bd934a26c69ffe31..457338839f1f40ef7e5d205a2ef76c16ff29177c 100644 (file)
@@ -149,8 +149,8 @@ void EnterCriticalSection(WapiCriticalSection *section)
        int stat;
 
        if ((stat = mono_mutex_lock(&section->mutex)) != 0) {
-               g_error (G_GNUC_PRETTY_FUNCTION
-                        ": EnterCriticalSection failed: %s", g_strerror(stat));
+               g_error ("%s: EnterCriticalSection failed: %s", __func__,
+                        g_strerror(stat));
        }
 }
 
index 7785fb0e55ccf1495dac12d77d57d15906b977fd..e891246356308f3703da3964aa43188ed00e5990 100644 (file)
@@ -120,7 +120,7 @@ errno_to_WSA (guint32 code, const gchar *function_name)
                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);
index 2f7da3a8d8c3688cf6cd526f384c1c8e1a3ed85f..30ceb3cbae24ef209841c3f3fa2fa7470e60972f 100644 (file)
 
 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_ */
index c99175dd34224c2e8c9cae062487d8fdd5041036..555d2782cab550e8a8f644e59e73032ae7da38b1 100644 (file)
 
 #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)
@@ -44,44 +49,26 @@ 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) {
@@ -91,6 +78,8 @@ static void event_own (gpointer handle)
                        _wapi_handle_set_signal_state (handle, FALSE, FALSE);
                }
        }
+
+       return(TRUE);
 }
 
 /**
@@ -116,58 +105,46 @@ static void event_own (gpointer handle)
 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);
 }
 
 /**
@@ -192,10 +169,10 @@ gboolean PulseEvent(gpointer 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);
        }
        
@@ -205,7 +182,7 @@ gboolean PulseEvent(gpointer handle)
        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) {
@@ -234,8 +211,8 @@ gboolean PulseEvent(gpointer handle)
                 * 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);
@@ -268,16 +245,15 @@ gboolean ResetEvent(gpointer 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,
@@ -287,13 +263,13 @@ gboolean ResetEvent(gpointer 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);
@@ -330,10 +306,10 @@ gboolean SetEvent(gpointer 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);
        }
        
@@ -343,7 +319,7 @@ gboolean SetEvent(gpointer handle)
        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) {
index ad03546705c6c7c84a8b89b1827481cc64f850b4..befdb7465369ddb0a6b4fc04eea6c3b380be3d30 100644 (file)
 
 #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,
@@ -73,6 +72,8 @@ extern void _wapi_handle_unlock_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);
@@ -92,374 +93,262 @@ extern 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);
-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_ */
index a1c3dde13efd889a11789b6069411d2e8b706dbb..b6bf47b208d9cac8e25fe4d352f3a17ac34b6d92 100644 (file)
@@ -17,6 +17,8 @@
 #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]={
@@ -59,1143 +46,845 @@ 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,
@@ -1207,118 +896,66 @@ 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);
@@ -1338,10 +975,6 @@ gboolean _wapi_handle_ops_isowned (gpointer handle)
  */
 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);
        }
@@ -1360,42 +993,63 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
        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);
                        }
 
@@ -1405,56 +1059,51 @@ again:
                         */
                        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;
@@ -1463,19 +1112,18 @@ again:
        }
        
 #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;
@@ -1489,171 +1137,211 @@ void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
        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,
@@ -1665,6 +1353,7 @@ 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;
@@ -1683,9 +1372,9 @@ gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir,
        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 */
@@ -1731,18 +1420,21 @@ gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir,
                        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;
@@ -1759,8 +1451,7 @@ _wapi_handle_process_kill (pid_t process, guint32 signo, gint *errnum)
        _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 ();
        }
@@ -1770,68 +1461,251 @@ _wapi_handle_process_kill (pid_t process, guint32 signo, gint *errnum)
                *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);
+               }
        }
 }
index 0fd2b4a7d4bec586e697c34a555b0913571306b9..fedf8f2c856dc009c703197999cb491af395b699 100644 (file)
 #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;
@@ -55,10 +49,9 @@ struct _WapiHandlePrivate_find
 };
 
 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_ */
index 636e9c8d53a075d9a16c19ab965e15b8c5b8d39b..1b65ccea4ec66c8e855a54da1f77e0c7025291ff 100644 (file)
@@ -45,8 +45,7 @@
 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,
@@ -69,15 +68,28 @@ static gboolean file_setfiletime(gpointer handle,
 
 /* 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,
@@ -90,25 +102,27 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
  * 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);
@@ -119,13 +133,17 @@ static gboolean pipe_write (gpointer handle, gconstpointer buffer,
 /* 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);
@@ -226,59 +244,29 @@ _wapi_set_last_error_from_errno (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)
@@ -323,54 +311,46 @@ static gboolean file_read(gpointer handle, gpointer buffer,
                          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);
@@ -387,13 +367,12 @@ static gboolean file_read(gpointer handle, gpointer buffer,
        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;
@@ -402,7 +381,7 @@ static gboolean file_read(gpointer handle, gpointer buffer,
        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;
@@ -447,21 +426,15 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                           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);
        }
@@ -470,54 +443,50 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                *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 ();
@@ -533,13 +502,12 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
        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;
@@ -548,7 +516,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
        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;
@@ -591,41 +559,34 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
 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 ();
@@ -639,32 +600,26 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
                         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);
@@ -683,8 +638,7 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
                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);
@@ -695,15 +649,14 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        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
@@ -712,23 +665,19 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 
 #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 ();
@@ -737,9 +686,9 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 
 #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
 
@@ -757,10 +706,8 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 #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);
@@ -769,31 +716,25 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 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);
@@ -806,12 +747,11 @@ static gboolean file_setendoffile(gpointer handle)
         * 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 ();
@@ -819,12 +759,11 @@ static gboolean file_setendoffile(gpointer handle)
        }
        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 ();
@@ -834,16 +773,13 @@ static gboolean file_setendoffile(gpointer handle)
        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 ();
@@ -855,15 +791,13 @@ static gboolean file_setendoffile(gpointer handle)
         * 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 ();
@@ -876,44 +810,37 @@ static gboolean file_setendoffile(gpointer handle)
 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 ();
@@ -934,8 +861,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
 #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);
@@ -946,43 +872,37 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
                                 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 ();
@@ -990,8 +910,7 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
        }
 
 #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
@@ -1014,9 +933,8 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
        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) {
@@ -1043,44 +961,35 @@ static gboolean file_setfiletime(gpointer handle,
                                 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);
@@ -1090,12 +999,11 @@ static gboolean file_setfiletime(gpointer 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);
@@ -1110,8 +1018,8 @@ static gboolean file_setfiletime(gpointer handle,
                 */
                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);
@@ -1130,8 +1038,8 @@ static gboolean file_setfiletime(gpointer handle,
                 */
                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);
@@ -1143,86 +1051,45 @@ static gboolean file_setfiletime(gpointer handle,
        }
 
 #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)
@@ -1235,21 +1102,15 @@ static gboolean console_read(gpointer handle, gpointer buffer,
                             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);
        }
@@ -1258,10 +1119,11 @@ static gboolean console_read(gpointer handle, gpointer buffer,
                *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);
@@ -1269,16 +1131,12 @@ static gboolean console_read(gpointer handle, gpointer buffer,
        }
        
        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
 
@@ -1298,21 +1156,15 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
                              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);
        }
@@ -1321,10 +1173,10 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
                *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);
@@ -1332,17 +1184,13 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
        }
        
        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 ();
@@ -1355,60 +1203,27 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
        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)
@@ -1421,21 +1236,15 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
                           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);
        }
@@ -1444,10 +1253,11 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
                *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);
@@ -1455,21 +1265,18 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
        }
        
 #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 ();
@@ -1477,7 +1284,7 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
        }
        
 #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) {
@@ -1492,21 +1299,15 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
                           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);
        }
@@ -1515,10 +1316,10 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
                *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);
@@ -1526,21 +1327,18 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
        }
        
 #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 ();
@@ -1569,7 +1367,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                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;
@@ -1592,7 +1390,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                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;
@@ -1617,8 +1415,7 @@ static guint32 convert_from_flags(int flags)
                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
        }
 
@@ -1627,6 +1424,7 @@ static guint32 convert_from_flags(int flags)
        return(fileaccess);
 }
 
+#if 0 /* unused */
 static mode_t convert_perms(guint32 sharemode)
 {
        mode_t perms=0600;
@@ -1640,7 +1438,102 @@ static mode_t convert_perms(guint32 sharemode)
 
        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:
@@ -1672,10 +1565,8 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                    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
@@ -1685,28 +1576,23 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        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);
@@ -1714,7 +1600,8 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        }
        
 #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);
@@ -1735,8 +1622,8 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        
        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);
@@ -1744,9 +1631,9 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                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);
@@ -1760,7 +1647,8 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        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);
@@ -1769,116 +1657,54 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                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);
 }
 
 /**
@@ -1897,7 +1723,7 @@ gboolean DeleteFile(const gunichar2 *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);
@@ -1907,8 +1733,7 @@ gboolean DeleteFile(const gunichar2 *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);
@@ -1948,7 +1773,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -1958,7 +1783,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -1967,7 +1792,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -1978,7 +1803,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -2053,7 +1878,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -2063,7 +1888,8 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_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);
@@ -2072,7 +1898,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_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_src);
@@ -2083,7 +1909,8 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        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);
@@ -2167,7 +1994,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
 
                                _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);
@@ -2197,84 +2024,52 @@ static gpointer stderr_handle=INVALID_HANDLE_VALUE;
 
 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)
@@ -2316,8 +2111,7 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
 
        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);
@@ -2330,7 +2124,7 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
        }
        
        /* Add a reference to this handle */
-       _wapi_handle_ref (_wapi_handle_fd_offset_to_handle (handle));
+       _wapi_handle_ref (handle);
        
        return(handle);
 }
@@ -2362,17 +2156,11 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
  * 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) {
@@ -2409,17 +2197,11 @@ gboolean ReadFile(gpointer fd_handle, gpointer buffer, guint32 numbytes,
  *
  * 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) {
@@ -2441,16 +2223,10 @@ gboolean WriteFile(gpointer fd_handle, gconstpointer buffer, guint32 numbytes,
  *
  * 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) {
@@ -2471,19 +2247,13 @@ gboolean FlushFileBuffers(gpointer fd_handle)
  *
  * 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);
        }
@@ -2520,20 +2290,14 @@ gboolean SetEndOfFile(gpointer fd_handle)
  * 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);
        }
@@ -2553,19 +2317,13 @@ guint32 SetFilePointer(gpointer fd_handle, gint32 movedistance,
  * %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);
        }
@@ -2589,19 +2347,13 @@ WapiFileType GetFileType(gpointer fd_handle)
  * @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);
        }
@@ -2634,20 +2386,14 @@ guint32 GetFileSize(gpointer fd_handle, guint32 *highsize)
  *
  * 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);
        }
@@ -2679,21 +2425,15 @@ gboolean GetFileTime(gpointer fd_handle, WapiFileTime *create_time,
  *
  * 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);
        }
@@ -2738,7 +2478,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        
        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);
@@ -2754,7 +2494,7 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
         */
        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);
@@ -2764,42 +2504,39 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        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
@@ -2814,11 +2551,10 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                /* 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
                
@@ -2827,18 +2563,17 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                              + 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)];
@@ -2848,17 +2583,17 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        }
        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);
@@ -3038,17 +2773,14 @@ mono_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
 
 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);
@@ -3058,7 +2790,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        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);
@@ -3066,13 +2798,12 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        }
 
 #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
@@ -3087,37 +2818,6 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
                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.
         *
@@ -3139,8 +2839,8 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
         * 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
@@ -3148,56 +2848,51 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 #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;
@@ -3208,11 +2903,11 @@ gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
        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);
        }
@@ -3233,7 +2928,7 @@ retry:
        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);
@@ -3252,8 +2947,8 @@ retry:
                }
        }
        
-       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.
@@ -3264,7 +2959,7 @@ retry:
        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 */
@@ -3283,8 +2978,7 @@ retry:
        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;
        }
@@ -3337,15 +3031,15 @@ cleanup:
  */
 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);
        }
@@ -3377,7 +3071,8 @@ gboolean FindClose (gpointer handle)
  *
  * 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;
@@ -3386,7 +3081,7 @@ gboolean CreateDirectory (const gunichar2 *name, WapiSecurityAttributes *securit
        
        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);
@@ -3396,7 +3091,7 @@ gboolean CreateDirectory (const gunichar2 *name, WapiSecurityAttributes *securit
        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);
@@ -3449,7 +3144,7 @@ gboolean RemoveDirectory (const gunichar2 *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);
@@ -3459,7 +3154,7 @@ gboolean RemoveDirectory (const gunichar2 *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);
@@ -3492,7 +3187,7 @@ guint32 GetFileAttributes (const gunichar2 *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);
@@ -3502,7 +3197,7 @@ guint32 GetFileAttributes (const gunichar2 *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);
@@ -3542,7 +3237,8 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        
        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);
@@ -3551,7 +3247,7 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        
        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);
@@ -3561,7 +3257,7 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        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);
@@ -3626,7 +3322,7 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
        
        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);
@@ -3636,7 +3332,7 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
        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);
@@ -3754,79 +3450,26 @@ extern gboolean SetCurrentDirectory (const gunichar2 *path)
        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
                
@@ -3834,10 +3477,10 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
                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);
@@ -3850,10 +3493,11 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        
        /* 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);
@@ -3861,95 +3505,29 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
                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)
@@ -3974,9 +3552,8 @@ 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;
@@ -3998,34 +3575,25 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf)
 }
 
 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;
        }
@@ -4035,13 +3603,13 @@ _wapi_io_add_callback (gpointer fd_handle,
        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);
@@ -4148,7 +3716,7 @@ static gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length)
        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) {
@@ -4175,7 +3743,7 @@ static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length)
        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) {
@@ -4186,31 +3754,19 @@ static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length)
        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);
        }
@@ -4219,7 +3775,7 @@ gboolean LockFile (gpointer fd_handle, guint32 offset_low, guint32 offset_high,
            !(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);
@@ -4230,51 +3786,36 @@ gboolean LockFile (gpointer fd_handle, guint32 offset_low, guint32 offset_high,
        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);
        }
@@ -4283,7 +3824,7 @@ gboolean UnlockFile (gpointer fd_handle, guint32 offset_low,
            !(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);
@@ -4294,21 +3835,18 @@ gboolean UnlockFile (gpointer fd_handle, guint32 offset_low,
        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));
 }
index 2966d80b1769a187a4d3b6b146f99d9b1c12e7b3..00b209c4eb50895ef4fff7195dcbe8177025e944 100644 (file)
@@ -14,6 +14,5 @@
 #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_ */
index 382dc54c9f9ce5f67632a132158b759f4935ada7..82835cc52b937ac0598b8bdb4c66fed8d2bd9e9a 100644 (file)
@@ -28,15 +28,3 @@ void _wapi_calc_timeout(struct timespec *timeout, guint32 ms)
        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);
-}
index 41fe02a389107043d1787a79ed220d7a09ae4be2..ac6558a4985a0182cb1156937c8f4d85276669d5 100644 (file)
 #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);
index ee10921578aea85b51a46f531f01034c8ec1fef6..7655d034ceaf82edfdfc0e82cc8bdab4349ee462 100644 (file)
 
 #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)
@@ -94,21 +114,21 @@ 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);
@@ -118,11 +138,12 @@ static void mutex_own (gpointer handle)
        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)
@@ -131,32 +152,120 @@ 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);
@@ -177,10 +286,10 @@ static gboolean mutex_check (gpointer handle, gpointer user_data)
        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);
        }
 
@@ -192,8 +301,7 @@ static gboolean mutex_check (gpointer handle, gpointer user_data)
        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;
@@ -211,6 +319,47 @@ static gboolean mutex_check (gpointer handle, gpointer user_data)
        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)
 {
@@ -219,10 +368,163 @@ 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.
@@ -245,74 +547,30 @@ void _wapi_mutex_check_abandoned (pid_t pid, pthread_t tid)
 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,
@@ -320,75 +578,54 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
        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);
        }
 
@@ -398,13 +635,12 @@ gboolean ReleaseMutex(gpointer handle)
        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;
@@ -416,13 +652,12 @@ gboolean ReleaseMutex(gpointer handle)
        
        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:
@@ -432,3 +667,31 @@ 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));
+}
index dcd66815e9bf6e025db9bed2ecbb0a553c922527..ce2423d3432f4dcedcf2e141ce75862618e87a21 100644 (file)
@@ -24,14 +24,9 @@ struct _WapiHandle_process
        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_ */
index d9345cb5733a7272f13af959494244d020a1e9e6..c60bc6c73304e8bef7a9e0ce1c69818c41a6d295 100644 (file)
@@ -36,11 +36,8 @@ extern char **environ;
 
 #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 */
@@ -57,31 +54,6 @@ static void process_ops_init (void)
                                            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,
@@ -130,8 +102,8 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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);
@@ -150,8 +122,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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);
@@ -163,8 +134,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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);
@@ -180,7 +150,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
        } 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
@@ -220,12 +190,12 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                        }
                }
 
-               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 :-( */
@@ -248,7 +218,8 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                        /* 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);
@@ -323,8 +294,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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);
@@ -355,7 +325,8 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                        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);
@@ -382,7 +353,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                                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);
@@ -396,7 +367,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
        }
 
 #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
        
@@ -410,7 +381,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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;
@@ -437,8 +408,7 @@ gboolean CreateProcess (const gunichar2 *appname, gunichar2 *cmdline,
                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;
@@ -458,21 +428,21 @@ cleanup:
        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);
 }
@@ -485,16 +455,17 @@ static void process_set_name (struct _WapiHandle_process *process_handle)
        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);
@@ -505,86 +476,75 @@ extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
 
 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);
                }
        }
 }
@@ -605,11 +565,10 @@ guint32 GetCurrentProcessId (void)
        mono_once (&process_current_once, process_set_current);
                
        ok=_wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
-                               (gpointer *)&current_process_handle, NULL);
+                               (gpointer *)&current_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.
@@ -636,33 +595,33 @@ static gboolean process_enum (gpointer handle, gpointer user_data)
 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);
 }
@@ -674,10 +633,10 @@ static gboolean process_open_compare (gpointer handle, gpointer user_data)
        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);
        }
 
@@ -703,10 +662,10 @@ gpointer OpenProcess (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUS
        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 */
@@ -731,11 +690,10 @@ gboolean GetExitCodeProcess (gpointer process, guint32 *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);
@@ -767,11 +725,10 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
        }
        
        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);
@@ -824,9 +781,8 @@ guint32 GetModuleBaseName (gpointer process, gpointer module,
        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) {
@@ -834,11 +790,10 @@ guint32 GetModuleBaseName (gpointer process, gpointer module,
        }
        
        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);
@@ -850,49 +805,46 @@ guint32 GetModuleBaseName (gpointer process, gpointer module,
                 */
                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);
@@ -916,11 +868,10 @@ gboolean GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
        }
        
        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);
@@ -940,11 +891,10 @@ gboolean SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
        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);
@@ -966,12 +916,11 @@ TerminateProcess (gpointer process, gint32 exitCode)
        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;
index 97d8340d0a6c879df46cbee047f14c4589c6cae8..43fbe1b0525948c8fba4abd8fc5604574d9309b7 100644 (file)
@@ -15,6 +15,8 @@
 
 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
 {
@@ -22,9 +24,4 @@ struct _WapiHandle_sem
        gint32 max;
 };
 
-struct _WapiHandlePrivate_sem
-{
-       int dummy;
-};
-
 #endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */
index 4538064d168e9321bccf8dea1d10dd292524d283..c6bd0939807231b8c58d8a5d730fd51647d3bddf 100644 (file)
 
 #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)
@@ -47,46 +52,39 @@ 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);
 }
 
 
@@ -110,34 +108,37 @@ static void sema_own (gpointer handle)
  */
 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);
        }
 
@@ -146,34 +147,20 @@ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32
        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);
 }
 
 /**
@@ -196,10 +183,10 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
        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);
        }
 
@@ -209,8 +196,8 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
        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
@@ -223,8 +210,7 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
        /* 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;
@@ -236,8 +222,7 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
        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:
index b0e828a222107e17c6c5f2dbb2ccf9ed4dc79d7b..db4197dcfd3ceb43fd4b9f482bc713fd09c3a76f 100644 (file)
 #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;
@@ -79,26 +72,19 @@ guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment)
        /* 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);
 
@@ -109,136 +95,110 @@ guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment)
         * 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,
@@ -246,39 +206,34 @@ try_again:
                         * 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);
@@ -291,35 +246,39 @@ try_again:
        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);
@@ -329,206 +288,36 @@ gpointer _wapi_shm_file_map (_wapi_shm_t type, guint32 segment,
        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);
 }
-
index 55ac5d575a64d6646cfce8e518b9caa1ba3fd04e..91af59ae9b7c4938971642290008933b32d7ddb5 100644 (file)
 
 #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_ */
index 4da7f58d8ad60065eedcc1b0574b951e9cd23fd7..438db6f23cfbd03b6aed16f657e7e22ed5623478 100644 (file)
@@ -20,9 +20,4 @@ struct _WapiHandle_socket
        int dummy;
 };
 
-struct _WapiHandlePrivate_socket
-{
-       WapiFDMapped fd_mapped;
-};
-
 #endif /* _WAPI_SOCKET_PRIVATE_H_ */
index df7ac8a25dcc2ff43a15000c381f8fa9bd6e0b34..9afc50b529041c92b16acdea72024b23e884f605 100644 (file)
@@ -53,11 +53,10 @@ static GPtrArray *sockets=NULL;
 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 */
@@ -70,88 +69,65 @@ static void socket_ops_init (void)
        /* 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);
 }
@@ -161,24 +137,24 @@ int WSACleanup(void)
        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);
 }
@@ -187,7 +163,7 @@ static void error_init(void)
 {
        int ret;
        
-       ret = pthread_key_create(&error_key, NULL);
+       ret = pthread_key_create (&error_key, NULL);
        g_assert (ret == 0);
 }
 
@@ -195,8 +171,8 @@ void WSASetLastError(int error)
 {
        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);
 }
 
@@ -205,19 +181,18 @@ int WSAGetLastError(void)
        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);
        }
@@ -228,46 +203,40 @@ int closesocket(guint32 fd_handle)
 
 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);
@@ -277,72 +246,45 @@ guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
                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);
@@ -353,27 +295,25 @@ int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
 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
                 */
@@ -381,24 +321,24 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
                
                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);
@@ -408,29 +348,28 @@ int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
 
 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);
@@ -441,29 +380,28 @@ int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
 
 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);
@@ -475,29 +413,28 @@ int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
 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);
@@ -508,29 +445,27 @@ int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
 
 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);
@@ -541,7 +476,7 @@ int _wapi_listen(guint32 fd, int backlog)
 
 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,
@@ -550,43 +485,41 @@ 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);
@@ -599,41 +532,39 @@ int _wapi_send(guint32 fd, const void *msg, size_t len, int send_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=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);
@@ -647,41 +578,40 @@ int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_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=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);
@@ -692,29 +622,28 @@ int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
 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);
@@ -725,29 +654,28 @@ int _wapi_setsockopt(guint32 fd, int level, int optname,
 
 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);
@@ -756,17 +684,15 @@ int _wapi_shutdown(guint32 fd, int how)
        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);
        }
@@ -774,17 +700,17 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u
        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);
@@ -796,80 +722,55 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u
        
        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;
                }
        }
@@ -883,76 +784,76 @@ WSAIoctl (guint32 fd, gint32 command,
          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);
        }
 
@@ -960,29 +861,28 @@ int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
        /* 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);
@@ -996,23 +896,23 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
 {
        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);
@@ -1023,41 +923,38 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
 
 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
@@ -1092,13 +989,12 @@ async_notifier (union sigval sig)
 }
 
 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;
index 93a38f21d5249dfd1e77d8c296e686927bd40a9c..bae837eadce0a228af461b27dfa0dd0b15eee9a3 100644 (file)
@@ -26,18 +26,14 @@ struct _WapiHandle_thread
 {
        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_ */
index f464f0b94230e4f83d2dcb43c2636bb23e2aa0d9..a4d09dca219f98c0c6cd423e55ecb0bf86166ff4 100644 (file)
@@ -52,12 +52,10 @@ static GHashTable *thread_hash=NULL;
 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 */
@@ -79,92 +77,89 @@ static void thread_ops_init (void)
 #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 */
@@ -173,7 +168,7 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
        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);
@@ -185,7 +180,7 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
 
 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);
 }
 
 /**
@@ -208,58 +203,24 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
                      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>
@@ -272,10 +233,11 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
        /* 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
@@ -286,36 +248,65 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
        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
        }
 
@@ -324,18 +315,6 @@ thread_hash_cleanup:
        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);
 }
 
@@ -348,7 +327,7 @@ gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSE
        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,
@@ -367,7 +346,7 @@ gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSE
        }
        
 #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);
@@ -399,44 +378,31 @@ void ExitThread(guint32 exitcode)
  */
 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);
 }
@@ -451,7 +417,7 @@ gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
  */
 guint32 GetCurrentThreadId(void)
 {
-       pthread_t tid=pthread_self();
+       pthread_t tid = pthread_self();
        
 #ifdef PTHREAD_POINTER_ID
        return(GPOINTER_TO_UINT(tid));
@@ -462,45 +428,19 @@ guint32 GetCurrentThreadId(void)
 
 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()
@@ -510,35 +450,56 @@ static gpointer thread_attach(guint32 *tid)
        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
        }
 
@@ -547,18 +508,6 @@ thread_hash_cleanup:
        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);
 }
 
@@ -613,34 +562,21 @@ gpointer GetCurrentThread(void)
  */
 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
 }
@@ -657,31 +593,20 @@ guint32 ResumeThread(gpointer handle)
 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);
                                }
@@ -689,7 +614,7 @@ guint32 SuspendThread(gpointer handle)
                }
        }
 
-       return thread_private_handle->thread->suspend_count++;
+       return (WAPI_SHARED_HANDLE_DATA(handle, thread).thread->suspend_count++);
 #else
        return(0xFFFFFFFF);
 #endif
@@ -741,8 +666,7 @@ guint32 TlsAlloc(void)
                        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);
@@ -752,7 +676,7 @@ guint32 TlsAlloc(void)
        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
                        
        
@@ -775,7 +699,7 @@ gboolean TlsFree(guint32 idx)
        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);
@@ -814,13 +738,13 @@ gpointer TlsGetValue(guint32 idx)
        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);
@@ -840,15 +764,14 @@ gboolean TlsSetValue(guint32 idx, gpointer value)
        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);
@@ -859,8 +782,8 @@ gboolean TlsSetValue(guint32 idx, gpointer value)
        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);
@@ -898,7 +821,7 @@ guint32 SleepEx(guint32 ms, gboolean alertable)
        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) {
@@ -934,8 +857,7 @@ again:
 #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;
@@ -967,63 +889,23 @@ BindIoCompletionCallback (gpointer handle,
 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);
 }
 
@@ -1033,27 +915,16 @@ gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
 
 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)
@@ -1066,20 +937,7 @@ 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 */
index 6599e0660f307150c3d0359bd34fce0f7687a4b6..e4f7e276e3d9367ba34fd3635add7cdc3ec6fc82 100644 (file)
@@ -71,8 +71,7 @@ void _wapi_timed_thread_exit(guint32 exitstatus)
        /* 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
 
@@ -287,14 +286,14 @@ void _wapi_timed_thread_suspend (TimedThread *thread)
        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);
        }
 
index 06042ec140e2414421c5ed3d3195329ff2269565..57977b7d90aa7decc71c7dc0d6d12cb0b3d1eb58 100644 (file)
@@ -63,7 +63,7 @@ guint32 GetTickCount (void)
        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);
index a236d17ed3eadc232a66f4d047c45225ecadf463..26c7bb12cb8b8ac32e1c2bced0b042281e4a114b 100644 (file)
@@ -50,18 +50,18 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
        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,
@@ -69,15 +69,15 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
        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;
                }
        }
@@ -88,10 +88,10 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
                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);
@@ -100,16 +100,15 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
        }
 
        /* 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)
@@ -122,31 +121,36 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
                         */
                        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);
@@ -211,18 +215,18 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
        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,
@@ -232,14 +236,14 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
 
        _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;
                }
        }
@@ -252,8 +256,7 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
        
        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);
@@ -274,41 +277,47 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer 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);
@@ -345,7 +354,7 @@ static gboolean test_and_own (guint32 numobjects, gpointer *handles,
        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;
@@ -368,7 +377,7 @@ static gboolean test_and_own (guint32 numobjects, gpointer *handles,
        }
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
+       g_message ("%s: unlocking handles", __func__);
 #endif
 
        /* calls the unlock function */
@@ -410,10 +419,12 @@ static gboolean test_and_own (guint32 numobjects, gpointer *handles,
  * %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;
@@ -421,10 +432,9 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
        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);
@@ -435,53 +445,54 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
        }
 
        /* 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);
        }
        
@@ -499,21 +510,29 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
        
        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);
@@ -535,7 +554,8 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
                } 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) {
index 2a7203c693704f81f2022a24f4fa1f32adc4cc65..2ac614adbc323ef4674e01f54ec0df0b729999a7 100644 (file)
 #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
@@ -35,7 +25,7 @@
 /* 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,
@@ -49,28 +39,27 @@ typedef enum {
        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,
@@ -80,16 +69,16 @@ typedef enum {
 
 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
@@ -106,10 +95,17 @@ struct _WapiHandleOps
 #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;
@@ -125,90 +121,64 @@ struct _WapiHandleShared
                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_ */