Changeset 6954 in vbox for trunk/src/VBox/Runtime/r3/posix/tls-posix.cpp
- Timestamp:
- Feb 14, 2008 2:41:39 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/tls-posix.cpp
r6940 r6954 1 1 /* $Id$ */ 2 2 /** @file 3 * innotek Portable Runtime - Thread s, POSIX.3 * innotek Portable Runtime - Thread Local Storage (TLS), POSIX. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 200 6-2007innotek GmbH7 * Copyright (C) 2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 32 32 #include <errno.h> 33 33 #include <pthread.h> 34 #include <signal.h>35 #if defined(RT_OS_SOLARIS)36 # include <sched.h>37 #endif38 34 39 35 #include <iprt/thread.h> 40 36 #include <iprt/log.h> 41 37 #include <iprt/assert.h> 42 #include <iprt/asm.h>43 38 #include <iprt/err.h> 44 #include "internal/thread.h"45 39 46 40 47 /******************************************************************************* 48 * Header Files * 49 *******************************************************************************/ 50 /** The pthread key in which we store the pointer to our own PRTTHREAD structure. */ 51 static pthread_key_t g_SelfKey; 41 AssertCompile(sizeof(pthread_key_t) == sizeof(RTTLS)); 52 42 53 43 54 /******************************************************************************* 55 * Internal Functions * 56 *******************************************************************************/ 57 static void *rtThreadNativeMain(void *pvArgs); 58 static void rtThreadKeyDestruct(void *pvValue); 59 60 61 int rtThreadNativeInit(void) 44 RTR3DECL(int) RTTlsAlloc(void) 62 45 { 63 /* 64 * Allocate the TLS (key in posix terms) where we store the pointer to 65 * a threads RTTHREADINT structure. 66 */ 67 68 int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct); 46 pthread_key_t iTls = NIL_RTTLS; 47 int rc = pthread_key_create(&iTls, NULL); 69 48 if (!rc) 70 return VINF_SUCCESS; 71 return VERR_NO_TLS_FOR_SELF; 49 { 50 Assert((RTTLS)iTls != NIL_RTTLS); 51 return iTls; 52 } 53 return NIL_RTTLS; 72 54 } 73 55 74 56 75 /** 76 * Destructor called when a thread terminates. 77 * @param pvValue The key value. PRTTHREAD in our case. 78 */ 79 static void rtThreadKeyDestruct(void *pvValue) 57 RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor) 80 58 { 81 /* 82 * Deal with alien threads. 83 */ 84 PRTTHREADINT pThread = (PRTTHREADINT)pvValue; 85 if (pThread->fIntFlags & RTTHREADINT_FLAGS_ALIEN) 86 { 87 pthread_setspecific(g_SelfKey, pThread); 88 rtThreadTerminate(pThread, 0); 89 pthread_setspecific(g_SelfKey, NULL); 90 } 91 } 92 93 94 /** 95 * Adopts a thread, this is called immediately after allocating the 96 * thread structure. 97 * 98 * @param pThread Pointer to the thread structure. 99 */ 100 int rtThreadNativeAdopt(PRTTHREADINT pThread) 101 { 102 /* 103 * Block SIGALRM - required for timer-posix.cpp. 104 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling. 105 * It will not help much if someone creates threads directly using pthread_create. :/ 106 */ 107 sigset_t SigSet; 108 sigemptyset(&SigSet); 109 sigaddset(&SigSet, SIGALRM); 110 sigprocmask(SIG_BLOCK, &SigSet, NULL); 111 112 int rc = pthread_setspecific(g_SelfKey, pThread); 113 if (!rc) 114 return VINF_SUCCESS; 115 return VERR_FAILED_TO_SET_SELF_TLS; 116 } 117 118 119 /** 120 * Wrapper which unpacks the params and calls thread function. 121 */ 122 static void *rtThreadNativeMain(void *pvArgs) 123 { 124 PRTTHREADINT pThread = (PRTTHREADINT)pvArgs; 125 126 /* 127 * Block SIGALRM - required for timer-posix.cpp. 128 * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling. 129 * It will not help much if someone creates threads directly using pthread_create. :/ 130 */ 131 sigset_t SigSet; 132 sigemptyset(&SigSet); 133 sigaddset(&SigSet, SIGALRM); 134 sigprocmask(SIG_BLOCK, &SigSet, NULL); 135 136 int rc = pthread_setspecific(g_SelfKey, pThread); 137 AssertReleaseMsg(!rc, ("failed to set self TLS. rc=%d thread '%s'\n", rc, pThread->szName)); 138 139 /* 140 * Call common main. 141 */ 142 pthread_t Self = pthread_self(); 143 Assert((uintptr_t)Self == (RTNATIVETHREAD)Self && (uintptr_t)Self != NIL_RTNATIVETHREAD); 144 rc = rtThreadMain(pThread, (uintptr_t)Self, &pThread->szName[0]); 145 146 pthread_setspecific(g_SelfKey, NULL); 147 pthread_exit((void *)rc); 148 return (void *)rc; 149 } 150 151 152 int rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread) 153 { 154 /* 155 * Set the default stack size. 156 */ 157 if (!pThread->cbStack) 158 pThread->cbStack = 512*1024; 159 160 /* 161 * Setup thread attributes. 162 */ 163 pthread_attr_t ThreadAttr; 164 int rc = pthread_attr_init(&ThreadAttr); 59 pthread_key_t iTls = NIL_RTTLS; 60 int rc = pthread_key_create(&iTls, pfnDestructor); 165 61 if (!rc) 166 62 { 167 rc = pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_DETACHED); 168 if (!rc) 169 { 170 rc = pthread_attr_setstacksize(&ThreadAttr, pThread->cbStack); 171 if (!rc) 172 { 173 /* 174 * Create the thread. 175 */ 176 pthread_t ThreadId; 177 rc = pthread_create(&ThreadId, &ThreadAttr, rtThreadNativeMain, pThread); 178 if (!rc) 179 { 180 *pNativeThread = (uintptr_t)ThreadId; 181 return VINF_SUCCESS; 182 } 183 } 184 } 185 pthread_attr_destroy(&ThreadAttr); 63 *piTls = iTls; 64 Assert((pthread_key_t)*piTls == iTls); 65 Assert(*piTls != NIL_RTTLS); 66 return VINF_SUCCESS; 186 67 } 187 68 return RTErrConvertFromErrno(rc); … … 189 70 190 71 191 RT DECL(RTTHREAD) RTThreadSelf(void)72 RTR3DECL(int) RTTlsFree(RTTLS iTls) 192 73 { 193 PRTTHREADINT pThread = (PRTTHREADINT)pthread_getspecific(g_SelfKey); 194 /** @todo import alien threads? */ 195 return pThread; 74 if (iTls == NIL_RTTLS) 75 return VINF_SUCCESS; 76 int rc = pthread_key_delete(iTls); 77 if (!rc) 78 return VINF_SUCCESS; 79 return RTErrConvertFromErrno(rc); 196 80 } 197 81 198 82 199 RT DECL(RTNATIVETHREAD) RTThreadNativeSelf(void)83 RTR3DECL(void *) RTTlsGet(RTTLS iTls) 200 84 { 201 return (RTNATIVETHREAD)pthread_self();85 return pthread_getspecific(iTls); 202 86 } 203 87 204 88 205 RT DECL(int) RTThreadSleep(unsigned cMillies)89 RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue) 206 90 { 207 LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies)); 208 if (!cMillies) 209 { 210 /* pthread_yield() isn't part of SuS, thus this fun. */ 211 #ifdef RT_OS_DARWIN 212 pthread_yield_np(); 213 #elif defined(RT_OS_FREEBSD) /* void pthread_yield */ 214 pthread_yield(); 215 #elif defined(RT_OS_SOLARIS) 216 sched_yield(); 217 #else 218 if (!pthread_yield()) 219 #endif 220 { 221 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies)); 222 return VINF_SUCCESS; 223 } 224 } 225 else 226 { 227 struct timespec ts; 228 struct timespec tsrem = {0,0}; 229 230 ts.tv_nsec = (cMillies % 1000) * 1000000; 231 ts.tv_sec = cMillies / 1000; 232 if (!nanosleep(&ts, &tsrem)) 233 { 234 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", VINF_SUCCESS, cMillies)); 235 return VINF_SUCCESS; 236 } 237 } 238 239 int rc = RTErrConvertFromErrno(errno); 240 LogFlow(("RTThreadSleep: returning %Vrc (cMillies=%d)\n", rc, cMillies)); 241 return rc; 91 if (RT_UNLIKELY(iTls == NIL_RTTLS)) 92 return VERR_INVALID_PARAMETER; 93 *ppvValue = pthread_getspecific(iTls); 94 return VINF_SUCCESS; 242 95 } 243 96 244 97 245 RT DECL(bool) RTThreadYield(void)98 RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue) 246 99 { 247 uint64_t u64TS = ASMReadTSC(); 248 #ifdef RT_OS_DARWIN 249 pthread_yield_np(); 250 #elif defined(RT_OS_SOLARIS) 251 sched_yield(); 252 #else 253 pthread_yield(); 254 #endif 255 u64TS = ASMReadTSC() - u64TS; 256 bool fRc = u64TS > 1500; 257 LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS)); 258 return fRc; 259 } 260 261 262 RTR3DECL(uint64_t) RTThreadGetAffinity(void) 263 { 264 return 1; 265 } 266 267 268 RTR3DECL(int) RTThreadSetAffinity(uint64_t u64Mask) 269 { 270 if (u64Mask != 1) 271 return VERR_INVALID_PARAMETER; 100 int rc = pthread_setspecific(iTls, pvValue); 101 if (RT_UNLIKELY(rc != 0)) 102 return RTErrConvertFromErrno(rc); 272 103 return VINF_SUCCESS; 273 104 }
Note:
See TracChangeset
for help on using the changeset viewer.