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