where appropriate. * globals.cc: New file for generic global variables. * mkglobals_h: New file to generate globals.h. * mkstatic: New Script used to build a (currently non-working) static libcygwin_s.a. * Makefile.in: Add unused rule to build a non-working libcygwin_s.a. (DLL_OFILES): Add globals.o. Make all objects rely on globals.h. (globals.h): New target. Generate globals.h. * cygtls.h: Honor new CYGTLS_HANDLE define to control when the HANDLE operator is allowed in _cygtls. * dcrt0.cc: Move most globals to globals.cc. * init.cc: Ditto. * environ.cc (strip_title_path): Remove now-unneeded extern. * fhandler_serial.cc (fhandler_serial::open): Ditto. * pinfo.cc: Ditto. (commune_process): Ditto. * shared.cc: Ditto. * glob.cc: Ditto. * strace.cc: Ditto. * exceptions.cc: Define CYGTLS_HANDLE before including winsup.h. * path.cc (stat_suffixes): Move here. * security.h: Add forward class path_conv declaration. * smallprint.cc (__small_vsprintf): Make a true c++ function. (__small_sprintf): Ditto. (small_printf): Ditto. (console_printf): Ditto. (__small_vswprintf): Ditto. (__small_swprintf): Ditto. * spawn.cc (spawn_guts): Remove _stdcall decoration in favor of regparm. (hExeced): Move to globals.cc * strfuncs.cc (current_codepage): Ditto. (active_codepage): Ditto. * sync.cc (lock_process::locker): Move here from dcrt0.cc. * syscalls.cc (stat_suffixes): Move to path.cc. * tty.cc (tty::create_master): Uncapitalize fatal warning for consistency. * winsup.h: Include globals.h to declare most of the grab bag list of globals which were previously defined here. * mount.h: Move USER_* defines back to shared_info.h. * speclib: Force temporary directory cleanup.
		
			
				
	
	
		
			152 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* sync.cc: Synchronization functions for cygwin.
 | 
						|
 | 
						|
   This file implements the methods for controlling the "muto" class
 | 
						|
   which is intended to operate similarly to a mutex but attempts to
 | 
						|
   avoid making expensive calls to the kernel.
 | 
						|
 | 
						|
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 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. */
 | 
						|
 | 
						|
#include "winsup.h"
 | 
						|
#include "miscfuncs.h"
 | 
						|
#include "sync.h"
 | 
						|
#include "thread.h"
 | 
						|
#include "cygtls.h"
 | 
						|
 | 
						|
#undef WaitForSingleObject
 | 
						|
 | 
						|
DWORD NO_COPY muto::exiting_thread;
 | 
						|
muto NO_COPY lock_process::locker;
 | 
						|
 | 
						|
void
 | 
						|
muto::grab ()
 | 
						|
{
 | 
						|
  tls = &_my_tls;
 | 
						|
}
 | 
						|
 | 
						|
/* Constructor */
 | 
						|
muto *
 | 
						|
muto::init (const char *s)
 | 
						|
{
 | 
						|
  char *already_exists = (char *) InterlockedExchangePointer (&name, s);
 | 
						|
  if (already_exists)
 | 
						|
    while (!bruteforce)
 | 
						|
      low_priority_sleep (0);
 | 
						|
  else
 | 
						|
    {
 | 
						|
      waiters = -1;
 | 
						|
      /* Create event which is used in the fallback case when blocking is necessary */
 | 
						|
      bruteforce = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
 | 
						|
      if (!bruteforce)
 | 
						|
	  api_fatal ("couldn't allocate muto '%s', %E", s);
 | 
						|
    }
 | 
						|
 | 
						|
  return this;
 | 
						|
}
 | 
						|
 | 
						|
#if 0 /* FIXME: Do we need this? mutos aren't destroyed until process exit */
 | 
						|
/* Destructor (racy?) */
 | 
						|
