summaryrefslogtreecommitdiffstats
path: root/winsup/cygserver/bsd_mutex.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2003-11-19 18:49:41 +0000
committerCorinna Vinschen <corinna@vinschen.de>2003-11-19 18:49:41 +0000
commit282113ba894449ed17e85b296cf0760d5206ac8d (patch)
tree830bd7ad49e085ea8cde78fea68848fbbca09880 /winsup/cygserver/bsd_mutex.cc
parent64cfc6f213541f0e9e8e57011af8a56aca8c8216 (diff)
downloadcygnal-282113ba894449ed17e85b296cf0760d5206ac8d.tar.gz
cygnal-282113ba894449ed17e85b296cf0760d5206ac8d.tar.bz2
cygnal-282113ba894449ed17e85b296cf0760d5206ac8d.zip
Don't use safe_new but new throughout. Fix copyright dates
throughout. * Makefile.in: Accomodate all new files and name changes. Add a *.d dependency. (sbindir): Add. (etcdir): Drop in favor of more appropriate sysconfdir definition. (sysconfdir): Add. (CXXFLAGS): Add -MMD flag. Add SYSCONFDIR definition. (.SUFFIXES): Add. (install): Add action items. (libclean): New target. (fullclean): Ditto. * bsd_helper.cc: New file. * bsd_helper.h: Ditto. * bsd_log.cc: Ditto. * bsd_log.h: Ditto. * bsd_mutex.cc: Ditto. * bsd_mutex.h: Ditto. * client.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. (client_request::handle_request): Add Message Queue and Semaphore handling. * cygserver.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. Use new debug/log/panic logging functions. (DEF_CONFIG_FILE): New definition for configuration file. Use throughout. (getfunc): Remove. (__cygserver__printf): Remove. (client_request_attach_tty::serve): Return error if impersonation fails. (print_usage): Pump up help message. (print_version): Add output of default configuration file. (main): Accommodate new options. Allow overwrite of threading options from config file. Call several new initialization functions. Drop printing dots. Don't define SIGHANDLE inline. * cygserver.conf: New file. * cygserver_process.h: Rename to process.h. * cygserver_transport.h: Rename to transport.h. * cygserver_transport_pipes.h: Rename to transport_pipes.h. * cygserver_transport_sockets.h: Rename to transport_sockets.h. * msg.cc: Rewrite. * sem.cc: Rewrite. * shm.cc: Rewrite. * sysv_msg.cc: New file, derived from FreeBSD version 1.52. * sysv_sem.cc: New file, derived from FreeBSD version 1.66. * sysv_shm.cc: New file, derived from FreeBSD version 1.89. * threaded_queue.cc: Rearrange to build as less as possible if __INSIDE_CYGWIN__. * transport.cc (transport_layer_base::impersonate_client): Define bool. (transport_layer_base::revert_to_self): Ditto. * transport.h (transport_layer_base::impersonate_client): Declare bool. (transport_layer_base::revert_to_self): Ditto. * transport_pipes.cc (transport_layer_pipes::transport_layer_pipes): Don't call init_security. (init_security): Remove. (transport_layer_pipes::accept): Use global sec_all_nih. (transport_layer_pipes::connect): Ditto. (transport_layer_pipes::impersonate_client): Define bool. (transport_layer_pipes::revert_to_self): Ditt. * transport_pipes.h (transport_layer_pipes::impersonate_client): Declare bool. (transport_layer_pipes::revert_to_self): Ditto. * woutsup.h: Include bsd compatibility headers. (SIGHANDLE): Add definition. (__cygserver__printf): Remove definition. (__noop_printf): Ditto. (debug_printf): Define using debug. (syscall_printf): Define using log. (system_printf): Ditto. Drop all other _printf definitions.
Diffstat (limited to 'winsup/cygserver/bsd_mutex.cc')
-rw-r--r--winsup/cygserver/bsd_mutex.cc253
1 files changed, 253 insertions, 0 deletions
diff --git a/winsup/cygserver/bsd_mutex.cc b/winsup/cygserver/bsd_mutex.cc
new file mode 100644
index 000000000..9c7485b7f
--- /dev/null
+++ b/winsup/cygserver/bsd_mutex.cc
@@ -0,0 +1,253 @@
+/* bsd_mutex.cc
+
+ Copyright 2003 Red Hat Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+#ifdef __OUTSIDE_CYGWIN__
+#include "woutsup.h"
+#include "cygerrno.h"
+#define _KERNEL 1
+#define __BSD_VISIBLE 1
+#include <sys/smallprint.h>
+
+#include "process.h"
+#include "cygserver_ipc.h"
+
+/* A BSD kernel global mutex. */
+struct mtx Giant;
+
+void
+mtx_init (mtx *m, const char *name, const void *, int)
+{
+ m->name = name;
+ m->owner = 0;
+ /* Can't use Windows Mutexes here since Windows Mutexes are only
+ unlockable by the lock owner. */
+ m->h = CreateSemaphore (NULL, 1, 1, NULL);
+ if (!m->h)
+ panic ("couldn't allocate %s mutex, %E\n", name);
+}
+
+void
+_mtx_lock (mtx *m, DWORD winpid, const char *file, int line)
+{
+ _log (file, line, LOG_DEBUG, "Try locking mutex %s", m->name);
+ if (WaitForSingleObject (m->h, INFINITE) != WAIT_OBJECT_0)
+ _panic (file, line, "wait for %s in %d failed, %E", m->name, winpid);
+ m->owner = winpid;
+ _log (file, line, LOG_DEBUG, "Locked mutex %s", m->name);
+}
+
+int
+mtx_owned (mtx *m)
+{
+ return m->owner > 0;
+}
+
+void
+_mtx_assert(mtx *m, int what, const char *file, int line)
+{
+ switch (what)
+ {
+ case MA_OWNED:
+ if (!mtx_owned (m))
+ _panic(file, line, "Mutex %s not owned", m->name);
+ break;
+ case MA_NOTOWNED:
+ if (mtx_owned (m))
+ _panic(file, line, "Mutex %s is owned", m->name);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+_mtx_unlock (mtx *m, const char *file, int line)
+{
+ m->owner = 0;
+ /* Cautiously check if mtx_destroy has been called (shutdown).
+ In that case, m->h is NULL. */
+ if (m->h && !ReleaseSemaphore (m->h, 1, NULL))
+ {
+ /* Check if the semaphore was already on it's max value. In this case,
+ ReleaseSemaphore returns FALSE with an error code which *sic* depends
+ on the OS. */
+ if ( (!wincap.is_winnt () && GetLastError () != ERROR_INVALID_PARAMETER)
+ || (wincap.is_winnt () && GetLastError () != ERROR_TOO_MANY_POSTS))
+ _panic (file, line, "release of mutex %s failed, %E", m->name);
+ }
+ _log (file, line, LOG_DEBUG, "Unlocked mutex %s", m->name);
+}
+
+void
+mtx_destroy (mtx *m)
+{
+ HANDLE tmp = m->h;
+ m->h = NULL;
+ if (tmp)
+ CloseHandle (tmp);
+}
+
+/*
+ * Helper functions for msleep/wakeup.
+ */
+static char *
+msleep_event_name (void *ident, char *name)
+{
+ if (wincap.has_terminal_services ())
+ __small_sprintf (name, "Global\\cygserver.msleep.evt.%08x", ident);
+ else
+ __small_sprintf (name, "cygserver.msleep.evt.%08x", ident);
+ return name;
+}
+
+/*
+ * Original description from BSD code:
+ *
+ * General sleep call. Suspends the current process until a wakeup is
+ * performed on the specified identifier. The process will then be made
+ * runnable with the specified priority. Sleeps at most timo/hz seconds
+ * (0 means no timeout). If pri includes PCATCH flag, signals are checked
+ * before and after sleeping, else signals are not checked. Returns 0 if
+ * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
+ * signal needs to be delivered, ERESTART is returned if the current system
+ * call should be restarted if possible, and EINTR is returned if the system
+ * call should be interrupted by the signal (return EINTR).
+ *
+ * The mutex argument is exited before the caller is suspended, and
+ * entered before msleep returns. If priority includes the PDROP
+ * flag the mutex is not entered before returning.
+ */
+static HANDLE msleep_glob_evt;
+
+void
+msleep_init (void)
+{
+ msleep_glob_evt = CreateEvent (NULL, TRUE, FALSE, NULL);
+ if (!msleep_glob_evt)
+ panic ("CreateEvent in msleep_init failed: %E");
+}
+
+static int
+win_priority (int priority)
+{
+ int p = (int)((p) & PRIO_MASK) - PZERO;
+ /* Generating a valid priority value is a bit tricky. The only valid
+ values on 9x and NT4 are -15, -2, -1, 0, 1, 2, 15. */
+ switch (p)
+ {
+ case -15: case -14: case -13: case -12: case -11:
+ return THREAD_PRIORITY_IDLE;
+ case -10: case -9: case -8: case -7: case -6:
+ return THREAD_PRIORITY_LOWEST;
+ case -5: case -4: case -3: case -2: case -1:
+ return THREAD_PRIORITY_BELOW_NORMAL;
+ case 0:
+ return THREAD_PRIORITY_NORMAL;
+ case 1: case 2: case 3: case 4: case 5:
+ return THREAD_PRIORITY_ABOVE_NORMAL;
+ case 6: case 7: case 8: case 9: case 10:
+ return THREAD_PRIORITY_HIGHEST;
+ case 11: case 12: case 13: case 14: case 15:
+ return THREAD_PRIORITY_TIME_CRITICAL;
+ }
+ return THREAD_PRIORITY_NORMAL;
+}
+
+/*
+ * Sets the thread priority, returns the old priority.
+ */
+static int
+set_priority (int priority)
+{
+ int old_prio = GetThreadPriority (GetCurrentThread ());
+ if (!SetThreadPriority (GetCurrentThread (), win_priority(priority)))
+ log (LOG_WARNING,
+ "Warning: Setting thread priority to %d failed with error %lu\n",
+ win_priority(priority), GetLastError ());
+ return old_prio;
+}
+
+int
+_msleep (void *ident, struct mtx *mtx, int priority,
+ const char *wmesg, int timo, struct thread *td)
+{
+ int ret = -1;
+ char name[64];
+ msleep_event_name (ident, name);
+ HANDLE evt = OpenEvent (EVENT_ALL_ACCESS, FALSE, name);
+ if (!evt)
+ evt = CreateEvent (NULL, TRUE, FALSE, name);
+ if (!evt)
+ panic ("CreateEvent in msleep (%s) failed: %E", wmesg);
+ if (mtx)
+ mtx_unlock (mtx);
+ int old_priority = set_priority (priority);
+ /* PCATCH can't be handled here. */
+ HANDLE obj[3] = { evt, td->client->handle (), msleep_glob_evt };
+ switch (WaitForMultipleObjects (3, obj, FALSE, timo ?: INFINITE))
+ {
+ case WAIT_OBJECT_0: /* wakeup() has been called. */
+ ret = 0;
+ break;
+ case WAIT_OBJECT_0 + 2: /* Shutdown event (triggered by wakeup_all). */
+ priority |= PDROP;
+ /*FALLTHRU*/
+ case WAIT_OBJECT_0 + 1: /* The dependent process has exited. */
+ ret = EIDRM;
+ break;
+ case WAIT_TIMEOUT:
+ ret = EWOULDBLOCK;
+ break;
+ default:
+ panic ("wait in msleep (%s) failed, %E", wmesg);
+ break;
+ }
+ set_priority (old_priority);
+ if (!(priority & PDROP) && mtx)
+ mtx_lock (mtx);
+ CloseHandle (evt);
+ return ret;
+}
+
+/*
+ * Make all threads sleeping on the specified identifier runnable.
+ */
+int
+wakeup (void *ident)
+{
+ char name[64];
+ msleep_event_name (ident, name);
+ HANDLE evt = OpenEvent (EVENT_MODIFY_STATE, FALSE, name);
+ if (!evt)
+ {
+ /* Another round of different error codes returned by 9x and NT
+ systems. Oh boy... */
+ if ( (!wincap.is_winnt () && GetLastError () != ERROR_INVALID_NAME)
+ || (wincap.is_winnt () && GetLastError () != ERROR_FILE_NOT_FOUND))
+ panic ("OpenEvent (%s) in wakeup failed: %E", name);
+ }
+ if (evt)
+ {
+ if (!SetEvent (evt))
+ panic ("SetEvent (%s) in wakeup failed, %E", name);
+ CloseHandle (evt);
+ }
+ return 0;
+}
+
+/*
+ * Wakeup all sleeping threads. Only called in the context of cygserver
+ * shutdown.
+ */
+void
+wakeup_all (void)
+{
+ SetEvent (msleep_glob_evt);
+}
+#endif /* __OUTSIDE_CYGWIN__ */