1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1999-2015, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 
7 #if defined(hpux)
8 # ifndef _INCLUDE_POSIX_SOURCE
9 #  define _INCLUDE_POSIX_SOURCE
10 # endif
11 #endif
12 
13 /* Define __EXTENSIONS__ for Solaris and old friends in strict mode. */
14 #ifndef __EXTENSIONS__
15 #define __EXTENSIONS__
16 #endif
17 
18 // Defines _XOPEN_SOURCE for access to POSIX functions.
19 // Must be before any other #includes.
20 #include "uposixdefs.h"
21 
22 #include "simplethread.h"
23 
24 #include "unicode/utypes.h"
25 #include "unicode/ustring.h"
26 #include "umutex.h"
27 #include "cmemory.h"
28 #include "cstring.h"
29 #include "uparse.h"
30 #include "unicode/resbund.h"
31 #include "unicode/udata.h"
32 #include "unicode/uloc.h"
33 #include "unicode/locid.h"
34 #include "putilimp.h"
35 #include "intltest.h"
36 
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h>    // tolower, toupper
40 
41 #if U_PLATFORM_USES_ONLY_WIN32_API
42     /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
43 #   undef POSIX
44 #elif U_PLATFORM_IMPLEMENTS_POSIX
45 #   define POSIX
46 #else
47 #   undef POSIX
48 #endif
49 
50 /* Needed by z/OS to get usleep */
51 #if U_PLATFORM == U_PF_OS390
52 #define __DOT1 1
53 #ifndef __UU
54 #   define __UU
55 #endif
56 #ifndef _XPG4_2
57 #   define _XPG4_2
58 #endif
59 #include <unistd.h>
60 #endif
61 
62 #if defined(POSIX)
63 #define HAVE_IMP
64 
65 #include <pthread.h>
66 
67 #if U_PLATFORM == U_PF_OS390
68 #include <sys/types.h>
69 #endif
70 
71 #if U_PLATFORM != U_PF_OS390
72 #include <signal.h>
73 #endif
74 
75 /* Define _XPG4_2 for Solaris and friends. */
76 #ifndef _XPG4_2
77 #define _XPG4_2
78 #endif
79 
80 /* Define __USE_XOPEN_EXTENDED for Linux and glibc. */
81 #ifndef __USE_XOPEN_EXTENDED
82 #define __USE_XOPEN_EXTENDED
83 #endif
84 
85 /* Define _INCLUDE_XOPEN_SOURCE_EXTENDED for HP/UX (11?). */
86 #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
87 #define _INCLUDE_XOPEN_SOURCE_EXTENDED
88 #endif
89 
90 #include <unistd.h>
91 
92 #endif
93 /* HPUX */
94 #ifdef sleep
95 #undef sleep
96 #endif
97 
98 
99 #include "unicode/putil.h"
100 
101 /* for mthreadtest*/
102 #include "unicode/numfmt.h"
103 #include "unicode/choicfmt.h"
104 #include "unicode/msgfmt.h"
105 #include "unicode/locid.h"
106 #include "unicode/ucol.h"
107 #include "unicode/calendar.h"
108 #include "ucaconf.h"
109 
110 #if U_PLATFORM_USES_ONLY_WIN32_API
111 #define HAVE_IMP
112 
113 #   define VC_EXTRALEAN
114 #   define WIN32_LEAN_AND_MEAN
115 #   define NOUSER
116 #   define NOSERVICE
117 #   define NOIME
118 #   define NOMCX
119 #include <windows.h>
120 #include <process.h>
121 
122 //-----------------------------------------------------------------------------------
123 //
124 //   class SimpleThread   Windows Implementation
125 //
126 //-----------------------------------------------------------------------------------
127 struct Win32ThreadImplementation
128 {
129     HANDLE         fHandle;
130     unsigned int   fThreadID;
131 };
132 
133 
SimpleThreadProc(void * arg)134 extern "C" unsigned int __stdcall SimpleThreadProc(void *arg)
135 {
136     ((SimpleThread*)arg)->run();
137     return 0;
138 }
139 
SimpleThread()140 SimpleThread::SimpleThread()
141 :fImplementation(0)
142 {
143     Win32ThreadImplementation *imp = new Win32ThreadImplementation;
144     imp->fHandle = 0;
145     fImplementation = imp;
146 }
147 
~SimpleThread()148 SimpleThread::~SimpleThread()
149 {
150     // Destructor.  Because we start the thread running with _beginthreadex(),
151     //              we own the Windows HANDLE for the thread and must
152     //              close it here.
153     Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
154     if (imp != 0) {
155         if (imp->fHandle != 0) {
156             CloseHandle(imp->fHandle);
157             imp->fHandle = 0;
158         }
159     }
160     delete (Win32ThreadImplementation*)fImplementation;
161 }
162 
start()163 int32_t SimpleThread::start()
164 {
165     Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
166     if(imp->fHandle != NULL) {
167         // The thread appears to have already been started.
168         //   This is probably an error on the part of our caller.
169         return -1;
170     }
171 
172     imp->fHandle = (HANDLE) _beginthreadex(
173         NULL,                                 // Security
174         0x20000,                              // Stack Size
175         SimpleThreadProc,                     // Function to Run
176         (void *)this,                         // Arg List
177         0,                                    // initflag.  Start running, not suspended
178         &imp->fThreadID                       // thraddr
179         );
180 
181     if (imp->fHandle == 0) {
182         // An error occured
183         int err = errno;
184         if (err == 0) {
185             err = -1;
186         }
187         return err;
188     }
189     return 0;
190 }
191 
192 
join()193 void SimpleThread::join() {
194     Win32ThreadImplementation *imp = (Win32ThreadImplementation*)fImplementation;
195     if (imp->fHandle == 0) {
196         // No handle, thread must not be running.
197         return;
198     }
199     WaitForSingleObject(imp->fHandle, INFINITE);
200 }
201 
202 #endif
203 
204 
205 //-----------------------------------------------------------------------------------
206 //
207 //   class SimpleThread   POSIX implementation
208 //
209 //-----------------------------------------------------------------------------------
210 #if defined(POSIX)
211 #define HAVE_IMP
212 
213 struct PosixThreadImplementation
214 {
215     pthread_t        fThread;
216 };
217 
SimpleThreadProc(void * arg)218 extern "C" void* SimpleThreadProc(void *arg)
219 {
220     // This is the code that is run in the new separate thread.
221     SimpleThread *This = (SimpleThread *)arg;
222     This->run();
223     return 0;
224 }
225 
SimpleThread()226 SimpleThread::SimpleThread()
227 {
228     PosixThreadImplementation *imp = new PosixThreadImplementation;
229     fImplementation = imp;
230 }
231 
~SimpleThread()232 SimpleThread::~SimpleThread()
233 {
234     PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
235     delete imp;
236     fImplementation = (void *)0xdeadbeef;
237 }
238 
start()239 int32_t SimpleThread::start()
240 {
241     int32_t        rc;
242     static pthread_attr_t attr;
243     static UBool attrIsInitialized = FALSE;
244 
245     PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
246 
247     if (attrIsInitialized == FALSE) {
248         rc = pthread_attr_init(&attr);
249 #if U_PLATFORM == U_PF_OS390
250         {
251             int detachstate = 0;  // jdc30: detach state of zero causes
252                                   //threads created with this attr to be in
253                                   //an undetached state.  An undetached
254                                   //thread will keep its resources after
255                                   //termination.
256             pthread_attr_setdetachstate(&attr, &detachstate);
257         }
258 #else
259         // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
260         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
261 #endif
262         attrIsInitialized = TRUE;
263     }
264     rc = pthread_create(&(imp->fThread), &attr, &SimpleThreadProc, (void*)this);
265 
266     if (rc != 0) {
267         // some kind of error occured, the thread did not start.
268     }
269 
270     return rc;
271 }
272 
join()273 void SimpleThread::join() {
274     PosixThreadImplementation *imp = (PosixThreadImplementation*)fImplementation;
275     pthread_join(imp->fThread, NULL);
276 }
277 
278 #endif
279 // end POSIX
280 
281 
282 #ifndef HAVE_IMP
283 #error  No implementation for threads! Cannot test.
284 #endif
285