1*d86ed7fbStbbdev /*
2*d86ed7fbStbbdev     Copyright (c) 2005-2020 Intel Corporation
3*d86ed7fbStbbdev 
4*d86ed7fbStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5*d86ed7fbStbbdev     you may not use this file except in compliance with the License.
6*d86ed7fbStbbdev     You may obtain a copy of the License at
7*d86ed7fbStbbdev 
8*d86ed7fbStbbdev         http://www.apache.org/licenses/LICENSE-2.0
9*d86ed7fbStbbdev 
10*d86ed7fbStbbdev     Unless required by applicable law or agreed to in writing, software
11*d86ed7fbStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12*d86ed7fbStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d86ed7fbStbbdev     See the License for the specific language governing permissions and
14*d86ed7fbStbbdev     limitations under the License.
15*d86ed7fbStbbdev */
16*d86ed7fbStbbdev 
17*d86ed7fbStbbdev /*
18*d86ed7fbStbbdev     The original source for this example is
19*d86ed7fbStbbdev     Copyright (c) 1994-2008 John E. Stone
20*d86ed7fbStbbdev     All rights reserved.
21*d86ed7fbStbbdev 
22*d86ed7fbStbbdev     Redistribution and use in source and binary forms, with or without
23*d86ed7fbStbbdev     modification, are permitted provided that the following conditions
24*d86ed7fbStbbdev     are met:
25*d86ed7fbStbbdev     1. Redistributions of source code must retain the above copyright
26*d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer.
27*d86ed7fbStbbdev     2. Redistributions in binary form must reproduce the above copyright
28*d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer in the
29*d86ed7fbStbbdev        documentation and/or other materials provided with the distribution.
30*d86ed7fbStbbdev     3. The name of the author may not be used to endorse or promote products
31*d86ed7fbStbbdev        derived from this software without specific prior written permission.
32*d86ed7fbStbbdev 
33*d86ed7fbStbbdev     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34*d86ed7fbStbbdev     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35*d86ed7fbStbbdev     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36*d86ed7fbStbbdev     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37*d86ed7fbStbbdev     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38*d86ed7fbStbbdev     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39*d86ed7fbStbbdev     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40*d86ed7fbStbbdev     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41*d86ed7fbStbbdev     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42*d86ed7fbStbbdev     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43*d86ed7fbStbbdev     SUCH DAMAGE.
44*d86ed7fbStbbdev */
45*d86ed7fbStbbdev 
46*d86ed7fbStbbdev #ifdef EMULATE_PTHREADS
47*d86ed7fbStbbdev 
48*d86ed7fbStbbdev #include <assert.h>
49*d86ed7fbStbbdev #include "pthread_w.hpp"
50*d86ed7fbStbbdev 
51*d86ed7fbStbbdev /*
52*d86ed7fbStbbdev     Basics
53*d86ed7fbStbbdev */
54*d86ed7fbStbbdev 
55*d86ed7fbStbbdev int pthread_create(pthread_t *thread,
56*d86ed7fbStbbdev                    pthread_attr_t *attr,
57*d86ed7fbStbbdev                    void *(*start_routine)(void *),
58*d86ed7fbStbbdev                    void *arg) {
59*d86ed7fbStbbdev     pthread_t th;
60*d86ed7fbStbbdev 
61*d86ed7fbStbbdev     if (thread == nullptr)
62*d86ed7fbStbbdev         return EINVAL;
63*d86ed7fbStbbdev     *thread = nullptr;
64*d86ed7fbStbbdev 
65*d86ed7fbStbbdev     if (start_routine == nullptr)
66*d86ed7fbStbbdev         return EINVAL;
67*d86ed7fbStbbdev 
68*d86ed7fbStbbdev     th = (pthread_t)malloc(sizeof(pthread_s));
69*d86ed7fbStbbdev     memset(th, 0, sizeof(pthread_s));
70*d86ed7fbStbbdev 
71*d86ed7fbStbbdev     th->winthread_handle =
72*d86ed7fbStbbdev         CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, &th->winthread_id);
73*d86ed7fbStbbdev     if (th->winthread_handle == nullptr)
74*d86ed7fbStbbdev         return EAGAIN; /*  GetLastError()  */
75*d86ed7fbStbbdev 
76*d86ed7fbStbbdev     *thread = th;
77*d86ed7fbStbbdev     return 0;
78*d86ed7fbStbbdev }
79*d86ed7fbStbbdev 
80*d86ed7fbStbbdev int pthread_join(pthread_t th, void **thread_return) {
81*d86ed7fbStbbdev     BOOL b_ret;
82*d86ed7fbStbbdev     DWORD dw_ret;
83*d86ed7fbStbbdev 
84*d86ed7fbStbbdev     if (thread_return)
85*d86ed7fbStbbdev         *thread_return = nullptr;
86*d86ed7fbStbbdev 
87*d86ed7fbStbbdev     if ((th == nullptr) || (th->winthread_handle == nullptr))
88*d86ed7fbStbbdev         return EINVAL;
89*d86ed7fbStbbdev 
90*d86ed7fbStbbdev     dw_ret = WaitForSingleObject(th->winthread_handle, INFINITE);
91*d86ed7fbStbbdev     if (dw_ret != WAIT_OBJECT_0)
92*d86ed7fbStbbdev         return ERROR_PTHREAD; /*  dw_ret == WAIT_FAILED; GetLastError()  */
93*d86ed7fbStbbdev 
94*d86ed7fbStbbdev     if (thread_return) {
95*d86ed7fbStbbdev         BOOL e_ret;
96*d86ed7fbStbbdev         DWORD exit_val;
97*d86ed7fbStbbdev         e_ret = GetExitCodeThread(th->winthread_handle, &exit_val);
98*d86ed7fbStbbdev         if (!e_ret)
99*d86ed7fbStbbdev             return ERROR_PTHREAD; /*  GetLastError()  */
100*d86ed7fbStbbdev         *thread_return = (void *)(std::size_t)exit_val;
101*d86ed7fbStbbdev     }
102*d86ed7fbStbbdev 
103*d86ed7fbStbbdev     b_ret = CloseHandle(th->winthread_handle);
104*d86ed7fbStbbdev     if (!b_ret)
105*d86ed7fbStbbdev         return ERROR_PTHREAD; /*  GetLastError()  */
106*d86ed7fbStbbdev     memset(th, 0, sizeof(pthread_s));
107*d86ed7fbStbbdev     free(th);
108*d86ed7fbStbbdev     th = nullptr;
109*d86ed7fbStbbdev 
110*d86ed7fbStbbdev     return 0;
111*d86ed7fbStbbdev }
112*d86ed7fbStbbdev 
113*d86ed7fbStbbdev void pthread_exit(void *retval) {
114*d86ed7fbStbbdev     /*  specific to PTHREAD_TO_WINTHREAD  */
115*d86ed7fbStbbdev 
116*d86ed7fbStbbdev     ExitThread((DWORD)(
117*d86ed7fbStbbdev         (std::size_t)retval)); /* thread becomes signalled so its death can be waited upon */
118*d86ed7fbStbbdev     /*NOTREACHED*/
119*d86ed7fbStbbdev     assert(0);
120*d86ed7fbStbbdev     return; /* void fnc; can't return an error code */
121*d86ed7fbStbbdev }
122*d86ed7fbStbbdev 
123*d86ed7fbStbbdev /*
124*d86ed7fbStbbdev     Mutex
125*d86ed7fbStbbdev */
126*d86ed7fbStbbdev 
127*d86ed7fbStbbdev int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr) {
128*d86ed7fbStbbdev     InitializeCriticalSection(&mutex->critsec);
129*d86ed7fbStbbdev     return 0;
130*d86ed7fbStbbdev }
131*d86ed7fbStbbdev 
132*d86ed7fbStbbdev int pthread_mutex_destroy(pthread_mutex_t *mutex) {
133*d86ed7fbStbbdev     return 0;
134*d86ed7fbStbbdev }
135*d86ed7fbStbbdev 
136*d86ed7fbStbbdev int pthread_mutex_lock(pthread_mutex_t *mutex) {
137*d86ed7fbStbbdev     EnterCriticalSection(&mutex->critsec);
138*d86ed7fbStbbdev     return 0;
139*d86ed7fbStbbdev }
140*d86ed7fbStbbdev 
141*d86ed7fbStbbdev int pthread_mutex_unlock(pthread_mutex_t *mutex) {
142*d86ed7fbStbbdev     LeaveCriticalSection(&mutex->critsec);
143*d86ed7fbStbbdev     return 0;
144*d86ed7fbStbbdev }
145*d86ed7fbStbbdev 
146*d86ed7fbStbbdev #endif /*  EMULATE_PTHREADS  */
147