newlib-cygwin/winsup/cygserver/bsd_mutex.cc

254 lines
6.9 KiB
C++
Raw Normal View History

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.
2003-11-20 02:49:41 +08:00
/* 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__ */