diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2003-11-19 18:49:41 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2003-11-19 18:49:41 +0000 |
commit | 282113ba894449ed17e85b296cf0760d5206ac8d (patch) | |
tree | 830bd7ad49e085ea8cde78fea68848fbbca09880 /winsup/cygserver/bsd_mutex.cc | |
parent | 64cfc6f213541f0e9e8e57011af8a56aca8c8216 (diff) | |
download | cygnal-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.cc | 253 |
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__ */ |