pthread.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. pthread.c
  9. Abstract:
  10. This module implements support for POSIX threads.
  11. Author:
  12. Evan Green 29-Apr-2015
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "pthreadp.h"
  20. #include <assert.h>
  21. #include <limits.h>
  22. #include <sys/mman.h>
  23. #include <unistd.h>
  24. //
  25. // ---------------------------------------------------------------- Definitions
  26. //
  27. //
  28. // ------------------------------------------------------ Data Type Definitions
  29. //
  30. /*++
  31. Structure Description:
  32. This structure stores a thread-local destructor entry.
  33. Members:
  34. ListEntry - Stores pointers to the next and previous elements in the
  35. destructor entry.
  36. DestructorRoutine - Stores a pointer to the routine to call.
  37. Argument - Stores a pointer to the argument to pass to the routine.
  38. SharedObjectHandle - Stores the shared object handle this destructor is
  39. associated with.
  40. --*/
  41. typedef struct _THREAD_DESTRUCTOR {
  42. LIST_ENTRY ListEntry;
  43. PTHREAD_ENTRY_ROUTINE DestructorRoutine;
  44. PVOID Argument;
  45. PVOID SharedObjectHandle;
  46. } THREAD_DESTRUCTOR, *PTHREAD_DESTRUCTOR;
  47. //
  48. // ----------------------------------------------- Internal Function Prototypes
  49. //
  50. VOID
  51. ClpThreadStart (
  52. PVOID Parameter
  53. );
  54. VOID
  55. ClpInitializeThreading (
  56. VOID
  57. );
  58. void
  59. ClpThreadSignalHandler (
  60. int Signal
  61. );
  62. int
  63. ClpAllocateThread (
  64. const pthread_attr_t *Attribute,
  65. void *(*StartRoutine)(void *),
  66. void *Argument,
  67. PPTHREAD *Thread
  68. );
  69. void
  70. ClpDestroyThread (
  71. PPTHREAD Thread
  72. );
  73. VOID
  74. ClpCallThreadDestructors (
  75. VOID
  76. );
  77. PPTHREAD
  78. ClpGetThreadFromId (
  79. pthread_t ThreadId
  80. );
  81. //
  82. // -------------------------------------------------------------------- Globals
  83. //
  84. //
  85. // Store the global thread list.
  86. //
  87. LIST_ENTRY ClThreadList;
  88. pthread_mutex_t ClThreadListMutex = PTHREAD_MUTEX_INITIALIZER;
  89. //
  90. // Store a thread-local pointer to the current thread.
  91. //
  92. __THREAD PPTHREAD ClCurrentThread;
  93. //
  94. // Store a thread-local list of destructor functions registered by the
  95. // compiler.
  96. //
  97. __THREAD LIST_ENTRY ClThreadDestructors;
  98. //
  99. // ------------------------------------------------------------------ Functions
  100. //
  101. PTHREAD_API
  102. pthread_t
  103. pthread_self (
  104. void
  105. )
  106. /*++
  107. Routine Description:
  108. This routine returns the thread ID for the current thread.
  109. Arguments:
  110. None.
  111. Return Value:
  112. None.
  113. --*/
  114. {
  115. PPTHREAD Thread;
  116. Thread = ClCurrentThread;
  117. //
  118. // If there is no current thread, then this must be the main thread.
  119. // Lazily allocate a new thread structure for it.
  120. //
  121. if (Thread == NULL) {
  122. ClpInitializeThreading();
  123. Thread = ClCurrentThread;
  124. }
  125. return (pthread_t)Thread;
  126. }
  127. PTHREAD_API
  128. int
  129. pthread_create (
  130. pthread_t *CreatedThread,
  131. const pthread_attr_t *Attribute,
  132. void *(*StartRoutine)(void *),
  133. void *Argument
  134. )
  135. /*++
  136. Routine Description:
  137. This routine creates and starts a new thread. The signal mask of the new
  138. thread is inherited from the current thread. The set of pending signals in
  139. the new thread will be initially empty.
  140. Arguments:
  141. CreatedThread - Supplies a pointer where the identifier of the new thread
  142. will be returned on success.
  143. Attribute - Supplies an optional pointer to the attributes of the thread.
  144. StartRoutine - Supplies a pointer to the routine to call on the new thread.
  145. Argument - Supplies the argument to pass to the start routine.
  146. Return Value:
  147. 0 on success.
  148. Returns an error number on failure.
  149. --*/
  150. {
  151. SIGNAL_SET InternalSignals;
  152. KSTATUS KernelStatus;
  153. pthread_attr_t LocalAttributes;
  154. PPTHREAD NewThread;
  155. int Status;
  156. //
  157. // Initialize the default attributes if none were supplied.
  158. //
  159. if (Attribute == NULL) {
  160. pthread_attr_init(&LocalAttributes);
  161. Attribute = &LocalAttributes;
  162. }
  163. Status = ClpAllocateThread(Attribute, StartRoutine, Argument, &NewThread);
  164. if (Status != 0) {
  165. return Status;
  166. }
  167. //
  168. // Force the main thread to get with the program in case this is the first
  169. // thread created.
  170. //
  171. pthread_self();
  172. pthread_mutex_lock(&(NewThread->StartMutex));
  173. //
  174. // Block all possible signals in the new thread while it sets itself up,
  175. // including the internal signals.
  176. //
  177. FILL_SIGNAL_SET(InternalSignals);
  178. NewThread->SignalMask = OsSetSignalBehavior(SignalMaskBlocked,
  179. SignalMaskOperationOverwrite,
  180. &InternalSignals);
  181. KernelStatus = OsCreateThread(NULL,
  182. 0,
  183. ClpThreadStart,
  184. NewThread,
  185. NewThread->Attribute.StackBase,
  186. NewThread->Attribute.StackSize,
  187. NewThread->OsData,
  188. &(NewThread->ThreadId));
  189. OsSetSignalBehavior(SignalMaskBlocked,
  190. SignalMaskOperationOverwrite,
  191. &(NewThread->SignalMask));
  192. if (!KSUCCESS(KernelStatus)) {
  193. Status = ClConvertKstatusToErrorNumber(KernelStatus);
  194. ClpDestroyThreadKeyData(NewThread);
  195. ClpDestroyThread(NewThread);
  196. return Status;
  197. }
  198. if ((NewThread->Attribute.Flags & PTHREAD_FLAG_DETACHED) != 0) {
  199. NewThread->State = PthreadStateDetached;
  200. } else {
  201. NewThread->State = PthreadStateNotJoined;
  202. }
  203. //
  204. // Add the thread to the global list.
  205. //
  206. pthread_mutex_lock(&ClThreadListMutex);
  207. INSERT_BEFORE(&(NewThread->ListEntry), &ClThreadList);
  208. pthread_mutex_unlock(&ClThreadListMutex);
  209. //
  210. // Let the thread run.
  211. //
  212. pthread_mutex_unlock(&(NewThread->StartMutex));
  213. *CreatedThread = (pthread_t)NewThread;
  214. return 0;
  215. }
  216. PTHREAD_API
  217. int
  218. pthread_detach (
  219. pthread_t ThreadId
  220. )
  221. /*++
  222. Routine Description:
  223. This routine marks the given thread as detached, which means that when it
  224. exits, its resources are automatically released without needing another
  225. thread to call join on it. It is illegal to call join on a detached thread,
  226. as the thread ID may be already released and reused.
  227. Arguments:
  228. ThreadId - Supplies the thread ID to detach.
  229. Return Value:
  230. 0 on success.
  231. Returns an error number on failure.
  232. --*/
  233. {
  234. ULONG OldState;
  235. PPTHREAD Thread;
  236. Thread = ClpGetThreadFromId(ThreadId);
  237. if (Thread == NULL) {
  238. return ESRCH;
  239. }
  240. //
  241. // Try to detach the thread.
  242. //
  243. OldState = RtlAtomicCompareExchange32(&(Thread->State),
  244. PthreadStateDetached,
  245. PthreadStateNotJoined);
  246. //
  247. // If the compare exchange was won, then the thread was successfully
  248. // detached.
  249. //
  250. if (OldState == PthreadStateNotJoined) {
  251. return 0;
  252. }
  253. //
  254. // If the thread has already exited, call join to clean up the remaining
  255. // thread resources.
  256. //
  257. if (OldState == PthreadStateExited) {
  258. return pthread_join(ThreadId, NULL);
  259. }
  260. //
  261. // The thread is either all funky or has already been joined in which case
  262. // the user is on drugs.
  263. //
  264. assert((OldState == PthreadStateJoined) ||
  265. (OldState == PthreadStateDetached));
  266. return EINVAL;
  267. }
  268. PTHREAD_API
  269. int
  270. pthread_join (
  271. pthread_t ThreadId,
  272. void **ReturnValue
  273. )
  274. /*++
  275. Routine Description:
  276. This routine waits for the given thread to exit and collects its return
  277. value. Detached threads cannot be joined.
  278. Arguments:
  279. ThreadId - Supplies the identifier of the thread to join with.
  280. ReturnValue - Supplies a pointer where the thread return value will be
  281. returned on success.
  282. Return Value:
  283. 0 on success.
  284. Returns an error number on failure.
  285. --*/
  286. {
  287. ULONG NewState;
  288. ULONG OldState;
  289. THREAD_ID OsThreadId;
  290. PPTHREAD Thread;
  291. pthread_testcancel();
  292. //
  293. // Don't be ridiculous.
  294. //
  295. if (ThreadId == pthread_self()) {
  296. return EDEADLK;
  297. }
  298. Thread = ClpGetThreadFromId(ThreadId);
  299. if (Thread == NULL) {
  300. return ESRCH;
  301. }
  302. //
  303. // Try to change the state from not joined or exited to joined. This may
  304. // race with other calls to join (weird), detach, and the thread exiting.
  305. //
  306. OldState = PthreadStateNotJoined;
  307. while ((OldState == PthreadStateNotJoined) ||
  308. (OldState == PthreadStateExited)) {
  309. NewState = RtlAtomicCompareExchange32(&(Thread->State),
  310. PthreadStateJoined,
  311. OldState);
  312. if (OldState == NewState) {
  313. break;
  314. }
  315. OldState = NewState;
  316. }
  317. if ((OldState == PthreadStateDetached) ||
  318. (OldState == PthreadStateJoined)) {
  319. return EINVAL;
  320. }
  321. //
  322. // Wait for the thread to exit.
  323. //
  324. OsThreadId = Thread->ThreadId;
  325. while (Thread->ThreadId != 0) {
  326. OsUserLock(&(Thread->ThreadId),
  327. UserLockWait,
  328. (PULONG)&OsThreadId,
  329. SYS_WAIT_TIME_INDEFINITE);
  330. }
  331. //
  332. // Get the return value if requested.
  333. //
  334. if (ReturnValue != NULL) {
  335. *ReturnValue = Thread->ReturnValue;
  336. }
  337. //
  338. // Remove and clean up the thread structure.
  339. //
  340. pthread_mutex_lock(&ClThreadListMutex);
  341. LIST_REMOVE(&(Thread->ListEntry));
  342. Thread->ListEntry.Next = NULL;
  343. pthread_mutex_unlock(&ClThreadListMutex);
  344. if (Thread->KeyData != NULL) {
  345. ClpDestroyThreadKeyData(Thread);
  346. }
  347. ClpDestroyThread(Thread);
  348. return 0;
  349. }
  350. PTHREAD_API
  351. __NO_RETURN
  352. void
  353. pthread_exit (
  354. void *ReturnValue
  355. )
  356. /*++
  357. Routine Description:
  358. This routine exits the current thread. If this is a detached thread, then
  359. all thread resources are destroyed immediately. If this is a joinable
  360. thread, then some state is kept around until another thread calls join to
  361. collect the return value.
  362. Arguments:
  363. ReturnValue - Supplies an optional return value to give to anyone that
  364. calls join.
  365. Return Value:
  366. None. This routine does not return.
  367. --*/
  368. {
  369. __pthread_cleanup_t *CleanupItem;
  370. PVOID DestroyRegion;
  371. UINTN DestroyRegionSize;
  372. ULONG OldState;
  373. SIGNAL_SET SignalMask;
  374. PPTHREAD Thread;
  375. //
  376. // Call C++ thread_local destructors.
  377. //
  378. Thread = (PPTHREAD)pthread_self();
  379. ClpCallThreadDestructors();
  380. Thread->ReturnValue = ReturnValue;
  381. //
  382. // Call the cleanup handlers as well.
  383. //
  384. while (Thread->CleanupStack != NULL) {
  385. CleanupItem = Thread->CleanupStack;
  386. Thread->CleanupStack = CleanupItem->__cleanup_prev;
  387. CleanupItem->__cleanup_routine(CleanupItem->__cleanup_arg);
  388. }
  389. //
  390. // Clean up all thread local keys.
  391. //
  392. ClpDestroyThreadKeyData(Thread);
  393. DestroyRegion = NULL;
  394. DestroyRegionSize = 0;
  395. //
  396. // Mask out all signals, as this thread will not be handling anything else,
  397. // and then exit. This may touch errno so it must be done before the thread
  398. // is torn down.
  399. //
  400. FILL_SIGNAL_SET(SignalMask);
  401. OsSetSignalBehavior(SignalMaskBlocked,
  402. SignalMaskOperationOverwrite,
  403. &SignalMask);
  404. //
  405. // Indicate that the thread has exited.
  406. //
  407. OldState = RtlAtomicCompareExchange32(&(Thread->State),
  408. PthreadStateExited,
  409. PthreadStateNotJoined);
  410. if (OldState == PthreadStateDetached) {
  411. //
  412. // No one will be joining this thread, it must clean itself up. The
  413. // kernel will help with the last deallocation since it is the stack.
  414. //
  415. pthread_mutex_lock(&ClThreadListMutex);
  416. LIST_REMOVE(&(Thread->ListEntry));
  417. Thread->ListEntry.Next = NULL;
  418. pthread_mutex_unlock(&ClThreadListMutex);
  419. DestroyRegion = Thread->ThreadAllocation;
  420. DestroyRegionSize = Thread->ThreadAllocationSize;
  421. Thread->ThreadAllocationSize = 0;
  422. ClpDestroyThread(Thread);
  423. }
  424. OsExitThread(DestroyRegion, DestroyRegionSize);
  425. abort();
  426. }
  427. PTHREAD_API
  428. int
  429. pthread_equal (
  430. pthread_t FirstThread,
  431. pthread_t SecondThread
  432. )
  433. /*++
  434. Routine Description:
  435. This routine compares two thread identifiers.
  436. Arguments:
  437. FirstThread - Supplies the first thread identifier to compare.
  438. SecondThread - Supplies the second thread identifier to compare.
  439. Return Value:
  440. Returns non-zero if the two thread IDs are equal.
  441. 0 if the thread IDs are not equal.
  442. --*/
  443. {
  444. return FirstThread == SecondThread;
  445. }
  446. PTHREAD_API
  447. int
  448. pthread_kill (
  449. pthread_t ThreadId,
  450. int Signal
  451. )
  452. /*++
  453. Routine Description:
  454. This routine sends a signal to the given thread.
  455. Arguments:
  456. ThreadId - Supplies the identifier of the thread to send the signal to.
  457. Signal - Supplies the signal number to send. Supply 0 to test if a signal
  458. can be sent, but not actually send any signal.
  459. Return Value:
  460. 0 on success.
  461. Returns an error number on failure.
  462. --*/
  463. {
  464. THREAD_ID KernelThreadId;
  465. KSTATUS Status;
  466. PPTHREAD Thread;
  467. Thread = ClpGetThreadFromId(ThreadId);
  468. if (Thread == NULL) {
  469. return ESRCH;
  470. }
  471. KernelThreadId = Thread->ThreadId;
  472. if (KernelThreadId == 0) {
  473. return ESRCH;
  474. }
  475. Status = OsSendSignal(SignalTargetThread,
  476. KernelThreadId,
  477. Signal,
  478. SIGNAL_CODE_THREAD_KILL,
  479. 0);
  480. if (!KSUCCESS(Status)) {
  481. return ClConvertKstatusToErrorNumber(Status);
  482. }
  483. return 0;
  484. }
  485. PTHREAD_API
  486. int
  487. pthread_sigqueue (
  488. pthread_t ThreadId,
  489. int Signal,
  490. const union sigval Value
  491. )
  492. /*++
  493. Routine Description:
  494. This routine queues a signal with data the given thread.
  495. Arguments:
  496. ThreadId - Supplies the identifier of the thread to send the signal to.
  497. Signal - Supplies the signal number to send. Supply 0 to test if a signal
  498. can be sent, but not actually send any signal.
  499. Value - Supplies the signal value to send.
  500. Return Value:
  501. 0 on success.
  502. Returns an error number on failure.
  503. --*/
  504. {
  505. KSTATUS Status;
  506. PPTHREAD Thread;
  507. ASSERT(sizeof(void *) >= sizeof(int));
  508. Thread = ClpGetThreadFromId(ThreadId);
  509. if (Thread == NULL) {
  510. return ESRCH;
  511. }
  512. Status = OsSendSignal(SignalTargetThread,
  513. Thread->ThreadId,
  514. Signal,
  515. SIGNAL_CODE_QUEUE,
  516. (UINTN)(Value.sival_ptr));
  517. if (!KSUCCESS(Status)) {
  518. return ClConvertKstatusToErrorNumber(Status);
  519. }
  520. return 0;
  521. }
  522. PTHREAD_API
  523. int
  524. pthread_cancel (
  525. pthread_t ThreadId
  526. )
  527. /*++
  528. Routine Description:
  529. This routine attempts to cancel (terminate) the thread with the given
  530. thread ID. This may not terminate the thread immediately if it has disabled
  531. or deferred cancellation.
  532. Arguments:
  533. ThreadId - Supplies the identifier of the thread to cancel.
  534. Return Value:
  535. 0 on success.
  536. ESRCH if a thread with the given ID could not be found.
  537. --*/
  538. {
  539. PPTHREAD Thread;
  540. Thread = ClpGetThreadFromId(ThreadId);
  541. if (Thread == NULL) {
  542. return ESRCH;
  543. }
  544. Thread->CancelRequested = TRUE;
  545. pthread_kill(ThreadId, SIGNAL_PTHREAD);
  546. return 0;
  547. }
  548. PTHREAD_API
  549. int
  550. pthread_setcancelstate (
  551. int State,
  552. int *OldState
  553. )
  554. /*++
  555. Routine Description:
  556. This routine atomically sets the thread cancellation state for the current
  557. thread and returns the old state. By default, new threads are created with
  558. cancellation enabled.
  559. Arguments:
  560. State - Supplies the new state to set. Valid values are
  561. PTHREAD_CANCEL_ENABLE and PTHREAD_CANCEL_DISABLE.
  562. OldState - Supplies the previously set cancellation state.
  563. Return Value:
  564. 0 on success.
  565. EINVAL if an invalid new state was supplied.
  566. --*/
  567. {
  568. ULONG PreviousState;
  569. PPTHREAD Thread;
  570. if ((State != PTHREAD_CANCEL_ENABLE) && (State != PTHREAD_CANCEL_DISABLE)) {
  571. return EINVAL;
  572. }
  573. Thread = (PPTHREAD)pthread_self();
  574. PreviousState = RtlAtomicExchange32(&(Thread->CancelState), State);
  575. if (OldState != NULL) {
  576. *OldState = PreviousState;
  577. }
  578. if (State == PTHREAD_CANCEL_ENABLE) {
  579. pthread_testcancel();
  580. }
  581. return 0;
  582. }
  583. PTHREAD_API
  584. int
  585. pthread_setcanceltype (
  586. int Type,
  587. int *OldType
  588. )
  589. /*++
  590. Routine Description:
  591. This routine atomically sets the thread cancellation type for the current
  592. thread and returns the old type. By default, new threads are created with
  593. deferred cancellation.
  594. Arguments:
  595. Type - Supplies the new type to set. Valid values are
  596. PTHREAD_CANCEL_DEFERRED and PTHREAD_CANCEL_ASYNCHRONOUS.
  597. OldType - Supplies the previously set cancellation type.
  598. Return Value:
  599. 0 on success.
  600. EINVAL if an invalid new type was supplied.
  601. --*/
  602. {
  603. ULONG PreviousType;
  604. PPTHREAD Thread;
  605. if ((Type != PTHREAD_CANCEL_DEFERRED) &&
  606. (Type != PTHREAD_CANCEL_ASYNCHRONOUS)) {
  607. return EINVAL;
  608. }
  609. Thread = (PPTHREAD)pthread_self();
  610. PreviousType = RtlAtomicExchange32(&(Thread->CancelType), Type);
  611. if (OldType != NULL) {
  612. *OldType = PreviousType;
  613. }
  614. if (Type == PTHREAD_CANCEL_ASYNCHRONOUS) {
  615. pthread_testcancel();
  616. }
  617. return 0;
  618. }
  619. PTHREAD_API
  620. void
  621. pthread_testcancel (
  622. void
  623. )
  624. /*++
  625. Routine Description:
  626. This routine creates a cancellation point in the calling thread. If
  627. cancellation is currently disabled, this does nothing.
  628. Arguments:
  629. None.
  630. Return Value:
  631. None.
  632. --*/
  633. {
  634. PPTHREAD Thread;
  635. Thread = (PPTHREAD)pthread_self();
  636. if (Thread->CancelState != PTHREAD_CANCEL_ENABLE) {
  637. return;
  638. }
  639. if (Thread->CancelRequested != FALSE) {
  640. pthread_exit(PTHREAD_CANCELED);
  641. }
  642. return;
  643. }
  644. PTHREAD_API
  645. pid_t
  646. pthread_gettid_np (
  647. pthread_t ThreadId
  648. )
  649. /*++
  650. Routine Description:
  651. This routine returns the kernel thread ID for the given POSIX thread ID.
  652. Arguments:
  653. ThreadId - Supplies the POSIX thread ID.
  654. Return Value:
  655. Returns the kernel thread ID.
  656. --*/
  657. {
  658. PPTHREAD Thread;
  659. Thread = (PPTHREAD)ThreadId;
  660. return Thread->ThreadId;
  661. }
  662. PTHREAD_API
  663. pid_t
  664. pthread_getthreadid_np (
  665. void
  666. )
  667. /*++
  668. Routine Description:
  669. This routine returns the kernel thread ID for the current thread.
  670. Arguments:
  671. None.
  672. Return Value:
  673. Returns the kernel thread ID.
  674. --*/
  675. {
  676. return pthread_gettid_np(pthread_self());
  677. }
  678. PTHREAD_API
  679. int
  680. pthread_getattr_np (
  681. pthread_t ThreadId,
  682. pthread_attr_t *Attribute
  683. )
  684. /*++
  685. Routine Description:
  686. This routine returns the current attributes for a given thread.
  687. Arguments:
  688. ThreadId - Supplies the thread to get attributes for.
  689. Attribute - Supplies a pointer where the attributes will be returned. The
  690. detach state, stack size, stack base, and guard size may be different
  691. from when the thread was created to reflect their actual values.
  692. Return Value:
  693. 0 on success.
  694. Returns an error number on failure.
  695. --*/
  696. {
  697. PPROCESS_ENVIRONMENT Environment;
  698. int Error;
  699. struct rlimit Limit;
  700. int OldError;
  701. PPTHREAD Thread;
  702. Thread = (PPTHREAD)ThreadId;
  703. if (Thread->State == PthreadStateDetached) {
  704. Thread->Attribute.Flags |= PTHREAD_FLAG_DETACHED;
  705. }
  706. //
  707. // For the main thread, try to get the stack size.
  708. //
  709. if (Thread->Attribute.StackSize == 0) {
  710. OldError = errno;
  711. if (getrlimit(RLIMIT_STACK, &Limit) < 0) {
  712. Error = errno;
  713. errno = OldError;
  714. return Error;
  715. }
  716. Thread->Attribute.StackSize = Limit.rlim_cur;
  717. if (Thread->Attribute.StackBase == NULL) {
  718. Environment = OsGetCurrentEnvironment();
  719. Thread->Attribute.StackBase = Environment->StartData->StackBase;
  720. }
  721. }
  722. memcpy(Attribute, &(Thread->Attribute), sizeof(PTHREAD_ATTRIBUTE));
  723. return 0;
  724. }
  725. PTHREAD_API
  726. void
  727. __pthread_cleanup_push (
  728. __pthread_cleanup_t *CleanupItem,
  729. __pthread_cleanup_func_t CleanupRoutine,
  730. void *Argument
  731. )
  732. /*++
  733. Routine Description:
  734. This routine pushes a new element onto the cleanup stack for the current
  735. thread.
  736. Arguments:
  737. CleanupItem - Supplies a pointer to the cleanup item context. This routine
  738. uses this buffer, so it cannot be freed until the cleanup item is
  739. popped.
  740. CleanupRoutine - Supplies a pointer to the routine to call if the thread
  741. exits.
  742. Argument - Supplies a pointer to pass to the cleanup routine.
  743. Return Value:
  744. None.
  745. --*/
  746. {
  747. PPTHREAD Thread;
  748. Thread = (PPTHREAD)pthread_self();
  749. CleanupItem->__cleanup_routine = CleanupRoutine;
  750. CleanupItem->__cleanup_arg = Argument;
  751. CleanupItem->__cleanup_prev = Thread->CleanupStack;
  752. Thread->CleanupStack = CleanupItem;
  753. return;
  754. }
  755. PTHREAD_API
  756. void
  757. __pthread_cleanup_pop (
  758. __pthread_cleanup_t *CleanupItem,
  759. int Execute
  760. )
  761. /*++
  762. Routine Description:
  763. This routine potentially pops an element from the cleanup stack.
  764. Arguments:
  765. CleanupItem - Supplies a pointer to the cleanup item to pop.
  766. Execute - Supplies an integer that is non-zero if the cleanup routine
  767. should be run, or zero if it should just be popped.
  768. Return Value:
  769. None.
  770. --*/
  771. {
  772. PPTHREAD Thread;
  773. Thread = (PPTHREAD)pthread_self();
  774. Thread->CleanupStack = CleanupItem->__cleanup_prev;
  775. if (Execute != 0) {
  776. CleanupItem->__cleanup_routine(CleanupItem->__cleanup_arg);
  777. }
  778. return;
  779. }
  780. LIBC_API
  781. int
  782. __cxa_thread_atexit_impl (
  783. PTHREAD_ENTRY_ROUTINE DestructorRoutine,
  784. void *Argument,
  785. void *DynamicObjectHandle
  786. )
  787. /*++
  788. Routine Description:
  789. This routine registers a new thread-local destructor, that is called when
  790. the thread is destroyed.
  791. Arguments:
  792. DestructorRoutine - Supplies a pointer to the routine to call when the
  793. thread is destroyed.
  794. Argument - Supplies an argument to pass to the destructor routine.
  795. DynamicObjectHandle - Supplies a pointer to the dynamic object this
  796. destructor is associated with.
  797. Return Value:
  798. 0 on success.
  799. Returns an error number on failure.
  800. --*/
  801. {
  802. PTHREAD_DESTRUCTOR Destructor;
  803. Destructor = malloc(sizeof(THREAD_DESTRUCTOR));
  804. if (Destructor == NULL) {
  805. return ENOMEM;
  806. }
  807. Destructor->DestructorRoutine = DestructorRoutine;
  808. Destructor->Argument = Argument;
  809. Destructor->SharedObjectHandle = DynamicObjectHandle;
  810. if (ClThreadDestructors.Next == NULL) {
  811. INITIALIZE_LIST_HEAD(&ClThreadDestructors);
  812. }
  813. INSERT_AFTER(&(Destructor->ListEntry), &ClThreadDestructors);
  814. return 0;
  815. }
  816. //
  817. // --------------------------------------------------------- Internal Functions
  818. //
  819. VOID
  820. ClpThreadStart (
  821. PVOID Parameter
  822. )
  823. /*++
  824. Routine Description:
  825. This routine implements the initial routine for a POSIX thread.
  826. Arguments:
  827. Parameter - Supplies a pointer to the parameter, which in this case is a
  828. pointer to the PTHREAD structure for this thread.
  829. Return Value:
  830. None. Actually, this routine never returns.
  831. --*/
  832. {
  833. PVOID Result;
  834. PPTHREAD Thread;
  835. Thread = Parameter;
  836. //
  837. // Acquire the start mutex to synchronize with the thread that created this
  838. // thread.
  839. //
  840. ClCurrentThread = Thread;
  841. pthread_mutex_lock(&(Thread->StartMutex));
  842. OsSetSignalBehavior(SignalMaskBlocked,
  843. SignalMaskOperationOverwrite,
  844. &(Thread->SignalMask));
  845. pthread_testcancel();
  846. Result = Thread->ThreadRoutine(Thread->ThreadParameter);
  847. pthread_exit(Result);
  848. return;
  849. }
  850. VOID
  851. ClpInitializeThreading (
  852. VOID
  853. )
  854. /*++
  855. Routine Description:
  856. This routine is called to initialize threading support, mostly performing
  857. some initialization tasks on the main thread that were deferred for
  858. better performance on non-threaded applications. This code must be called
  859. on the main thread.
  860. Arguments:
  861. None.
  862. Return Value:
  863. None.
  864. --*/
  865. {
  866. struct sigaction Action;
  867. UINTN AllocationSize;
  868. PPTHREAD Thread;
  869. AllocationSize = sizeof(PTHREAD) +
  870. (PTHREAD_KEYS_MAX * sizeof(PTHREAD_KEY_DATA));
  871. Thread = OsHeapAllocate(AllocationSize, PTHREAD_ALLOCATION_TAG);
  872. if (Thread == NULL) {
  873. return;
  874. }
  875. memset(Thread, 0, AllocationSize);
  876. pthread_mutex_init(&(Thread->StartMutex), NULL);
  877. Thread->KeyData = (PPTHREAD_KEY_DATA)(Thread + 1);
  878. //
  879. // Set the thread ID pointer of the main thread in the kernel so that
  880. // other threads can join the main thread if desired.
  881. //
  882. OsSetThreadIdPointer(&(Thread->ThreadId));
  883. Thread->State = PthreadStateNotJoined;
  884. ClCurrentThread = Thread;
  885. //
  886. // Add the thread to the global list.
  887. //
  888. pthread_mutex_lock(&ClThreadListMutex);
  889. ASSERT(ClThreadList.Next == NULL);
  890. INITIALIZE_LIST_HEAD(&ClThreadList);
  891. INSERT_AFTER(&(Thread->ListEntry), &ClThreadList);
  892. pthread_mutex_unlock(&ClThreadListMutex);
  893. //
  894. // Also register the thread signal handler and the set ID signal handler.
  895. //
  896. sigemptyset(&(Action.sa_mask));
  897. Action.sa_flags = 0;
  898. Action.sa_handler = ClpThreadSignalHandler;
  899. ClpSetSignalAction(SIGNAL_PTHREAD, &Action, NULL);
  900. Action.sa_handler = ClpSetIdSignalHandler;
  901. ClpSetSignalAction(SIGNAL_SETID, &Action, NULL);
  902. //
  903. // Make sure the PLT entry for the exit thread routine is wired up.
  904. // Detached threads carefully tear themselves down, and cannot handle a
  905. // PLT lookup by the time they call exit thread.
  906. //
  907. // This does not actually exit the current thread, it simply returns.
  908. //
  909. OsExitThread(NULL, -1);
  910. return;
  911. }
  912. void
  913. ClpThreadSignalHandler (
  914. int Signal
  915. )
  916. /*++
  917. Routine Description:
  918. This routine implements the thread signal handler, which manages
  919. cancellation requests.
  920. Arguments:
  921. Signal - Supplies the signal number that occurred.
  922. Return Value:
  923. None.
  924. --*/
  925. {
  926. PPTHREAD Thread;
  927. Thread = (PPTHREAD)pthread_self();
  928. ASSERT(Thread->CancelRequested != FALSE);
  929. if (Thread->CancelType == PTHREAD_CANCEL_ASYNCHRONOUS) {
  930. pthread_testcancel();
  931. }
  932. return;
  933. }
  934. int
  935. ClpAllocateThread (
  936. const pthread_attr_t *Attribute,
  937. void *(*StartRoutine)(void *),
  938. void *Argument,
  939. PPTHREAD *Thread
  940. )
  941. /*++
  942. Routine Description:
  943. This routine allocates and initializes a new thread structure.
  944. Arguments:
  945. Attribute - Supplies a required pointer to the attributes of the thread.
  946. StartRoutine - Supplies a pointer to the routine to call on the new thread.
  947. Argument - Supplies the argument to pass to the start routine.
  948. Thread - Supplies a pointer where a pointer to the thread will be returned
  949. on success.
  950. Return Value:
  951. 0 on success.
  952. Returns an error number on failure.
  953. --*/
  954. {
  955. PVOID Allocation;
  956. PPTHREAD_ATTRIBUTE AttributeInternal;
  957. UINTN GuardSize;
  958. KSTATUS KernelStatus;
  959. ULONG MapFlags;
  960. UINTN MapSize;
  961. PPTHREAD NewThread;
  962. UINTN PageSize;
  963. PVOID Stack;
  964. UINTN StackSize;
  965. int Status;
  966. Allocation = NULL;
  967. //
  968. // If the caller wants something non-standard for a stack, then allocate
  969. // the stack.
  970. //
  971. GuardSize = 0;
  972. NewThread = NULL;
  973. PageSize = sysconf(_SC_PAGE_SIZE);
  974. AttributeInternal = (PPTHREAD_ATTRIBUTE)Attribute;
  975. Stack = AttributeInternal->StackBase;
  976. StackSize = 0;
  977. MapSize = sizeof(PTHREAD) + (PTHREAD_KEYS_MAX * sizeof(PTHREAD_KEY_DATA));
  978. //
  979. // Also allocate a stack if none was supplied but a weird guard size was
  980. // requested.
  981. //
  982. if ((Stack == NULL) && (AttributeInternal->GuardSize != PageSize)) {
  983. StackSize = ALIGN_RANGE_UP(AttributeInternal->StackSize, 16);
  984. MapSize += StackSize;
  985. MapSize = ALIGN_RANGE_UP(MapSize, PageSize);
  986. GuardSize = ALIGN_RANGE_UP(AttributeInternal->GuardSize, PageSize);
  987. MapSize += GuardSize;
  988. }
  989. MapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
  990. Allocation = mmap(Stack, MapSize, PROT_READ | PROT_WRITE, MapFlags, -1, 0);
  991. if (Allocation == MAP_FAILED) {
  992. Status = errno;
  993. goto AllocateThreadEnd;
  994. }
  995. if ((Stack == NULL) && (AttributeInternal->GuardSize != PageSize)) {
  996. if (GuardSize != 0) {
  997. if (mprotect(Stack, GuardSize, PROT_NONE) < 0) {
  998. Status = errno;
  999. goto AllocateThreadEnd;
  1000. }
  1001. }
  1002. }
  1003. NewThread = Allocation + GuardSize + StackSize;
  1004. memcpy(&(NewThread->Attribute),
  1005. AttributeInternal,
  1006. sizeof(PTHREAD_ATTRIBUTE));
  1007. NewThread->Attribute.StackBase = Stack;
  1008. if (StackSize != 0) {
  1009. NewThread->Attribute.StackSize = StackSize;
  1010. }
  1011. NewThread->ThreadRoutine = StartRoutine;
  1012. NewThread->ThreadParameter = Argument;
  1013. NewThread->ThreadAllocation = Allocation;
  1014. NewThread->ThreadAllocationSize = MapSize;
  1015. NewThread->KeyData = (PPTHREAD_KEY_DATA)(NewThread + 1);
  1016. pthread_mutex_init(&(NewThread->StartMutex), NULL);
  1017. KernelStatus = OsCreateThreadData(&(NewThread->OsData));
  1018. if (!KSUCCESS(KernelStatus)) {
  1019. Status = ClConvertKstatusToErrorNumber(KernelStatus);
  1020. goto AllocateThreadEnd;
  1021. }
  1022. Status = 0;
  1023. AllocateThreadEnd:
  1024. if (Status != 0) {
  1025. if (Allocation != NULL) {
  1026. munmap(Allocation, MapSize);
  1027. }
  1028. NewThread = NULL;
  1029. }
  1030. *Thread = NewThread;
  1031. return Status;
  1032. }
  1033. void
  1034. ClpDestroyThread (
  1035. PPTHREAD Thread
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. This routine frees a thread structure. The thread better not be alive there.
  1040. Arguments:
  1041. Thread - Supplies a pointer to the thread structure to destroy.
  1042. Return Value:
  1043. None.
  1044. --*/
  1045. {
  1046. assert(Thread->KeyData == NULL);
  1047. pthread_mutex_destroy(&(Thread->StartMutex));
  1048. if (Thread->OsData != NULL) {
  1049. OsDestroyThreadData(Thread->OsData);
  1050. Thread->OsData = NULL;
  1051. }
  1052. if (Thread->ThreadAllocationSize != 0) {
  1053. munmap(Thread->ThreadAllocation, Thread->ThreadAllocationSize);
  1054. }
  1055. return;
  1056. }
  1057. VOID
  1058. ClpCallThreadDestructors (
  1059. VOID
  1060. )
  1061. /*++
  1062. Routine Description:
  1063. This routine calls all the thread destructor routines in the reverse order
  1064. as they were registered.
  1065. Arguments:
  1066. None.
  1067. Return Value:
  1068. None.
  1069. --*/
  1070. {
  1071. PLIST_ENTRY CurrentEntry;
  1072. PTHREAD_DESTRUCTOR Destructor;
  1073. if (ClThreadDestructors.Next == NULL) {
  1074. return;
  1075. }
  1076. CurrentEntry = ClThreadDestructors.Next;
  1077. while (CurrentEntry != &ClThreadDestructors) {
  1078. Destructor = LIST_VALUE(CurrentEntry, THREAD_DESTRUCTOR, ListEntry);
  1079. CurrentEntry = CurrentEntry->Next;
  1080. Destructor->DestructorRoutine(Destructor->Argument);
  1081. free(Destructor);
  1082. }
  1083. return;
  1084. }
  1085. PPTHREAD
  1086. ClpGetThreadFromId (
  1087. pthread_t ThreadId
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. This routine looks up the given thread based on its thread ID.
  1092. Arguments:
  1093. ThreadId - Supplies the thread ID to look up.
  1094. Return Value:
  1095. Returns a pointer to the internal thread structure on success.
  1096. NULL on failure.
  1097. --*/
  1098. {
  1099. PLIST_ENTRY CurrentEntry;
  1100. PPTHREAD CurrentThread;
  1101. PPTHREAD FoundThread;
  1102. if (ClThreadList.Next == NULL) {
  1103. pthread_self();
  1104. }
  1105. FoundThread = NULL;
  1106. pthread_mutex_lock(&ClThreadListMutex);
  1107. CurrentEntry = ClThreadList.Next;
  1108. while (CurrentEntry != &ClThreadList) {
  1109. CurrentThread = LIST_VALUE(CurrentEntry, PTHREAD, ListEntry);
  1110. if (CurrentThread == (PPTHREAD)ThreadId) {
  1111. FoundThread = CurrentThread;
  1112. break;
  1113. }
  1114. CurrentEntry = CurrentEntry->Next;
  1115. }
  1116. pthread_mutex_unlock(&ClThreadListMutex);
  1117. return FoundThread;
  1118. }