1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
31 #include <osl/diagnose.h>
32 #include <osl/thread.h>
34 #include <rtl/alloc.h>
35 #include <rtl/tencinfo.h>
38 Thread-data structure hidden behind oslThread:
40 typedef struct _osl_TThreadImpl
43 TID m_ThreadId
; /* identifier for this thread */
47 oslWorkerFunction m_WorkerFunction
;
49 sal_Bool m_StartSuspended
;
55 #define THREADIMPL_FLAGS_TERMINATE 0x0001
56 #define THREADIMPL_FLAGS_SLEEP 0x0002
59 // static mutex to control access to private members of oslMutexImpl
60 static HMTX MutexLock
= NULL
;
62 /*****************************************************************************/
64 HAB
osl_getPMinternal_HAB(oslThread hThread
)
66 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)hThread
;
68 if(pThreadImpl
== NULL
) /* valid ptr? */
74 return pThreadImpl
->m_hab
;
78 HMQ
osl_getPMinternal_HMQ(oslThread hThread
)
80 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)hThread
;
82 if(pThreadImpl
== NULL
) /* valid ptr? */
88 return pThreadImpl
->m_hmq
;
93 /*****************************************************************************/
94 /* oslWorkerWrapperFunction */
95 /*****************************************************************************/
96 static void oslWorkerWrapperFunction(void* pData
)
99 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)pData
;
101 #if OSL_DEBUG_LEVEL>0
102 printf("oslWorkerWrapperFunction pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl
, pThreadImpl
->m_ThreadId
);
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
);
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
);
114 /* call worker-function with data */
115 pThreadImpl
->m_WorkerFunction( pThreadImpl
->m_pData
);
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
);
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
);
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
);
133 /*****************************************************************************/
134 /* oslCreateThread */
135 /*****************************************************************************/
136 static oslThread
oslCreateThread(oslWorkerFunction pWorker
,
140 osl_TThreadImpl
* pThreadImpl
;
142 /* alloc mem. for our internal data structure */
143 pThreadImpl
= (osl_TThreadImpl
*)malloc(sizeof(osl_TThreadImpl
));
145 OSL_ASSERT(pThreadImpl
);
147 pThreadImpl
->m_WorkerFunction
= pWorker
;
148 pThreadImpl
->m_pData
= pThreadData
;
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;
157 if ( nFlags
== sal_True
)
159 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
162 pThreadImpl
->m_ThreadId
= (TID
) _beginthread( oslWorkerWrapperFunction
, /* worker-function */
163 NULL
, /* unused parameter */
164 1024*1024, /* max. Stacksize */
166 if ( nFlags
== sal_True
)
168 if( pThreadImpl
->m_ThreadId
!= -1 )
169 DosSuspendThread( pThreadImpl
->m_ThreadId
);
170 DosReleaseMutexSem( MutexLock
);
172 #if OSL_DEBUG_LEVEL>0
173 printf("oslCreateThread pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl
, pThreadImpl
->m_ThreadId
);
175 if(pThreadImpl
->m_ThreadId
== -1)
178 if (pThreadImpl
->m_hEvent
!= 0)
179 DosCloseEventSem(pThreadImpl
->m_hEvent
);
185 pThreadImpl
->m_hEvent
= 0;
191 /*****************************************************************************/
192 /* osl_createThread */
193 /*****************************************************************************/
194 oslThread SAL_CALL
osl_createThread(oslWorkerFunction pWorker
,
197 return oslCreateThread(pWorker
,pThreadData
,sal_False
);
200 /*****************************************************************************/
201 /* osl_createSuspendedThread */
202 /*****************************************************************************/
203 oslThread SAL_CALL
osl_createSuspendedThread(oslWorkerFunction pWorker
,
206 return oslCreateThread(pWorker
,pThreadData
,sal_True
);
209 /*****************************************************************************/
210 /* osl_getThreadIdentifier */
211 /*****************************************************************************/
212 oslThreadIdentifier SAL_CALL
osl_getThreadIdentifier(oslThread Thread
)
214 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
216 if (pThreadImpl
!= NULL
)
217 return ((oslThreadIdentifier
)pThreadImpl
->m_ThreadId
);
223 DosGetInfoBlocks( &pptib
, &pppib
);
224 return ((oslThreadIdentifier
) pptib
->tib_ptib2
->tib2_ultid
);
228 /*****************************************************************************/
229 /* osl_destroyThread */
230 /*****************************************************************************/
231 void SAL_CALL
osl_destroyThread(oslThread Thread
)
233 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
235 if(Thread
== 0) /* valid ptr? */
237 /* thread already destroyed or not created */
241 if(pThreadImpl
->m_ThreadId
!= -1) /* valid handle ? */
244 DosKillThread( pThreadImpl
->m_ThreadId
);
248 /*****************************************************************************/
249 /* osl_freeThreadHandle */
250 /*****************************************************************************/
251 void SAL_CALL
osl_freeThreadHandle(oslThread Thread
)
253 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
255 if(Thread
== 0) /* valid ptr? */
257 /* thread already destroyed or not created */
261 if (pThreadImpl
->m_hEvent
!= 0)
262 DosCloseEventSem(pThreadImpl
->m_hEvent
);
268 /*****************************************************************************/
269 /* osl_resumeThread */
270 /*****************************************************************************/
271 void SAL_CALL
osl_resumeThread(oslThread Thread
)
273 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
275 OSL_ASSERT(pThreadImpl
); /* valid ptr? */
277 DosResumeThread( pThreadImpl
->m_ThreadId
);
280 /*****************************************************************************/
281 /* osl_suspendThread */
282 /*****************************************************************************/
283 void SAL_CALL
osl_suspendThread(oslThread Thread
)
285 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
287 OSL_ASSERT(pThreadImpl
); /* valid ptr? */
289 DosSuspendThread( pThreadImpl
->m_ThreadId
);
292 /*****************************************************************************/
293 /* osl_setThreadPriority */
294 /*****************************************************************************/
295 void SAL_CALL
osl_setThreadPriority(oslThread Thread
,
296 oslThreadPriority Priority
)
298 ULONG nOs2PriorityClass
;
299 ULONG nOs2PriorityDelta
;
300 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
302 OSL_ASSERT(pThreadImpl
); /* valid ptr? */
306 case osl_Thread_PriorityHighest
:
308 nOs2PriorityClass
= PRTYC_REGULAR
;
309 nOs2PriorityDelta
= PRTYD_MAXIMUM
;
312 case osl_Thread_PriorityAboveNormal
:
314 nOs2PriorityClass
= PRTYC_REGULAR
;
315 nOs2PriorityDelta
= 16;
318 case osl_Thread_PriorityNormal
:
320 nOs2PriorityClass
= PRTYC_REGULAR
;
321 nOs2PriorityDelta
= 0;
324 case osl_Thread_PriorityBelowNormal
:
326 nOs2PriorityClass
= PRTYC_REGULAR
;
327 nOs2PriorityDelta
= -16;
330 case osl_Thread_PriorityLowest
:
332 nOs2PriorityClass
= PRTYC_REGULAR
;
333 nOs2PriorityDelta
= PRTYD_MINIMUM
;
336 case osl_Thread_PriorityUnknown
:
337 OSL_ASSERT(FALSE
); /* only fools try this...*/
339 /* let release-version behave friendly */
343 OSL_ASSERT(FALSE
); /* enum expanded, but forgotten here...*/
345 /* let release-version behave friendly */
349 DosSetPriority( PRTYS_THREAD
,
350 nOs2PriorityClass
, nOs2PriorityDelta
,
351 pThreadImpl
->m_ThreadId
);
355 /*****************************************************************************/
356 /* osl_getThreadPriority */
357 /*****************************************************************************/
359 #define BYTE1FROMULONG(ul) ((UCHAR) (ul))
360 #define BYTE2FROMULONG(ul) ((UCHAR) ((ULONG) ul >> 8))
362 oslThreadPriority SAL_CALL
osl_getThreadPriority(const oslThread Thread
)
364 ULONG nOs2PriorityClass
;
365 ULONG nOs2PriorityDelta
;
367 oslThreadPriority Priority
;
369 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
371 /* invalid arguments ?*/
372 if(pThreadImpl
==0 || pThreadImpl
->m_ThreadId
==-1)
374 return osl_Thread_PriorityUnknown
;
377 /* get current priorities */
382 DosGetInfoBlocks( &pptib
, &pppib
);
383 nOs2PriorityClass
= BYTE1FROMULONG( pptib
->tib_ptib2
->tib2_ulpri
);
384 nOs2PriorityDelta
= BYTE2FROMULONG( pptib
->tib_ptib2
->tib2_ulpri
);
387 /* map OS2 priority to enum */
388 switch(nOs2PriorityClass
)
390 case PRTYC_TIMECRITICAL
:
391 Priority
= osl_Thread_PriorityHighest
;
396 if( nOs2PriorityDelta
== 0 )
398 Priority
= osl_Thread_PriorityNormal
;
402 if( nOs2PriorityDelta
< -16 )
404 Priority
= osl_Thread_PriorityLowest
;
408 if( nOs2PriorityDelta
< 0 )
410 Priority
= osl_Thread_PriorityBelowNormal
;
414 if( nOs2PriorityDelta
> 0 )
416 Priority
= osl_Thread_PriorityAboveNormal
;
420 Priority
= osl_Thread_PriorityHighest
;
424 Priority
= osl_Thread_PriorityLowest
;
428 OSL_ASSERT(FALSE
); /* OS/2 API changed, incorporate new prio-level! */
430 /* release-version behaves friendly */
431 Priority
= osl_Thread_PriorityUnknown
;
437 /*****************************************************************************/
438 /* osl_isThreadRunning */
439 /*****************************************************************************/
440 sal_Bool SAL_CALL
osl_isThreadRunning(const oslThread Thread
)
442 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
445 /* invalid arguments ?*/
446 if(pThreadImpl
==0 || pThreadImpl
->m_ThreadId
==-1)
451 if( osl_getThreadIdentifier( 0 ) == osl_getThreadIdentifier( Thread
) )
454 rc
= DosWaitThread( &pThreadImpl
->m_ThreadId
, DCWW_NOWAIT
);
456 return( rc
!= ERROR_INVALID_THREADID
);
459 /*****************************************************************************/
460 /* osl_joinWithThread */
461 /*****************************************************************************/
462 void SAL_CALL
osl_joinWithThread(oslThread Thread
)
464 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
466 /* invalid arguments?*/
467 if(pThreadImpl
==0 || pThreadImpl
->m_ThreadId
==-1)
469 /* assume thread is not running */
473 DosWaitThread( &pThreadImpl
->m_ThreadId
, DCWW_WAIT
);
476 /*****************************************************************************/
478 /*****************************************************************************/
479 void SAL_CALL
osl_waitThread(const TimeValue
* pDelay
)
485 millisecs
= pDelay
->Seconds
* 1000 + pDelay
->Nanosec
/ 1000000;
490 /*****************************************************************************/
491 /* osl_terminateThread */
492 /*****************************************************************************/
493 void SAL_CALL
osl_terminateThread(oslThread Thread
)
495 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
497 /* invalid arguments?*/
498 if (pThreadImpl
==0 || pThreadImpl
->m_ThreadId
==-1)
500 /* assume thread is not running */
504 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
505 pThreadImpl
->m_Flags
|= THREADIMPL_FLAGS_TERMINATE
;
506 DosReleaseMutexSem( MutexLock
);
510 /*****************************************************************************/
511 /* osl_scheduleThread */
512 /*****************************************************************************/
513 sal_Bool SAL_CALL
osl_scheduleThread(oslThread Thread
)
515 osl_TThreadImpl
* pThreadImpl
= (osl_TThreadImpl
*)Thread
;
519 /* invalid arguments?*/
520 if (pThreadImpl
==0 || pThreadImpl
->m_ThreadId
==-1)
522 /* assume thread is not running */
526 if (pThreadImpl
->m_Flags
& THREADIMPL_FLAGS_SLEEP
)
528 OSL_ASSERT (pThreadImpl
->m_hEvent
!= 0);
530 DosWaitEventSem(pThreadImpl
->m_hEvent
, pThreadImpl
->m_Timeout
);
532 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
534 pThreadImpl
->m_Timeout
= 0;
536 pThreadImpl
->m_Flags
&= ~THREADIMPL_FLAGS_SLEEP
;
538 DosReleaseMutexSem( MutexLock
);
541 return ((pThreadImpl
->m_Flags
& THREADIMPL_FLAGS_TERMINATE
) == 0);
544 /*****************************************************************************/
545 /* osl_yieldThread */
546 /*****************************************************************************/
547 void SAL_CALL
osl_yieldThread()
552 void osl_setThreadName(char const * name
) {
559 oslThreadKeyCallbackFunction pfnCallback
;
560 struct _TLS
*pNext
, *pPrev
;
563 static PTLS g_pThreadKeyList
= NULL
;
565 static void AddKeyToList( PTLS pTls
)
569 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
571 pTls
->pNext
= g_pThreadKeyList
;
574 if ( g_pThreadKeyList
)
575 g_pThreadKeyList
->pPrev
= pTls
;
577 g_pThreadKeyList
= pTls
;
579 DosReleaseMutexSem( MutexLock
);
583 static void RemoveKeyFromList( PTLS pTls
)
587 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
589 pTls
->pPrev
->pNext
= pTls
->pNext
;
592 OSL_ASSERT( pTls
== g_pThreadKeyList
);
593 g_pThreadKeyList
= pTls
->pNext
;
597 pTls
->pNext
->pPrev
= pTls
->pPrev
;
598 DosReleaseMutexSem( MutexLock
);
602 void SAL_CALL
_osl_callThreadKeyCallbackOnThreadDetach(void)
606 DosRequestMutexSem( MutexLock
, SEM_INDEFINITE_WAIT
);
607 pTls
= g_pThreadKeyList
;
610 if ( pTls
->pfnCallback
)
612 void *pValue
= (void*)*pTls
->pulPtr
;
615 pTls
->pfnCallback( pValue
);
620 DosReleaseMutexSem( MutexLock
);
623 /*****************************************************************************/
624 /* osl_createThreadKey */
625 /*****************************************************************************/
626 oslThreadKey SAL_CALL
osl_createThreadKey(oslThreadKeyCallbackFunction pCallback
)
628 PTLS pTls
= (PTLS
)rtl_allocateMemory( sizeof(TLS
) );
632 pTls
->pfnCallback
= pCallback
;
633 if (DosAllocThreadLocalMemory(1, &pTls
->pulPtr
) != NO_ERROR
)
635 rtl_freeMemory( pTls
);
641 AddKeyToList( pTls
);
645 return ((oslThreadKey
)pTls
);
648 /*****************************************************************************/
649 /* osl_destroyThreadKey */
650 /*****************************************************************************/
651 void SAL_CALL
osl_destroyThreadKey(oslThreadKey Key
)
655 PTLS pTls
= (PTLS
)Key
;
657 RemoveKeyFromList( pTls
);
658 DosFreeThreadLocalMemory(pTls
->pulPtr
);
659 rtl_freeMemory( pTls
);
663 /*****************************************************************************/
664 /* osl_getThreadKeyData */
665 /*****************************************************************************/
666 void * SAL_CALL
osl_getThreadKeyData(oslThreadKey Key
)
670 PTLS pTls
= (PTLS
)Key
;
672 return ((void *) *pTls
->pulPtr
);
678 /*****************************************************************************/
679 /* osl_setThreadKeyData */
680 /*****************************************************************************/
681 sal_Bool SAL_CALL
osl_setThreadKeyData(oslThreadKey Key
, void *pData
)
685 PTLS pTls
= (PTLS
)Key
;
686 void* pOldData
= NULL
;
687 BOOL fSuccess
= TRUE
; //YD cannot fail
689 if ( pTls
->pfnCallback
)
690 pOldData
= (void*)*pTls
->pulPtr
;
692 *pTls
->pulPtr
= (ULONG
)pData
;
694 if ( fSuccess
&& pTls
->pfnCallback
&& pOldData
)
695 pTls
->pfnCallback( pOldData
);
697 return (sal_Bool
)(fSuccess
!= FALSE
);
705 /*****************************************************************************/
706 /* osl_getThreadTextEncoding */
707 /*****************************************************************************/
709 ULONG g_dwTLSTextEncodingIndex
= (ULONG
)-1;
711 sal_uInt32 SAL_CALL
_GetACP( void)
714 ULONG aulCpList
[8] = {0};
717 rc
= DosQueryCp( sizeof( aulCpList
), aulCpList
, &ulListSize
);
719 return 437; // in case of error, return codepage EN_US
720 // current codepage is first of list, others are the prepared codepages.
724 rtl_TextEncoding SAL_CALL
osl_getThreadTextEncoding(void)
726 rtl_TextEncoding _encoding
;
728 if ( (ULONG
)-1 == g_dwTLSTextEncodingIndex
) {
729 rtl_TextEncoding defaultEncoding
;
730 const char * pszEncoding
;
732 /* create thread specific data key */
733 g_dwTLSTextEncodingIndex
= osl_createThreadKey( NULL
);
735 /* determine default text encoding */
736 pszEncoding
= getenv ("SOLAR_USER_RTL_TEXTENCODING");
738 defaultEncoding
= atoi(pszEncoding
);
740 defaultEncoding
= rtl_getTextEncodingFromWindowsCodePage( _GetACP());
742 //OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
743 //g_thread.m_textencoding.m_default = defaultEncoding;
744 osl_setThreadKeyData( g_dwTLSTextEncodingIndex
, (void*)defaultEncoding
);
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");
753 _encoding
= atoi(pszEncoding
);
755 _encoding
= rtl_getTextEncodingFromWindowsCodePage( _GetACP());
756 /* save for future reference */
757 osl_setThreadKeyData( g_dwTLSTextEncodingIndex
, (void*)_encoding
);
763 /*****************************************************************************/
764 /* osl_getThreadTextEncoding */
765 /*****************************************************************************/
766 rtl_TextEncoding SAL_CALL
osl_setThreadTextEncoding( rtl_TextEncoding Encoding
)
768 rtl_TextEncoding oldEncoding
= osl_getThreadTextEncoding();
770 osl_setThreadKeyData( g_dwTLSTextEncodingIndex
, (void*)Encoding
);