From 282113ba894449ed17e85b296cf0760d5206ac8d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 19 Nov 2003 18:49:41 +0000 Subject: 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. --- winsup/cygserver/bsd_mutex.cc | 253 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 winsup/cygserver/bsd_mutex.cc (limited to 'winsup/cygserver/bsd_mutex.cc') 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 + +#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__ */ -- cgit v1.2.3