2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/thredsup.c
5 * PURPOSE: CSR Server DLL Thread Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 * Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *******************************************************************/
17 #define CsrHashThread(t) (HandleToUlong(t) % NUMBER_THREAD_HASH_BUCKETS)
19 /* GLOBALS ********************************************************************/
21 LIST_ENTRY CsrThreadHashTable
[NUMBER_THREAD_HASH_BUCKETS
];
24 /* PRIVATE FUNCTIONS **********************************************************/
30 * The ProtectHandle routine protects an object handle against closure.
32 * @return TRUE or FALSE.
39 ProtectHandle(IN HANDLE ObjectHandle
)
42 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
44 /* Query current state */
45 Status
= NtQueryObject(ObjectHandle
,
46 ObjectHandleFlagInformation
,
50 if (NT_SUCCESS(Status
))
52 /* Enable protect from close */
53 HandleInfo
.ProtectFromClose
= TRUE
;
54 Status
= NtSetInformationObject(ObjectHandle
,
55 ObjectHandleFlagInformation
,
58 if (NT_SUCCESS(Status
)) return TRUE
;
61 /* We failed to or set the state */
66 * @name UnProtectHandle
69 * The UnProtectHandle routine unprotects an object handle against closure.
71 * @return TRUE or FALSE.
78 UnProtectHandle(IN HANDLE ObjectHandle
)
81 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
83 /* Query current state */
84 Status
= NtQueryObject(ObjectHandle
,
85 ObjectHandleFlagInformation
,
89 if (NT_SUCCESS(Status
))
91 /* Disable protect from close */
92 HandleInfo
.ProtectFromClose
= FALSE
;
93 Status
= NtSetInformationObject(ObjectHandle
,
94 ObjectHandleFlagInformation
,
97 if (NT_SUCCESS(Status
)) return TRUE
;
100 /* We failed to or set the state */
105 * @name CsrAllocateThread
107 * The CsrAllocateThread routine allocates a new CSR Thread object.
110 * Pointer to the CSR Process which will contain this CSR Thread.
112 * @return Pointer to the newly allocated CSR Thread.
119 CsrAllocateThread(IN PCSR_PROCESS CsrProcess
)
121 PCSR_THREAD CsrThread
;
123 /* Allocate the structure */
124 CsrThread
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, sizeof(CSR_THREAD
));
125 if (!CsrThread
) return NULL
;
127 /* Reference the Thread and Process */
128 CsrLockedReferenceThread(CsrThread
);
129 CsrLockedReferenceProcess(CsrProcess
);
131 /* Set the Parent Process */
132 CsrThread
->Process
= CsrProcess
;
139 * @name CsrLockedReferenceThread
141 * The CsrLockedReferenceThread references a CSR Thread while the
142 * Process Lock is already being held.
145 * Pointer to the CSR Thread to be referenced.
149 * @remarks This routine will return with the Process Lock held.
154 CsrLockedReferenceThread(IN PCSR_THREAD CsrThread
)
156 /* Increment the reference count */
157 ++CsrThread
->ReferenceCount
;
161 * @name CsrLocateThreadByClientId
163 * The CsrLocateThreadByClientId routine locates the CSR Thread and,
164 * optionally, its parent CSR Process, corresponding to a Client ID.
167 * Optional pointer to a CSR Process pointer which will contain
168 * the CSR Thread's parent.
171 * Pointer to a Client ID structure containing the Unique Thread ID
174 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
182 CsrLocateThreadByClientId(OUT PCSR_PROCESS
*Process OPTIONAL
,
183 IN PCLIENT_ID ClientId
)
186 PLIST_ENTRY ListHead
, NextEntry
;
187 PCSR_THREAD FoundThread
;
188 // ASSERT(ProcessStructureListLocked());
190 if (Process
) *Process
= NULL
;
192 /* Hash the Thread */
193 i
= CsrHashThread(ClientId
->UniqueThread
);
195 /* Set the list pointers */
196 ListHead
= &CsrThreadHashTable
[i
];
197 NextEntry
= ListHead
->Flink
;
200 while (NextEntry
!= ListHead
)
203 FoundThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
205 /* Move to the next entry */
206 NextEntry
= NextEntry
->Flink
;
208 /* Compare the CID */
209 // if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
210 if ( FoundThread
->ClientId
.UniqueProcess
== ClientId
->UniqueProcess
&&
211 FoundThread
->ClientId
.UniqueThread
== ClientId
->UniqueThread
)
213 /* Match found, return the process */
214 if (Process
) *Process
= FoundThread
->Process
;
216 /* Return thread too */
226 * @name CsrLocateThreadInProcess
228 * The CsrLocateThreadInProcess routine locates the CSR Thread
229 * corresponding to a Client ID inside a specific CSR Process.
232 * Optional pointer to the CSR Process which contains the CSR Thread
233 * that will be looked up.
236 * Pointer to a Client ID structure containing the Unique Thread ID
239 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
242 * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
248 CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL
,
251 PLIST_ENTRY ListHead
, NextEntry
;
252 PCSR_THREAD FoundThread
= NULL
;
254 /* Use the Root Process if none was specified */
255 if (!CsrProcess
) CsrProcess
= CsrRootProcess
;
257 /* Save the List pointers */
258 ListHead
= &CsrProcess
->ThreadList
;
259 NextEntry
= ListHead
->Flink
;
262 while (NextEntry
!= ListHead
)
264 /* Get Thread Entry */
265 FoundThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
267 /* Check for TID Match */
268 if (FoundThread
->ClientId
.UniqueThread
== Cid
->UniqueThread
) break;
270 /* Move to the next entry */
271 NextEntry
= NextEntry
->Flink
;
274 /* Return what we found */
279 * @name CsrInsertThread
281 * The CsrInsertThread routine inserts a CSR Thread into its parent's
282 * Thread List and into the Thread Hash Table.
285 * Pointer to the CSR Process containing this CSR Thread.
288 * Pointer to the CSR Thread to be inserted.
297 CsrInsertThread(IN PCSR_PROCESS Process
,
298 IN PCSR_THREAD Thread
)
303 // ASSERT(ProcessStructureListLocked());
305 /* Make sure the thread isn't already dead by the time we got this */
306 Status
= NtQueryInformationThread(Thread
->ThreadHandle
,
311 if (!NT_SUCCESS(Status
)) return Status
;
312 if (ThreadInfo
) return STATUS_THREAD_IS_TERMINATING
;
314 /* Insert it into the Regular List */
315 InsertTailList(&Process
->ThreadList
, &Thread
->Link
);
317 /* Increase Thread Count */
318 Process
->ThreadCount
++;
320 /* Hash the Thread */
321 i
= CsrHashThread(Thread
->ClientId
.UniqueThread
);
323 /* Insert it there too */
324 InsertHeadList(&CsrThreadHashTable
[i
], &Thread
->HashLinks
);
325 return STATUS_SUCCESS
;
329 * @name CsrDeallocateThread
331 * The CsrDeallocateThread frees the memory associated with a CSR Thread.
334 * Pointer to the CSR Thread to be freed.
338 * @remarks Do not call this routine. It is reserved for the internal
339 * thread management routines when a CSR Thread has been cleanly
340 * dereferenced and killed.
345 CsrDeallocateThread(IN PCSR_THREAD CsrThread
)
347 /* Free the process object from the heap */
348 // ASSERT(CsrThread->WaitBlock == NULL);
349 RtlFreeHeap(CsrHeap
, 0, CsrThread
);
353 * @name CsrRemoveThread
355 * The CsrRemoveThread function undoes a CsrInsertThread operation and
356 * removes the CSR Thread from the the Hash Table and Thread List.
359 * Pointer to the CSR Thread to remove.
363 * @remarks If this CSR Thread is the last one inside a CSR Process, the
364 * parent will be dereferenced and the CsrProcessLastThreadTerminated
367 * After executing this routine, the CSR Thread will have the
368 * CsrThreadInTermination flag set.
373 CsrRemoveThread(IN PCSR_THREAD CsrThread
)
375 ASSERT(ProcessStructureListLocked());
377 /* Remove it from the List */
378 RemoveEntryList(&CsrThread
->Link
);
380 /* Decreate the thread count of the process */
381 CsrThread
->Process
->ThreadCount
--;
383 /* Remove it from the Hash List as well */
384 if (CsrThread
->HashLinks
.Flink
) RemoveEntryList(&CsrThread
->HashLinks
);
386 /* Check if this is the last Thread */
387 if (CsrThread
->Process
->ThreadCount
== 0)
389 /* Check if it's not already been marked for deletion */
390 if ((CsrThread
->Process
->Flags
& CsrProcessLastThreadTerminated
) == 0)
392 /* Let everyone know this process is about to lose the thread */
393 CsrThread
->Process
->Flags
|= CsrProcessLastThreadTerminated
;
395 /* Reference the Process */
396 CsrLockedDereferenceProcess(CsrThread
->Process
);
400 /* Mark the thread for deletion */
401 CsrThread
->Flags
|= CsrThreadInTermination
;
405 * @name CsrThreadRefcountZero
407 * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
408 * all its active references. It removes and de-allocates the CSR Thread.
411 * Pointer to the CSR Thread that is to be deleted.
415 * @remarks Do not call this routine. It is reserved for the internal
416 * thread management routines when a CSR Thread has lost all
419 * This routine is called with the Process Lock held.
424 CsrThreadRefcountZero(IN PCSR_THREAD CsrThread
)
426 PCSR_PROCESS CsrProcess
= CsrThread
->Process
;
428 ASSERT(ProcessStructureListLocked());
430 /* Remove this thread */
431 CsrRemoveThread(CsrThread
);
433 /* Release the Process Lock */
434 CsrReleaseProcessLock();
436 /* Close the NT Thread Handle */
437 if (CsrThread
->ThreadHandle
)
439 UnProtectHandle(CsrThread
->ThreadHandle
);
440 Status
= NtClose(CsrThread
->ThreadHandle
);
442 if (!NT_SUCCESS(Status
))
443 DPRINT1("CSR: NtClose failed, we are going to ASSERT, Status = 0x%08lx; P:[0x%x, 0x%x] T:[0x%x, 0x%x] Process: 0x%p; Thread: 0x%p; ThreadHandle: 0x%p\n",
444 Status
, CsrProcess
->ClientId
.UniqueProcess
, CsrProcess
->ClientId
.UniqueThread
,
445 CsrThread
->ClientId
.UniqueProcess
, CsrThread
->ClientId
.UniqueThread
,
446 CsrProcess
, CsrThread
, CsrThread
->ThreadHandle
);
448 ASSERT(NT_SUCCESS(Status
));
451 /* De-allocate the CSR Thread Object */
452 CsrDeallocateThread(CsrThread
);
454 /* Remove a reference from the process */
455 CsrDereferenceProcess(CsrProcess
);
459 * @name CsrLockedDereferenceThread
461 * The CsrLockedDereferenceThread dereferences a CSR Thread while the
462 * Process Lock is already being held.
465 * Pointer to the CSR Thread to be dereferenced.
469 * @remarks This routine will return with the Process Lock held.
474 CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread
)
478 /* Decrease reference count */
479 LockCount
= --CsrThread
->ReferenceCount
;
480 ASSERT(LockCount
>= 0);
483 /* Call the generic cleanup code */
484 CsrAcquireProcessLock();
485 CsrThreadRefcountZero(CsrThread
);
490 /* PUBLIC FUNCTIONS ***********************************************************/
493 * @name CsrAddStaticServerThread
496 * The CsrAddStaticServerThread routine adds a new CSR Thread to the
497 * CSR Server Process (CsrRootProcess).
500 * Handle to an existing NT Thread to which to associate this
504 * Pointer to the Client ID structure of the NT Thread to associate
505 * with this CSR Thread.
508 * Initial CSR Thread Flags to associate to this CSR Thread. Usually
509 * CsrThreadIsServerThread.
511 * @return Pointer to the newly allocated CSR Thread.
518 CsrAddStaticServerThread(IN HANDLE hThread
,
519 IN PCLIENT_ID ClientId
,
520 IN ULONG ThreadFlags
)
522 PCSR_THREAD CsrThread
;
525 CsrAcquireProcessLock();
527 /* Allocate the Server Thread */
528 CsrThread
= CsrAllocateThread(CsrRootProcess
);
531 /* Setup the Object */
532 CsrThread
->ThreadHandle
= hThread
;
533 ProtectHandle(hThread
);
534 CsrThread
->ClientId
= *ClientId
;
535 CsrThread
->Flags
= ThreadFlags
;
537 /* Insert it into the Thread List */
538 InsertTailList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
540 /* Increment the thread count */
541 CsrRootProcess
->ThreadCount
++;
545 DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread
);
548 /* Release the Process Lock and return */
549 CsrReleaseProcessLock();
554 * @name CsrCreateRemoteThread
557 * The CsrCreateRemoteThread routine creates a CSR Thread object for
558 * an NT Thread which is not part of the current NT Process.
561 * Handle to an existing NT Thread to which to associate this
565 * Pointer to the Client ID structure of the NT Thread to associate
566 * with this CSR Thread.
568 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
575 CsrCreateRemoteThread(IN HANDLE hThread
,
576 IN PCLIENT_ID ClientId
)
580 PCSR_THREAD CsrThread
;
581 PCSR_PROCESS CsrProcess
;
582 KERNEL_USER_TIMES KernelTimes
;
584 /* Get the Thread Create Time */
585 Status
= NtQueryInformationThread(hThread
,
590 if (!NT_SUCCESS(Status
))
592 DPRINT1("Failed to query thread times: %lx\n", Status
);
596 /* Lock the Owner Process */
597 Status
= CsrLockProcessByClientId(ClientId
->UniqueProcess
, &CsrProcess
);
598 if (!NT_SUCCESS(Status
))
600 DPRINT1("No known process for %lx\n", ClientId
->UniqueProcess
);
604 /* Make sure the thread didn't terminate */
605 if (KernelTimes
.ExitTime
.QuadPart
)
607 /* Unlock the process and return */
608 CsrUnlockProcess(CsrProcess
);
609 DPRINT1("Dead thread: %I64x\n", KernelTimes
.ExitTime
.QuadPart
);
610 return STATUS_THREAD_IS_TERMINATING
;
613 /* Allocate a CSR Thread Structure */
614 CsrThread
= CsrAllocateThread(CsrProcess
);
617 DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__
);
618 CsrUnlockProcess(CsrProcess
);
619 return STATUS_NO_MEMORY
;
622 /* Duplicate the Thread Handle */
623 Status
= NtDuplicateObject(NtCurrentProcess(),
629 DUPLICATE_SAME_ACCESS
);
631 if (!NT_SUCCESS(Status
))
633 DPRINT1("Thread duplication failed: %lx\n", Status
);
634 ThreadHandle
= hThread
;
637 /* Save the data we have */
638 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
639 CsrThread
->ClientId
= *ClientId
;
640 CsrThread
->ThreadHandle
= ThreadHandle
;
641 ProtectHandle(ThreadHandle
);
642 CsrThread
->Flags
= 0;
644 /* Insert the Thread into the Process */
645 Status
= CsrInsertThread(CsrProcess
, CsrThread
);
646 if (!NT_SUCCESS(Status
))
649 if (CsrThread
->ThreadHandle
!= hThread
) NtClose(CsrThread
->ThreadHandle
);
650 CsrUnlockProcess(CsrProcess
);
651 CsrDeallocateThread(CsrThread
);
655 /* Release the lock and return */
656 CsrUnlockProcess(CsrProcess
);
657 return STATUS_SUCCESS
;
661 * @name CsrCreateThread
664 * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
667 * Pointer to the CSR Process which will contain the CSR Thread.
670 * Handle to an existing NT Thread to which to associate this
674 * Pointer to the Client ID structure of the NT Thread to associate
675 * with this CSR Thread.
677 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
684 CsrCreateThread(IN PCSR_PROCESS CsrProcess
,
686 IN PCLIENT_ID ClientId
,
687 IN BOOLEAN HaveClient
)
690 PCSR_THREAD CsrThread
, CurrentThread
;
691 PCSR_PROCESS CurrentProcess
;
692 CLIENT_ID CurrentCid
;
693 KERNEL_USER_TIMES KernelTimes
;
697 /* Get the current thread and CID */
698 CurrentThread
= CsrGetClientThread();
699 CurrentCid
= CurrentThread
->ClientId
;
701 /* Acquire the Process Lock */
702 CsrAcquireProcessLock();
704 /* Get the current Process and make sure the Thread is valid with this CID */
705 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
707 /* Something is wrong if we get an empty thread back */
710 DPRINT1("CSRSRV: %s: invalid thread!\n", __FUNCTION__
);
711 CsrReleaseProcessLock();
712 return STATUS_THREAD_IS_TERMINATING
;
717 /* Acquire the Process Lock */
718 CsrAcquireProcessLock();
721 /* Get the Thread Create Time */
722 Status
= NtQueryInformationThread(hThread
,
727 if (!NT_SUCCESS(Status
))
729 CsrReleaseProcessLock();
733 /* Allocate a CSR Thread Structure */
734 CsrThread
= CsrAllocateThread(CsrProcess
);
737 DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__
);
738 CsrReleaseProcessLock();
739 return STATUS_NO_MEMORY
;
742 /* Save the data we have */
743 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
744 CsrThread
->ClientId
= *ClientId
;
745 CsrThread
->ThreadHandle
= hThread
;
746 ProtectHandle(hThread
);
747 CsrThread
->Flags
= 0;
749 /* Insert the Thread into the Process */
750 Status
= CsrInsertThread(CsrProcess
, CsrThread
);
751 if (!NT_SUCCESS(Status
))
754 CsrUnlockProcess(CsrProcess
);
755 CsrDeallocateThread(CsrThread
);
759 /* Release the lock and return */
760 CsrReleaseProcessLock();
762 return STATUS_SUCCESS
;
766 * @name CsrDereferenceThread
769 * The CsrDereferenceThread routine removes a reference from a CSR Thread.
772 * Pointer to the CSR Thread to dereference.
776 * @remarks If the reference count has reached zero (ie: the CSR Thread has
777 * no more active references), it will be deleted.
782 CsrDereferenceThread(IN PCSR_THREAD CsrThread
)
784 /* Acquire process lock */
785 CsrAcquireProcessLock();
787 /* Decrease reference count */
788 ASSERT(CsrThread
->ReferenceCount
> 0);
789 if ((--CsrThread
->ReferenceCount
) == 0)
791 /* Call the generic cleanup code */
792 CsrThreadRefcountZero(CsrThread
);
796 /* Just release the lock */
797 CsrReleaseProcessLock();
802 * @name CsrDestroyThread
805 * The CsrDestroyThread routine destroys the CSR Thread corresponding to
809 * Pointer to the Client ID Structure corresponding to the CSR
810 * Thread which is about to be destroyed.
812 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
813 * if the CSR Thread is already terminating.
820 CsrDestroyThread(IN PCLIENT_ID Cid
)
822 CLIENT_ID ClientId
= *Cid
;
823 PCSR_THREAD CsrThread
;
824 PCSR_PROCESS CsrProcess
;
827 CsrAcquireProcessLock();
829 /* Find the thread */
830 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
833 /* Make sure we got one back, and that it's not already gone */
834 if (!CsrThread
|| (CsrThread
->Flags
& CsrThreadTerminated
))
836 /* Release the lock and return failure */
837 CsrReleaseProcessLock();
838 return STATUS_THREAD_IS_TERMINATING
;
841 /* Set the terminated flag */
842 CsrThread
->Flags
|= CsrThreadTerminated
;
844 /* Acquire the Wait Lock */
845 CsrAcquireWaitLock();
847 /* Do we have an active wait block? */
848 if (CsrThread
->WaitBlock
)
850 /* Notify waiters of termination */
851 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
855 CsrProcessTerminating
,
859 /* Release the Wait Lock */
860 CsrReleaseWaitLock();
862 /* Dereference the thread */
863 CsrLockedDereferenceThread(CsrThread
);
865 /* Release the Process Lock and return success */
866 CsrReleaseProcessLock();
867 return STATUS_SUCCESS
;
871 * @name CsrExecServerThread
874 * The CsrExecServerThread routine creates an NT Thread and then
875 * initializes a CSR Thread for it.
877 * @param ThreadHandler
878 * Pointer to the thread's startup routine.
881 * Initial CSR Thread Flags to set to the CSR Thread.
883 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
885 * @remarks This routine is similar to CsrAddStaticServerThread, but it
886 * also creates an NT Thread instead of expecting one to already
892 CsrExecServerThread(IN PVOID ThreadHandler
,
895 PCSR_THREAD CsrThread
;
900 /* Acquire process lock */
901 CsrAcquireProcessLock();
903 /* Allocate a CSR Thread in the Root Process */
904 ASSERT(CsrRootProcess
!= NULL
);
905 CsrThread
= CsrAllocateThread(CsrRootProcess
);
909 CsrReleaseProcessLock();
910 return STATUS_NO_MEMORY
;
913 /* Create the Thread */
914 Status
= RtlCreateUserThread(NtCurrentProcess(),
924 if (!NT_SUCCESS(Status
))
927 CsrDeallocateThread(CsrThread
);
928 CsrReleaseProcessLock();
932 /* Setup the Thread Object */
933 CsrThread
->ThreadHandle
= hThread
;
934 ProtectHandle(hThread
);
935 CsrThread
->ClientId
= ClientId
;
936 CsrThread
->Flags
= Flags
;
938 /* Insert it into the Thread List */
939 InsertHeadList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
941 /* Increase the thread count */
942 CsrRootProcess
->ThreadCount
++;
945 CsrReleaseProcessLock();
950 * @name CsrLockThreadByClientId
953 * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
954 * to the given Thread ID and optionally returns it.
957 * Thread ID corresponding to the CSR Thread which will be locked.
960 * Optional pointer to a CSR Thread pointer which will hold the
961 * CSR Thread corresponding to the given Thread ID.
963 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
965 * @remarks Locking a CSR Thread is defined as acquiring an extra
966 * reference to it and returning with the Process Lock held.
971 CsrLockThreadByClientId(IN HANDLE Tid
,
972 OUT PCSR_THREAD
*CsrThread
)
974 PLIST_ENTRY NextEntry
;
975 PCSR_THREAD CurrentThread
= NULL
;
976 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
979 /* Acquire the lock */
980 CsrAcquireProcessLock();
983 ASSERT(CsrThread
!= NULL
);
986 /* Convert to Hash */
987 i
= CsrHashThread(Tid
);
989 /* Setup the List Pointers */
990 NextEntry
= CsrThreadHashTable
[i
].Flink
;
993 while (NextEntry
!= &CsrThreadHashTable
[i
])
996 CurrentThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
998 /* Check for TID Match */
999 if ((CurrentThread
->ClientId
.UniqueThread
== Tid
) &&
1000 (CurrentThread
->Flags
& CsrThreadTerminated
) == 0)
1002 /* Get out of here */
1006 /* Move to the next entry */
1007 NextEntry
= NextEntry
->Flink
;
1010 /* Nothing found if we got back to the list */
1011 if (NextEntry
== &CsrThreadHashTable
[i
]) CurrentThread
= NULL
;
1013 /* Did the loop find something? */
1016 /* Reference the found thread */
1017 Status
= STATUS_SUCCESS
;
1018 CsrLockedReferenceThread(CurrentThread
);
1019 *CsrThread
= CurrentThread
;
1023 /* Nothing found, release the lock */
1024 Status
= STATUS_UNSUCCESSFUL
;
1025 CsrReleaseProcessLock();
1028 /* Return the status */
1033 * @name CsrReferenceThread
1036 * The CsrReferenceThread routine increases the active reference count of
1040 * Pointer to the CSR Thread whose reference count will be increased.
1044 * @remarks Do not use this routine if the Process Lock is already held.
1049 CsrReferenceThread(IN PCSR_THREAD CsrThread
)
1051 /* Acquire process lock */
1052 CsrAcquireProcessLock();
1055 ASSERT((CsrThread
->Flags
& CsrThreadTerminated
) == 0);
1056 ASSERT(CsrThread
->ReferenceCount
!= 0);
1058 /* Increment reference count */
1059 CsrThread
->ReferenceCount
++;
1061 /* Release the lock */
1062 CsrReleaseProcessLock();
1066 * @name CsrUnlockThread
1069 * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
1072 * Pointer to a previously locked CSR Thread.
1074 * @return STATUS_SUCCESS.
1076 * @remarks This routine must be called with the Process Lock held.
1081 CsrUnlockThread(IN PCSR_THREAD CsrThread
)
1083 /* Dereference the Thread */
1084 ASSERT(ProcessStructureListLocked());
1085 CsrLockedDereferenceThread(CsrThread
);
1087 /* Release the lock and return */
1088 CsrReleaseProcessLock();
1089 return STATUS_SUCCESS
;