ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

profobj.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       GPL - See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel
00004  * FILE:            ntoskrnl/ke/profobj.c
00005  * PURPOSE:         Kernel Profiling
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS *******************************************************************/
00016 
00017 KIRQL KiProfileIrql = PROFILE_LEVEL;
00018 LIST_ENTRY KiProfileListHead;
00019 LIST_ENTRY KiProfileSourceListHead;
00020 KSPIN_LOCK KiProfileLock;
00021 ULONG KiProfileTimeInterval = 78125; /* Default resolution 7.8ms (sysinternals) */
00022 ULONG KiProfileAlignmentFixupInterval;
00023 
00024 /* FUNCTIONS *****************************************************************/
00025 
00026 VOID
00027 NTAPI
00028 KeInitializeProfile(PKPROFILE Profile,
00029                     PKPROCESS Process,
00030                     PVOID ImageBase,
00031                     SIZE_T ImageSize,
00032                     ULONG BucketSize,
00033                     KPROFILE_SOURCE ProfileSource,
00034                     KAFFINITY Affinity)
00035 {
00036     /* Initialize the Header */
00037     Profile->Type = ProfileObject;
00038     Profile->Size = sizeof(KPROFILE);
00039 
00040     /* Copy all the settings we were given */
00041     Profile->Process = Process;
00042     Profile->RangeBase = ImageBase;
00043     Profile->BucketShift = BucketSize - 2; /* See ntinternals.net -- Alex */
00044     Profile->RangeLimit = (PVOID)((ULONG_PTR)ImageBase + ImageSize);
00045     Profile->Started = FALSE;
00046     Profile->Source = ProfileSource;
00047     Profile->Affinity = Affinity;
00048 }
00049 
00050 BOOLEAN
00051 NTAPI
00052 KeStartProfile(IN PKPROFILE Profile,
00053                IN PVOID Buffer)
00054 {
00055     KIRQL OldIrql;
00056     PKPROFILE_SOURCE_OBJECT SourceBuffer;
00057     PKPROFILE_SOURCE_OBJECT CurrentSource;
00058     BOOLEAN FreeBuffer = TRUE, SourceFound = FALSE, StartedProfile;
00059     PKPROCESS ProfileProcess;
00060     PLIST_ENTRY NextEntry;
00061 
00062     /* Allocate a buffer first, before we raise IRQL */
00063     SourceBuffer = ExAllocatePoolWithTag(NonPagedPool,
00064                                          sizeof(KPROFILE_SOURCE_OBJECT),
00065                                          'forP');
00066     if (!SourceBuffer) return FALSE;
00067     RtlZeroMemory(SourceBuffer, sizeof(KPROFILE_SOURCE_OBJECT));
00068 
00069     /* Raise to profile IRQL and acquire the profile lock */
00070     KeRaiseIrql(KiProfileIrql, &OldIrql);
00071     KeAcquireSpinLockAtDpcLevel(&KiProfileLock);
00072 
00073     /* Make sure it's not running */
00074     if (!Profile->Started)
00075     {
00076         /* Set it as Started */
00077         Profile->Buffer = Buffer;
00078         Profile->Started = TRUE;
00079         StartedProfile = TRUE;
00080 
00081         /* Get the process, if any */
00082         ProfileProcess = Profile->Process;
00083 
00084         /* Check where we should insert it */
00085         if (ProfileProcess)
00086         {
00087             /* Insert it into the Process List */
00088             InsertTailList(&ProfileProcess->ProfileListHead, &Profile->ProfileListEntry);
00089         }
00090         else
00091         {
00092             /* Insert it into the Global List */
00093             InsertTailList(&KiProfileListHead, &Profile->ProfileListEntry);
00094         }
00095 
00096         /* Start looping */
00097         for (NextEntry = KiProfileSourceListHead.Flink;
00098              NextEntry != &KiProfileSourceListHead;
00099              NextEntry = NextEntry->Flink)
00100         {
00101             /* Get the entry */
00102             CurrentSource = CONTAINING_RECORD(NextEntry,
00103                                               KPROFILE_SOURCE_OBJECT,
00104                                               ListEntry);
00105 
00106             /* Check if it's the same as the one being requested now */
00107             if (CurrentSource->Source == Profile->Source)
00108             {
00109                 /* It is, break out */
00110                 SourceFound = TRUE;
00111                 break;
00112             }
00113         }
00114 
00115         /* See if the loop found something */
00116         if (!SourceFound)
00117         {
00118             /* Nothing found, use our allocated buffer */
00119             CurrentSource = SourceBuffer;
00120 
00121             /* Set up the Source Object */
00122             CurrentSource->Source = Profile->Source;
00123             InsertHeadList(&KiProfileSourceListHead, &CurrentSource->ListEntry);
00124 
00125             /* Don't free the pool later on */
00126             FreeBuffer = FALSE;
00127         }
00128     }
00129     else
00130     {
00131         /* Already running so nothing to start */
00132         StartedProfile = FALSE;
00133     }
00134 
00135     /* Release the profile lock */
00136     KeReleaseSpinLockFromDpcLevel(&KiProfileLock);
00137 
00138     /* Tell HAL to start the profile interrupt */
00139     HalStartProfileInterrupt(Profile->Source);
00140 
00141     /* Lower back to original IRQL */
00142     KeLowerIrql(OldIrql);
00143 
00144     /* Free the pool */
00145     if (FreeBuffer) ExFreePool(SourceBuffer);
00146 
00147     /* Return whether we could start the profile */
00148     return StartedProfile;
00149 }
00150 
00151 BOOLEAN
00152 NTAPI
00153 KeStopProfile(IN PKPROFILE Profile)
00154 {
00155     KIRQL OldIrql;
00156     PKPROFILE_SOURCE_OBJECT CurrentSource = NULL;
00157     PLIST_ENTRY NextEntry;
00158     BOOLEAN SourceFound = FALSE, StoppedProfile;
00159 
00160     /* Raise to profile IRQL and acquire the profile lock */
00161     KeRaiseIrql(KiProfileIrql, &OldIrql);
00162     KeAcquireSpinLockAtDpcLevel(&KiProfileLock);
00163 
00164     /* Make sure it's running */
00165     if (Profile->Started)
00166     {
00167         /* Remove it from the list and disable */
00168         RemoveEntryList(&Profile->ProfileListEntry);
00169         Profile->Started = FALSE;
00170         StoppedProfile = TRUE;
00171 
00172         /* Start looping */
00173         for (NextEntry = KiProfileSourceListHead.Flink;
00174              NextEntry != &KiProfileSourceListHead;
00175              NextEntry = NextEntry->Flink)
00176         {
00177             /* Get the entry */
00178             CurrentSource = CONTAINING_RECORD(NextEntry,
00179                                               KPROFILE_SOURCE_OBJECT,
00180                                               ListEntry);
00181 
00182             /* Check if this is the Source Object */
00183             if (CurrentSource->Source == Profile->Source)
00184             {
00185                 /* Remember we found one */
00186                 SourceFound = TRUE;
00187 
00188                 /* Remove it and break out */
00189                 RemoveEntryList(&CurrentSource->ListEntry);
00190                 break;
00191             }
00192         }
00193 
00194     }
00195     else
00196     {
00197         /* It wasn't! */
00198         StoppedProfile = FALSE;
00199     }
00200 
00201     /* Release the profile lock */
00202     KeReleaseSpinLockFromDpcLevel(&KiProfileLock);
00203 
00204     /* Stop the profile interrupt */
00205     HalStopProfileInterrupt(Profile->Source);
00206 
00207     /* Lower back to original IRQL */
00208     KeLowerIrql(OldIrql);
00209 
00210     /* Free the Source Object */
00211     if (SourceFound) ExFreePool(CurrentSource);
00212 
00213     /* Return whether we could stop the profile */
00214     return StoppedProfile;
00215 }
00216 
00217 ULONG
00218 NTAPI
00219 KeQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource)
00220 {
00221     HAL_PROFILE_SOURCE_INFORMATION ProfileSourceInformation;
00222     ULONG ReturnLength, Interval;
00223     NTSTATUS Status;
00224 
00225     /* Check what profile this is */
00226     if (ProfileSource == ProfileTime)
00227     {
00228         /* Return the time interval */
00229         Interval = KiProfileTimeInterval;
00230     }
00231     else if (ProfileSource == ProfileAlignmentFixup)
00232     {
00233         /* Return the alignment interval */
00234         Interval = KiProfileAlignmentFixupInterval;
00235     }
00236     else
00237     {
00238         /* Request it from HAL */
00239         ProfileSourceInformation.Source = ProfileSource;
00240         Status = HalQuerySystemInformation(HalProfileSourceInformation,
00241                                            sizeof(HAL_PROFILE_SOURCE_INFORMATION),
00242                                            &ProfileSourceInformation,
00243                                            &ReturnLength);
00244 
00245         /* Check if HAL handled it and supports this profile */
00246         if (NT_SUCCESS(Status) && (ProfileSourceInformation.Supported))
00247         {
00248             /* Get the interval */
00249             Interval = ProfileSourceInformation.Interval;
00250         }
00251         else
00252         {
00253             /* Unsupported or invalid source, fail */
00254             Interval = 0;
00255         }
00256     }
00257 
00258     /* Return the interval we got */
00259     return Interval;
00260 }
00261 
00262 VOID
00263 NTAPI
00264 KeSetIntervalProfile(IN KPROFILE_SOURCE ProfileSource,
00265                      IN ULONG Interval)
00266 {
00267     HAL_PROFILE_SOURCE_INTERVAL ProfileSourceInterval;
00268 
00269     /* Check what profile this is */
00270     if (ProfileSource == ProfileTime)
00271     {
00272         /* Set the interval through HAL */
00273         KiProfileTimeInterval = (ULONG)HalSetProfileInterval(Interval);
00274     }
00275     else if (ProfileSource == ProfileAlignmentFixup)
00276     {
00277         /* Set the alignment interval */
00278         KiProfileAlignmentFixupInterval = Interval;
00279     }
00280     else
00281     {
00282         /* HAL handles any other interval */
00283         ProfileSourceInterval.Source = ProfileSource;
00284         ProfileSourceInterval.Interval = Interval;
00285         HalSetSystemInformation(HalProfileSourceInterval,
00286                                 sizeof(HAL_PROFILE_SOURCE_INTERVAL),
00287                                 &ProfileSourceInterval);
00288     }
00289 }
00290 
00291 /*
00292  * @implemented
00293  */
00294 VOID
00295 NTAPI
00296 KeProfileInterrupt(IN PKTRAP_FRAME TrapFrame)
00297 {
00298     /* Called from HAL for Timer Profiling */
00299     KeProfileInterruptWithSource(TrapFrame, ProfileTime);
00300 }
00301 
00302 VOID
00303 NTAPI
00304 KiParseProfileList(IN PKTRAP_FRAME TrapFrame,
00305                    IN KPROFILE_SOURCE Source,
00306                    IN PLIST_ENTRY ListHead)
00307 {
00308     PULONG BucketValue;
00309     PKPROFILE Profile;
00310     PLIST_ENTRY NextEntry;
00311     ULONG_PTR ProgramCounter;
00312 
00313     /* Get the Program Counter */
00314     ProgramCounter = KeGetTrapFramePc(TrapFrame);
00315 
00316     /* Loop the List */
00317     for (NextEntry = ListHead->Flink;
00318          NextEntry != ListHead;
00319          NextEntry = NextEntry->Flink)
00320     {
00321         /* Get the entry */
00322         Profile = CONTAINING_RECORD(NextEntry, KPROFILE, ProfileListEntry);
00323 
00324         /* Check if the source is good, and if it's within the range */
00325         if ((Profile->Source != Source) ||
00326             (ProgramCounter < (ULONG_PTR)Profile->RangeBase) ||
00327             (ProgramCounter > (ULONG_PTR)Profile->RangeLimit))
00328         {
00329             continue;
00330         }
00331 
00332         /* Get the Pointer to the Bucket Value representing this Program Counter */
00333         BucketValue = (PULONG)((((ULONG_PTR)Profile->Buffer +
00334                                (ProgramCounter - (ULONG_PTR)Profile->RangeBase))
00335                                 >> Profile->BucketShift) &~ 0x3);
00336 
00337         /* Increment the value */
00338         ++BucketValue;
00339     }
00340 }
00341 
00342 /*
00343  * @implemented
00344  *
00345  * Remarks:
00346  *         Called from HAL, this function looks up the process
00347  *         entries, finds the proper source object, verifies the
00348  *         ranges with the trapframe data, and inserts the information
00349  *         from the trap frame into the buffer, while using buckets and
00350  *         shifting like we specified. -- Alex
00351  */
00352 VOID
00353 NTAPI
00354 KeProfileInterruptWithSource(IN PKTRAP_FRAME TrapFrame,
00355                              IN KPROFILE_SOURCE Source)
00356 {
00357     PKPROCESS Process = KeGetCurrentThread()->ApcState.Process;
00358 
00359     /* We have to parse 2 lists. Per-Process and System-Wide */
00360     KiParseProfileList(TrapFrame, Source, &Process->ProfileListHead);
00361     KiParseProfileList(TrapFrame, Source, &KiProfileListHead);
00362 }
00363 
00364 /*
00365  * @implemented
00366  */
00367 VOID
00368 NTAPI
00369 KeSetProfileIrql(IN KIRQL ProfileIrql)
00370 {
00371     /* Set the IRQL at which Profiling will run */
00372     KiProfileIrql = ProfileIrql;
00373 }

Generated on Sun May 27 2012 04:37:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.