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