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) \
18 (HandleToUlong(t)&(256 - 1))
20 /* GLOBALS ********************************************************************/
22 LIST_ENTRY CsrThreadHashTable
[256];
25 /* PRIVATE FUNCTIONS **********************************************************/
31 * The ProtectHandle routine protects an object handle against closure.
33 * @return TRUE or FALSE.
40 ProtectHandle(IN HANDLE ObjectHandle
)
43 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
45 /* Query current state */
46 Status
= NtQueryObject(ObjectHandle
,
47 ObjectHandleFlagInformation
,
51 if (NT_SUCCESS(Status
))
53 /* Enable protect from close */
54 HandleInfo
.ProtectFromClose
= TRUE
;
55 Status
= NtSetInformationObject(ObjectHandle
,
56 ObjectHandleFlagInformation
,
59 if (NT_SUCCESS(Status
)) return TRUE
;
62 /* We failed to or set the state */
67 * @name UnProtectHandle
70 * The UnProtectHandle routine unprotects an object handle against closure.
72 * @return TRUE or FALSE.
79 UnProtectHandle(IN HANDLE ObjectHandle
)
82 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
84 /* Query current state */
85 Status
= NtQueryObject(ObjectHandle
,
86 ObjectHandleFlagInformation
,
90 if (NT_SUCCESS(Status
))
92 /* Disable protect from close */
93 HandleInfo
.ProtectFromClose
= FALSE
;
94 Status
= NtSetInformationObject(ObjectHandle
,
95 ObjectHandleFlagInformation
,
98 if (NT_SUCCESS(Status
)) return TRUE
;
101 /* We failed to or set the state */
106 * @name CsrAllocateThread
108 * The CsrAllocateThread routine allocates a new CSR Thread object.
111 * Pointer to the CSR Process which will contain this CSR Thread.
113 * @return Pointer to the newly allocated CSR Thread.
120 CsrAllocateThread(IN PCSR_PROCESS CsrProcess
)
122 PCSR_THREAD CsrThread
;
124 /* Allocate the structure */
125 CsrThread
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, sizeof(CSR_THREAD
));
126 if (!CsrThread
) return(NULL
);
128 /* Reference the Thread and Process */
129 CsrThread
->ReferenceCount
++;
130 CsrProcess
->ReferenceCount
++;
132 /* Set the Parent Process */
133 CsrThread
->Process
= CsrProcess
;
140 * @name CsrLockedReferenceThread
142 * The CsrLockedReferenceThread references a CSR Thread while the
143 * Process Lock is already being held.
146 * Pointer to the CSR Thread to be referenced.
150 * @remarks This routine will return with the Process Lock held.
155 CsrLockedReferenceThread(IN PCSR_THREAD CsrThread
)
157 /* Increment the reference count */
158 ++CsrThread
->ReferenceCount
;
162 * @name CsrLocateThreadByClientId
164 * The CsrLocateThreadByClientId routine locates the CSR Thread and,
165 * optionally, its parent CSR Process, corresponding to a Client ID.
168 * Optional pointer to a CSR Process pointer which will contain
169 * the CSR Thread's parent.
172 * Pointer to a Client ID structure containing the Unique Thread ID
175 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
183 CsrLocateThreadByClientId(OUT PCSR_PROCESS
*Process OPTIONAL
,
184 IN PCLIENT_ID ClientId
)
187 PLIST_ENTRY ListHead
, NextEntry
;
188 PCSR_THREAD FoundThread
;
189 // ASSERT(ProcessStructureListLocked());
191 /* Hash the Thread */
192 i
= CsrHashThread(ClientId
->UniqueThread
);
194 /* Set the list pointers */
195 ListHead
= &CsrThreadHashTable
[i
];
196 NextEntry
= ListHead
->Flink
;
199 while (NextEntry
!= ListHead
)
202 FoundThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
204 /* Compare the CID */
205 // FIXME: if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
206 if (FoundThread
->ClientId
.UniqueThread
== ClientId
->UniqueThread
)
208 /* Match found, return the process */
209 *Process
= FoundThread
->Process
;
211 /* Return thread too */
212 // DPRINT1("Found: %p %p\n", FoundThread, FoundThread->Process);
217 NextEntry
= NextEntry
->Flink
;
225 * @name CsrLocateThreadInProcess
227 * The CsrLocateThreadInProcess routine locates the CSR Thread
228 * corresponding to a Client ID inside a specific CSR Process.
231 * Optional pointer to the CSR Process which contains the CSR Thread
232 * that will be looked up.
235 * Pointer to a Client ID structure containing the Unique Thread ID
238 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
241 * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
247 CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL
,
250 PLIST_ENTRY ListHead
, NextEntry
;
251 PCSR_THREAD FoundThread
= NULL
;
253 /* Use the Root Process if none was specified */
254 if (!CsrProcess
) CsrProcess
= CsrRootProcess
;
256 /* Save the List pointers */
257 // DPRINT1("Searching in: %p %d\n", CsrProcess, CsrProcess->ThreadCount);
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;
271 NextEntry
= NextEntry
->Flink
;
274 /* Return what we found */
275 // DPRINT1("Found: %p\n", FoundThread);
280 * @name CsrInsertThread
282 * The CsrInsertThread routine inserts a CSR Thread into its parent's
283 * Thread List and into the Thread Hash Table.
286 * Pointer to the CSR Process containing this CSR Thread.
289 * Pointer to the CSR Thread to be inserted.
298 CsrInsertThread(IN PCSR_PROCESS Process
,
299 IN PCSR_THREAD Thread
)
302 // ASSERT(ProcessStructureListLocked());
304 /* Insert it into the Regular List */
305 InsertTailList(&Process
->ThreadList
, &Thread
->Link
);
307 /* Increase Thread Count */
308 Process
->ThreadCount
++;
310 /* Hash the Thread */
311 i
= CsrHashThread(Thread
->ClientId
.UniqueThread
);
312 // DPRINT1("TID %lx HASH: %lx\n", Thread->ClientId.UniqueThread, i);
314 /* Insert it there too */
315 InsertHeadList(&CsrThreadHashTable
[i
], &Thread
->HashLinks
);
319 * @name CsrDeallocateThread
321 * The CsrDeallocateThread frees the memory associated with a CSR Thread.
324 * Pointer to the CSR Thread to be freed.
328 * @remarks Do not call this routine. It is reserved for the internal
329 * thread management routines when a CSR Thread has been cleanly
330 * dereferenced and killed.
335 CsrDeallocateThread(IN PCSR_THREAD CsrThread
)
337 /* Free the process object from the heap */
338 // ASSERT(CsrThread->WaitBlock == NULL);
339 RtlFreeHeap(CsrHeap
, 0, CsrThread
);
343 * @name CsrRemoveThread
345 * The CsrRemoveThread function undoes a CsrInsertThread operation and
346 * removes the CSR Thread from the the Hash Table and Thread List.
349 * Pointer to the CSR Thread to remove.
353 * @remarks If this CSR Thread is the last one inside a CSR Process, the
354 * parent will be dereferenced and the CsrProcessLastThreadTerminated
357 * After executing this routine, the CSR Thread will have the
358 * CsrThreadInTermination flag set.
363 CsrRemoveThread(IN PCSR_THREAD CsrThread
)
365 ASSERT(ProcessStructureListLocked());
367 /* Remove it from the List */
368 RemoveEntryList(&CsrThread
->Link
);
370 /* Decreate the thread count of the process */
371 CsrThread
->Process
->ThreadCount
--;
373 /* Remove it from the Hash List as well */
374 if (CsrThread
->HashLinks
.Flink
) RemoveEntryList(&CsrThread
->HashLinks
);
376 /* Check if this is the last Thread */
377 if (!CsrThread
->Process
->ThreadCount
)
379 /* Check if it's not already been marked for deletion */
380 if (!(CsrThread
->Process
->Flags
& CsrProcessLastThreadTerminated
))
382 /* Let everyone know this process is about to lose the thread */
383 CsrThread
->Process
->Flags
|= CsrProcessLastThreadTerminated
;
385 /* Reference the Process */
386 CsrLockedDereferenceProcess(CsrThread
->Process
);
390 /* Mark the thread for deletion */
391 CsrThread
->Flags
|= CsrThreadInTermination
;
395 * @name CsrThreadRefcountZero
397 * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
398 * all its active references. It removes and de-allocates the CSR Thread.
401 * Pointer to the CSR Thread that is to be deleted.
405 * @remarks Do not call this routine. It is reserved for the internal
406 * thread management routines when a CSR Thread has lost all
409 * This routine is called with the Process Lock held.
414 CsrThreadRefcountZero(IN PCSR_THREAD CsrThread
)
416 PCSR_PROCESS CsrProcess
= CsrThread
->Process
;
418 ASSERT(ProcessStructureListLocked());
420 /* Remove this thread */
421 CsrRemoveThread(CsrThread
);
423 /* Release the Process Lock */
424 CsrReleaseProcessLock();
426 /* Close the NT Thread Handle */
427 if (CsrThread
->ThreadHandle
)
429 UnProtectHandle(CsrThread
->ThreadHandle
);
430 Status
= NtClose(CsrThread
->ThreadHandle
);
431 ASSERT(NT_SUCCESS(Status
));
434 /* De-allocate the CSR Thread Object */
435 CsrDeallocateThread(CsrThread
);
437 /* Remove a reference from the process */
438 CsrDereferenceProcess(CsrProcess
);
442 * @name CsrLockedDereferenceThread
444 * The CsrLockedDereferenceThread dereferences a CSR Thread while the
445 * Process Lock is already being held.
448 * Pointer to the CSR Thread to be dereferenced.
452 * @remarks This routine will return with the Process Lock held.
457 CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread
)
461 /* Decrease reference count */
462 LockCount
= --CsrThread
->ReferenceCount
;
463 ASSERT(LockCount
>= 0);
466 /* Call the generic cleanup code */
467 CsrThreadRefcountZero(CsrThread
);
468 CsrAcquireProcessLock();
473 /* PUBLIC FUNCTIONS ***********************************************************/
476 * @name CsrAddStaticServerThread
479 * The CsrAddStaticServerThread routine adds a new CSR Thread to the
480 * CSR Server Process (CsrRootProcess).
483 * Handle to an existing NT Thread to which to associate this
487 * Pointer to the Client ID structure of the NT Thread to associate
488 * with this CSR Thread.
491 * Initial CSR Thread Flags to associate to this CSR Thread. Usually
492 * CsrThreadIsServerThread.
494 * @return Pointer to the newly allocated CSR Thread.
501 CsrAddStaticServerThread(IN HANDLE hThread
,
502 IN PCLIENT_ID ClientId
,
503 IN ULONG ThreadFlags
)
505 PCSR_THREAD CsrThread
;
508 CsrAcquireProcessLock();
510 /* Allocate the Server Thread */
511 CsrThread
= CsrAllocateThread(CsrRootProcess
);
514 /* Setup the Object */
515 CsrThread
->ThreadHandle
= hThread
;
516 ProtectHandle(hThread
);
517 CsrThread
->ClientId
= *ClientId
;
518 CsrThread
->Flags
= ThreadFlags
;
520 /* Insert it into the Thread List */
521 InsertTailList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
523 /* Increment the thread count */
524 CsrRootProcess
->ThreadCount
++;
528 DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread
);
531 /* Release the Process Lock and return */
532 CsrReleaseProcessLock();
537 * @name CsrCreateRemoteThread
540 * The CsrCreateRemoteThread routine creates a CSR Thread object for
541 * an NT Thread which is not part of the current NT Process.
544 * Handle to an existing NT Thread to which to associate this
548 * Pointer to the Client ID structure of the NT Thread to associate
549 * with this CSR Thread.
551 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
559 CsrCreateRemoteThread(IN HANDLE hThread
,
560 IN PCLIENT_ID ClientId
)
564 PCSR_THREAD CsrThread
;
565 PCSR_PROCESS CsrProcess
;
566 KERNEL_USER_TIMES KernelTimes
;
567 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
569 /* Get the Thread Create Time */
570 Status
= NtQueryInformationThread(hThread
,
575 if (!NT_SUCCESS(Status
))
577 DPRINT1("Failed to query thread times: %lx\n", Status
);
581 /* Lock the Owner Process */
582 Status
= CsrLockProcessByClientId(&ClientId
->UniqueProcess
, &CsrProcess
);
583 if (!NT_SUCCESS(Status
))
585 DPRINT1("No known process for %lx\n", ClientId
->UniqueProcess
);
589 /* Make sure the thread didn't terminate */
590 if (KernelTimes
.ExitTime
.QuadPart
)
592 /* Unlock the process and return */
593 CsrUnlockProcess(CsrProcess
);
594 DPRINT1("Dead thread: %I64x\n", KernelTimes
.ExitTime
.QuadPart
);
595 return STATUS_THREAD_IS_TERMINATING
;
598 /* Allocate a CSR Thread Structure */
599 CsrThread
= CsrAllocateThread(CsrProcess
);
602 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__
);
603 CsrUnlockProcess(CsrProcess
);
604 return STATUS_NO_MEMORY
;
607 /* Duplicate the Thread Handle */
608 Status
= NtDuplicateObject(NtCurrentProcess(),
614 DUPLICATE_SAME_ACCESS
);
616 if (!NT_SUCCESS(Status
))
618 DPRINT1("Thread duplication failed: %lx\n", Status
);
619 ThreadHandle
= hThread
;
622 /* Save the data we have */
623 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
624 CsrThread
->ClientId
= *ClientId
;
625 CsrThread
->ThreadHandle
= ThreadHandle
;
626 ProtectHandle(ThreadHandle
);
627 CsrThread
->Flags
= 0;
629 /* Insert the Thread into the Process */
630 CsrInsertThread(CsrProcess
, CsrThread
);
632 /* Release the lock and return */
633 CsrUnlockProcess(CsrProcess
);
634 return STATUS_SUCCESS
;
638 * @name CsrCreateThread
641 * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
644 * Pointer to the CSR Process which will contain the CSR Thread.
647 * Handle to an existing NT Thread to which to associate this
651 * Pointer to the Client ID structure of the NT Thread to associate
652 * with this CSR Thread.
654 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
663 CsrCreateThread(IN PCSR_PROCESS CsrProcess
,
665 IN PCLIENT_ID ClientId
,
666 IN BOOLEAN HaveClient
)
669 PCSR_THREAD CsrThread
, CurrentThread
;
670 PCSR_PROCESS CurrentProcess
;
671 CLIENT_ID CurrentCid
;
672 KERNEL_USER_TIMES KernelTimes
;
673 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
677 /* Get the current thread and CID */
678 CurrentThread
= NtCurrentTeb()->CsrClientThread
;
679 CurrentCid
= CurrentThread
->ClientId
;
681 /* Acquire the Process Lock */
682 CsrAcquireProcessLock();
684 /* Get the current Process and make sure the Thread is valid with this CID */
685 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
688 DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__
);
689 CsrReleaseProcessLock();
690 return STATUS_THREAD_IS_TERMINATING
;
695 /* Acquire the Process Lock */
696 CsrAcquireProcessLock();
699 /* Get the Thread Create Time */
700 Status
= NtQueryInformationThread(hThread
,
705 if (!NT_SUCCESS(Status
))
707 CsrReleaseProcessLock();
711 /* Allocate a CSR Thread Structure */
712 CsrThread
= CsrAllocateThread(CsrProcess
);
715 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__
);
716 CsrReleaseProcessLock();
717 return STATUS_NO_MEMORY
;
720 /* Save the data we have */
721 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
722 CsrThread
->ClientId
= *ClientId
;
723 CsrThread
->ThreadHandle
= hThread
;
724 ProtectHandle(hThread
);
725 CsrThread
->Flags
= 0;
727 /* Insert the Thread into the Process */
728 CsrInsertThread(CsrProcess
, CsrThread
);
730 /* Release the lock and return */
731 CsrReleaseProcessLock();
732 return STATUS_SUCCESS
;
735 CsrCreateThread(IN PCSR_PROCESS CsrProcess
,
737 IN PCLIENT_ID ClientId
)
739 PCSR_THREAD CsrThread
;
740 PCSR_PROCESS CurrentProcess
;
741 PCSR_THREAD CurrentThread
= CsrGetClientThread();
742 CLIENT_ID CurrentCid
;
743 KERNEL_USER_TIMES KernelTimes
;
745 /* Get the current thread and CID */
746 CurrentCid
= CurrentThread
->ClientId
;
748 /* Acquire the Process Lock */
749 CsrAcquireProcessLock();
751 /* Get the current Process and make sure the Thread is valid with this CID */
752 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
,
755 /* Something is wrong if we get an empty thread back */
758 DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__
);
759 CsrReleaseProcessLock();
760 return STATUS_THREAD_IS_TERMINATING
;
763 /* Get the Thread Create Time */
764 NtQueryInformationThread(hThread
,
770 /* Allocate a CSR Thread Structure */
771 if (!(CsrThread
= CsrAllocateThread(CsrProcess
)))
773 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__
);
774 CsrReleaseProcessLock();
775 return STATUS_NO_MEMORY
;
778 /* Save the data we have */
779 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
780 CsrThread
->ClientId
= *ClientId
;
781 CsrThread
->ThreadHandle
= hThread
;
782 CsrThread
->Flags
= 0;
784 /* Insert the Thread into the Process */
785 CsrInsertThread(CsrProcess
, CsrThread
);
787 /* Release the lock and return */
788 CsrReleaseProcessLock();
789 return STATUS_SUCCESS
;
794 * @name CsrDereferenceThread
797 * The CsrDereferenceThread routine removes a reference from a CSR Thread.
800 * Pointer to the CSR Thread to dereference.
804 * @remarks If the reference count has reached zero (ie: the CSR Thread has
805 * no more active references), it will be deleted.
810 CsrDereferenceThread(IN PCSR_THREAD CsrThread
)
812 /* Acquire process lock */
813 CsrAcquireProcessLock();
815 /* Decrease reference count */
816 ASSERT(CsrThread
->ReferenceCount
> 0);
817 if (!(--CsrThread
->ReferenceCount
))
819 /* Call the generic cleanup code */
820 CsrThreadRefcountZero(CsrThread
);
824 /* Just release the lock */
825 CsrReleaseProcessLock();
830 * @name CsrDestroyThread
833 * The CsrDestroyThread routine destroys the CSR Thread corresponding to
837 * Pointer to the Client ID Structure corresponding to the CSR
838 * Thread which is about to be destroyed.
840 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
841 * if the CSR Thread is already terminating.
848 CsrDestroyThread(IN PCLIENT_ID Cid
)
850 CLIENT_ID ClientId
= *Cid
;
851 PCSR_THREAD CsrThread
;
852 PCSR_PROCESS CsrProcess
;
855 CsrAcquireProcessLock();
857 /* Find the thread */
858 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
861 /* Make sure we got one back, and that it's not already gone */
862 if (!CsrThread
|| CsrThread
->Flags
& CsrThreadTerminated
)
864 /* Release the lock and return failure */
865 CsrReleaseProcessLock();
866 return STATUS_THREAD_IS_TERMINATING
;
869 /* Set the terminated flag */
870 CsrThread
->Flags
|= CsrThreadTerminated
;
872 /* Acquire the Wait Lock */
873 CsrAcquireWaitLock();
875 /* Do we have an active wait block? */
876 if (CsrThread
->WaitBlock
)
878 /* Notify waiters of termination */
879 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
883 CsrProcessTerminating
,
887 /* Release the Wait Lock */
888 CsrReleaseWaitLock();
890 /* Dereference the thread */
891 CsrLockedDereferenceThread(CsrThread
);
893 /* Release the Process Lock and return success */
894 CsrReleaseProcessLock();
895 return STATUS_SUCCESS
;
899 * @name CsrExecServerThread
902 * The CsrExecServerThread routine creates an NT Thread and then
903 * initializes a CSR Thread for it.
905 * @param ThreadHandler
906 * Pointer to the thread's startup routine.
909 * Initial CSR Thread Flags to set to the CSR Thread.
911 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
914 * @remarks This routine is similar to CsrAddStaticServerThread, but it
915 * also creates an NT Thread instead of expecting one to already
921 CsrExecServerThread(IN PVOID ThreadHandler
,
924 PCSR_THREAD CsrThread
;
929 /* Acquire process lock */
930 CsrAcquireProcessLock();
932 /* Allocate a CSR Thread in the Root Process */
933 ASSERT(CsrRootProcess
!= NULL
);
934 CsrThread
= CsrAllocateThread(CsrRootProcess
);
938 CsrReleaseProcessLock();
939 return STATUS_NO_MEMORY
;
942 /* Create the Thread */
943 Status
= RtlCreateUserThread(NtCurrentProcess(),
953 if (!NT_SUCCESS(Status
))
956 CsrDeallocateThread(CsrThread
);
957 CsrReleaseProcessLock();
961 /* Setup the Thread Object */
962 CsrThread
->ThreadHandle
= hThread
;
963 ProtectHandle(hThread
);
964 CsrThread
->ClientId
= ClientId
;
965 CsrThread
->Flags
= Flags
;
967 /* Insert it into the Thread List */
968 InsertHeadList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
970 /* Increase the thread count */
971 CsrRootProcess
->ThreadCount
++;
974 CsrReleaseProcessLock();
979 * @name CsrLockThreadByClientId
982 * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
983 * to the given Thread ID and optionally returns it.
986 * Thread ID corresponding to the CSR Thread which will be locked.
989 * Optional pointer to a CSR Thread pointer which will hold the
990 * CSR Thread corresponding to the given Thread ID.
992 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
995 * @remarks Locking a CSR Thread is defined as acquiring an extra
996 * reference to it and returning with the Process Lock held.
1001 CsrLockThreadByClientId(IN HANDLE Tid
,
1002 OUT PCSR_THREAD
*CsrThread
)
1004 PLIST_ENTRY NextEntry
;
1005 PCSR_THREAD CurrentThread
= NULL
;
1006 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1009 /* Acquire the lock */
1010 CsrAcquireProcessLock();
1012 /* Assume failure */
1013 ASSERT(CsrThread
!= NULL
);
1016 /* Convert to Hash */
1017 i
= CsrHashThread(Tid
);
1019 /* Setup the List Pointers */
1020 NextEntry
= CsrThreadHashTable
[i
].Flink
;
1023 while (NextEntry
!= &CsrThreadHashTable
[i
])
1025 /* Get the Process */
1026 CurrentThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
1028 /* Check for PID Match */
1029 if ((CurrentThread
->ClientId
.UniqueThread
== Tid
) &&
1030 !(CurrentThread
->Flags
& CsrThreadTerminated
))
1032 /* Get out of here */
1037 NextEntry
= NextEntry
->Flink
;
1040 /* Nothing found if we got back to the list */
1041 if (NextEntry
== &CsrThreadHashTable
[i
]) CurrentThread
= NULL
;
1043 /* Did the loop find something? */
1046 /* Reference the found thread */
1047 Status
= STATUS_SUCCESS
;
1048 CurrentThread
->ReferenceCount
++;
1049 *CsrThread
= CurrentThread
;
1053 /* Nothing found, release the lock */
1054 Status
= STATUS_UNSUCCESSFUL
;
1055 CsrReleaseProcessLock();
1058 /* Return the status */
1063 * @name CsrReferenceThread
1066 * The CsrReferenceThread routine increases the active reference count of
1070 * Pointer to the CSR Thread whose reference count will be increased.
1074 * @remarks Do not use this routine if the Process Lock is already held.
1079 CsrReferenceThread(IN PCSR_THREAD CsrThread
)
1081 /* Acquire process lock */
1082 CsrAcquireProcessLock();
1085 ASSERT(CsrThread
->Flags
& CsrThreadTerminated
); // CSR_THREAD_DESTROYED in ASSERT
1086 ASSERT(CsrThread
->ReferenceCount
!= 0);
1088 /* Increment reference count */
1089 CsrThread
->ReferenceCount
++;
1091 /* Release the lock */
1092 CsrReleaseProcessLock();
1096 * @name CsrUnlockThread
1099 * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
1102 * Pointer to a previously locked CSR Thread.
1104 * @return STATUS_SUCCESS.
1106 * @remarks This routine must be called with the Process Lock held.
1111 CsrUnlockThread(IN PCSR_THREAD CsrThread
)
1113 /* Dereference the Thread */
1114 ASSERT(ProcessStructureListLocked());
1115 CsrLockedDereferenceThread(CsrThread
);
1117 /* Release the lock and return */
1118 CsrReleaseProcessLock();
1119 return STATUS_SUCCESS
;