xref: /relibc/pthreads-emb/pte_threadStart.c (revision a12978ccca4c576f02971f5cfc2cbefe23e4daba)
1062c5bc4SJason Schmidlapp /*
2062c5bc4SJason Schmidlapp  * pte_threadStart.c
3062c5bc4SJason Schmidlapp  *
4062c5bc4SJason Schmidlapp  * Description:
5062c5bc4SJason Schmidlapp  * This translation unit implements routines which are private to
6062c5bc4SJason Schmidlapp  * the implementation and may be used throughout it.
7062c5bc4SJason Schmidlapp  *
8062c5bc4SJason Schmidlapp  * --------------------------------------------------------------------------
9062c5bc4SJason Schmidlapp  *
10062c5bc4SJason Schmidlapp  *      Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
11062c5bc4SJason Schmidlapp  *      Copyright(C) 2008 Jason Schmidlapp
12062c5bc4SJason Schmidlapp  *
13062c5bc4SJason Schmidlapp  *      Contact Email: jschmidlapp@users.sourceforge.net
14062c5bc4SJason Schmidlapp  *
15062c5bc4SJason Schmidlapp  *
16062c5bc4SJason Schmidlapp  *      Based upon Pthreads-win32 - POSIX Threads Library for Win32
17062c5bc4SJason Schmidlapp  *      Copyright(C) 1998 John E. Bossom
18062c5bc4SJason Schmidlapp  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
19062c5bc4SJason Schmidlapp  *
20062c5bc4SJason Schmidlapp  *      Contact Email: rpj@callisto.canberra.edu.au
21062c5bc4SJason Schmidlapp  *
22062c5bc4SJason Schmidlapp  *      The original list of contributors to the Pthreads-win32 project
23062c5bc4SJason Schmidlapp  *      is contained in the file CONTRIBUTORS.ptw32 included with the
24062c5bc4SJason Schmidlapp  *      source code distribution. The list can also be seen at the
25062c5bc4SJason Schmidlapp  *      following World Wide Web location:
26062c5bc4SJason Schmidlapp  *      http://sources.redhat.com/pthreads-win32/contributors.html
27062c5bc4SJason Schmidlapp  *
28062c5bc4SJason Schmidlapp  *      This library is free software; you can redistribute it and/or
29062c5bc4SJason Schmidlapp  *      modify it under the terms of the GNU Lesser General Public
30062c5bc4SJason Schmidlapp  *      License as published by the Free Software Foundation; either
31062c5bc4SJason Schmidlapp  *      version 2 of the License, or (at your option) any later version.
32062c5bc4SJason Schmidlapp  *
33062c5bc4SJason Schmidlapp  *      This library is distributed in the hope that it will be useful,
34062c5bc4SJason Schmidlapp  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
35062c5bc4SJason Schmidlapp  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36062c5bc4SJason Schmidlapp  *      Lesser General Public License for more details.
37062c5bc4SJason Schmidlapp  *
38062c5bc4SJason Schmidlapp  *      You should have received a copy of the GNU Lesser General Public
39062c5bc4SJason Schmidlapp  *      License along with this library in the file COPYING.LIB;
40062c5bc4SJason Schmidlapp  *      if not, write to the Free Software Foundation, Inc.,
41062c5bc4SJason Schmidlapp  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
42062c5bc4SJason Schmidlapp  */
43062c5bc4SJason Schmidlapp 
44062c5bc4SJason Schmidlapp #include <stdio.h>
45062c5bc4SJason Schmidlapp #include <stdlib.h>
46062c5bc4SJason Schmidlapp 
47062c5bc4SJason Schmidlapp #include "pthread.h"
48062c5bc4SJason Schmidlapp #include "implement.h"
49062c5bc4SJason Schmidlapp 
50062c5bc4SJason Schmidlapp #if defined(PTE_CLEANUP_CXX)
51062c5bc4SJason Schmidlapp 
52062c5bc4SJason Schmidlapp # if defined(__GNUC__) && __GNUC__ < 3
53062c5bc4SJason Schmidlapp #   include <new>
54062c5bc4SJason Schmidlapp # else
55062c5bc4SJason Schmidlapp #   include <new>
56062c5bc4SJason Schmidlapp using
57062c5bc4SJason Schmidlapp std::terminate_handler;
58062c5bc4SJason Schmidlapp using
59062c5bc4SJason Schmidlapp std::terminate;
60062c5bc4SJason Schmidlapp using
61062c5bc4SJason Schmidlapp std::set_terminate;
62062c5bc4SJason Schmidlapp # endif
63062c5bc4SJason Schmidlapp 
64062c5bc4SJason Schmidlapp typedef terminate_handler terminate_function;
65062c5bc4SJason Schmidlapp 
66062c5bc4SJason Schmidlapp static terminate_function pte_oldTerminate;
67062c5bc4SJason Schmidlapp 
68062c5bc4SJason Schmidlapp void
pte_terminate()69062c5bc4SJason Schmidlapp pte_terminate ()
70062c5bc4SJason Schmidlapp {
71062c5bc4SJason Schmidlapp   set_terminate (pte_oldTerminate);
72062c5bc4SJason Schmidlapp   (void) pte_thread_detach_np();
73062c5bc4SJason Schmidlapp //  terminate ();
74062c5bc4SJason Schmidlapp }
75062c5bc4SJason Schmidlapp 
76062c5bc4SJason Schmidlapp #endif
77062c5bc4SJason Schmidlapp 
pte_threadStart(void * vthreadParms)78062c5bc4SJason Schmidlapp int pte_threadStart (void *vthreadParms)
79062c5bc4SJason Schmidlapp {
80062c5bc4SJason Schmidlapp   ThreadParms * threadParms = (ThreadParms *) vthreadParms;
81062c5bc4SJason Schmidlapp   pthread_t self;
82062c5bc4SJason Schmidlapp   pte_thread_t * sp;
83062c5bc4SJason Schmidlapp   void *(*start) (void *);
84062c5bc4SJason Schmidlapp   void * arg;
85062c5bc4SJason Schmidlapp 
86062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_C
87062c5bc4SJason Schmidlapp #include <setjmp.h>
88062c5bc4SJason Schmidlapp 
89062c5bc4SJason Schmidlapp   int setjmp_rc;
90062c5bc4SJason Schmidlapp #endif
91062c5bc4SJason Schmidlapp 
92062c5bc4SJason Schmidlapp   void * status = (void *) 0;
93062c5bc4SJason Schmidlapp 
94062c5bc4SJason Schmidlapp   self = threadParms->tid;
95*a12978ccSJeremy Soller   sp = (pte_thread_t *) self;
96062c5bc4SJason Schmidlapp   start = threadParms->start;
97062c5bc4SJason Schmidlapp   arg = threadParms->arg;
98062c5bc4SJason Schmidlapp //  free (threadParms);
99062c5bc4SJason Schmidlapp 
100062c5bc4SJason Schmidlapp   pthread_setspecific (pte_selfThreadKey, sp);
101062c5bc4SJason Schmidlapp 
102062c5bc4SJason Schmidlapp   sp->state = PThreadStateRunning;
103062c5bc4SJason Schmidlapp 
104062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_C
105062c5bc4SJason Schmidlapp 
106062c5bc4SJason Schmidlapp 
107062c5bc4SJason Schmidlapp   setjmp_rc = setjmp (sp->start_mark);
108062c5bc4SJason Schmidlapp 
109062c5bc4SJason Schmidlapp 
110062c5bc4SJason Schmidlapp   if (0 == setjmp_rc)
111062c5bc4SJason Schmidlapp     {
112062c5bc4SJason Schmidlapp 
113062c5bc4SJason Schmidlapp       /*
114062c5bc4SJason Schmidlapp        * Run the caller's routine;
115062c5bc4SJason Schmidlapp        */
116062c5bc4SJason Schmidlapp       sp->exitStatus = status = (*start) (arg);
117062c5bc4SJason Schmidlapp     }
118062c5bc4SJason Schmidlapp   else
119062c5bc4SJason Schmidlapp     {
120062c5bc4SJason Schmidlapp       switch (setjmp_rc)
121062c5bc4SJason Schmidlapp         {
122062c5bc4SJason Schmidlapp         case PTE_EPS_CANCEL:
123062c5bc4SJason Schmidlapp           status = sp->exitStatus = PTHREAD_CANCELED;
124062c5bc4SJason Schmidlapp           break;
125062c5bc4SJason Schmidlapp         case PTE_EPS_EXIT:
126062c5bc4SJason Schmidlapp           status = sp->exitStatus;
127062c5bc4SJason Schmidlapp           break;
128062c5bc4SJason Schmidlapp         default:
129062c5bc4SJason Schmidlapp           status = sp->exitStatus = PTHREAD_CANCELED;
130062c5bc4SJason Schmidlapp           break;
131062c5bc4SJason Schmidlapp         }
132062c5bc4SJason Schmidlapp     }
133062c5bc4SJason Schmidlapp 
134062c5bc4SJason Schmidlapp #else /* PTE_CLEANUP_C */
135062c5bc4SJason Schmidlapp 
136062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_CXX
137062c5bc4SJason Schmidlapp 
138062c5bc4SJason Schmidlapp   pte_oldTerminate = set_terminate (&pte_terminate);
139062c5bc4SJason Schmidlapp 
140062c5bc4SJason Schmidlapp   try
141062c5bc4SJason Schmidlapp     {
142062c5bc4SJason Schmidlapp       /*
143062c5bc4SJason Schmidlapp       * Run the caller's routine in a nested try block so that we
144062c5bc4SJason Schmidlapp       * can run the user's terminate function, which may call
145062c5bc4SJason Schmidlapp       * pthread_exit() or be canceled.
146062c5bc4SJason Schmidlapp       */
147062c5bc4SJason Schmidlapp       try
148062c5bc4SJason Schmidlapp         {
149062c5bc4SJason Schmidlapp           status = sp->exitStatus = (*start) (arg);
150062c5bc4SJason Schmidlapp         }
151062c5bc4SJason Schmidlapp       catch (pte_exception &)
152062c5bc4SJason Schmidlapp         {
153062c5bc4SJason Schmidlapp           /*
154062c5bc4SJason Schmidlapp           * Pass these through to the outer block.
155062c5bc4SJason Schmidlapp           */
156062c5bc4SJason Schmidlapp           throw;
157062c5bc4SJason Schmidlapp         }
158062c5bc4SJason Schmidlapp       catch (...)
159062c5bc4SJason Schmidlapp         {
160062c5bc4SJason Schmidlapp           /*
161062c5bc4SJason Schmidlapp           * We want to run the user's terminate function if supplied.
162062c5bc4SJason Schmidlapp           * That function may call pthread_exit() or be canceled, which will
163062c5bc4SJason Schmidlapp           * be handled by the outer try block.
164062c5bc4SJason Schmidlapp           *
165062c5bc4SJason Schmidlapp           * pte_terminate() will be called if there is no user
166062c5bc4SJason Schmidlapp           * supplied function.
167062c5bc4SJason Schmidlapp           */
168062c5bc4SJason Schmidlapp 
169062c5bc4SJason Schmidlapp           terminate_function
170062c5bc4SJason Schmidlapp           term_func = set_terminate (0);
171062c5bc4SJason Schmidlapp           set_terminate (term_func);
172062c5bc4SJason Schmidlapp 
173062c5bc4SJason Schmidlapp           if (term_func != 0)
174062c5bc4SJason Schmidlapp             {
175062c5bc4SJason Schmidlapp               term_func ();
176062c5bc4SJason Schmidlapp             }
177062c5bc4SJason Schmidlapp 
178062c5bc4SJason Schmidlapp           throw;
179062c5bc4SJason Schmidlapp         }
180062c5bc4SJason Schmidlapp     }
181062c5bc4SJason Schmidlapp   catch (pte_exception_cancel &)
182062c5bc4SJason Schmidlapp     {
183062c5bc4SJason Schmidlapp       /*
184062c5bc4SJason Schmidlapp       * Thread was canceled.
185062c5bc4SJason Schmidlapp       */
186062c5bc4SJason Schmidlapp       status = sp->exitStatus = PTHREAD_CANCELED;
187062c5bc4SJason Schmidlapp     }
188062c5bc4SJason Schmidlapp   catch (pte_exception_exit &)
189062c5bc4SJason Schmidlapp     {
190062c5bc4SJason Schmidlapp       /*
191062c5bc4SJason Schmidlapp       * Thread was exited via pthread_exit().
192062c5bc4SJason Schmidlapp       */
193062c5bc4SJason Schmidlapp       status = sp->exitStatus;
194062c5bc4SJason Schmidlapp     }
195062c5bc4SJason Schmidlapp   catch (...)
196062c5bc4SJason Schmidlapp     {
197062c5bc4SJason Schmidlapp       /*
198062c5bc4SJason Schmidlapp       * A system unexpected exception has occurred running the user's
199062c5bc4SJason Schmidlapp       * terminate routine. We get control back within this block - cleanup
200062c5bc4SJason Schmidlapp       * and release the exception out of thread scope.
201062c5bc4SJason Schmidlapp       */
202062c5bc4SJason Schmidlapp       status = sp->exitStatus = PTHREAD_CANCELED;
203062c5bc4SJason Schmidlapp       (void) pthread_mutex_lock (&sp->cancelLock);
204062c5bc4SJason Schmidlapp       sp->state = PThreadStateException;
205062c5bc4SJason Schmidlapp       (void) pthread_mutex_unlock (&sp->cancelLock);
206062c5bc4SJason Schmidlapp       (void) pte_thread_detach_np();
207062c5bc4SJason Schmidlapp       (void) set_terminate (pte_oldTerminate);
208062c5bc4SJason Schmidlapp       throw;
209062c5bc4SJason Schmidlapp 
210062c5bc4SJason Schmidlapp       /*
211062c5bc4SJason Schmidlapp       * Never reached.
212062c5bc4SJason Schmidlapp       */
213062c5bc4SJason Schmidlapp     }
214062c5bc4SJason Schmidlapp 
215062c5bc4SJason Schmidlapp   (void) set_terminate (pte_oldTerminate);
216062c5bc4SJason Schmidlapp 
217062c5bc4SJason Schmidlapp #else
218062c5bc4SJason Schmidlapp 
219062c5bc4SJason Schmidlapp #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
220062c5bc4SJason Schmidlapp 
221062c5bc4SJason Schmidlapp #endif /* PTE_CLEANUP_CXX */
222062c5bc4SJason Schmidlapp #endif /* PTE_CLEANUP_C */
223062c5bc4SJason Schmidlapp 
224062c5bc4SJason Schmidlapp   /*
225062c5bc4SJason Schmidlapp    * We need to cleanup the pthread now if we have
226062c5bc4SJason Schmidlapp    * been statically linked, in which case the cleanup
227062c5bc4SJason Schmidlapp    * in dllMain won't get done. Joinable threads will
228062c5bc4SJason Schmidlapp    * only be partially cleaned up and must be fully cleaned
229062c5bc4SJason Schmidlapp    * up by pthread_join() or pthread_detach().
230062c5bc4SJason Schmidlapp    *
231062c5bc4SJason Schmidlapp    * Note: if this library has been statically linked,
232062c5bc4SJason Schmidlapp    * implicitly created pthreads (those created
233062c5bc4SJason Schmidlapp    * for OS threads which have called pthreads routines)
234062c5bc4SJason Schmidlapp    * must be cleaned up explicitly by the application
235062c5bc4SJason Schmidlapp    * (by calling pte_thread_detach_np()).
236062c5bc4SJason Schmidlapp    */
237062c5bc4SJason Schmidlapp   (void) pte_thread_detach_and_exit_np ();
238062c5bc4SJason Schmidlapp 
239062c5bc4SJason Schmidlapp   //pte_osThreadExit(status);
240062c5bc4SJason Schmidlapp 
241062c5bc4SJason Schmidlapp   /*
242062c5bc4SJason Schmidlapp    * Never reached.
243062c5bc4SJason Schmidlapp    */
244062c5bc4SJason Schmidlapp 
245062c5bc4SJason Schmidlapp   return (unsigned) status;
246062c5bc4SJason Schmidlapp 
247062c5bc4SJason Schmidlapp }				/* pte_threadStart */
248