123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- /*++
- Copyright (c) 2015 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- profile.c
- Abstract:
- This module implements the system profiler application.
- Author:
- Chris Stevens 18-Jan-2015
- Environment:
- User Mode
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/minocaos.h>
- #include <minoca/kernel/sp.h>
- #include <minoca/lib/mlibc.h>
- #include <assert.h>
- #include <errno.h>
- #include <getopt.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- //
- // --------------------------------------------------------------------- Macros
- //
- #define PRINT_ERROR(...) fprintf(stderr, "\nprofile: " __VA_ARGS__)
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define PROFILE_VERSION_MAJOR 1
- #define PROFILE_VERSION_MINOR 0
- #define PROFILE_USAGE \
- "usage: profile [-d <type>] [-e <type>]\n\n" \
- "The profile utility enables, disables or gets system profiling state.\n\n"\
- "Options:\n" \
- " -d, --disable <type> -- Disable a system profiler. Valid values are \n" \
- " stack, memory, thread, and all.\n" \
- " -e, --enable <type> -- Enable a system profiler. Valid values are \n" \
- " stack, memory, thread, all.\n" \
- " --help -- Display this help text.\n" \
- " --version -- Display the application version and exit.\n\n"
- #define PROFILE_OPTIONS_STRING "e:d:Vh"
- #define PROFILE_TYPE_COUNT 4
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure defines the information for a given profile type option.
- Members:
- Name - Stores the command line name for the profile type option.
- TypeFlags - Stores bitmask of type flags for the system profilers that
- correspond to the name. See PROFILER_TYPE_FLAG_* for definitions.
- --*/
- typedef struct _PROFILE_TYPE_DATA {
- PSTR Name;
- ULONG TypeFlags;
- } PROFILE_TYPE_DATA, *PPROFILE_TYPE_DATA;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- struct option ProfileLongOptions[] = {
- {"disable", required_argument, 0, 'd'},
- {"enable", required_argument, 0, 'e'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {NULL, 0, 0, 0},
- };
- PROFILE_TYPE_DATA ProfileTypeData[PROFILE_TYPE_COUNT] = {
- {
- "all",
- PROFILER_TYPE_FLAG_STACK_SAMPLING |
- PROFILER_TYPE_FLAG_MEMORY_STATISTICS |
- PROFILER_TYPE_FLAG_THREAD_STATISTICS
- },
- {
- "stack",
- PROFILER_TYPE_FLAG_STACK_SAMPLING
- },
- {
- "memory",
- PROFILER_TYPE_FLAG_MEMORY_STATISTICS
- },
- {
- "thread",
- PROFILER_TYPE_FLAG_THREAD_STATISTICS
- },
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- int
- main (
- int ArgumentCount,
- char **Arguments
- )
- /*++
- Routine Description:
- This routine implements the kernel test program.
- Arguments:
- ArgumentCount - Supplies the number of elements in the arguments array.
- Arguments - Supplies an array of strings. The array count is bounded by the
- previous parameter, and the strings are null-terminated.
- Return Value:
- 0 on success.
- Non-zero on failure.
- --*/
- {
- ULONG DisableFlags;
- ULONG EnableFlags;
- ULONG Index;
- INT Option;
- INT ReturnValue;
- UINTN Size;
- SP_GET_SET_STATE_INFORMATION StateInformation;
- KSTATUS Status;
- DisableFlags = 0;
- EnableFlags = 0;
- ReturnValue = 0;
- //
- // Process the control arguments.
- //
- while (TRUE) {
- Option = getopt_long(ArgumentCount,
- Arguments,
- PROFILE_OPTIONS_STRING,
- ProfileLongOptions,
- NULL);
- if (Option == -1) {
- break;
- }
- if ((Option == '?') || (Option == ':')) {
- ReturnValue = 1;
- goto MainEnd;
- }
- switch (Option) {
- case 'd':
- for (Index = 0; Index < PROFILE_TYPE_COUNT; Index += 1) {
- if (strcasecmp(optarg, ProfileTypeData[Index].Name) == 0) {
- DisableFlags = ProfileTypeData[Index].TypeFlags;
- break;
- }
- }
- if (Index == PROFILE_TYPE_COUNT) {
- PRINT_ERROR("Invalid profiling type: %s\n", optarg);
- ReturnValue = 1;
- goto MainEnd;
- }
- break;
- case 'e':
- for (Index = 0; Index < PROFILE_TYPE_COUNT; Index += 1) {
- if (strcasecmp(optarg, ProfileTypeData[Index].Name) == 0) {
- EnableFlags = ProfileTypeData[Index].TypeFlags;
- break;
- }
- }
- if (Index == PROFILE_TYPE_COUNT) {
- PRINT_ERROR("Invalid profiling type: %s\n", optarg);
- ReturnValue = 1;
- goto MainEnd;
- }
- break;
- case 'V':
- printf("profile version %d.%02d\n",
- PROFILE_VERSION_MAJOR,
- PROFILE_VERSION_MINOR);
- ReturnValue = 1;
- goto MainEnd;
- case 'h':
- printf(PROFILE_USAGE);
- return 1;
- default:
- assert(FALSE);
- ReturnValue = 1;
- goto MainEnd;
- }
- }
- //
- // If there is nothing to enable or disable, then just get and print the
- // status.
- //
- if ((EnableFlags == 0) && (DisableFlags == 0)) {
- Size = sizeof(SP_GET_SET_STATE_INFORMATION);
- RtlZeroMemory(&StateInformation, Size);
- Status = OsGetSetSystemInformation(SystemInformationSp,
- SpInformationGetSetState,
- &StateInformation,
- &Size,
- FALSE);
- if (!KSUCCESS(Status)) {
- ReturnValue = ClConvertKstatusToErrorNumber(Status);
- PRINT_ERROR("Failed to get profiling information: %s.\n",
- strerror(ReturnValue));
- goto MainEnd;
- }
- if (Size < sizeof(SP_GET_SET_STATE_INFORMATION)) {
- Status = STATUS_DATA_LENGTH_MISMATCH;
- ReturnValue = ClConvertKstatusToErrorNumber(Status);
- PRINT_ERROR("Failed to get profiling information: %s.\n",
- strerror(ReturnValue));
- goto MainEnd;
- }
- for (Index = 1; Index < PROFILE_TYPE_COUNT; Index += 1) {
- if ((StateInformation.ProfilerTypeFlags &
- ProfileTypeData[Index].TypeFlags) != 0) {
- printf("%s - enabled\n", ProfileTypeData[Index].Name);
- } else {
- printf("%s - disabled\n", ProfileTypeData[Index].Name);
- }
- }
- //
- // Disable and enable the profiler types specified, unless they are equal.
- //
- } else if (DisableFlags != EnableFlags) {
- //
- // Don't disable anything that is about to be enabled.
- //
- DisableFlags &= ~EnableFlags;
- if (DisableFlags != 0) {
- Size = sizeof(SP_GET_SET_STATE_INFORMATION);
- StateInformation.Operation = SpGetSetStateOperationDisable;
- StateInformation.ProfilerTypeFlags = DisableFlags;
- Status = OsGetSetSystemInformation(SystemInformationSp,
- SpInformationGetSetState,
- &StateInformation,
- &Size,
- TRUE);
- if (!KSUCCESS(Status)) {
- ReturnValue = ClConvertKstatusToErrorNumber(Status);
- PRINT_ERROR("Failed to disable profiling information: %s.\n",
- strerror(ReturnValue));
- goto MainEnd;
- }
- }
- if (EnableFlags != 0) {
- Size = sizeof(SP_GET_SET_STATE_INFORMATION);
- StateInformation.Operation = SpGetSetStateOperationEnable;
- StateInformation.ProfilerTypeFlags = EnableFlags;
- Status = OsGetSetSystemInformation(SystemInformationSp,
- SpInformationGetSetState,
- &StateInformation,
- &Size,
- TRUE);
- if (!KSUCCESS(Status)) {
- ReturnValue = ClConvertKstatusToErrorNumber(Status);
- PRINT_ERROR("Failed to enable profiling information: %s.\n",
- strerror(ReturnValue));
- goto MainEnd;
- }
- }
- //
- // Tell the user that no action was taken.
- //
- } else {
- printf("Attempt to enable and disable the same profiling types "
- "ignored.\n");
- }
- MainEnd:
- return ReturnValue;
- }
|