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