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