- Timestamp:
- Oct 10, 2004, 1:14:29 PM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/emx/src/lib/process/thread_internals.c
-
Property cvs2svn:cvs-rev
changed from
1.5
to1.6
r1574 r1575 35 35 #include <errno.h> 36 36 #include <sys/smutex.h> 37 #include <sys/builtin.h> 38 #include <sys/fmutex.h> 37 39 #include <emx/umalloc.h> 38 40 #include <emx/syscalls.h> 39 41 #include <InnoTekLIBC/thread.h> 40 42 #include <InnoTekLIBC/backend.h> 43 #include <InnoTekLIBC/signals.h> 41 44 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_THREAD 42 45 #include <InnoTekLIBC/logstrict.h> … … 51 54 static int gfPreAllocThrd; 52 55 56 /** Mutex for the thread database. */ 57 static _fmutex gmtxThrdDB; 58 /** Thread database. (Protected gmtxThrdDB.) */ 59 static __LIBC_PTHREAD gpThrdDB; 60 /** Number of threads in the thread database. (Protected gmtxThrdDB.) */ 61 static unsigned gcThrdDBEntries; 62 /** Zombie thread database. (Protected gmtxThrdDB.) */ 63 static __LIBC_PTHREAD gpThrdDBZombies; 64 /** Number of threads in the zombie thread database. (Protected gmtxThrdDB.) */ 65 static unsigned gcThrdDBZombies; 66 53 67 /** Head of the thread termination callback list. */ 54 68 static __LIBC_PTHREADTERMCBREGREC gpTermHead; … … 63 77 * Initialize a thread structure. 64 78 * 65 * @param pThrd Pointer to the thread structure which is to be initialized. 79 * @param pThrd Pointer to the thread structure which is to be initialized. 80 * @param pParentThrd Pointer to the thread structure for the parent thread. 81 * If NULL and thread id is 1 then inherit from parent process. 82 * If NULL and thread is not null or no record of parent then 83 * use defaults. 66 84 */ 67 static void threadInit(__LIBC_PTHREAD pThrd )85 static void threadInit(__LIBC_PTHREAD pThrd, const __LIBC_PTHREAD pParentThrd) 68 86 { 69 87 bzero(pThrd, sizeof(*pThrd)); 70 88 pThrd->iRand = 1; 71 __libc_Back_threadInit(pThrd); 89 pThrd->cRefs = 1; 90 /* ASSUMES sigemptyset() is equivalent with memsetting a sigset_t. */ 91 if (pParentThrd) 92 { 93 /* 94 * Gain exclusive access to the signal stuff. 95 */ 96 int rc = __libc_back_signalSemRequest(); 97 98 /* 99 * Copy signal stuff. 100 */ 101 pThrd->SigSetBlocked = pParentThrd->SigSetBlocked; 102 if (pParentThrd->fSigSetBlockedOld) 103 { 104 pThrd->SigSetBlockedOld = pParentThrd->SigSetBlockedOld; 105 pThrd->fSigSetBlockedOld = pParentThrd->fSigSetBlockedOld; 106 } 107 108 /* 109 * Release semaphore. 110 */ 111 if (!rc) 112 __libc_back_signalSemRelease(); 113 } 114 else 115 { 116 /** @todo try find info from parent process. */ 117 } 118 119 __libc_Back_threadInit(pThrd, pParentThrd); 120 } 121 122 123 void __libc_threadUse(__LIBC_PTHREAD pThrd) 124 { 125 LIBCLOG_ENTER("pThrd=%p\n", (void *)pThrd); 126 int rc; 127 128 /* 129 * Check that pThrd isn't already in use and set gpTLS to point at pThrd. 130 */ 131 assert(!pThrd->pNext && !pThrd->tid && !*__libc_gpTLS); 132 *__libc_gpTLS = pThrd; 133 134 /* 135 * Set the thread id of this thread. 136 */ 137 pThrd->tid = _gettid(); 138 139 /* 140 * Insert this thread into the thread database. 141 * Note that there might be a dead thread by the same id in the database. 142 * This have to be removed of course. 143 */ 144 /** @todo rewrite to use a read/write semaphore, not mutex. */ 145 if (gmtxThrdDB.fs == _FMS_UNINIT) 146 _fmutex_create(&gmtxThrdDB, 0); 147 148 rc = _fmutex_request(&gmtxThrdDB, 0); 149 if (!rc) 150 { 151 /* Remove any zombie threads. */ 152 __LIBC_PTHREAD pPrev = NULL; 153 __LIBC_PTHREAD p = gpThrdDB; 154 while (p) 155 { 156 if (p->tid == pThrd->tid) 157 { 158 /* remove it and place it in the zombie list */ 159 __LIBC_PTHREAD pNext = p->pNext; 160 if (pPrev) 161 pPrev->pNext = pNext; 162 else 163 gpThrdDB = pNext; 164 gcThrdDBEntries--; 165 166 p->pNext = gpThrdDBZombies; 167 gpThrdDBZombies = p; 168 gcThrdDBZombies++; 169 p = pNext; 170 /* paranoid as always, we continue scanning the entire list. */ 171 } 172 else 173 { 174 /* next */ 175 pPrev = p; 176 p = p->pNext; 177 } 178 } 179 180 /* Insert it */ 181 pThrd->pNext = gpThrdDB; 182 gpThrdDB = pThrd; 183 gcThrdDBEntries++; 184 185 _fmutex_release(&gmtxThrdDB); 186 } 187 188 LIBCLOG_RETURN_VOID(); 72 189 } 73 190 … … 81 198 /* 82 199 * Setup a temporary thread block on the stack so _hmalloc() 83 * can't end up calling us recursivly if something goes wrong 200 * can't end up calling us recursivly if something goes wrong. 84 201 */ 85 202 __LIBC_THREAD Thrd; 86 threadInit(&Thrd );203 threadInit(&Thrd, NULL); 87 204 *__libc_gpTLS = &Thrd; 88 205 … … 92 209 { 93 210 pThrd = _hmalloc(sizeof(__LIBC_THREAD)); 94 assert(pThrd); /* deep, deep, de pp, shit. abort the process in a controlled manner... */211 assert(pThrd); /* deep, deep, deep, shit. abort the process in a controlled manner... */ 95 212 } 96 213 *pThrd = Thrd; 97 214 98 *__libc_gpTLS = pThrd;99 LIBCLOG_MSG("Created thread block %p\n", pThrd);215 __libc_threadUse(pThrd); 216 LIBCLOG_MSG("Created thread block %p\n", (void*)pThrd); 100 217 } 101 218 … … 113 230 __LIBC_PTHREAD pThrd = _hmalloc(sizeof(__LIBC_THREAD)); 114 231 if (pThrd) 115 threadInit(pThrd );232 threadInit(pThrd, __libc_threadCurrentNoAuto()); 116 233 LIBCLOG_RETURN_P(pThrd); 117 234 } 118 235 119 236 120 void __libc_threadFree(__LIBC_PTHREAD pThrd) 121 { 122 LIBCLOG_ENTER("pThrd=%p\n", (void *)pThrd); 123 /* 124 * Clean up members. 125 */ 126 __libc_Back_threadCleanup(pThrd); 127 128 /* 129 * Release storage. 130 */ 131 if (pThrd != &gPreAllocThrd) 132 free(pThrd); 133 else 134 __lxchg(&gfPreAllocThrd, 0); 135 LIBCLOG_RETURN_VOID(); 136 } 137 237 void __libc_threadDereference(__LIBC_PTHREAD pThrd) 238 { 239 LIBCLOG_ENTER("pThrd=%p (tid=%d)\n", (void *)pThrd, pThrd->tid); 240 /* 241 * Take owner ship of the DB semaphore. 242 */ 243 _fmutex_request(&gmtxThrdDB, 0); 244 if (pThrd->cRefs) 245 pThrd->cRefs--; 246 if (pThrd->cRefs) 247 { 248 #ifdef DEBUG_LOGGING 249 unsigned cRefs = pThrd->cRefs; 250 #endif 251 _fmutex_release(&gmtxThrdDB); 252 LIBCLOG_RETURN_MSG_VOID("ret void. cRefs=%d\n", cRefs); 253 } 254 LIBCLOG_MSG("unlinking and disposing the thread.\n"); 255 256 /* 257 * Thread is dead, unlink it. 258 */ 259 if (pThrd->tid) 260 { 261 if (pThrd == gpThrdDB) 262 { 263 gpThrdDB = pThrd->pNext; 264 gcThrdDBEntries--; 265 } 266 else 267 { 268 __LIBC_PTHREAD p; 269 for (p = gpThrdDB; p->pNext; p = p->pNext) 270 if (p->pNext == pThrd) 271 { 272 p->pNext = pThrd->pNext; 273 gcThrdDBEntries--; 274 p = NULL; 275 break; 276 } 277 278 /* not found? search zombie DB. */ 279 if (p) 280 { 281 if (gpThrdDBZombies == pThrd) 282 { 283 gpThrdDBZombies = pThrd->pNext; 284 gcThrdDBZombies--; 285 } 286 else 287 { 288 for (p = gpThrdDBZombies; p->pNext; p = p->pNext) 289 if (p->pNext == pThrd) 290 { 291 p->pNext = pThrd->pNext; 292 gcThrdDBZombies--; 293 p = NULL; 294 break; 295 } 296 } 297 } 298 299 assert(p); /* it must be found! */ 300 if (p) 301 pThrd = NULL; 302 } 303 } 304 305 _fmutex_release(&gmtxThrdDB); 306 307 308 /* 309 * Dispose of the thread 310 */ 311 if (pThrd) 312 { 313 /* 314 * Clean up members. 315 */ 316 __libc_Back_threadCleanup(pThrd); 317 318 /* 319 * Clear the TLS if it's for the current thread. 320 */ 321 if (*__libc_gpTLS == pThrd) 322 *__libc_gpTLS = NULL; 323 324 /* 325 * Release storage. 326 */ 327 if (pThrd != &gPreAllocThrd) 328 free(pThrd); 329 else 330 __lxchg(&gfPreAllocThrd, 0); 331 } 332 333 LIBCLOG_RETURN_MSG_VOID("ret (gcThrdDBEntires=%d gcThrdDBZombies=%d)\n", gcThrdDBEntries, gcThrdDBZombies); 334 } 335 336 337 __LIBC_PTHREAD __libc_threadLookup(unsigned tid) 338 { 339 LIBCLOG_ENTER("tid=%d\n", tid); 340 int rc; 341 __LIBC_PTHREAD pThrd; 342 343 /* can't search something which isn't there. */ 344 if (gmtxThrdDB.fs == _FMS_UNINIT) 345 LIBCLOG_RETURN_P(NULL); 346 347 rc = _fmutex_request(&gmtxThrdDB, 0); 348 if (rc) 349 LIBCLOG_RETURN_MSG(NULL, "ret NULL (fmutex f**ked. rc=%d)\n", rc); 350 351 for (pThrd = gpThrdDB; pThrd; pThrd = pThrd->pNext) 352 if (pThrd->tid == tid) 353 { 354 pThrd->cRefs++; 355 break; 356 } 357 358 _fmutex_release(&gmtxThrdDB); 359 360 LIBCLOG_RETURN_P(pThrd); 361 } 362 363 364 __LIBC_PTHREAD __libc_threadLookup2(int (pfnCallback)(__LIBC_PTHREAD pCur, __LIBC_PTHREAD pBest, void *pvParam), void *pvParam) 365 { 366 LIBCLOG_ENTER("pfnCallback=%p pvParam=%p\n", (void *)pfnCallback, pvParam); 367 int rc; 368 __LIBC_PTHREAD pThrd; 369 __LIBC_PTHREAD pBest = NULL; 370 371 /* can't search something which isn't there. */ 372 if (gmtxThrdDB.fs == _FMS_UNINIT) 373 LIBCLOG_RETURN_P(NULL); 374 375 rc = _fmutex_request(&gmtxThrdDB, 0); 376 if (rc) 377 LIBCLOG_RETURN_MSG(NULL, "ret NULL (fmutex f**ked. rc=%d)\n", rc); 378 379 for (pThrd = gpThrdDB; pThrd; pThrd = pThrd->pNext) 380 { 381 rc = pfnCallback(pThrd, pBest, pvParam); 382 if (rc == 0) 383 continue; 384 else if (rc == 1) 385 { 386 pBest = pThrd; 387 continue; 388 } 389 else if (rc == 2) 390 { 391 pBest = pThrd; 392 break; 393 } 394 else if (rc == -1) 395 break; 396 else 397 { 398 LIBC_ASSERTM_FAILED("Callback returned %d, allowed values are 2, 1, 0 and -1!\n", rc); 399 break; 400 } 401 } 402 403 if (pBest) 404 pBest->cRefs++; 405 406 _fmutex_release(&gmtxThrdDB); 407 408 LIBCLOG_RETURN_MSG(pBest, "ret %p (tid=%d)\n", (void *)pBest, pBest ? pBest->tid : 0); 409 } 410 411 412 413 int __libc_threadEnum(int (pfnCallback)(__LIBC_PTHREAD pCur, void *pvParam), void *pvParam) 414 { 415 LIBCLOG_ENTER("pfnCallback=%p pvParam=%p\n", (void *)pfnCallback, pvParam); 416 int rc; 417 __LIBC_PTHREAD pThrd; 418 419 /* can't search something which isn't there. */ 420 if (gmtxThrdDB.fs == _FMS_UNINIT) 421 LIBCLOG_RETURN_P(NULL); 422 423 rc = _fmutex_request(&gmtxThrdDB, 0); 424 if (rc) 425 LIBCLOG_RETURN_MSG(NULL, "ret NULL (fmutex f**ked. rc=%d)\n", rc); 426 427 for (pThrd = gpThrdDB; pThrd; pThrd = pThrd->pNext) 428 { 429 rc = pfnCallback(pThrd, pvParam); 430 if (rc == 0) 431 continue; 432 else if (rc == -1) 433 break; 434 else 435 { 436 LIBC_ASSERTM_FAILED("Callback returned %d, allowed values are 0 and -1!\n", rc); 437 break; 438 } 439 } 440 441 _fmutex_release(&gmtxThrdDB); 442 443 LIBCLOG_RETURN_INT(rc); 444 } 138 445 139 446 int __libc_ThreadRegisterTermCallback(__LIBC_PTHREADTERMCBREGREC pRegRec) … … 151 458 || pRegRec->fFlags) 152 459 { 153 LIBC_ASSERTM(!pRegRec->pNext, "pNext must be NULL not %p\n", pRegRec->pNext);460 LIBC_ASSERTM(!pRegRec->pNext, "pNext must be NULL not %p\n", (void * )pRegRec->pNext); 154 461 LIBC_ASSERTM(pRegRec->pfnCallback, "pfnCallback not be NULL\n"); 155 462 LIBC_ASSERTM(!pRegRec->fFlags, "fFlags must be ZERO not %u\n", pRegRec->fFlags); … … 175 482 { 176 483 _smutex_release(&gsmtxTerm); 177 LIBC_ASSERTM_FAILED("Double registration of %p\n", pRegRec);484 LIBC_ASSERTM_FAILED("Double registration of %p\n", (void *)pRegRec); 178 485 LIBCLOG_RETURN_INT(-1); 179 486 } … … 201 508 { 202 509 /* call it */ 203 LIBCLOG_MSG("calling %p with %p\n", pCur->pfnCallback,pCur);510 LIBCLOG_MSG("calling %p with %p\n", (void *)pCur->pfnCallback, (void *)pCur); 204 511 pCur->pfnCallback(pCur, fFlags); 205 512 -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.