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