1 /*
2  * pthread_self.c
3  *
4  * Description:
5  * This translation unit implements miscellaneous thread functions.
6  *
7  * --------------------------------------------------------------------------
8  *
9  *      Pthreads4w - POSIX Threads for Windows
10  *      Copyright 1998 John E. Bossom
11  *      Copyright 1999-2018, Pthreads4w contributors
12  *
13  *      Homepage: https://sourceforge.net/projects/pthreads4w/
14  *
15  *      The current list of contributors is contained
16  *      in the file CONTRIBUTORS included with the source
17  *      code distribution. The list can also be seen at the
18  *      following World Wide Web location:
19  *
20  *      https://sourceforge.net/p/pthreads4w/wiki/Contributors/
21  *
22  * Licensed under the Apache License, Version 2.0 (the "License");
23  * you may not use this file except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *     http://www.apache.org/licenses/LICENSE-2.0
27  *
28  * Unless required by applicable law or agreed to in writing, software
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38 
39 #include "pthread.h"
40 #include "implement.h"
41 
42 pthread_t
pthread_self(void)43 pthread_self (void)
44      /*
45       * ------------------------------------------------------
46       * DOCPUBLIC
47       *      This function returns a reference to the current running
48       *      thread.
49       *
50       * PARAMETERS
51       *      N/A
52       *
53       *
54       * DESCRIPTION
55       *      This function returns a reference to the current running
56       *      thread.
57       *
58       * RESULTS
59       *              pthread_t       reference to the current thread
60       *
61       * ------------------------------------------------------
62       */
63 {
64   pthread_t self;
65   pthread_t nil = {NULL, 0};
66   __ptw32_thread_t * sp;
67 
68 #if defined(_UWIN)
69   if (!__ptw32_selfThreadKey)
70     return nil;
71 #endif
72 
73   sp = (__ptw32_thread_t *) pthread_getspecific (__ptw32_selfThreadKey);
74 
75   if (sp != NULL)
76     {
77       self = sp->ptHandle;
78     }
79   else
80     {
81       int fail =  __PTW32_FALSE;
82 
83       /*
84        * Need to create an implicit 'self' for the currently
85        * executing thread.
86        */
87       self = __ptw32_new ();
88       sp = (__ptw32_thread_t *) self.p;
89 
90       if (sp != NULL)
91         {
92     	  /*
93     	   * This is a non-POSIX thread which has chosen to call
94     	   * a POSIX threads function for some reason. We assume that
95     	   * it isn't joinable, but we do assume that it's
96     	   * (deferred) cancelable.
97     	   */
98     	  sp->implicit = 1;
99     	  sp->detachState = PTHREAD_CREATE_DETACHED;
100     	  sp->thread = GetCurrentThreadId ();
101 
102 #if defined(NEED_DUPLICATEHANDLE)
103     	  /*
104     	   * DuplicateHandle does not exist on WinCE.
105     	   *
106     	   * NOTE:
107     	   * GetCurrentThread only returns a pseudo-handle
108     	   * which is only valid in the current thread context.
109     	   * Therefore, you should not pass the handle to
110     	   * other threads for whatever purpose.
111     	   */
112     	  sp->threadH = GetCurrentThread ();
113 #else
114     	  if (!DuplicateHandle (GetCurrentProcess (),
115 				GetCurrentThread (),
116 				GetCurrentProcess (),
117 				&sp->threadH,
118 				0, FALSE, DUPLICATE_SAME_ACCESS))
119     	    {
120     		  fail =  __PTW32_TRUE;
121     	    }
122 #endif
123 
124     	  if (!fail)
125     	    {
126 
127 #if defined(HAVE_CPU_AFFINITY)
128 
129     	      /*
130     	       * Get this threads CPU affinity by temporarily setting the threads
131     	       * affinity to that of the process to get the old thread affinity,
132     	       * then reset to the old affinity.
133     	       */
134 	      DWORD_PTR vThreadMask, vProcessMask, vSystemMask;
135     	      if (GetProcessAffinityMask(GetCurrentProcess(), &vProcessMask, &vSystemMask))
136     	        {
137     	          vThreadMask = SetThreadAffinityMask(sp->threadH, vProcessMask);
138     	          if (vThreadMask)
139     	            {
140     	              if (SetThreadAffinityMask(sp->threadH, vThreadMask))
141     	                {
142     	                  sp->cpuset = (size_t) vThreadMask;
143     	                }
144     	              else fail =  __PTW32_TRUE;
145     	            }
146     	          else fail =  __PTW32_TRUE;
147     	        }
148     	      else fail =  __PTW32_TRUE;
149 
150 #endif
151 
152     	      sp->sched_priority = GetThreadPriority (sp->threadH);
153     	      pthread_setspecific (__ptw32_selfThreadKey, (void *) sp);
154     	    }
155         }
156 
157       if (fail)
158         {
159     	  /*
160     	   * Thread structs are never freed but are reused so if this
161     	   * continues to fail at least we don't leak memory.
162     	   */
163     	  __ptw32_threadReusePush (self);
164     	  /*
165     	   * As this is a win32 thread calling us and we have failed,
166     	   * return a value that makes sense to win32.
167     	   */
168     	  return nil;
169         }
170       else
171 	{
172 	  /*
173 	   * This implicit POSIX thread is running (it called us).
174 	   * No other thread can reference us yet because all API calls
175 	   * passing a pthread_t should recognise an invalid thread id
176 	   * through the reuse counter inequality.
177 	   */
178     	  sp->state = PThreadStateRunning;
179 	}
180     }
181 
182   return (self);
183 }
184