* cygthread.h (cygthread::avail): Make LONG for easier use with Interlocked*
functions. * cygthread.cc (cygthread::init): Eliminate unneeded muto. (cygthread::operator new): Don't lock. Instead change use of avail variable into tri-state: available (1), not available (-1), uninitialized (0). (cygthread::terminate_thread): Set avail to uninitialized. (cygthread::detach): Eliminate local 'avail'. Always set avail to 1 unless signalled. * cygthread.cc (cygthread::operator new): Be more defensive when messing with
This commit is contained in:
		| @@ -1,6 +1,18 @@ | ||||
| 2003-04-04  Christopher Faylor  <cgf@redhat.com> | ||||
|  | ||||
| 	* cygthread.cc (operator new): Be more defensive when messing with | ||||
| 	* cygthread.h (cygthread::avail): Make LONG for easier use with | ||||
| 	Interlocked* functions. | ||||
| 	* cygthread.cc (cygthread::init): Eliminate unneeded muto. | ||||
| 	(cygthread::operator new): Don't lock.  Instead change use of avail | ||||
| 	variable into tri-state: available (1), not available (-1), | ||||
| 	uninitialized (0). | ||||
| 	(cygthread::terminate_thread): Set avail to uninitialized. | ||||
| 	(cygthread::detach): Eliminate local 'avail'.  Always set avail to 1 | ||||
| 	unless signalled. | ||||
|  | ||||
| 2003-04-04  Christopher Faylor  <cgf@redhat.com> | ||||
|  | ||||
| 	* cygthread.cc (cygthread::operator new): Be more defensive when messing with | ||||
| 	threads that are marked "unavailable". | ||||
|  | ||||
| 2003-04-03  Christopher Faylor  <cgf@redhat.com> | ||||
|   | ||||
| @@ -94,12 +94,10 @@ cygthread::simplestub (VOID *arg) | ||||
|   ExitThread (0); | ||||
| } | ||||
|  | ||||
| static NO_COPY muto *cygthread_protect; | ||||
| /* Start things going.  Called from dll_crt0_1. */ | ||||
| void | ||||
| cygthread::init () | ||||
| { | ||||
|   new_muto (cygthread_protect); | ||||
|   main_thread_id = GetCurrentThreadId (); | ||||
| } | ||||
|  | ||||
| @@ -129,30 +127,27 @@ cygthread::freerange () | ||||
| void * cygthread::operator | ||||
| new (size_t) | ||||
| { | ||||
|   DWORD id; | ||||
|   LONG is_avail; | ||||
|   cygthread *info; | ||||
|  | ||||
|   cygthread_protect->acquire (); | ||||
|  | ||||
|   /* Search the threads array for an empty slot to use */ | ||||
|   for (info = threads; info < threads + NTHREADS; info++) | ||||
|     if ((LONG) (id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, -1)) < 0) | ||||
|       /* being considered */; | ||||
|     else if (id > 0) | ||||
|     if ((is_avail = InterlockedExchange (&info->avail, -1)) < 0) | ||||
|       /* in use */; | ||||
|     else if (is_avail > 0) | ||||
|       { | ||||
| 	/* available */ | ||||
| #ifdef DEBUGGING | ||||
| 	if (info->__name) | ||||
| 	  api_fatal ("name not NULL? id %p, i %d", id, info - threads); | ||||
| 	  api_fatal ("name not NULL? id %p, i %d", info->id, info - threads); | ||||
| 	if (!info->h) | ||||
| 	  api_fatal ("h not set? id %p, i %d", id, info - threads); | ||||
| 	  api_fatal ("h not set? id %p, i %d", info->id, info - threads); | ||||
| #endif | ||||
| 	goto out; | ||||
|       } | ||||
|     else if (info->id) | ||||
|       InterlockedExchange ((LPLONG) &info->avail, 0);	/* Not available yet */ | ||||
|     else | ||||
|       { | ||||
| 	/* Available as soon as thread is created */ | ||||
| 	/* Uninitialized.  Available as soon as thread is created */ | ||||
| 	info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info, | ||||
| 				CREATE_SUSPENDED, &info->id); | ||||
| 	goto out; | ||||
| @@ -160,15 +155,13 @@ new (size_t) | ||||
|  | ||||
| #ifdef DEBUGGING | ||||
|   char buf[1024]; | ||||
|   if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) | ||||
|   if (!GetEnvironmentVariable ("CYGWIN_FREERANGE_NOCHECK", buf, sizeof (buf))) | ||||
|     api_fatal ("Overflowed cygwin thread pool"); | ||||
| #endif | ||||
|  | ||||
|   info = freerange ();	/* exhausted thread pool */ | ||||
|  | ||||
| out: | ||||
|   InterlockedExchange ((LPLONG) &info->avail, 0); | ||||
|   cygthread_protect->release (); | ||||
|   return info; | ||||
| } | ||||
|  | ||||
| @@ -270,21 +263,21 @@ cygthread::terminate_thread () | ||||
|   thread_sync = ev = h = NULL; | ||||
|   __name = NULL; | ||||
|   id = 0; | ||||
|   (void) InterlockedExchange (&avail, 0); /* No longer initialized */ | ||||
| } | ||||
|  | ||||
| /* Detach the cygthread from the current thread.  Note that the | ||||
|    theory is that cygthreads are only associated with one thread. | ||||
|    So, there should be no problems with multiple threads doing waits | ||||
|    on the one cygthread. */ | ||||
|    So, there should be never be multiple threads doing waits | ||||
|    on the same cygthread. */ | ||||
| bool | ||||
| cygthread::detach (HANDLE sigwait) | ||||
| { | ||||
|   bool signalled = false; | ||||
|   if (avail) | ||||
|     system_printf ("called detach on available thread %d?", avail); | ||||
|   if (avail >= 0) | ||||
|     system_printf ("called detach but avail %d, thread %d?", avail, id); | ||||
|   else | ||||
|     { | ||||
|       DWORD avail = id; | ||||
|       DWORD res; | ||||
|  | ||||
|       if (!sigwait) | ||||
| @@ -304,18 +297,17 @@ cygthread::detach (HANDLE sigwait) | ||||
| 	    res = WaitForSingleObject (*this, INFINITE); | ||||
| 	  else | ||||
| 	    { | ||||
| 	      signalled = true; | ||||
| 	      terminate_thread (); | ||||
| 	      set_sig_errno (EINTR);	/* caller should be dealing with return | ||||
| 					   values. */ | ||||
| 	      avail = 0; | ||||
| 	      signalled = true; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|       thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO", | ||||
| 		     res, id); | ||||
|  | ||||
|       if (!avail) | ||||
|       if (signalled) | ||||
| 	/* already handled */; | ||||
|       else if (is_freerange) | ||||
| 	{ | ||||
| @@ -325,8 +317,8 @@ cygthread::detach (HANDLE sigwait) | ||||
|       else | ||||
| 	{ | ||||
| 	  ResetEvent (*this); | ||||
| 	  /* Mark the thread as available by setting avail to non-zero */ | ||||
| 	  (void) InterlockedExchange ((LPLONG) &this->avail, avail); | ||||
| 	  /* Mark the thread as available by setting avail to positive value */ | ||||
| 	  (void) InterlockedExchange (&avail, 1); | ||||
| 	} | ||||
|     } | ||||
|   return signalled; | ||||
|   | ||||
| @@ -8,7 +8,7 @@ details. */ | ||||
|  | ||||
| class cygthread | ||||
| { | ||||
|   DWORD avail; | ||||
|   LONG avail;	/* 1: available, 0: ininitialized, -1: not available */ | ||||
|   DWORD id; | ||||
|   HANDLE h; | ||||
|   HANDLE ev; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user