1*062c5bc4SJason Schmidlapp /* 2*062c5bc4SJason Schmidlapp * pte_threadStart.c 3*062c5bc4SJason Schmidlapp * 4*062c5bc4SJason Schmidlapp * Description: 5*062c5bc4SJason Schmidlapp * This translation unit implements routines which are private to 6*062c5bc4SJason Schmidlapp * the implementation and may be used throughout it. 7*062c5bc4SJason Schmidlapp * 8*062c5bc4SJason Schmidlapp * -------------------------------------------------------------------------- 9*062c5bc4SJason Schmidlapp * 10*062c5bc4SJason Schmidlapp * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems 11*062c5bc4SJason Schmidlapp * Copyright(C) 2008 Jason Schmidlapp 12*062c5bc4SJason Schmidlapp * 13*062c5bc4SJason Schmidlapp * Contact Email: jschmidlapp@users.sourceforge.net 14*062c5bc4SJason Schmidlapp * 15*062c5bc4SJason Schmidlapp * 16*062c5bc4SJason Schmidlapp * Based upon Pthreads-win32 - POSIX Threads Library for Win32 17*062c5bc4SJason Schmidlapp * Copyright(C) 1998 John E. Bossom 18*062c5bc4SJason Schmidlapp * Copyright(C) 1999,2005 Pthreads-win32 contributors 19*062c5bc4SJason Schmidlapp * 20*062c5bc4SJason Schmidlapp * Contact Email: rpj@callisto.canberra.edu.au 21*062c5bc4SJason Schmidlapp * 22*062c5bc4SJason Schmidlapp * The original list of contributors to the Pthreads-win32 project 23*062c5bc4SJason Schmidlapp * is contained in the file CONTRIBUTORS.ptw32 included with the 24*062c5bc4SJason Schmidlapp * source code distribution. The list can also be seen at the 25*062c5bc4SJason Schmidlapp * following World Wide Web location: 26*062c5bc4SJason Schmidlapp * http://sources.redhat.com/pthreads-win32/contributors.html 27*062c5bc4SJason Schmidlapp * 28*062c5bc4SJason Schmidlapp * This library is free software; you can redistribute it and/or 29*062c5bc4SJason Schmidlapp * modify it under the terms of the GNU Lesser General Public 30*062c5bc4SJason Schmidlapp * License as published by the Free Software Foundation; either 31*062c5bc4SJason Schmidlapp * version 2 of the License, or (at your option) any later version. 32*062c5bc4SJason Schmidlapp * 33*062c5bc4SJason Schmidlapp * This library is distributed in the hope that it will be useful, 34*062c5bc4SJason Schmidlapp * but WITHOUT ANY WARRANTY; without even the implied warranty of 35*062c5bc4SJason Schmidlapp * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 36*062c5bc4SJason Schmidlapp * Lesser General Public License for more details. 37*062c5bc4SJason Schmidlapp * 38*062c5bc4SJason Schmidlapp * You should have received a copy of the GNU Lesser General Public 39*062c5bc4SJason Schmidlapp * License along with this library in the file COPYING.LIB; 40*062c5bc4SJason Schmidlapp * if not, write to the Free Software Foundation, Inc., 41*062c5bc4SJason Schmidlapp * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 42*062c5bc4SJason Schmidlapp */ 43*062c5bc4SJason Schmidlapp 44*062c5bc4SJason Schmidlapp #include <stdio.h> 45*062c5bc4SJason Schmidlapp #include <stdlib.h> 46*062c5bc4SJason Schmidlapp 47*062c5bc4SJason Schmidlapp #include "pthread.h" 48*062c5bc4SJason Schmidlapp #include "implement.h" 49*062c5bc4SJason Schmidlapp 50*062c5bc4SJason Schmidlapp #if defined(PTE_CLEANUP_CXX) 51*062c5bc4SJason Schmidlapp 52*062c5bc4SJason Schmidlapp # if defined(__GNUC__) && __GNUC__ < 3 53*062c5bc4SJason Schmidlapp # include <new> 54*062c5bc4SJason Schmidlapp # else 55*062c5bc4SJason Schmidlapp # include <new> 56*062c5bc4SJason Schmidlapp using 57*062c5bc4SJason Schmidlapp std::terminate_handler; 58*062c5bc4SJason Schmidlapp using 59*062c5bc4SJason Schmidlapp std::terminate; 60*062c5bc4SJason Schmidlapp using 61*062c5bc4SJason Schmidlapp std::set_terminate; 62*062c5bc4SJason Schmidlapp # endif 63*062c5bc4SJason Schmidlapp 64*062c5bc4SJason Schmidlapp typedef terminate_handler terminate_function; 65*062c5bc4SJason Schmidlapp 66*062c5bc4SJason Schmidlapp static terminate_function pte_oldTerminate; 67*062c5bc4SJason Schmidlapp 68*062c5bc4SJason Schmidlapp void 69*062c5bc4SJason Schmidlapp pte_terminate () 70*062c5bc4SJason Schmidlapp { 71*062c5bc4SJason Schmidlapp set_terminate (pte_oldTerminate); 72*062c5bc4SJason Schmidlapp (void) pte_thread_detach_np(); 73*062c5bc4SJason Schmidlapp // terminate (); 74*062c5bc4SJason Schmidlapp } 75*062c5bc4SJason Schmidlapp 76*062c5bc4SJason Schmidlapp #endif 77*062c5bc4SJason Schmidlapp 78*062c5bc4SJason Schmidlapp int pte_threadStart (void *vthreadParms) 79*062c5bc4SJason Schmidlapp { 80*062c5bc4SJason Schmidlapp ThreadParms * threadParms = (ThreadParms *) vthreadParms; 81*062c5bc4SJason Schmidlapp pthread_t self; 82*062c5bc4SJason Schmidlapp pte_thread_t * sp; 83*062c5bc4SJason Schmidlapp void *(*start) (void *); 84*062c5bc4SJason Schmidlapp void * arg; 85*062c5bc4SJason Schmidlapp 86*062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_C 87*062c5bc4SJason Schmidlapp #include <setjmp.h> 88*062c5bc4SJason Schmidlapp 89*062c5bc4SJason Schmidlapp int setjmp_rc; 90*062c5bc4SJason Schmidlapp #endif 91*062c5bc4SJason Schmidlapp 92*062c5bc4SJason Schmidlapp void * status = (void *) 0; 93*062c5bc4SJason Schmidlapp 94*062c5bc4SJason Schmidlapp self = threadParms->tid; 95*062c5bc4SJason Schmidlapp sp = (pte_thread_t *) self.p; 96*062c5bc4SJason Schmidlapp start = threadParms->start; 97*062c5bc4SJason Schmidlapp arg = threadParms->arg; 98*062c5bc4SJason Schmidlapp // free (threadParms); 99*062c5bc4SJason Schmidlapp 100*062c5bc4SJason Schmidlapp pthread_setspecific (pte_selfThreadKey, sp); 101*062c5bc4SJason Schmidlapp 102*062c5bc4SJason Schmidlapp sp->state = PThreadStateRunning; 103*062c5bc4SJason Schmidlapp 104*062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_C 105*062c5bc4SJason Schmidlapp 106*062c5bc4SJason Schmidlapp 107*062c5bc4SJason Schmidlapp setjmp_rc = setjmp (sp->start_mark); 108*062c5bc4SJason Schmidlapp 109*062c5bc4SJason Schmidlapp 110*062c5bc4SJason Schmidlapp if (0 == setjmp_rc) 111*062c5bc4SJason Schmidlapp { 112*062c5bc4SJason Schmidlapp 113*062c5bc4SJason Schmidlapp /* 114*062c5bc4SJason Schmidlapp * Run the caller's routine; 115*062c5bc4SJason Schmidlapp */ 116*062c5bc4SJason Schmidlapp sp->exitStatus = status = (*start) (arg); 117*062c5bc4SJason Schmidlapp } 118*062c5bc4SJason Schmidlapp else 119*062c5bc4SJason Schmidlapp { 120*062c5bc4SJason Schmidlapp switch (setjmp_rc) 121*062c5bc4SJason Schmidlapp { 122*062c5bc4SJason Schmidlapp case PTE_EPS_CANCEL: 123*062c5bc4SJason Schmidlapp status = sp->exitStatus = PTHREAD_CANCELED; 124*062c5bc4SJason Schmidlapp break; 125*062c5bc4SJason Schmidlapp case PTE_EPS_EXIT: 126*062c5bc4SJason Schmidlapp status = sp->exitStatus; 127*062c5bc4SJason Schmidlapp break; 128*062c5bc4SJason Schmidlapp default: 129*062c5bc4SJason Schmidlapp status = sp->exitStatus = PTHREAD_CANCELED; 130*062c5bc4SJason Schmidlapp break; 131*062c5bc4SJason Schmidlapp } 132*062c5bc4SJason Schmidlapp } 133*062c5bc4SJason Schmidlapp 134*062c5bc4SJason Schmidlapp #else /* PTE_CLEANUP_C */ 135*062c5bc4SJason Schmidlapp 136*062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_CXX 137*062c5bc4SJason Schmidlapp 138*062c5bc4SJason Schmidlapp pte_oldTerminate = set_terminate (&pte_terminate); 139*062c5bc4SJason Schmidlapp 140*062c5bc4SJason Schmidlapp try 141*062c5bc4SJason Schmidlapp { 142*062c5bc4SJason Schmidlapp /* 143*062c5bc4SJason Schmidlapp * Run the caller's routine in a nested try block so that we 144*062c5bc4SJason Schmidlapp * can run the user's terminate function, which may call 145*062c5bc4SJason Schmidlapp * pthread_exit() or be canceled. 146*062c5bc4SJason Schmidlapp */ 147*062c5bc4SJason Schmidlapp try 148*062c5bc4SJason Schmidlapp { 149*062c5bc4SJason Schmidlapp status = sp->exitStatus = (*start) (arg); 150*062c5bc4SJason Schmidlapp } 151*062c5bc4SJason Schmidlapp catch (pte_exception &) 152*062c5bc4SJason Schmidlapp { 153*062c5bc4SJason Schmidlapp /* 154*062c5bc4SJason Schmidlapp * Pass these through to the outer block. 155*062c5bc4SJason Schmidlapp */ 156*062c5bc4SJason Schmidlapp throw; 157*062c5bc4SJason Schmidlapp } 158*062c5bc4SJason Schmidlapp catch (...) 159*062c5bc4SJason Schmidlapp { 160*062c5bc4SJason Schmidlapp /* 161*062c5bc4SJason Schmidlapp * We want to run the user's terminate function if supplied. 162*062c5bc4SJason Schmidlapp * That function may call pthread_exit() or be canceled, which will 163*062c5bc4SJason Schmidlapp * be handled by the outer try block. 164*062c5bc4SJason Schmidlapp * 165*062c5bc4SJason Schmidlapp * pte_terminate() will be called if there is no user 166*062c5bc4SJason Schmidlapp * supplied function. 167*062c5bc4SJason Schmidlapp */ 168*062c5bc4SJason Schmidlapp 169*062c5bc4SJason Schmidlapp terminate_function 170*062c5bc4SJason Schmidlapp term_func = set_terminate (0); 171*062c5bc4SJason Schmidlapp set_terminate (term_func); 172*062c5bc4SJason Schmidlapp 173*062c5bc4SJason Schmidlapp if (term_func != 0) 174*062c5bc4SJason Schmidlapp { 175*062c5bc4SJason Schmidlapp term_func (); 176*062c5bc4SJason Schmidlapp } 177*062c5bc4SJason Schmidlapp 178*062c5bc4SJason Schmidlapp throw; 179*062c5bc4SJason Schmidlapp } 180*062c5bc4SJason Schmidlapp } 181*062c5bc4SJason Schmidlapp catch (pte_exception_cancel &) 182*062c5bc4SJason Schmidlapp { 183*062c5bc4SJason Schmidlapp /* 184*062c5bc4SJason Schmidlapp * Thread was canceled. 185*062c5bc4SJason Schmidlapp */ 186*062c5bc4SJason Schmidlapp status = sp->exitStatus = PTHREAD_CANCELED; 187*062c5bc4SJason Schmidlapp } 188*062c5bc4SJason Schmidlapp catch (pte_exception_exit &) 189*062c5bc4SJason Schmidlapp { 190*062c5bc4SJason Schmidlapp /* 191*062c5bc4SJason Schmidlapp * Thread was exited via pthread_exit(). 192*062c5bc4SJason Schmidlapp */ 193*062c5bc4SJason Schmidlapp status = sp->exitStatus; 194*062c5bc4SJason Schmidlapp } 195*062c5bc4SJason Schmidlapp catch (...) 196*062c5bc4SJason Schmidlapp { 197*062c5bc4SJason Schmidlapp /* 198*062c5bc4SJason Schmidlapp * A system unexpected exception has occurred running the user's 199*062c5bc4SJason Schmidlapp * terminate routine. We get control back within this block - cleanup 200*062c5bc4SJason Schmidlapp * and release the exception out of thread scope. 201*062c5bc4SJason Schmidlapp */ 202*062c5bc4SJason Schmidlapp status = sp->exitStatus = PTHREAD_CANCELED; 203*062c5bc4SJason Schmidlapp (void) pthread_mutex_lock (&sp->cancelLock); 204*062c5bc4SJason Schmidlapp sp->state = PThreadStateException; 205*062c5bc4SJason Schmidlapp (void) pthread_mutex_unlock (&sp->cancelLock); 206*062c5bc4SJason Schmidlapp (void) pte_thread_detach_np(); 207*062c5bc4SJason Schmidlapp (void) set_terminate (pte_oldTerminate); 208*062c5bc4SJason Schmidlapp throw; 209*062c5bc4SJason Schmidlapp 210*062c5bc4SJason Schmidlapp /* 211*062c5bc4SJason Schmidlapp * Never reached. 212*062c5bc4SJason Schmidlapp */ 213*062c5bc4SJason Schmidlapp } 214*062c5bc4SJason Schmidlapp 215*062c5bc4SJason Schmidlapp (void) set_terminate (pte_oldTerminate); 216*062c5bc4SJason Schmidlapp 217*062c5bc4SJason Schmidlapp #else 218*062c5bc4SJason Schmidlapp 219*062c5bc4SJason Schmidlapp #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. 220*062c5bc4SJason Schmidlapp 221*062c5bc4SJason Schmidlapp #endif /* PTE_CLEANUP_CXX */ 222*062c5bc4SJason Schmidlapp #endif /* PTE_CLEANUP_C */ 223*062c5bc4SJason Schmidlapp 224*062c5bc4SJason Schmidlapp /* 225*062c5bc4SJason Schmidlapp * We need to cleanup the pthread now if we have 226*062c5bc4SJason Schmidlapp * been statically linked, in which case the cleanup 227*062c5bc4SJason Schmidlapp * in dllMain won't get done. Joinable threads will 228*062c5bc4SJason Schmidlapp * only be partially cleaned up and must be fully cleaned 229*062c5bc4SJason Schmidlapp * up by pthread_join() or pthread_detach(). 230*062c5bc4SJason Schmidlapp * 231*062c5bc4SJason Schmidlapp * Note: if this library has been statically linked, 232*062c5bc4SJason Schmidlapp * implicitly created pthreads (those created 233*062c5bc4SJason Schmidlapp * for OS threads which have called pthreads routines) 234*062c5bc4SJason Schmidlapp * must be cleaned up explicitly by the application 235*062c5bc4SJason Schmidlapp * (by calling pte_thread_detach_np()). 236*062c5bc4SJason Schmidlapp */ 237*062c5bc4SJason Schmidlapp (void) pte_thread_detach_and_exit_np (); 238*062c5bc4SJason Schmidlapp 239*062c5bc4SJason Schmidlapp //pte_osThreadExit(status); 240*062c5bc4SJason Schmidlapp 241*062c5bc4SJason Schmidlapp /* 242*062c5bc4SJason Schmidlapp * Never reached. 243*062c5bc4SJason Schmidlapp */ 244*062c5bc4SJason Schmidlapp 245*062c5bc4SJason Schmidlapp return (unsigned) status; 246*062c5bc4SJason Schmidlapp 247*062c5bc4SJason Schmidlapp } /* pte_threadStart */ 248*062c5bc4SJason Schmidlapp 249