xref: /AOO41X/main/sal/osl/os2/thread.c (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 #include "system.h"
26 
27 #include <osl/diagnose.h>
28 #include <osl/thread.h>
29 #include <osl/time.h>
30 #include <rtl/alloc.h>
31 #include <rtl/tencinfo.h>
32 
33 /*
34     Thread-data structure hidden behind oslThread:
35 */
36 typedef struct _osl_TThreadImpl
37 {
38 
39     TID                  m_ThreadId;        /* identifier for this thread */
40     sal_Int32            m_Flags;
41     HEV                  m_hEvent;
42     sal_uInt32           m_Timeout;
43     oslWorkerFunction    m_WorkerFunction;
44     void*                m_pData;
45     sal_Bool             m_StartSuspended;
46     HAB                  m_hab;
47     HMQ                  m_hmq;
48 
49 } osl_TThreadImpl;
50 
51 #define THREADIMPL_FLAGS_TERMINATE    0x0001
52 #define THREADIMPL_FLAGS_SLEEP        0x0002
53 
54 
55 // static mutex to control access to private members of oslMutexImpl
56 static HMTX MutexLock = NULL;
57 
58 /*****************************************************************************/
59 
60 HAB osl_getPMinternal_HAB(oslThread hThread)
61 {
62     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread;
63 
64     if(pThreadImpl == NULL) /* valid ptr? */
65     {
66         return NULL;
67     }
68     else
69     {
70         return pThreadImpl->m_hab;
71     }
72 }
73 
74 HMQ osl_getPMinternal_HMQ(oslThread hThread)
75 {
76     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread;
77 
78     if(pThreadImpl == NULL) /* valid ptr? */
79     {
80         return NULL;
81     }
82     else
83     {
84         return pThreadImpl->m_hmq;
85     }
86 }
87 
88 
89 /*****************************************************************************/
90 /* oslWorkerWrapperFunction */
91 /*****************************************************************************/
92 static void oslWorkerWrapperFunction(void* pData)
93 {
94     BOOL rc;
95     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)pData;
96 
97 #if OSL_DEBUG_LEVEL>0
98 printf("oslWorkerWrapperFunction pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId);
99 #endif
100     /* Inizialize PM for this thread */
101     pThreadImpl->m_hab = WinInitialize( 0 );
102 #if OSL_DEBUG_LEVEL>0
103 printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hab %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hab);
104 #endif
105     pThreadImpl->m_hmq = WinCreateMsgQueue( pThreadImpl->m_hab, 0 );
106 #if OSL_DEBUG_LEVEL>0
107 printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hmq %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hmq);
108 #endif
109 
110     /* call worker-function with data */
111     pThreadImpl->m_WorkerFunction( pThreadImpl->m_pData );
112 
113     /* Free all PM-resources for this thread */
114 #if OSL_DEBUG_LEVEL>0
115 printf("pThreadImpl->m_ThreadId %d, about to destroy queue\n", pThreadImpl->m_ThreadId);
116 #endif
117     rc = WinDestroyMsgQueue( pThreadImpl->m_hmq );
118 #if OSL_DEBUG_LEVEL>0
119 printf("pThreadImpl->m_ThreadId %d, WinDestroyMsgQueue rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc);
120 printf("pThreadImpl->m_ThreadId %d, about to terminate hab\n", pThreadImpl->m_ThreadId);
121 #endif
122     rc = WinTerminate( pThreadImpl->m_hab );
123 #if OSL_DEBUG_LEVEL>0
124 printf("pThreadImpl->m_ThreadId %d, WinTerminate rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc);
125 #endif
126 }
127 
128 
129 /*****************************************************************************/
130 /* oslCreateThread */
131 /*****************************************************************************/
132 static oslThread oslCreateThread(oslWorkerFunction pWorker,
133                                  void* pThreadData,
134                                  sal_Bool nFlags)
135 {
136     osl_TThreadImpl* pThreadImpl;
137 
138     /* alloc mem. for our internal data structure */
139     pThreadImpl = (osl_TThreadImpl*)malloc(sizeof(osl_TThreadImpl));
140 
141     OSL_ASSERT(pThreadImpl);
142 
143     pThreadImpl->m_WorkerFunction= pWorker;
144     pThreadImpl->m_pData= pThreadData;
145 
146     pThreadImpl->m_Flags   = 0;
147     pThreadImpl->m_hEvent  = 0;
148     pThreadImpl->m_Timeout = 0;
149     pThreadImpl->m_StartSuspended = nFlags;
150     pThreadImpl->m_hab = 0;
151     pThreadImpl->m_hmq = 0;
152 
153     if ( nFlags == sal_True )
154     {
155         DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
156     }
157 
158     pThreadImpl->m_ThreadId = (TID) _beginthread( oslWorkerWrapperFunction,    /* worker-function */
159                                                   NULL,                        /* unused parameter */
160                                                   1024*1024,                   /* max. Stacksize */
161                                                   pThreadImpl );
162     if ( nFlags == sal_True )
163     {
164         if( pThreadImpl->m_ThreadId != -1 )
165             DosSuspendThread( pThreadImpl->m_ThreadId );
166         DosReleaseMutexSem( MutexLock);
167     }
168 #if OSL_DEBUG_LEVEL>0
169 printf("oslCreateThread pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId);
170 #endif
171     if(pThreadImpl->m_ThreadId == -1)
172     {
173         /* create failed */
174         if (pThreadImpl->m_hEvent != 0)
175             DosCloseEventSem(pThreadImpl->m_hEvent);
176 
177         free(pThreadImpl);
178         return 0;
179     }
180 
181     pThreadImpl->m_hEvent= 0;
182 
183     return pThreadImpl;
184 
185 }
186 
187 /*****************************************************************************/
188 /* osl_createThread */
189 /*****************************************************************************/
190 oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker,
191                                  void* pThreadData)
192 {
193     return oslCreateThread(pWorker,pThreadData,sal_False);
194 }
195 
196 /*****************************************************************************/
197 /* osl_createSuspendedThread */
198 /*****************************************************************************/
199 oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker,
200                                           void* pThreadData)
201 {
202     return oslCreateThread(pWorker,pThreadData,sal_True);
203 }
204 
205 /*****************************************************************************/
206 /* osl_getThreadIdentifier */
207 /*****************************************************************************/
208 oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
209 {
210     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
211 
212     if (pThreadImpl != NULL)
213         return ((oslThreadIdentifier)pThreadImpl->m_ThreadId);
214     else
215         {
216         PTIB pptib = NULL;
217         PPIB pppib = NULL;
218 
219         DosGetInfoBlocks( &pptib, &pppib );
220         return ((oslThreadIdentifier) pptib->tib_ptib2->tib2_ultid );
221         }
222 }
223 
224 /*****************************************************************************/
225 /* osl_destroyThread */
226 /*****************************************************************************/
227 void SAL_CALL osl_destroyThread(oslThread Thread)
228 {
229     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
230 
231     if(Thread == 0) /* valid ptr? */
232     {
233         /* thread already destroyed or not created */
234         return;
235     }
236 
237     if(pThreadImpl->m_ThreadId != -1)    /* valid handle ? */
238     {
239         /* cancel thread  */
240         DosKillThread( pThreadImpl->m_ThreadId );
241     }
242 }
243 
244 /*****************************************************************************/
245 /* osl_freeThreadHandle */
246 /*****************************************************************************/
247 void SAL_CALL osl_freeThreadHandle(oslThread Thread)
248 {
249     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
250 
251     if(Thread == 0)        /* valid ptr? */
252     {
253         /* thread already destroyed or not created */
254         return;
255     }
256 
257     if (pThreadImpl->m_hEvent != 0)
258         DosCloseEventSem(pThreadImpl->m_hEvent);
259 
260     /* free memory */
261     free(Thread);
262 }
263 
264 /*****************************************************************************/
265 /* osl_resumeThread */
266 /*****************************************************************************/
267 void SAL_CALL osl_resumeThread(oslThread Thread)
268 {
269     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
270 
271     OSL_ASSERT(pThreadImpl);        /* valid ptr? */
272 
273     DosResumeThread( pThreadImpl->m_ThreadId );
274 }
275 
276 /*****************************************************************************/
277 /* osl_suspendThread */
278 /*****************************************************************************/
279 void SAL_CALL osl_suspendThread(oslThread Thread)
280 {
281     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
282 
283     OSL_ASSERT(pThreadImpl);        /* valid ptr? */
284 
285     DosSuspendThread( pThreadImpl->m_ThreadId );
286 }
287 
288 /*****************************************************************************/
289 /* osl_setThreadPriority */
290 /*****************************************************************************/
291 void SAL_CALL osl_setThreadPriority(oslThread Thread,
292                            oslThreadPriority Priority)
293 {
294     ULONG nOs2PriorityClass;
295     ULONG nOs2PriorityDelta;
296     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
297 
298     OSL_ASSERT(pThreadImpl);        /* valid ptr? */
299 
300     switch(Priority) {
301 
302     case osl_Thread_PriorityHighest:
303 
304         nOs2PriorityClass = PRTYC_REGULAR;
305         nOs2PriorityDelta = PRTYD_MAXIMUM;
306         break;
307 
308     case osl_Thread_PriorityAboveNormal:
309 
310         nOs2PriorityClass = PRTYC_REGULAR;
311         nOs2PriorityDelta = 16;
312         break;
313 
314     case osl_Thread_PriorityNormal:
315 
316         nOs2PriorityClass = PRTYC_REGULAR;
317         nOs2PriorityDelta = 0;
318         break;
319 
320     case osl_Thread_PriorityBelowNormal:
321 
322         nOs2PriorityClass = PRTYC_REGULAR;
323         nOs2PriorityDelta = -16;
324         break;
325 
326     case osl_Thread_PriorityLowest:
327 
328         nOs2PriorityClass = PRTYC_REGULAR;
329         nOs2PriorityDelta = PRTYD_MINIMUM;
330         break;
331 
332     case osl_Thread_PriorityUnknown:
333         OSL_ASSERT(FALSE);        /* only fools try this...*/
334 
335         /* let release-version behave friendly */
336         return;
337 
338     default:
339         OSL_ASSERT(FALSE);        /* enum expanded, but forgotten here...*/
340 
341         /* let release-version behave friendly */
342         return;
343     }
344 
345     DosSetPriority( PRTYS_THREAD,
346                     nOs2PriorityClass, nOs2PriorityDelta,
347                     pThreadImpl->m_ThreadId );
348 
349 }
350 
351 /*****************************************************************************/
352 /* osl_getThreadPriority  */
353 /*****************************************************************************/
354 
355 #define BYTE1FROMULONG(ul) ((UCHAR) (ul))
356 #define BYTE2FROMULONG(ul) ((UCHAR) ((ULONG) ul >> 8))
357 
358 oslThreadPriority  SAL_CALL osl_getThreadPriority(const oslThread Thread)
359 {
360     ULONG nOs2PriorityClass;
361     ULONG nOs2PriorityDelta;
362 
363     oslThreadPriority Priority;
364 
365     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
366 
367     /* invalid arguments ?*/
368     if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
369     {
370         return osl_Thread_PriorityUnknown;
371     }
372 
373     /* get current priorities */
374     {
375     PTIB pptib = NULL;
376     PPIB pppib = NULL;
377 
378     DosGetInfoBlocks( &pptib, &pppib );
379     nOs2PriorityClass = BYTE1FROMULONG( pptib->tib_ptib2->tib2_ulpri );
380     nOs2PriorityDelta = BYTE2FROMULONG( pptib->tib_ptib2->tib2_ulpri );
381     }
382 
383     /* map OS2 priority to enum */
384     switch(nOs2PriorityClass)
385     {
386     case PRTYC_TIMECRITICAL:
387         Priority= osl_Thread_PriorityHighest;
388         break;
389 
390     case PRTYC_REGULAR:
391 
392         if( nOs2PriorityDelta == 0 )
393         {
394             Priority= osl_Thread_PriorityNormal;
395             break;
396         }
397 
398         if( nOs2PriorityDelta < -16 )
399         {
400             Priority= osl_Thread_PriorityLowest;
401             break;
402         }
403 
404         if( nOs2PriorityDelta < 0 )
405         {
406             Priority= osl_Thread_PriorityBelowNormal;
407             break;
408         }
409 
410         if( nOs2PriorityDelta > 0 )
411         {
412             Priority= osl_Thread_PriorityAboveNormal;
413             break;
414         }
415 
416         Priority= osl_Thread_PriorityHighest;
417         break;
418 
419     case PRTYC_IDLETIME:
420         Priority= osl_Thread_PriorityLowest;
421         break;
422 
423     default:
424         OSL_ASSERT(FALSE);        /* OS/2 API changed, incorporate new prio-level! */
425 
426         /* release-version behaves friendly */
427         Priority= osl_Thread_PriorityUnknown;
428     }
429 
430     return Priority;
431 }
432 
433 /*****************************************************************************/
434 /* osl_isThreadRunning */
435 /*****************************************************************************/
436 sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
437 {
438     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
439     APIRET rc;
440 
441     /* invalid arguments ?*/
442     if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
443     {
444         return sal_False;
445     }
446 
447     if( osl_getThreadIdentifier( 0 ) == osl_getThreadIdentifier( Thread ) )
448         return sal_True;
449 
450     rc = DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_NOWAIT );
451 
452     return( rc != ERROR_INVALID_THREADID );
453 }
454 
455 /*****************************************************************************/
456 /* osl_joinWithThread */
457 /*****************************************************************************/
458 void SAL_CALL osl_joinWithThread(oslThread Thread)
459 {
460     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
461 
462     /* invalid arguments?*/
463     if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
464     {
465         /* assume thread is not running */
466         return;
467     }
468 
469     DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_WAIT );
470 }
471 
472 /*****************************************************************************/
473 /* osl_waitThread */
474 /*****************************************************************************/
475 void SAL_CALL osl_waitThread(const TimeValue* pDelay)
476 {
477     int millisecs;
478 
479     OSL_ASSERT(pDelay);
480 
481     millisecs = pDelay->Seconds * 1000 + pDelay->Nanosec / 1000000;
482 
483     DosSleep(millisecs);
484 }
485 
486 /*****************************************************************************/
487 /* osl_terminateThread */
488 /*****************************************************************************/
489 void SAL_CALL osl_terminateThread(oslThread Thread)
490 {
491     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
492 
493     /* invalid arguments?*/
494     if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
495     {
496         /* assume thread is not running */
497         return;
498     }
499 
500     DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
501     pThreadImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
502     DosReleaseMutexSem( MutexLock);
503 }
504 
505 
506 /*****************************************************************************/
507 /* osl_scheduleThread */
508 /*****************************************************************************/
509 sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
510 {
511     osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
512 
513     osl_yieldThread();
514 
515     /* invalid arguments?*/
516     if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
517     {
518         /* assume thread is not running */
519         return sal_False;
520     }
521 
522     if (pThreadImpl->m_Flags & THREADIMPL_FLAGS_SLEEP)
523     {
524         OSL_ASSERT (pThreadImpl->m_hEvent != 0);
525 
526         DosWaitEventSem(pThreadImpl->m_hEvent, pThreadImpl->m_Timeout);
527 
528         DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
529 
530         pThreadImpl->m_Timeout = 0;
531 
532         pThreadImpl->m_Flags &= ~THREADIMPL_FLAGS_SLEEP;
533 
534         DosReleaseMutexSem( MutexLock);
535     }
536 
537     return ((pThreadImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) == 0);
538 }
539 
540 /*****************************************************************************/
541 /* osl_yieldThread */
542 /*****************************************************************************/
543 void SAL_CALL osl_yieldThread()
544 {
545     DosSleep(0);
546 }
547 
548 void osl_setThreadName(char const * name) {
549     (void) name;
550 }
551 
552 typedef struct _TLS
553 {
554     PULONG                          pulPtr;
555     oslThreadKeyCallbackFunction    pfnCallback;
556     struct _TLS                     *pNext, *pPrev;
557 } TLS, *PTLS;
558 
559 static  PTLS        g_pThreadKeyList = NULL;
560 
561 static void AddKeyToList( PTLS pTls )
562 {
563     if ( pTls )
564     {
565         DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
566 
567         pTls->pNext = g_pThreadKeyList;
568         pTls->pPrev = 0;
569 
570         if ( g_pThreadKeyList )
571             g_pThreadKeyList->pPrev = pTls;
572 
573         g_pThreadKeyList = pTls;
574 
575         DosReleaseMutexSem( MutexLock);
576     }
577 }
578 
579 static void RemoveKeyFromList( PTLS pTls )
580 {
581     if ( pTls )
582     {
583         DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
584         if ( pTls->pPrev )
585             pTls->pPrev->pNext = pTls->pNext;
586         else
587         {
588             OSL_ASSERT( pTls == g_pThreadKeyList );
589             g_pThreadKeyList = pTls->pNext;
590         }
591 
592         if ( pTls->pNext )
593             pTls->pNext->pPrev = pTls->pPrev;
594         DosReleaseMutexSem( MutexLock);
595     }
596 }
597 
598 void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void)
599 {
600     PTLS    pTls;
601 
602     DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
603     pTls = g_pThreadKeyList;
604     while ( pTls )
605     {
606         if ( pTls->pfnCallback )
607         {
608             void    *pValue = (void*)*pTls->pulPtr;
609 
610             if ( pValue )
611                 pTls->pfnCallback( pValue );
612         }
613 
614         pTls = pTls->pNext;
615     }
616     DosReleaseMutexSem( MutexLock);
617 }
618 
619 /*****************************************************************************/
620 /* osl_createThreadKey */
621 /*****************************************************************************/
622 oslThreadKey SAL_CALL osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)
623 {
624     PTLS    pTls = (PTLS)rtl_allocateMemory( sizeof(TLS) );
625 
626     if ( pTls )
627     {
628         pTls->pfnCallback = pCallback;
629         if (DosAllocThreadLocalMemory(1, &pTls->pulPtr) != NO_ERROR)
630         {
631             rtl_freeMemory( pTls );
632             pTls = 0;
633         }
634         else
635         {
636             *pTls->pulPtr = 0;
637             AddKeyToList( pTls );
638         }
639     }
640 
641     return ((oslThreadKey)pTls);
642 }
643 
644 /*****************************************************************************/
645 /* osl_destroyThreadKey */
646 /*****************************************************************************/
647 void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
648 {
649     if (Key != 0)
650     {
651         PTLS    pTls = (PTLS)Key;
652 
653         RemoveKeyFromList( pTls );
654         DosFreeThreadLocalMemory(pTls->pulPtr);
655         rtl_freeMemory( pTls );
656     }
657 }
658 
659 /*****************************************************************************/
660 /* osl_getThreadKeyData */
661 /*****************************************************************************/
662 void * SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
663 {
664     if (Key != 0)
665     {
666         PTLS    pTls = (PTLS)Key;
667 
668         return ((void *) *pTls->pulPtr);
669     }
670 
671     return (NULL);
672 }
673 
674 /*****************************************************************************/
675 /* osl_setThreadKeyData */
676 /*****************************************************************************/
677 sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
678 {
679     if (Key != 0)
680     {
681         PTLS    pTls = (PTLS)Key;
682         void*   pOldData = NULL;
683         BOOL    fSuccess = TRUE; //YD cannot fail
684 
685         if ( pTls->pfnCallback )
686             pOldData = (void*)*pTls->pulPtr;
687 
688         *pTls->pulPtr = (ULONG)pData;
689 
690         if ( fSuccess && pTls->pfnCallback && pOldData )
691             pTls->pfnCallback( pOldData );
692 
693         return (sal_Bool)(fSuccess != FALSE);
694     }
695 
696     return (sal_False);
697 }
698 
699 
700 
701 /*****************************************************************************/
702 /* osl_getThreadTextEncoding */
703 /*****************************************************************************/
704 
705 ULONG   g_dwTLSTextEncodingIndex = (ULONG)-1;
706 
707 sal_uInt32 SAL_CALL _GetACP( void)
708 {
709     APIRET  rc;
710     ULONG   aulCpList[8]  = {0};
711     ULONG   ulListSize;
712 
713     rc = DosQueryCp( sizeof( aulCpList), aulCpList, &ulListSize);
714     if (rc)
715         return 437; // in case of error, return codepage EN_US
716     // current codepage is first of list, others are the prepared codepages.
717     return aulCpList[0];
718 }
719 
720 rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding(void)
721 {
722     rtl_TextEncoding    _encoding;
723 
724     if ( (ULONG)-1 == g_dwTLSTextEncodingIndex ) {
725         rtl_TextEncoding defaultEncoding;
726         const char *     pszEncoding;
727 
728         /* create thread specific data key */
729         g_dwTLSTextEncodingIndex = osl_createThreadKey( NULL);
730 
731         /* determine default text encoding */
732         pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
733         if (pszEncoding)
734             defaultEncoding = atoi(pszEncoding);
735         else
736             defaultEncoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP());
737 
738         //OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
739         //g_thread.m_textencoding.m_default = defaultEncoding;
740         osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)defaultEncoding);
741     }
742 
743     _encoding = (rtl_TextEncoding)osl_getThreadKeyData( g_dwTLSTextEncodingIndex );
744     if (0 == _encoding) {
745         const char *     pszEncoding;
746         /* determine default text encoding */
747         pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
748         if (pszEncoding)
749             _encoding = atoi(pszEncoding);
750         else
751             _encoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP());
752         /* save for future reference */
753         osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)_encoding);
754     }
755 
756     return _encoding;
757 }
758 
759 /*****************************************************************************/
760 /* osl_getThreadTextEncoding */
761 /*****************************************************************************/
762 rtl_TextEncoding SAL_CALL osl_setThreadTextEncoding( rtl_TextEncoding Encoding )
763 {
764     rtl_TextEncoding oldEncoding = osl_getThreadTextEncoding();
765 
766     osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)Encoding);
767 
768     return oldEncoding;
769 }
770 
771 
772 
773