thread.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152
  1. /*++
  2. Copyright (c) 2012 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. thread.c
  9. Abstract:
  10. This module implements support for threads in the kernel.
  11. Author:
  12. Evan Green 6-Aug-2012
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/kernel.h>
  20. #include "psp.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // Define the number of times to try and get the thread list.
  26. //
  27. #define THREAD_LIST_TRIES 100
  28. //
  29. // Define the fudge factor to add to the reported allocation to account for
  30. // new threads sneaking in between calls.
  31. //
  32. #define THREAD_LIST_FUDGE_FACTOR 2
  33. //
  34. // Define the number of threads the reaper attempts to clean up in one pass.
  35. //
  36. #define THREAD_DEFAULT_REAP_COUNT 16
  37. //
  38. // Define the number of dead threads that are allowed to sit on the dead
  39. // threads list before thread creation starts to kick in helping to destroy
  40. // threads.
  41. //
  42. #define THREAD_CREATE_DEAD_THREAD_THRESHOLD 50
  43. //
  44. // Define the number of threads that thread creation will reap if the number of
  45. // dead threads has exceeded the threshold.
  46. //
  47. #define THREAD_CREATE_REAP_COUNT 2
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. PKTHREAD
  52. PspCreateThread (
  53. PKPROCESS OwningProcess,
  54. PVOID KernelStack,
  55. ULONG KernelStackSize,
  56. PTHREAD_ENTRY_ROUTINE ThreadRoutine,
  57. PVOID ThreadParameter,
  58. PCSTR Name,
  59. ULONG Flags
  60. );
  61. VOID
  62. PspReaperThread (
  63. PVOID Parameter
  64. );
  65. VOID
  66. PspReapThreads (
  67. UINTN ReapCount
  68. );
  69. VOID
  70. PspDestroyThread (
  71. PVOID ThreadObject
  72. );
  73. KSTATUS
  74. PspGetThreadList (
  75. PROCESS_ID ProcessId,
  76. PVOID Buffer,
  77. PULONG BufferSize
  78. );
  79. KSTATUS
  80. PspGetThreadInformation (
  81. PKTHREAD Thread,
  82. PTHREAD_INFORMATION Buffer,
  83. PULONG BufferSize
  84. );
  85. //
  86. // ------------------------------------------------------ Data Type Definitions
  87. //
  88. //
  89. // -------------------------------------------------------------------- Globals
  90. //
  91. //
  92. // Globals related to thread manipulation.
  93. //
  94. //
  95. // Stores the ID for the next thread to be created.
  96. //
  97. volatile THREAD_ID PsNextThreadId = 0;
  98. //
  99. // Stores the list of exited threads waiting to be cleaned up.
  100. //
  101. KSPIN_LOCK PsDeadThreadsLock;
  102. LIST_ENTRY PsDeadThreadsListHead;
  103. UINTN PsDeadThreadsCount;
  104. PKEVENT PsDeadThreadsEvent;
  105. //
  106. // ------------------------------------------------------------------ Functions
  107. //
  108. KERNEL_API
  109. KSTATUS
  110. PsCreateKernelThread (
  111. PTHREAD_ENTRY_ROUTINE ThreadRoutine,
  112. PVOID ThreadParameter,
  113. PCSTR Name
  114. )
  115. /*++
  116. Routine Description:
  117. This routine creates and launches a new kernel thread with default
  118. parameters.
  119. Arguments:
  120. ThreadRoutine - Supplies the entry point to the thread.
  121. ThreadParameter - Supplies the parameter to pass to the entry point
  122. routine.
  123. Name - Supplies an optional name to identify the thread.
  124. Return Value:
  125. Returns a pointer to the new thread on success, or NULL on failure.
  126. --*/
  127. {
  128. THREAD_CREATION_PARAMETERS Parameters;
  129. RtlZeroMemory(&Parameters, sizeof(THREAD_CREATION_PARAMETERS));
  130. Parameters.Name = Name;
  131. if (Name != NULL) {
  132. Parameters.NameSize = RtlStringLength(Name) + 1;
  133. }
  134. Parameters.ThreadRoutine = ThreadRoutine;
  135. Parameters.Parameter = ThreadParameter;
  136. return PsCreateThread(&Parameters);
  137. }
  138. KERNEL_API
  139. KSTATUS
  140. PsCreateThread (
  141. PTHREAD_CREATION_PARAMETERS Parameters
  142. )
  143. /*++
  144. Routine Description:
  145. This routine creates and initializes a new thread, and adds it to the
  146. ready list for execution.
  147. Arguments:
  148. Parameters - Supplies a pointer to the thread creation parameters.
  149. Return Value:
  150. Status code.
  151. --*/
  152. {
  153. PKTHREAD CurrentThread;
  154. UINTN KernelStackSize;
  155. PKTHREAD NewThread;
  156. BOOL ParameterIsStack;
  157. KSTATUS Status;
  158. PPROCESS_ENVIRONMENT UserEnvironment;
  159. KernelStackSize = 0;
  160. if ((Parameters->Flags & THREAD_FLAG_USER_MODE) == 0) {
  161. KernelStackSize = Parameters->StackSize;
  162. }
  163. NewThread = PspCreateThread(Parameters->Process,
  164. NULL,
  165. KernelStackSize,
  166. Parameters->ThreadRoutine,
  167. Parameters->Parameter,
  168. Parameters->Name,
  169. Parameters->Flags);
  170. if (NewThread == NULL) {
  171. Status = STATUS_UNSUCCESSFUL;
  172. goto CreateThreadEnd;
  173. }
  174. if (Parameters->ThreadIdPointer != NULL) {
  175. if ((PVOID)(Parameters->ThreadIdPointer) >= KERNEL_VA_START) {
  176. *(Parameters->ThreadIdPointer) = NewThread->ThreadId;
  177. } else {
  178. //
  179. // Save the new ID to user mode, and remember this as the thread
  180. // ID pointer.
  181. //
  182. MmUserWrite32(Parameters->ThreadIdPointer, NewThread->ThreadId);
  183. NewThread->ThreadIdPointer = Parameters->ThreadIdPointer;
  184. }
  185. }
  186. ArSetThreadPointer(NewThread, Parameters->ThreadPointer);
  187. //
  188. // Copy the thread permissions and identity from the current thread.
  189. //
  190. CurrentThread = KeGetCurrentThread();
  191. Status = PspCopyThreadCredentials(NewThread, CurrentThread);
  192. if (!KSUCCESS(Status)) {
  193. goto CreateThreadEnd;
  194. }
  195. //
  196. // Create the user mode stack if needed.
  197. //
  198. ParameterIsStack = FALSE;
  199. if ((Parameters->Flags & THREAD_FLAG_USER_MODE) != 0) {
  200. if (Parameters->UserStack == NULL) {
  201. NewThread->Flags |= THREAD_FLAG_FREE_USER_STACK;
  202. if (Parameters->StackSize == 0) {
  203. Parameters->StackSize =
  204. NewThread->Limits[ResourceLimitStack].Current;
  205. }
  206. Status = PspSetThreadUserStackSize(NewThread,
  207. Parameters->StackSize);
  208. if (!KSUCCESS(Status)) {
  209. goto CreateThreadEnd;
  210. }
  211. Parameters->UserStack = NewThread->UserStack;
  212. } else {
  213. NewThread->UserStack = Parameters->UserStack;
  214. NewThread->UserStackSize = Parameters->StackSize;
  215. }
  216. //
  217. // Copy the signal mask from the current thread.
  218. //
  219. NewThread->BlockedSignals = CurrentThread->BlockedSignals;
  220. //
  221. // Set up the environment if there is one.
  222. //
  223. if (Parameters->Environment != NULL) {
  224. ParameterIsStack = TRUE;
  225. Parameters->Environment->StartData->StackBase =
  226. NewThread->UserStack;
  227. Status = PsCopyEnvironment(Parameters->Environment,
  228. &UserEnvironment,
  229. FALSE,
  230. NewThread,
  231. NULL,
  232. 0);
  233. if (!KSUCCESS(Status)) {
  234. goto CreateThreadEnd;
  235. }
  236. }
  237. }
  238. PspPrepareThreadForFirstRun(NewThread, NULL, ParameterIsStack);
  239. //
  240. // Insert the thread onto the ready list.
  241. //
  242. KeSetThreadReady(NewThread);
  243. Status = STATUS_SUCCESS;
  244. CreateThreadEnd:
  245. if (!KSUCCESS(Status)) {
  246. if (NewThread != NULL) {
  247. PspSetThreadUserStackSize(NewThread, 0);
  248. PspDestroyCredentials(NewThread);
  249. KeAcquireQueuedLock(NewThread->OwningProcess->QueuedLock);
  250. LIST_REMOVE(&(NewThread->ProcessEntry));
  251. NewThread->ProcessEntry.Next = NULL;
  252. NewThread->OwningProcess->ThreadCount -= 1;
  253. ASSERT(NewThread->OwningProcess->ThreadCount != 0);
  254. KeReleaseQueuedLock(NewThread->OwningProcess->QueuedLock);
  255. ObReleaseReference(NewThread);
  256. }
  257. }
  258. return Status;
  259. }
  260. KSTATUS
  261. PsGetThreadList (
  262. PROCESS_ID ProcessId,
  263. ULONG AllocationTag,
  264. PVOID *Buffer,
  265. PULONG BufferSize
  266. )
  267. /*++
  268. Routine Description:
  269. This routine returns information about the active processes in the system.
  270. Arguments:
  271. ProcessId - Supplies the identifier of the process to get thread
  272. information for.
  273. AllocationTag - Supplies the allocation tag to use for the allocation
  274. this routine will make on behalf of the caller.
  275. Buffer - Supplies a pointer where a non-paged pool buffer will be returned
  276. containing the array of thread information. The caller is responsible
  277. for freeing this memory from non-paged pool. The type returned here
  278. will be an array (where each element may be a different size) of
  279. THREAD_INFORMATION structures.
  280. BufferSize - Supplies a pointer where the size of the buffer in bytes
  281. will be returned on success.
  282. Return Value:
  283. STATUS_SUCCESS on success.
  284. STATUS_INSUFFICIENT_RESOURCES if memory could not be allocated for the
  285. information buffer.
  286. STATUS_BUFFER_TOO_SMALL if the thread list is so volatile that it cannot
  287. be sized. This is only returned in extremely rare cases, as this routine
  288. makes multiple attempts.
  289. --*/
  290. {
  291. PVOID Allocation;
  292. ULONG Size;
  293. KSTATUS Status;
  294. ULONG Try;
  295. Allocation = NULL;
  296. Size = 0;
  297. Status = STATUS_BUFFER_TOO_SMALL;
  298. for (Try = 0; Try < THREAD_LIST_TRIES; Try += 1) {
  299. Status = PspGetThreadList(ProcessId, NULL, &Size);
  300. if (!KSUCCESS(Status)) {
  301. goto GetThreadListEnd;
  302. }
  303. ASSERT(Size != 0);
  304. Size = Size * THREAD_LIST_FUDGE_FACTOR;
  305. Allocation = MmAllocateNonPagedPool(Size, AllocationTag);
  306. if (Allocation == NULL) {
  307. Status = STATUS_INSUFFICIENT_RESOURCES;
  308. goto GetThreadListEnd;
  309. }
  310. Status = PspGetThreadList(ProcessId, Allocation, &Size);
  311. if (KSUCCESS(Status)) {
  312. break;
  313. }
  314. MmFreeNonPagedPool(Allocation);
  315. Allocation = NULL;
  316. }
  317. GetThreadListEnd:
  318. if (!KSUCCESS(Status)) {
  319. if (Allocation != NULL) {
  320. MmFreeNonPagedPool(Allocation);
  321. Allocation = NULL;
  322. }
  323. Size = 0;
  324. }
  325. *Buffer = Allocation;
  326. *BufferSize = Size;
  327. return Status;
  328. }
  329. KSTATUS
  330. PsGetThreadInformation (
  331. PROCESS_ID ProcessId,
  332. THREAD_ID ThreadId,
  333. PTHREAD_INFORMATION Buffer,
  334. PULONG BufferSize
  335. )
  336. /*++
  337. Routine Description:
  338. This routine returns information about a given thread.
  339. Arguments:
  340. ProcessId - Supplies the process ID owning the thread.
  341. ThreadId - Supplies the ID of the thread to get information about.
  342. Buffer - Supplies an optional pointer to a buffer to write the data into.
  343. This must be non-paged memory if the thread requested belongs to the
  344. kernel process.
  345. BufferSize - Supplies a pointer that on input contains the size of the
  346. input buffer. On output, returns the size needed to contain the data.
  347. Return Value:
  348. STATUS_SUCCESS on success.
  349. STATUS_NO_SUCH_PROCESS if no process with the given identifier exists.
  350. STATUS_NO_SUCH_THREAD if the no thread with the given identifier exists.
  351. STATUS_BUFFER_TOO_SMALL if a buffer was supplied but was not big enough to
  352. contain all the information.
  353. --*/
  354. {
  355. PKPROCESS Process;
  356. KSTATUS Status;
  357. PKTHREAD Thread;
  358. Thread = NULL;
  359. Process = PspGetProcessById(ProcessId);
  360. if (Process == NULL) {
  361. Status = STATUS_NO_SUCH_PROCESS;
  362. goto GetThreadInformationEnd;
  363. }
  364. Thread = PspGetThreadById(Process, ThreadId);
  365. if (Thread == NULL) {
  366. Status = STATUS_NO_SUCH_THREAD;
  367. goto GetThreadInformationEnd;
  368. }
  369. Status = PspGetThreadInformation(Thread, Buffer, BufferSize);
  370. if (!KSUCCESS(Status)) {
  371. goto GetThreadInformationEnd;
  372. }
  373. GetThreadInformationEnd:
  374. if (Process != NULL) {
  375. ObReleaseReference(Process);
  376. }
  377. if (Thread != NULL) {
  378. ObReleaseReference(Thread);
  379. }
  380. return Status;
  381. }
  382. INTN
  383. PsSysCreateThread (
  384. PVOID SystemCallParameter
  385. )
  386. /*++
  387. Routine Description:
  388. This routine creates a new thread for the current process.
  389. Arguments:
  390. SystemCallParameter - Supplies a pointer to the parameters supplied with
  391. the system call. This structure will be a stack-local copy of the
  392. actual parameters passed from user-mode.
  393. Return Value:
  394. STATUS_SUCCESS or positive integer on success.
  395. Error status code on failure.
  396. --*/
  397. {
  398. PKPROCESS CurrentProcess;
  399. PSTR Name;
  400. PSYSTEM_CALL_CREATE_THREAD Parameters;
  401. KSTATUS Status;
  402. THREAD_CREATION_PARAMETERS ThreadParameters;
  403. CurrentProcess = PsGetCurrentProcess();
  404. ASSERT(CurrentProcess != PsGetKernelProcess());
  405. Name = NULL;
  406. Parameters = (PSYSTEM_CALL_CREATE_THREAD)SystemCallParameter;
  407. if ((Parameters->Name != NULL) && (Parameters->NameBufferLength != 0)) {
  408. Status = MmCreateCopyOfUserModeString(Parameters->Name,
  409. Parameters->NameBufferLength,
  410. PS_ALLOCATION_TAG,
  411. &Name);
  412. if (!KSUCCESS(Status)) {
  413. goto SysCreateThreadEnd;
  414. }
  415. }
  416. //
  417. // Enable locking on the handle table, which will exist for the remainder
  418. // of the process lifetime.
  419. //
  420. Status = ObEnableHandleTableLocking(CurrentProcess->HandleTable);
  421. if (!KSUCCESS(Status)) {
  422. goto SysCreateThreadEnd;
  423. }
  424. //
  425. // Create and launch the thread.
  426. //
  427. RtlZeroMemory(&ThreadParameters, sizeof(THREAD_CREATION_PARAMETERS));
  428. ThreadParameters.Name = Parameters->Name;
  429. ThreadParameters.NameSize = Parameters->NameBufferLength;
  430. ThreadParameters.ThreadRoutine = Parameters->ThreadRoutine;
  431. ThreadParameters.Parameter = Parameters->Parameter;
  432. ThreadParameters.UserStack = Parameters->StackBase;
  433. ThreadParameters.StackSize = Parameters->StackSize;
  434. ThreadParameters.Flags = THREAD_FLAG_USER_MODE;
  435. ThreadParameters.ThreadPointer = Parameters->ThreadPointer;
  436. ThreadParameters.ThreadIdPointer = Parameters->ThreadId;
  437. if ((PVOID)(ThreadParameters.ThreadIdPointer) >= KERNEL_VA_START) {
  438. Status = STATUS_ACCESS_VIOLATION;
  439. goto SysCreateThreadEnd;
  440. }
  441. Status = PsCreateThread(&ThreadParameters);
  442. if (!KSUCCESS(Status)) {
  443. goto SysCreateThreadEnd;
  444. }
  445. //
  446. // Update the stack base and size on output.
  447. //
  448. Parameters->StackBase = ThreadParameters.UserStack;
  449. Parameters->StackSize = ThreadParameters.StackSize;
  450. //
  451. // Null out the name parameters as that memory is now owned by the object
  452. // manager.
  453. //
  454. Name = NULL;
  455. Status = STATUS_SUCCESS;
  456. SysCreateThreadEnd:
  457. if (Name != NULL) {
  458. MmFreePagedPool(Name);
  459. }
  460. return Status;
  461. }
  462. INTN
  463. PsSysExitThread (
  464. PVOID SystemCallParameter
  465. )
  466. /*++
  467. Routine Description:
  468. This routine terminates the current thread.
  469. Arguments:
  470. SystemCallParameter - Supplies a pointer to the parameters supplied with
  471. the system call. This structure will be a stack-local copy of the
  472. actual parameters passed from user-mode.
  473. Return Value:
  474. Does not return. Eventually exits by killing the thread.
  475. --*/
  476. {
  477. PSYSTEM_CALL_EXIT_THREAD Parameters;
  478. PKTHREAD Thread;
  479. PVOID ThreadIdPointer;
  480. Parameters = SystemCallParameter;
  481. //
  482. // Before killing the thread, unmap a region if requested. This is used by
  483. // the user-modes thread library to clean up the stack for the thread that
  484. // just exited.
  485. //
  486. if ((Parameters->UnmapSize != 0) && (Parameters->UnmapAddress != NULL)) {
  487. //
  488. // Clear the thread ID pointer if it's in the unmap region. This saves
  489. // the C library a system call.
  490. //
  491. Thread = KeGetCurrentThread();
  492. ThreadIdPointer = Thread->ThreadIdPointer;
  493. if ((ThreadIdPointer >= Parameters->UnmapAddress) &&
  494. (ThreadIdPointer <
  495. Parameters->UnmapAddress + Parameters->UnmapSize)) {
  496. Thread->ThreadIdPointer = NULL;
  497. }
  498. MmUnmapFileSection(PsGetCurrentProcess(),
  499. Parameters->UnmapAddress,
  500. Parameters->UnmapSize,
  501. NULL);
  502. }
  503. PspThreadTermination();
  504. //
  505. // Execution should never get here.
  506. //
  507. ASSERT(FALSE);
  508. return STATUS_UNSUCCESSFUL;
  509. }
  510. INTN
  511. PsSysSetThreadPointer (
  512. PVOID SystemCallParameter
  513. )
  514. /*++
  515. Routine Description:
  516. This routine sets the thread pointer for the current thread.
  517. Arguments:
  518. SystemCallParameter - Supplies a pointer to the parameters supplied with
  519. the system call. This is supplies the thread pointer directly, which is
  520. passed from user mode via a register.
  521. Return Value:
  522. STATUS_SUCCESS or positive integer on success.
  523. Error status code on failure.
  524. --*/
  525. {
  526. ArSetThreadPointer(KeGetCurrentThread(), SystemCallParameter);
  527. return STATUS_SUCCESS;
  528. }
  529. INTN
  530. PsSysSetThreadIdPointer (
  531. PVOID SystemCallParameter
  532. )
  533. /*++
  534. Routine Description:
  535. This routine sets the thread ID pointer for the current thread.
  536. Arguments:
  537. SystemCallParameter - Supplies a pointer to the parameters supplied with
  538. the system call. This is supplies the thread ID pointer directly, which
  539. is passed from user mode via a register.
  540. Return Value:
  541. STATUS_SUCCESS or positive integer on success.
  542. Error status code on failure.
  543. --*/
  544. {
  545. PVOID Pointer;
  546. PKTHREAD Thread;
  547. Pointer = SystemCallParameter;
  548. Thread = KeGetCurrentThread();
  549. if (Pointer < USER_VA_END) {
  550. Thread->ThreadIdPointer = Pointer;
  551. //
  552. // As a convenience, also set the thread ID if the pointer is being set
  553. // to a new value. This is useful when the executable becomes
  554. // multithreaded and the main thread needs to catch up setting up a
  555. // thread structure.
  556. //
  557. if (Pointer != NULL) {
  558. MmUserWrite32(Pointer, Thread->ThreadId);
  559. }
  560. }
  561. return STATUS_SUCCESS;
  562. }
  563. VOID
  564. PsQueueThreadCleanup (
  565. PKTHREAD Thread
  566. )
  567. /*++
  568. Routine Description:
  569. This routine queues the work item that cleans up a dead thread. This routine
  570. must not be executed by the thread being destroyed! This routine must be
  571. called at dispatch level.
  572. Arguments:
  573. Thread - Supplies a pointer to the thread to clean up.
  574. Return Value:
  575. None.
  576. --*/
  577. {
  578. RUNLEVEL OldRunLevel;
  579. ASSERT(KeGetCurrentThread() != Thread);
  580. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  581. KeAcquireSpinLock(&PsDeadThreadsLock);
  582. ASSERT(Thread->SchedulerEntry.ListEntry.Next == NULL);
  583. INSERT_AFTER(&(Thread->SchedulerEntry.ListEntry), &PsDeadThreadsListHead);
  584. PsDeadThreadsCount += 1;
  585. KeSignalEvent(PsDeadThreadsEvent, SignalOptionSignalAll);
  586. KeReleaseSpinLock(&PsDeadThreadsLock);
  587. KeLowerRunLevel(OldRunLevel);
  588. return;
  589. }
  590. KSTATUS
  591. PspSetThreadUserStackSize (
  592. PKTHREAD Thread,
  593. UINTN NewStackSize
  594. )
  595. /*++
  596. Routine Description:
  597. This routine changes the given thread's user mode stack size.
  598. Arguments:
  599. Thread - Supplies a pointer to the thread whose stack size should be
  600. changed.
  601. NewStackSize - Supplies the new stack size to set. If 0 is supplied, the
  602. user mode stack will be destroyed.
  603. Return Value:
  604. Status code.
  605. --*/
  606. {
  607. ULONG Flags;
  608. PVOID MaxMapRegion;
  609. ULONG PageSize;
  610. KSTATUS Status;
  611. VM_ALLOCATION_PARAMETERS VaRequest;
  612. PageSize = MmPageSize();
  613. if (NewStackSize > USER_STACK_MAX) {
  614. NewStackSize = USER_STACK_MAX;
  615. }
  616. NewStackSize = ALIGN_RANGE_UP(NewStackSize, PageSize);
  617. //
  618. // Shrink or destroy the stack if requested. This whole routine assumes the
  619. // stack grows down.
  620. //
  621. if (NewStackSize <= Thread->UserStackSize) {
  622. Status = STATUS_SUCCESS;
  623. if ((Thread->UserStackSize != 0) &&
  624. (NewStackSize != Thread->UserStackSize)) {
  625. Status = MmUnmapFileSection(Thread->OwningProcess,
  626. Thread->UserStack,
  627. Thread->UserStackSize - NewStackSize,
  628. NULL);
  629. if (NewStackSize != 0) {
  630. Thread->UserStack += Thread->UserStackSize - NewStackSize;
  631. }
  632. Thread->UserStackSize = NewStackSize;
  633. }
  634. if (NewStackSize == 0) {
  635. Thread->UserStack = NULL;
  636. Thread->UserStackSize = 0;
  637. }
  638. //
  639. // Create or grow the stack.
  640. //
  641. } else {
  642. VaRequest.Address = NULL;
  643. VaRequest.Size = NewStackSize;
  644. VaRequest.Strategy = AllocationStrategyHighestAddress;
  645. if (Thread->UserStackSize != 0) {
  646. VaRequest.Strategy = AllocationStrategyFixedAddress;
  647. VaRequest.Address = Thread->UserStack + Thread->UserStackSize -
  648. NewStackSize;
  649. if (VaRequest.Address > Thread->UserStack) {
  650. Status = STATUS_INTEGER_OVERFLOW;
  651. goto SetThreadUserStackSizeEnd;
  652. }
  653. VaRequest.Size = NewStackSize - Thread->UserStackSize;
  654. }
  655. ASSERT(Thread->UserStackSize == 0);
  656. ASSERT(Thread->UserStack == NULL);
  657. //
  658. // Check against the current resource limit.
  659. //
  660. if (NewStackSize > Thread->Limits[ResourceLimitStack].Current) {
  661. Status = STATUS_INSUFFICIENT_RESOURCES;
  662. goto SetThreadUserStackSizeEnd;
  663. }
  664. Flags = IMAGE_SECTION_READABLE | IMAGE_SECTION_WRITABLE;
  665. VaRequest.Alignment = 0;
  666. VaRequest.Min = 0;
  667. VaRequest.Max = MAX_ADDRESS;
  668. VaRequest.MemoryType = MemoryTypeReserved;
  669. Status = MmMapFileSection(INVALID_HANDLE,
  670. 0,
  671. &VaRequest,
  672. Flags,
  673. FALSE,
  674. NULL);
  675. if (!KSUCCESS(Status)) {
  676. goto SetThreadUserStackSizeEnd;
  677. }
  678. //
  679. // If this was the first time the stack size has been set, save the
  680. // upper limit for memory mapped regions. This gives the stack some
  681. // breathing room to grow.
  682. //
  683. if ((Thread->UserStackSize == 0) &&
  684. (Thread->OwningProcess->AddressSpace->MaxMemoryMap == 0)) {
  685. MaxMapRegion = VaRequest.Address;
  686. if (NewStackSize < USER_STACK_HEADROOM) {
  687. MaxMapRegion = VaRequest.Address + NewStackSize -
  688. USER_STACK_HEADROOM;
  689. }
  690. Thread->OwningProcess->AddressSpace->MaxMemoryMap = MaxMapRegion;
  691. }
  692. //
  693. // Don't free the stack for the first thread, as it contains the
  694. // environment and arguments. Do free it for all the other threads
  695. // that used the kernel to allocate a stack.
  696. //
  697. if (Thread->OwningProcess->ThreadCount > 1) {
  698. Thread->Flags |= THREAD_FLAG_FREE_USER_STACK;
  699. }
  700. Thread->UserStack = VaRequest.Address;
  701. Thread->UserStackSize = NewStackSize;
  702. Status = STATUS_SUCCESS;
  703. }
  704. SetThreadUserStackSizeEnd:
  705. return Status;
  706. }
  707. VOID
  708. PspKernelThreadStart (
  709. VOID
  710. )
  711. /*++
  712. Routine Description:
  713. This routine performs common initialization for all kernel mode threads, and
  714. executes the primary thread routine.
  715. Arguments:
  716. None.
  717. Return Value:
  718. Does not return. Eventually exits by killing the thread.
  719. --*/
  720. {
  721. PTHREAD_ENTRY_ROUTINE Entry;
  722. PKTHREAD Thread;
  723. //
  724. // Run the thread.
  725. //
  726. Thread = KeGetCurrentThread();
  727. Entry = Thread->ThreadRoutine;
  728. Entry(Thread->ThreadParameter);
  729. //
  730. // The thread returned, so exit.
  731. //
  732. PspThreadTermination();
  733. return;
  734. }
  735. KSTATUS
  736. PspInitializeThreadSupport (
  737. VOID
  738. )
  739. /*++
  740. Routine Description:
  741. This routine performs one-time system initialization for thread support.
  742. Arguments:
  743. None.
  744. Return Value:
  745. Status code.
  746. --*/
  747. {
  748. KSTATUS Status;
  749. ASSERT(KeGetCurrentProcessorNumber() == 0);
  750. ASSERT(PsDeadThreadsCount == 0);
  751. KeInitializeSpinLock(&PsDeadThreadsLock);
  752. INITIALIZE_LIST_HEAD(&PsDeadThreadsListHead);
  753. PsDeadThreadsEvent = KeCreateEvent(NULL);
  754. if (PsDeadThreadsEvent == NULL) {
  755. Status = STATUS_INSUFFICIENT_RESOURCES;
  756. goto InitializeThreadSupportEnd;
  757. }
  758. //
  759. // Create the reaper thread.
  760. //
  761. Status = PsCreateKernelThread(PspReaperThread, NULL, "PspReaperThread");
  762. if (!KSUCCESS(Status)) {
  763. goto InitializeThreadSupportEnd;
  764. }
  765. Status = STATUS_SUCCESS;
  766. InitializeThreadSupportEnd:
  767. return Status;
  768. }
  769. PKTHREAD
  770. PspCloneThread (
  771. PKPROCESS DestinationProcess,
  772. PKTHREAD Thread,
  773. PVOID KernelStack,
  774. UINTN KernelStackSize,
  775. PTRAP_FRAME TrapFrame
  776. )
  777. /*++
  778. Routine Description:
  779. This routine clones a user mode thread from another process into the
  780. destination thread. This routine is designed to support the fork process
  781. system call.
  782. Arguments:
  783. DestinationProcess - Supplies a pointer to the process the new thread
  784. should be created under.
  785. Thread - Supplies a pointer to the thread to clone.
  786. KernelStack - Supplies a pointer to the kernel stack to use.
  787. KernelStackSize - Supplies the size of the supplied kernel stack in bytes.
  788. TrapFrame - Supplies a pointer to the trap frame to set initial thread
  789. state to. A copy of this trap frame will be made.
  790. Return Value:
  791. Returns a pointer to the new thread on success, or NULL on failure.
  792. --*/
  793. {
  794. PKTHREAD NewThread;
  795. KSTATUS Status;
  796. NewThread = PspCreateThread(DestinationProcess,
  797. KernelStack,
  798. KernelStackSize,
  799. Thread->ThreadRoutine,
  800. Thread->ThreadParameter,
  801. Thread->Header.Name,
  802. Thread->Flags & THREAD_FLAG_CREATION_MASK);
  803. if (NewThread == NULL) {
  804. Status = STATUS_UNSUCCESSFUL;
  805. goto CloneThreadEnd;
  806. }
  807. //
  808. // Copy the existing thread's credentials to the new thread.
  809. //
  810. Status = PspCopyThreadCredentials(NewThread, Thread);
  811. if (!KSUCCESS(Status)) {
  812. goto CloneThreadEnd;
  813. }
  814. Status = PspArchCloneThread(Thread, NewThread);
  815. if (!KSUCCESS(Status)) {
  816. goto CloneThreadEnd;
  817. }
  818. //
  819. // The user stack is presumed to be set up in the new process at the same
  820. // place.
  821. //
  822. NewThread->BlockedSignals = Thread->BlockedSignals;
  823. NewThread->UserStack = Thread->UserStack;
  824. NewThread->UserStackSize = Thread->UserStackSize;
  825. PspPrepareThreadForFirstRun(NewThread, TrapFrame, FALSE);
  826. NewThread->ThreadPointer = Thread->ThreadPointer;
  827. NewThread->ThreadIdPointer = Thread->ThreadIdPointer;
  828. //
  829. // Insert the thread onto the ready list.
  830. //
  831. KeSetThreadReady(NewThread);
  832. Status = STATUS_SUCCESS;
  833. CloneThreadEnd:
  834. if (!KSUCCESS(Status)) {
  835. if (NewThread != NULL) {
  836. ASSERT(NewThread->SupplementaryGroups == NULL);
  837. ObReleaseReference(NewThread);
  838. NewThread = NULL;
  839. }
  840. }
  841. return NewThread;
  842. }
  843. KSTATUS
  844. PspResetThread (
  845. PKTHREAD Thread,
  846. PTRAP_FRAME TrapFrame,
  847. PINTN ReturnValue
  848. )
  849. /*++
  850. Routine Description:
  851. This routine resets a user mode thread. It assumes that the user mode stack
  852. was freed out from under it, and sets up a new stack.
  853. Arguments:
  854. Thread - Supplies a pointer to the thread to reset. The thread must be a
  855. user mode thread. A new user mode stack will be allocated for it, the
  856. old one will not be freed. Commonly, this parameter will be a pointer
  857. to the currently running thread.
  858. TrapFrame - Supplies a pointer to the initial trap frame to reset the thread
  859. to.
  860. ReturnValue - Supplies a pointer that receives the value that the reset
  861. user mode thread should return when exiting back to user mode.
  862. Return Value:
  863. Status code.
  864. --*/
  865. {
  866. PPROCESS_ENVIRONMENT Environment;
  867. KSTATUS Status;
  868. PPROCESS_ENVIRONMENT UserEnvironment;
  869. //
  870. // Create the user mode stack.
  871. //
  872. ASSERT((Thread->Flags & THREAD_FLAG_USER_MODE) != 0);
  873. Thread->ThreadIdPointer = NULL;
  874. Status = PspSetThreadUserStackSize(
  875. Thread,
  876. Thread->Limits[ResourceLimitStack].Current);
  877. if (!KSUCCESS(Status)) {
  878. goto CreateThreadEnd;
  879. }
  880. Thread->ThreadParameter = NULL;
  881. Environment = Thread->OwningProcess->Environment;
  882. Environment->StartData->StackBase = Thread->UserStack;
  883. Status = PsCopyEnvironment(Environment,
  884. &UserEnvironment,
  885. FALSE,
  886. Thread,
  887. NULL,
  888. 0);
  889. if (!KSUCCESS(Status)) {
  890. goto CreateThreadEnd;
  891. }
  892. *ReturnValue = PspArchResetThreadContext(Thread, TrapFrame);
  893. Status = STATUS_SUCCESS;
  894. CreateThreadEnd:
  895. if (!KSUCCESS(Status)) {
  896. PspSetThreadUserStackSize(Thread, 0);
  897. }
  898. return Status;
  899. }
  900. PKTHREAD
  901. PspGetThreadById (
  902. PKPROCESS Process,
  903. THREAD_ID ThreadId
  904. )
  905. /*++
  906. Routine Description:
  907. This routine returns the thread with the given thread ID under the given
  908. process. This routine also increases the reference count of the returned
  909. thread.
  910. Arguments:
  911. Process - Supplies a pointer to the process to search under.
  912. ThreadId - Supplies the thread ID to search for.
  913. Return Value:
  914. Returns a pointer to the thread with the corresponding ID. The reference
  915. count will be increased by one.
  916. NULL if no such thread could be found.
  917. --*/
  918. {
  919. PLIST_ENTRY CurrentEntry;
  920. PKTHREAD FoundThread;
  921. PKTHREAD Thread;
  922. ASSERT(KeGetRunLevel() == RunLevelLow);
  923. FoundThread = NULL;
  924. KeAcquireQueuedLock(Process->QueuedLock);
  925. CurrentEntry = Process->ThreadListHead.Next;
  926. while (CurrentEntry != &(Process->ThreadListHead)) {
  927. Thread = LIST_VALUE(CurrentEntry, KTHREAD, ProcessEntry);
  928. if (Thread->ThreadId == ThreadId) {
  929. FoundThread = Thread;
  930. ObAddReference(FoundThread);
  931. break;
  932. }
  933. CurrentEntry = CurrentEntry->Next;
  934. }
  935. KeReleaseQueuedLock(Process->QueuedLock);
  936. return FoundThread;
  937. }
  938. VOID
  939. PspThreadTermination (
  940. VOID
  941. )
  942. /*++
  943. Routine Description:
  944. This routine is called when a thread finishes execution, it performs some
  945. cleanup and calls the scheduler to exit the thread. This routine runs in
  946. the context of the thread itself.
  947. Arguments:
  948. None.
  949. Return Value:
  950. Does not return. Eventually exits by killing the thread.
  951. --*/
  952. {
  953. PFPU_CONTEXT FpuContext;
  954. BOOL LastThread;
  955. PKPROCESS Process;
  956. PKTHREAD Thread;
  957. SYSTEM_CALL_USER_LOCK WakeOperation;
  958. LastThread = FALSE;
  959. Thread = KeGetCurrentThread();
  960. Process = Thread->OwningProcess;
  961. //
  962. // Mark that the thread is exiting so that it does not get chosen for any
  963. // new signals.
  964. //
  965. Thread->Flags |= THREAD_FLAG_EXITING;
  966. //
  967. // Free the user mode stack before decrementing the thread count.
  968. //
  969. PspSetThreadUserStackSize(Thread, 0);
  970. //
  971. // Decrement the thread count. If this is the last thread, unload all
  972. // images in the process.
  973. //
  974. KeAcquireQueuedLock(Process->QueuedLock);
  975. ASSERT((Process->ThreadCount != 0) && (Process->ThreadCount < 0x10000000));
  976. Process->ThreadCount -= 1;
  977. if (Process->ThreadCount == 0) {
  978. //
  979. // The last thread shouldn't be exiting without having first set the
  980. // exit flags.
  981. //
  982. ASSERT((Process == PsGetKernelProcess()) || (Process->ExitReason != 0));
  983. LastThread = TRUE;
  984. }
  985. //
  986. // If a stop was requested and this thread happened to be the last one
  987. // being waited for, signal the all stopped event.
  988. //
  989. if ((Process->DebugData != NULL) &&
  990. (Process->ThreadCount != 0) &&
  991. (Process->StoppedThreadCount == Process->ThreadCount)) {
  992. KeSignalEvent(Process->DebugData->AllStoppedEvent,
  993. SignalOptionSignalAll);
  994. }
  995. //
  996. // The thread may have been responsible for dispatching some signals. Pass
  997. // those on to other threads.
  998. //
  999. PspCleanupThreadSignals();
  1000. KeReleaseQueuedLock(Process->QueuedLock);
  1001. //
  1002. // Wake any threads waiting on the thread ID address.
  1003. //
  1004. if ((LastThread == FALSE) && (Thread->ThreadIdPointer != NULL)) {
  1005. ASSERT((PVOID)(Thread->ThreadIdPointer) < USER_VA_END);
  1006. ASSERT(sizeof(THREAD_ID) == sizeof(ULONG));
  1007. MmUserWrite32(Thread->ThreadIdPointer, 0);
  1008. WakeOperation.Address = (PULONG)(Thread->ThreadIdPointer);
  1009. WakeOperation.Value = 1;
  1010. WakeOperation.Operation = UserLockWake;
  1011. WakeOperation.TimeoutInMilliseconds = 0;
  1012. PspUserLockWake(&WakeOperation);
  1013. }
  1014. PspDestroyCredentials(Thread);
  1015. //
  1016. // Free up the FPU context. The thread could still get context swapped here,
  1017. // which is why it's NULLed and then freed. The context swap code watches
  1018. // out for this case where the using FPU flag is set but the context is
  1019. // gone.
  1020. //
  1021. FpuContext = Thread->FpuContext;
  1022. if (FpuContext != NULL) {
  1023. Thread->FpuContext = NULL;
  1024. ArDestroyFpuContext(FpuContext);
  1025. }
  1026. //
  1027. // If this was the last thread in the process, clean up the dying process.
  1028. //
  1029. if (LastThread != FALSE) {
  1030. PspProcessTermination(Process);
  1031. }
  1032. KeRaiseRunLevel(RunLevelDispatch);
  1033. KeSchedulerEntry(SchedulerReasonThreadExiting);
  1034. //
  1035. // Execution should never get here.
  1036. //
  1037. KeCrashSystem(CRASH_THREAD_ERROR,
  1038. (UINTN)Thread,
  1039. Thread->State,
  1040. 0,
  1041. 0);
  1042. return;
  1043. }
  1044. //
  1045. // --------------------------------------------------------- Internal Functions
  1046. //
  1047. PKTHREAD
  1048. PspCreateThread (
  1049. PKPROCESS OwningProcess,
  1050. PVOID KernelStack,
  1051. ULONG KernelStackSize,
  1052. PTHREAD_ENTRY_ROUTINE ThreadRoutine,
  1053. PVOID ThreadParameter,
  1054. PCSTR Name,
  1055. ULONG Flags
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. This routine creates and initializes a new thread. It will not create a
  1060. user mode stack.
  1061. Arguments:
  1062. OwningProcess - Supplies a pointer to the process responsible for creating
  1063. this thread.
  1064. KernelStack - Supplies an optional pointer to a kernel stack. If NULL is
  1065. supplied, then one will be created.
  1066. KernelStackSize - Supplies the initial size of the kernel mode stack, in
  1067. bytes. Supply 0 to use a default size.
  1068. ThreadRoutine - Supplies the entry point to thread.
  1069. ThreadParameter - Supplies the parameter to pass to the entry point routine.
  1070. Name - Supplies an optional name to identify the thread.
  1071. Flags - Supplies a set of flags governing the behavior and characteristics
  1072. of the thread. See THREAD_FLAG_* definitions.
  1073. Return Value:
  1074. Returns a pointer to the new thread on success, or NULL on failure.
  1075. --*/
  1076. {
  1077. PKTHREAD CurrentThread;
  1078. ULONG NameLength;
  1079. PKTHREAD NewThread;
  1080. ULONG ObjectFlags;
  1081. KSTATUS Status;
  1082. BOOL UserMode;
  1083. ASSERT(KeGetRunLevel() == RunLevelLow);
  1084. ASSERT((Flags & ~THREAD_FLAG_CREATION_MASK) == 0);
  1085. //
  1086. // Before creating a new thread, make sure there aren't too many dead
  1087. // threads hanging around. If there are dead threads, attempt to help the
  1088. // system out be reaping some before creating a new thread.
  1089. //
  1090. if (PsDeadThreadsCount > THREAD_CREATE_DEAD_THREAD_THRESHOLD) {
  1091. PspReapThreads(THREAD_CREATE_REAP_COUNT);
  1092. }
  1093. CurrentThread = KeGetCurrentThread();
  1094. UserMode = FALSE;
  1095. if ((Flags & THREAD_FLAG_USER_MODE) != 0) {
  1096. UserMode = TRUE;
  1097. }
  1098. if (KernelStackSize == 0) {
  1099. ASSERT(KernelStack == NULL);
  1100. KernelStackSize = DEFAULT_KERNEL_STACK_SIZE;
  1101. }
  1102. if (OwningProcess == NULL) {
  1103. OwningProcess = CurrentThread->OwningProcess;
  1104. if (UserMode == FALSE) {
  1105. OwningProcess = PsKernelProcess;
  1106. }
  1107. }
  1108. ASSERT((ThreadRoutine == NULL) ||
  1109. ((UserMode == FALSE) && ((PVOID)ThreadRoutine >= KERNEL_VA_START)) ||
  1110. ((UserMode != FALSE) && ((PVOID)ThreadRoutine < USER_VA_END)));
  1111. NameLength = 0;
  1112. if (Name != NULL) {
  1113. NameLength = RtlStringLength(Name) + 1;
  1114. }
  1115. //
  1116. // Allocate the new thread's structure.
  1117. //
  1118. ObjectFlags = OBJECT_FLAG_USE_NAME_DIRECTLY;
  1119. NewThread = ObCreateObject(ObjectThread,
  1120. OwningProcess,
  1121. Name,
  1122. NameLength,
  1123. sizeof(KTHREAD),
  1124. PspDestroyThread,
  1125. ObjectFlags,
  1126. PS_ALLOCATION_TAG);
  1127. if (NewThread == NULL) {
  1128. Status = STATUS_INSUFFICIENT_RESOURCES;
  1129. goto CreateThreadEnd;
  1130. }
  1131. INITIALIZE_LIST_HEAD(&(NewThread->SignalListHead));
  1132. NewThread->OwningProcess = OwningProcess;
  1133. NewThread->State = ThreadStateFirstTime;
  1134. NewThread->KernelStackSize = KernelStackSize;
  1135. NewThread->ThreadRoutine = ThreadRoutine;
  1136. NewThread->ThreadParameter = ThreadParameter;
  1137. NewThread->Flags = Flags;
  1138. NewThread->SignalPending = ThreadNoSignalPending;
  1139. NewThread->SchedulerEntry.Type = SchedulerEntryThread;
  1140. NewThread->SchedulerEntry.Parent = CurrentThread->SchedulerEntry.Parent;
  1141. NewThread->ThreadPointer = PsInitialThreadPointer;
  1142. //
  1143. // Allocate a kernel stack unless one was provided. Touch the top level
  1144. // page directory to ensure that the stack can be switched onto when it's
  1145. // time to run this thread.
  1146. //
  1147. NewThread->KernelStack = KernelStack;
  1148. if (KernelStack == NULL) {
  1149. NewThread->KernelStack = MmAllocateKernelStack(KernelStackSize);
  1150. if (NewThread->KernelStack == NULL) {
  1151. Status = STATUS_INSUFFICIENT_RESOURCES;
  1152. goto CreateThreadEnd;
  1153. }
  1154. //
  1155. // Touch the top level table even if this is the owning process and
  1156. // current process are the same. The allocated stack may have been
  1157. // cached, but still created after this process was started.
  1158. //
  1159. MmUpdatePageDirectory(OwningProcess->AddressSpace,
  1160. NewThread->KernelStack,
  1161. KernelStackSize);
  1162. }
  1163. //
  1164. // Create a timer to be used for most operations that can time out.
  1165. //
  1166. NewThread->BuiltinTimer = KeCreateTimer(PS_ALLOCATION_TAG);
  1167. if (NewThread->BuiltinTimer == NULL) {
  1168. Status = STATUS_INSUFFICIENT_RESOURCES;
  1169. goto CreateThreadEnd;
  1170. }
  1171. //
  1172. // Create a built in wait block for the thread.
  1173. //
  1174. NewThread->BuiltinWaitBlock = ObCreateWaitBlock(0);
  1175. if (NewThread->BuiltinWaitBlock == NULL) {
  1176. Status = STATUS_INSUFFICIENT_RESOURCES;
  1177. goto CreateThreadEnd;
  1178. }
  1179. //
  1180. // Give the thread a unique ID.
  1181. //
  1182. NewThread->ThreadId = RtlAtomicAdd32((PULONG)&PsNextThreadId, 1);
  1183. //
  1184. // Add the thread to the process.
  1185. //
  1186. KeAcquireQueuedLock(OwningProcess->QueuedLock);
  1187. INSERT_BEFORE(&(NewThread->ProcessEntry), &(OwningProcess->ThreadListHead));
  1188. OwningProcess->ThreadCount += 1;
  1189. KeReleaseQueuedLock(OwningProcess->QueuedLock);
  1190. SpProcessNewThread(OwningProcess->Identifiers.ProcessId,
  1191. NewThread->ThreadId);
  1192. Status = STATUS_SUCCESS;
  1193. CreateThreadEnd:
  1194. if (!KSUCCESS(Status)) {
  1195. if (NewThread != NULL) {
  1196. if (KernelStack != NULL) {
  1197. NewThread->KernelStack = NULL;
  1198. NewThread->KernelStackSize = 0;
  1199. }
  1200. ObReleaseReference(NewThread);
  1201. NewThread = NULL;
  1202. }
  1203. }
  1204. return NewThread;
  1205. }
  1206. VOID
  1207. PspReaperThread (
  1208. PVOID Parameter
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. This routine waits on the dead thread event and when the event is signaled
  1213. it attempts to reap the default number of threads until the event is no
  1214. longer signaled.
  1215. Arguments:
  1216. Parameter - Supplies a pointer supplied by the creator of the thread. This
  1217. parameter is not used.
  1218. Return Value:
  1219. None. This thread never exits.
  1220. --*/
  1221. {
  1222. while (TRUE) {
  1223. KeWaitForEvent(PsDeadThreadsEvent, FALSE, WAIT_TIME_INDEFINITE);
  1224. PspReapThreads(THREAD_DEFAULT_REAP_COUNT);
  1225. }
  1226. return;
  1227. }
  1228. VOID
  1229. PspReapThreads (
  1230. UINTN TargetReapCount
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. This routine checks for any threads that need to be cleaned up, dequeues
  1235. them, and then frees the threads and all associated memory. This routine
  1236. runs at low level.
  1237. Arguments:
  1238. TargetReapCount - Supplies the maximum number of threads to reap.
  1239. Return Value:
  1240. None.
  1241. --*/
  1242. {
  1243. PLIST_ENTRY CurrentEntry;
  1244. LIST_ENTRY ListHead;
  1245. RUNLEVEL OldRunLevel;
  1246. UINTN ReapCount;
  1247. PKTHREAD Thread;
  1248. ASSERT(KeGetRunLevel() == RunLevelLow);
  1249. //
  1250. // Acquire the lock and move up to the requested number of threads to the
  1251. // local list.
  1252. //
  1253. ReapCount = 0;
  1254. INITIALIZE_LIST_HEAD(&ListHead);
  1255. OldRunLevel = KeRaiseRunLevel(RunLevelDispatch);
  1256. KeAcquireSpinLock(&PsDeadThreadsLock);
  1257. while ((LIST_EMPTY(&PsDeadThreadsListHead) == FALSE) &&
  1258. (ReapCount < TargetReapCount)) {
  1259. CurrentEntry = PsDeadThreadsListHead.Next;
  1260. LIST_REMOVE(CurrentEntry);
  1261. INSERT_BEFORE(CurrentEntry, &ListHead);
  1262. ReapCount += 1;
  1263. }
  1264. PsDeadThreadsCount -= ReapCount;
  1265. //
  1266. // Only unsignal the event if there are no threads left to reap.
  1267. //
  1268. if (LIST_EMPTY(&PsDeadThreadsListHead) != FALSE) {
  1269. KeSignalEvent(PsDeadThreadsEvent, SignalOptionUnsignal);
  1270. }
  1271. KeReleaseSpinLock(&PsDeadThreadsLock);
  1272. KeLowerRunLevel(OldRunLevel);
  1273. //
  1274. // Now that execution is running back at passive, calmly walk the local
  1275. // list, signal anyone waiting on the thread exiting, and destroy the
  1276. // threads.
  1277. //
  1278. while (LIST_EMPTY(&ListHead) == FALSE) {
  1279. Thread = LIST_VALUE(ListHead.Next,
  1280. KTHREAD,
  1281. SchedulerEntry.ListEntry);
  1282. LIST_REMOVE(&(Thread->SchedulerEntry.ListEntry));
  1283. Thread->SchedulerEntry.ListEntry.Next = NULL;
  1284. //
  1285. // Remove the thread from the process before the reference count
  1286. // drops to zero so that acquiring the process lock and adding
  1287. // a reference synchronizes against the thread destroying itself
  1288. // during or after that process lock is released.
  1289. //
  1290. KeAcquireQueuedLock(Thread->OwningProcess->QueuedLock);
  1291. LIST_REMOVE(&(Thread->ProcessEntry));
  1292. Thread->ProcessEntry.Next = NULL;
  1293. //
  1294. // The thread has been removed from the process's thread list. Add
  1295. // its resource usage to the process' counts. This is where a process'
  1296. // max resident set is updated (by setting it in the thread and then
  1297. // updating to the parent).
  1298. //
  1299. Thread->ResourceUsage.MaxResidentSet =
  1300. Thread->OwningProcess->AddressSpace->MaxResidentSet;
  1301. PspAddResourceUsages(&(Thread->OwningProcess->ResourceUsage),
  1302. &(Thread->ResourceUsage));
  1303. KeReleaseQueuedLock(Thread->OwningProcess->QueuedLock);
  1304. //
  1305. // Signal everyone waiting on the thread to die.
  1306. //
  1307. ObSignalObject(Thread, SignalOptionSignalAll);
  1308. ObReleaseReference(Thread);
  1309. }
  1310. return;
  1311. }
  1312. VOID
  1313. PspDestroyThread (
  1314. PVOID ThreadObject
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. This routine frees all memory associated with a thread. It is assumed that
  1319. the thread has already been unlinked from any queues or ready lists.
  1320. Arguments:
  1321. ThreadObject - Supplies the thread to free.
  1322. Return Value:
  1323. None.
  1324. --*/
  1325. {
  1326. BOOL DestroyProcess;
  1327. BOOL LastThread;
  1328. PKPROCESS Process;
  1329. BOOL SignalQueued;
  1330. PSIGNAL_QUEUE_ENTRY SignalQueueEntry;
  1331. PKTHREAD Thread;
  1332. ASSERT(KeGetRunLevel() == RunLevelLow);
  1333. ASSERT(KeGetCurrentThread() != ThreadObject);
  1334. Thread = (PKTHREAD)ThreadObject;
  1335. ASSERT((Thread->State == ThreadStateExited) ||
  1336. (Thread->State == ThreadStateFirstTime));
  1337. ASSERT(Thread->Header.ReferenceCount == 0);
  1338. ASSERT(Thread->ProcessEntry.Next == NULL);
  1339. ASSERT(Thread->SupplementaryGroups == NULL);
  1340. //
  1341. // Clean up any queued signals that snuck on while the thread was dying.
  1342. //
  1343. while (LIST_EMPTY(&(Thread->SignalListHead)) == FALSE) {
  1344. SignalQueueEntry = LIST_VALUE(Thread->SignalListHead.Next,
  1345. SIGNAL_QUEUE_ENTRY,
  1346. ListEntry);
  1347. LIST_REMOVE(&(SignalQueueEntry->ListEntry));
  1348. SignalQueueEntry->ListEntry.Next = NULL;
  1349. if (SignalQueueEntry->CompletionRoutine != NULL) {
  1350. SignalQueueEntry->CompletionRoutine(SignalQueueEntry);
  1351. }
  1352. }
  1353. DestroyProcess = FALSE;
  1354. //
  1355. // Destroy the built in timer.
  1356. //
  1357. if (Thread->BuiltinTimer != NULL) {
  1358. KeDestroyTimer(Thread->BuiltinTimer);
  1359. }
  1360. //
  1361. // Destroy the built in wait block.
  1362. //
  1363. if (Thread->BuiltinWaitBlock != NULL) {
  1364. ObDestroyWaitBlock(Thread->BuiltinWaitBlock);
  1365. }
  1366. Process = Thread->OwningProcess;
  1367. //
  1368. // If the thread never got a chance to run, remove it from the owning
  1369. // process's list and if this is the last thread, make sure the process has
  1370. // an exit status before proceeding.
  1371. //
  1372. if (Thread->State == ThreadStateFirstTime) {
  1373. LastThread = FALSE;
  1374. if (Thread->ProcessEntry.Next != NULL) {
  1375. KeAcquireQueuedLock(Process->QueuedLock);
  1376. LIST_REMOVE(&(Thread->ProcessEntry));
  1377. Process->ThreadCount -= 1;
  1378. if (Process->ThreadCount == 0) {
  1379. LastThread = TRUE;
  1380. }
  1381. KeReleaseQueuedLock(Process->QueuedLock);
  1382. Thread->ProcessEntry.Next = NULL;
  1383. } else if (Process->ThreadCount == 0) {
  1384. LastThread = TRUE;
  1385. }
  1386. if ((LastThread != FALSE) && (Process->ExitReason == 0)) {
  1387. PspSetProcessExitStatus(Process,
  1388. CHILD_SIGNAL_REASON_KILLED,
  1389. SIGNAL_ABORT);
  1390. }
  1391. }
  1392. if (LIST_EMPTY(&(Process->ThreadListHead)) != FALSE) {
  1393. DestroyProcess = TRUE;
  1394. }
  1395. //
  1396. // Free the kernel stack.
  1397. //
  1398. if (Thread->KernelStack != NULL) {
  1399. MmFreeKernelStack(Thread->KernelStack, Thread->KernelStackSize);
  1400. Thread->KernelStack = NULL;
  1401. }
  1402. //
  1403. // Remove the thread from its scheduling group.
  1404. //
  1405. if (Thread->State != ThreadStateFirstTime) {
  1406. KeUnlinkSchedulerEntry(&(Thread->SchedulerEntry));
  1407. }
  1408. //
  1409. // Potentially clean up the process if the last thread just exited. This
  1410. // will clean up all blocked signals.
  1411. //
  1412. if (DestroyProcess != FALSE) {
  1413. //
  1414. // Send the child signal to the parent.
  1415. //
  1416. SignalQueued = PspQueueChildSignalToParent(Process,
  1417. Process->ExitStatus,
  1418. Process->ExitReason);
  1419. ObSignalObject(Process, SignalOptionSignalAll);
  1420. //
  1421. // If the parent was not signaled, then just remove the process from
  1422. // the global list.
  1423. //
  1424. if (SignalQueued == FALSE) {
  1425. PspRemoveProcessFromLists(Process);
  1426. }
  1427. //
  1428. // Clean up any queued signals that snuck on while the process was
  1429. // dying.
  1430. //
  1431. while (LIST_EMPTY(&(Process->SignalListHead)) == FALSE) {
  1432. SignalQueueEntry = LIST_VALUE(Process->SignalListHead.Next,
  1433. SIGNAL_QUEUE_ENTRY,
  1434. ListEntry);
  1435. LIST_REMOVE(&(SignalQueueEntry->ListEntry));
  1436. SignalQueueEntry->ListEntry.Next = NULL;
  1437. if (SignalQueueEntry->CompletionRoutine != NULL) {
  1438. SignalQueueEntry->CompletionRoutine(SignalQueueEntry);
  1439. }
  1440. }
  1441. //
  1442. // Also clean up any blocked signals.
  1443. //
  1444. while (LIST_EMPTY(&(Process->UnreapedChildList)) == FALSE) {
  1445. SignalQueueEntry = LIST_VALUE(Process->UnreapedChildList.Next,
  1446. SIGNAL_QUEUE_ENTRY,
  1447. ListEntry);
  1448. ASSERT(IS_CHILD_SIGNAL(SignalQueueEntry));
  1449. LIST_REMOVE(&(SignalQueueEntry->ListEntry));
  1450. SignalQueueEntry->ListEntry.Next = NULL;
  1451. if (SignalQueueEntry->CompletionRoutine != NULL) {
  1452. SignalQueueEntry->CompletionRoutine(SignalQueueEntry);
  1453. }
  1454. }
  1455. }
  1456. return;
  1457. }
  1458. KSTATUS
  1459. PspGetThreadList (
  1460. PROCESS_ID ProcessId,
  1461. PVOID Buffer,
  1462. PULONG BufferSize
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. This routine returns information about the threads in a given process.
  1467. Arguments:
  1468. ProcessId - Supplies the ID of the process to get thread information for.
  1469. Buffer - Supplies an optional pointer to a buffer to write the data into.
  1470. BufferSize - Supplies a pointer that on input contains the size of the
  1471. input buffer. On output, returns the size needed to contain the data.
  1472. Return Value:
  1473. STATUS_SUCCESS on success.
  1474. STATUS_NO_SUCH_PROCESS if the supplied process ID does not correspond to
  1475. any active process.
  1476. STATUS_BUFFER_TOO_SMALL if a buffer was supplied but was not big enough to
  1477. contain all the information.
  1478. --*/
  1479. {
  1480. PKPROCESS Process;
  1481. ULONG RemainingSize;
  1482. ULONG Size;
  1483. KSTATUS Status;
  1484. PKTHREAD Thread;
  1485. PLIST_ENTRY ThreadEntry;
  1486. ULONG ThreadSize;
  1487. KSTATUS ThreadStatus;
  1488. ASSERT(KeGetRunLevel() == RunLevelLow);
  1489. Process = PspGetProcessById(ProcessId);
  1490. if (Process == NULL) {
  1491. return STATUS_NO_SUCH_PROCESS;
  1492. }
  1493. RemainingSize = *BufferSize;
  1494. Size = 0;
  1495. Status = STATUS_SUCCESS;
  1496. KeAcquireQueuedLock(Process->QueuedLock);
  1497. ThreadEntry = Process->ThreadListHead.Next;
  1498. while (ThreadEntry != &(Process->ThreadListHead)) {
  1499. Thread = LIST_VALUE(ThreadEntry, KTHREAD, ProcessEntry);
  1500. ThreadEntry = ThreadEntry->Next;
  1501. ThreadSize = RemainingSize;
  1502. ThreadStatus = PspGetThreadInformation(Thread, Buffer, &ThreadSize);
  1503. if (!KSUCCESS(ThreadStatus)) {
  1504. Status = ThreadStatus;
  1505. } else if (RemainingSize >= ThreadSize) {
  1506. Buffer += ThreadSize;
  1507. RemainingSize -= ThreadSize;
  1508. }
  1509. Size += ThreadSize;
  1510. }
  1511. KeReleaseQueuedLock(Process->QueuedLock);
  1512. ObReleaseReference(Process);
  1513. *BufferSize = Size;
  1514. return Status;
  1515. }
  1516. KSTATUS
  1517. PspGetThreadInformation (
  1518. PKTHREAD Thread,
  1519. PTHREAD_INFORMATION Buffer,
  1520. PULONG BufferSize
  1521. )
  1522. /*++
  1523. Routine Description:
  1524. This routine returns information about a given thread.
  1525. Arguments:
  1526. Thread - Supplies a pointer to the thread.
  1527. Buffer - Supplies an optional pointer to a buffer to write the data into.
  1528. BufferSize - Supplies a pointer that on input contains the size of the
  1529. input buffer. On output, returns the size needed to contain the data.
  1530. Return Value:
  1531. STATUS_SUCCESS on success.
  1532. STATUS_BUFFER_TOO_SMALL if a buffer was supplied but was not big enough to
  1533. contain all the information.
  1534. --*/
  1535. {
  1536. KSTATUS Status;
  1537. ULONG ThreadSize;
  1538. ASSERT(KeGetRunLevel() == RunLevelLow);
  1539. Status = STATUS_SUCCESS;
  1540. ThreadSize = sizeof(THREAD_INFORMATION);
  1541. if (Thread->Header.NameLength != 0) {
  1542. ThreadSize += Thread->Header.NameLength -
  1543. (ANYSIZE_ARRAY * sizeof(CHAR));
  1544. }
  1545. if (*BufferSize >= ThreadSize) {
  1546. Buffer->StructureSize = ThreadSize;
  1547. Buffer->ThreadId = Thread->ThreadId;
  1548. PspGetThreadResourceUsage(Thread, &(Buffer->ResourceUsage));
  1549. Buffer->Name[0] = '\0';
  1550. if (Thread->Header.NameLength != 0) {
  1551. RtlStringCopy(Buffer->Name,
  1552. Thread->Header.Name,
  1553. Thread->Header.NameLength);
  1554. }
  1555. } else if (Buffer != NULL) {
  1556. Status = STATUS_BUFFER_TOO_SMALL;
  1557. }
  1558. *BufferSize = ThreadSize;
  1559. return Status;
  1560. }