Home | History | Annotate | Download | only in pthreads-win32
      1 /*
      2  * ptw32_throw.c
      3  *
      4  * Description:
      5  * This translation unit implements routines which are private to
      6  * the implementation and may be used throughout it.
      7  *
      8  * --------------------------------------------------------------------------
      9  *
     10  *      Pthreads-win32 - POSIX Threads Library for Win32
     11  *      Copyright(C) 1998 John E. Bossom
     12  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
     13  *
     14  *      Contact Email: rpj (at) callisto.canberra.edu.au
     15  *
     16  *      The current list of contributors is contained
     17  *      in the file CONTRIBUTORS included with the source
     18  *      code distribution. The list can also be seen at the
     19  *      following World Wide Web location:
     20  *      http://sources.redhat.com/pthreads-win32/contributors.html
     21  *
     22  *      This library is free software; you can redistribute it and/or
     23  *      modify it under the terms of the GNU Lesser General Public
     24  *      License as published by the Free Software Foundation; either
     25  *      version 2 of the License, or (at your option) any later version.
     26  *
     27  *      This library is distributed in the hope that it will be useful,
     28  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
     29  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     30  *      Lesser General Public License for more details.
     31  *
     32  *      You should have received a copy of the GNU Lesser General Public
     33  *      License along with this library in the file COPYING.LIB;
     34  *      if not, write to the Free Software Foundation, Inc.,
     35  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
     36  */
     37 
     38 #include "pthread.h"
     39 #include "implement.h"
     40 
     41 #if defined(__CLEANUP_C)
     42 # include <setjmp.h>
     43 #endif
     44 
     45 /*
     46  * ptw32_throw
     47  *
     48  * All canceled and explicitly exited POSIX threads go through
     49  * here. This routine knows how to exit both POSIX initiated threads and
     50  * 'implicit' POSIX threads for each of the possible language modes (C,
     51  * C++, and SEH).
     52  */
     53 #if defined(_MSC_VER)
     54 /*
     55  * Ignore the warning:
     56  * "C++ exception specification ignored except to indicate that
     57  * the function is not __declspec(nothrow)."
     58  */
     59 #pragma warning(disable:4290)
     60 #endif
     61 void
     62 ptw32_throw (DWORD exception)
     63 #if defined(__CLEANUP_CXX)
     64   throw(ptw32_exception_cancel,ptw32_exception_exit)
     65 #endif
     66 {
     67   /*
     68    * Don't use pthread_self() to avoid creating an implicit POSIX thread handle
     69    * unnecessarily.
     70    */
     71   ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);
     72 
     73 #if defined(__CLEANUP_SEH)
     74   DWORD exceptionInformation[3];
     75 #endif
     76 
     77   sp->state = PThreadStateExiting;
     78 
     79   if (exception != PTW32_EPS_CANCEL && exception != PTW32_EPS_EXIT)
     80     {
     81       /* Should never enter here */
     82       exit (1);
     83     }
     84 
     85   if (NULL == sp || sp->implicit)
     86     {
     87       /*
     88        * We're inside a non-POSIX initialised Win32 thread
     89        * so there is no point to jump or throw back to. Just do an
     90        * explicit thread exit here after cleaning up POSIX
     91        * residue (i.e. cleanup handlers, POSIX thread handle etc).
     92        */
     93 #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
     94       unsigned exitCode = 0;
     95 
     96       switch (exception)
     97 	{
     98 	case PTW32_EPS_CANCEL:
     99 	  exitCode = (unsigned)(size_t) PTHREAD_CANCELED;
    100 	  break;
    101 	case PTW32_EPS_EXIT:
    102 	  if (NULL != sp)
    103 	    {
    104 	      exitCode = (unsigned)(size_t) sp->exitStatus;
    105 	    }
    106 	  break;
    107 	}
    108 #endif
    109 
    110 #if defined(PTW32_STATIC_LIB)
    111 
    112       pthread_win32_thread_detach_np ();
    113 
    114 #endif
    115 
    116 #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
    117       _endthreadex (exitCode);
    118 #else
    119       _endthread ();
    120 #endif
    121 
    122     }
    123 
    124 #if defined(__CLEANUP_SEH)
    125 
    126 
    127   exceptionInformation[0] = (DWORD) (exception);
    128   exceptionInformation[1] = (DWORD) (0);
    129   exceptionInformation[2] = (DWORD) (0);
    130 
    131   RaiseException (EXCEPTION_PTW32_SERVICES, 0, 3, exceptionInformation);
    132 
    133 #else /* __CLEANUP_SEH */
    134 
    135 #if defined(__CLEANUP_C)
    136 
    137   ptw32_pop_cleanup_all (1);
    138   longjmp (sp->start_mark, exception);
    139 
    140 #else /* __CLEANUP_C */
    141 
    142 #if defined(__CLEANUP_CXX)
    143 
    144   switch (exception)
    145     {
    146     case PTW32_EPS_CANCEL:
    147       throw ptw32_exception_cancel ();
    148       break;
    149     case PTW32_EPS_EXIT:
    150       throw ptw32_exception_exit ();
    151       break;
    152     }
    153 
    154 #else
    155 
    156 #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
    157 
    158 #endif /* __CLEANUP_CXX */
    159 
    160 #endif /* __CLEANUP_C */
    161 
    162 #endif /* __CLEANUP_SEH */
    163 
    164   /* Never reached */
    165 }
    166 
    167 
    168 void
    169 ptw32_pop_cleanup_all (int execute)
    170 {
    171   while (NULL != ptw32_pop_cleanup (execute))
    172     {
    173     }
    174 }
    175 
    176 
    177 DWORD
    178 ptw32_get_exception_services_code (void)
    179 {
    180 #if defined(__CLEANUP_SEH)
    181 
    182   return EXCEPTION_PTW32_SERVICES;
    183 
    184 #else
    185 
    186   return (DWORD)0;
    187 
    188 #endif
    189 }
    190