muto::~muto ()
 | 
						|
{
 | 
						|
  while (visits)
 | 
						|
    release ();
 | 
						|
 | 
						|
  HANDLE h = bruteforce;
 | 
						|
  bruteforce = NULL;
 | 
						|
  /* Just need to close the event handle */
 | 
						|
  if (h)
 | 
						|
    CloseHandle (h);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Acquire the lock.  Argument is the number of milliseconds to wait for
 | 
						|
   the lock.  Multiple visits from the same thread are allowed and should
 | 
						|
   be handled correctly.
 | 
						|
 | 
						|
   Note: The goal here is to minimize, as much as possible, calls to the
 | 
						|
   OS.  Hence the use of InterlockedIncrement, etc., rather than (much) more
 | 
						|
   expensive OS mutexes.  Also note that the only two valid "ms" times are
 | 
						|
   0 and INFINITE. */
 | 
						|
int
 | 
						|
muto::acquire (DWORD ms)
 | 
						|
{
 | 
						|
  void *this_tls = &_my_tls;
 | 
						|
#if 0
 | 
						|
  if (exiting_thread)
 | 
						|
    return this_tid == exiting_thread;
 | 
						|
#endif
 | 
						|
 | 
						|
  if (tls != this_tls)
 | 
						|
    {
 | 
						|
      /* Increment the waiters part of the class.  Need to do this first to
 | 
						|
	 avoid potential races. */
 | 
						|
      LONG was_waiting = ms ? InterlockedIncrement (&waiters) : 0;
 | 
						|
 | 
						|
      while (was_waiting || InterlockedExchange (&sync, 1) != 0)
 | 
						|
	switch (WaitForSingleObject (bruteforce, ms))
 | 
						|
	    {
 | 
						|
	    case WAIT_OBJECT_0:
 | 
						|
	      was_waiting = 0;
 | 
						|
	      break;
 | 
						|
	    default:
 | 
						|
	      return 0;	/* failed. */
 | 
						|
	    }
 | 
						|
 | 
						|
      /* Have to do it this way to avoid a race */
 | 
						|
      if (!ms)
 | 
						|
	InterlockedIncrement (&waiters);
 | 
						|
 | 
						|
      tls = this_tls;	/* register this thread. */
 | 
						|
    }
 | 
						|
 | 
						|
  return ++visits;	/* Increment visit count. */
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
muto::acquired ()
 | 
						|
{
 | 
						|
  return tls == &_my_tls;
 | 
						|
}
 | 
						|
 | 
						|
/* Return the muto lock.  Needs to be called once per every acquire. */
 | 
						|
int
 | 
						|
muto::release ()
 | 
						|
{
 | 
						|
  void *this_tls = &_my_tls;
 | 
						|
 | 
						|
  if (tls != this_tls || !visits)
 | 
						|
    {
 | 
						|
      SetLastError (ERROR_NOT_OWNER);	/* Didn't have the lock. */
 | 
						|
      return 0;	/* failed. */
 | 
						|
    }
 | 
						|
 | 
						|
  /* FIXME: Need to check that other thread has not exited, too. */
 | 
						|
  if (!--visits)
 | 
						|
    {
 | 
						|
      tls = 0;		/* We were the last unlocker. */
 | 
						|
      InterlockedExchange (&sync, 0); /* Reset trigger. */
 | 
						|
      /* This thread had incremented waiters but had never decremented it.
 | 
						|
	 Decrement it now.  If it is >= 0 then there are possibly other
 | 
						|
	 threads waiting for the lock, so trigger bruteforce.  */
 | 
						|
      if (InterlockedDecrement (&waiters) >= 0)
 | 
						|
	SetEvent (bruteforce); /* Wake up one of the waiting threads */
 | 
						|
      else if (*name == '!')
 | 
						|
	{
 | 
						|
	  CloseHandle (bruteforce);	/* If *name == '!' and there are no
 | 
						|
					   other waiters, then this is the
 | 
						|
					   last time this muto will ever be
 | 
						|
					   used, so close the handle. */
 | 
						|
#ifdef DEBUGGING
 | 
						|
	  bruteforce = NULL;
 | 
						|
#endif
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  return 1;	/* success. */
 | 
						|
}
 |