[WSD] Add perfmon counter object implementation. WSD installation now
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 6 Apr 2006 06:05:05 +0000 (06:05 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 6 Apr 2006 06:05:05 +0000 (06:05 +0000)
registers the WSD provider as a performance counter provider, reporting
I/O and completion statistics to perfmon or any other performance
monitoring tool

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@289 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

inc/user/wsd/ibsp_regpath.h [new file with mode: 0644]
tools/wsdinstall/user/SOURCES
tools/wsdinstall/user/installsp.c
ulp/wsd/user/SOURCES
ulp/wsd/user/ibsp_iblow.c
ulp/wsd/user/ibsp_perfmon.c [new file with mode: 0644]
ulp/wsd/user/ibsp_perfmon.h [new file with mode: 0644]
ulp/wsd/user/ibspdebug.h
ulp/wsd/user/ibspdll.c
ulp/wsd/user/ibspdll.def
ulp/wsd/user/ibspdll.sln [deleted file]

diff --git a/inc/user/wsd/ibsp_regpath.h b/inc/user/wsd/ibsp_regpath.h
new file mode 100644 (file)
index 0000000..9066119
--- /dev/null
@@ -0,0 +1,66 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+#ifndef _IBSP_REGPATH_H_\r
+#define _IBSP_REGPATH_H_\r
+\r
+/* these definitions are common for installSP and WSD projects */\r
+#define IBSP_PM_REGISTRY_PATH  \\r
+       TEXT("SYSTEM\\CurrentControlSet\\Services\\IBWSD\\")\r
+#define IBSP_PM_EVENTLOG_PATH  \\r
+       TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\IBWSD")\r
+#define IBSP_PM_SUBKEY_NAME            TEXT("IBWSD")\r
+#define IBSP_PM_SUBKEY_PERF            TEXT("Performance")\r
+#define IBSP_PM_INI_FILE               "ibsp_perfcounters.ini"\r
+#define IBSP_PM_SYM_H_FILE             "ibsp_perfini.h"\r
+\r
+\r
+enum IBSP_PM_COUNTERS\r
+{\r
+       BYTES_SEND = 0,\r
+       BYTES_RECV,\r
+       BYTES_WRITE,\r
+       BYTES_READ,\r
+       BYTES_TOTAL,\r
+       COMP_SEND,\r
+       COMP_RECV,\r
+       COMP_TOTAL,\r
+       INTR_TOTAL,\r
+       IBSP_PM_NUM_COUNTERS\r
+\r
+};\r
+\r
+\r
+/* counter symbol names */\r
+#define IBSP_PM_OBJ                                            0\r
+#define IBSP_PM_COUNTER( X )                   ((X + 1) * 2)\r
+\r
+#endif /* _IBSP_REGPATH_H_ */\r
index a068fdd..9a4c915 100644 (file)
@@ -4,11 +4,18 @@ TARGETTYPE=PROGRAM
 UMTYPE=console\r
 USE_CRTDLL=1\r
 \r
+INCLUDES=..\..\..\inc;\\r
+       ..\..\..\inc\user;\\r
+       $(PLATFORM_SDK_PATH)\include;\r
+\r
 SOURCES=\\r
        installsp.c\r
 \r
+USER_C_FLAGS=$(USER_C_FLAGS) -DPERFMON_ENABLED\r
+\r
 TARGETLIBS=\\r
-       $(SDK_LIB_PATH)\ws2_32.lib\r
+       $(SDK_LIB_PATH)\ws2_32.lib \\r
+       $(SDK_LIB_PATH)\LoadPerf.lib \r
 \r
 MSC_WARNING_LEVEL= /W3\r
 \r
index 8111f08..c721210 100644 (file)
 #include <stdio.h>\r
 \r
 /* Initialize the LSP's provider path for Infiband Service Provider dll */\r
-static const WCHAR *provider_path = L"%SYSTEMROOT%\\system32\\ibwsd.dll";\r
-static const WCHAR *provider_name = L"OpenIB Winsock Direct for InfiniBand";\r
-static const char *winsock_key_path = "System\\CurrentControlSet\\Services\\Winsock\\Parameters\\TCP on SAN";\r
-static const char *openib_key_name = "OpenIB Alliance";\r
+static const WCHAR provider_path[] = L"%SYSTEMROOT%\\system32\\ibwsd.dll";\r
+static const WCHAR provider_name[] = L"OpenIB Winsock Direct for InfiniBand";\r
+static const char winsock_key_path[] =\r
+       "System\\CurrentControlSet\\Services\\Winsock\\Parameters\\TCP on SAN";\r
+static const char openib_key_name[] = "OpenIB Alliance";\r
 \r
 /* Unique provider GUID generated with "uuidgen -s" */\r
 static GUID provider_guid = {\r
@@ -60,6 +61,316 @@ static GUID provider_guid = {
 #define WSCInstallProvider     WSCInstallProvider64_32\r
 #endif /* _WIN64 */\r
 \r
+#ifdef PERFMON_ENABLED\r
+#include <Loadperf.h>\r
+#include "wsd/ibsp_regpath.h"\r
+\r
+\r
+typedef struct _pm_symbol_def\r
+{\r
+       DWORD   name_def;\r
+       CHAR    name_str[40];\r
+       CHAR    name_desc[40];\r
+       CHAR    help_desc[256];\r
+\r
+} pm_symbol_def_t;\r
+\r
+static pm_symbol_def_t  _pm_symbols[]=\r
+{\r
+       { IBSP_PM_OBJ,\r
+       "IBSP_PM_OBJ",\r
+       "IB Winsock Direct",\r
+       "InfiniBand Windows Sockets Direct Provider."\r
+       },\r
+       { IBSP_PM_COUNTER(BYTES_SEND),\r
+       "IBSP_PM_BYTES_TX_SEC",\r
+       "Send bytes/sec",\r
+       "Send bytes/second, excluding RDMA Write."\r
+       },\r
+       { IBSP_PM_COUNTER(BYTES_RECV),\r
+       "IBSP_PM_BYTES_RX_SEC",\r
+       "Recv bytes/sec",\r
+       "Receive bytes/second, excluding RDMA Read."\r
+       },\r
+       { IBSP_PM_COUNTER(BYTES_WRITE),\r
+       "IBSP_PM_RDMA_WR_SEC",\r
+       "RDMA Write bytes/sec",\r
+       "RDMA Write bytes/second."\r
+       },\r
+       { IBSP_PM_COUNTER(BYTES_READ),\r
+       "IBSP_PM_RDMA_RD_SEC",\r
+       "RDMA Read bytes/sec",\r
+       "RDMA Read bytes/second."\r
+       },\r
+       { IBSP_PM_COUNTER(BYTES_TOTAL),\r
+       "IBSP_PM_BYTES_SEC",\r
+       "Total bytes/sec",\r
+       "Total bytes transmitted per second, including send, "\r
+       "receive, RDMA Write, and RDMA Read."\r
+       },\r
+       { IBSP_PM_COUNTER(COMP_SEND),\r
+       "IBSP_PM_SEND_COMPLETIONS_SEC",\r
+       "Send Completions/sec",\r
+       "Send and RDMA Write Completions/sec."\r
+       },\r
+       { IBSP_PM_COUNTER(COMP_RECV),\r
+       "IBSP_PM_RECV_COMPLETIONS_SEC",\r
+       "Recv Completions/sec",\r
+       "Recv and RDMA Read Completions/sec."\r
+       },\r
+       { IBSP_PM_COUNTER(COMP_TOTAL),\r
+       "IBSP_PM_COMPLETIONS_SEC",\r
+       "Total Completions/sec",\r
+       "Total Completions processed per second."\r
+       },\r
+       { IBSP_PM_COUNTER(INTR_TOTAL),\r
+       "IBSP_PM_COMPLETIONS_INTR",\r
+       "Total Interrupts/sec",\r
+       "Completion Queue events per second."\r
+       }\r
+};\r
+\r
+#define IBSP_PM_NUM_SYMBOLS  (sizeof(_pm_symbols)/sizeof(pm_symbol_def_t))\r
+#define IBSP_PM_LANGUAGE "009" /* good for English */\r
+\r
+\r
+static DWORD\r
+_IBSPPerfmonIniFilesGenerate( void )\r
+{\r
+       FILE    *f_handle;\r
+       DWORD   num;\r
+\r
+       /* create ".h" file first */\r
+       f_handle = fopen( IBSP_PM_SYM_H_FILE, "w+" );\r
+\r
+       if( !f_handle )\r
+       {\r
+               fprintf(\r
+                       stderr, "Create Header file %s  failed\n", IBSP_PM_SYM_H_FILE );\r
+               return ERROR_FILE_INVALID;\r
+       }\r
+\r
+       fprintf(\r
+               f_handle, "/* %s Generated by program */ \r\n", IBSP_PM_SYM_H_FILE );\r
+               \r
+       \r
+       for( num = 0; num < IBSP_PM_NUM_SYMBOLS; num++ )\r
+       {\r
+               fprintf( f_handle, "#define\t%s\t%d\r\n",\r
+                       _pm_symbols[num].name_str, _pm_symbols[num].name_def );\r
+       }\r
+\r
+       fflush( f_handle );\r
+       fclose( f_handle );\r
+\r
+       /* create 'ini' file next */\r
+       f_handle = fopen( IBSP_PM_INI_FILE, "w+" );\r
+\r
+       if( !f_handle )\r
+       {\r
+               fprintf( stderr, "Create INI file %s  failed\n", IBSP_PM_INI_FILE );\r
+               return ERROR_FILE_INVALID;\r
+       }\r
+       \r
+       fprintf( f_handle, "[info]\r\ndrivername=" IBSP_PM_SUBKEY_NAME\r
+               "\r\nsymbolfile=" IBSP_PM_SYM_H_FILE "\r\n\r\n" );\r
+       fprintf( f_handle,"[languages]\r\n" IBSP_PM_LANGUAGE\r
+               "=language" IBSP_PM_LANGUAGE "\r\n\r\n" );\r
+\r
+       fprintf( f_handle, \r
+               "[objects]\r\n%s_" IBSP_PM_LANGUAGE "_NAME=%s\r\n\r\n[text]\r\n",\r
+               _pm_symbols[0].name_str, _pm_symbols[0].name_desc );\r
+       \r
+       for( num = 0; num < IBSP_PM_NUM_SYMBOLS; num++ )\r
+       {\r
+               fprintf( f_handle,"%s_" IBSP_PM_LANGUAGE "_NAME=%s\r\n",\r
+                       _pm_symbols[num].name_str, _pm_symbols[num].name_desc );\r
+               fprintf( f_handle,"%s_" IBSP_PM_LANGUAGE "_HELP=%s\r\n",\r
+                       _pm_symbols[num].name_str, _pm_symbols[num].help_desc );\r
+       }\r
+\r
+       fflush( f_handle );\r
+       fclose( f_handle );\r
+\r
+       return ERROR_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+_IBSPPerfmonIniFilesRemove( void )\r
+{\r
+       if( !DeleteFile( IBSP_PM_INI_FILE ) )\r
+       {\r
+               fprintf( stderr, "Delete file %s failed status %d\n",\r
+                       IBSP_PM_INI_FILE, GetLastError() );\r
+       }\r
+       if( !DeleteFile( IBSP_PM_SYM_H_FILE ) )\r
+       {\r
+               fprintf( stderr,"Delete file %s failed status %d\n",\r
+                       IBSP_PM_SYM_H_FILE, GetLastError() );\r
+       }\r
+}\r
+\r
+\r
+/* Try to create IB WSD Performance Register Keys */\r
+static LONG\r
+_IBSPPerfmonRegisterKeys( void )\r
+{\r
+       LONG    reg_status;\r
+       HKEY    pm_hkey;\r
+       DWORD   typesSupp = 7;\r
+\r
+       reg_status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF, 0, NULL,\r
+               REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pm_hkey, NULL );\r
+\r
+       if( reg_status != ERROR_SUCCESS )\r
+       {\r
+               fprintf( stderr,\r
+                       "_IBSPPerfmonRegisterKeys Create Key %s failed with %d\n",\r
+                       IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF, reg_status );\r
+               return reg_status;\r
+       }\r
+\r
+       /* create/assign values to the key */\r
+       RegSetValueExW( pm_hkey, L"Library", 0, REG_EXPAND_SZ,\r
+               (LPBYTE)provider_path, sizeof(provider_path) );\r
+\r
+       RegSetValueEx( pm_hkey, TEXT("Open"), 0, REG_SZ,\r
+               (LPBYTE)TEXT("IBSPPmOpen"), sizeof(TEXT("IBSPPmOpen")) );\r
+\r
+       RegSetValueEx( pm_hkey, TEXT("Collect"), 0, REG_SZ,\r
+               (LPBYTE)TEXT("IBSPPmCollectData"), sizeof(TEXT("IBSPPmCollectData")) );\r
+\r
+       RegSetValueEx( pm_hkey, TEXT("Close"), 0, REG_SZ,\r
+               (LPBYTE)TEXT("IBSPPmClose"), sizeof(TEXT("IBSPPmClose")) );\r
+\r
+       RegFlushKey( pm_hkey );\r
+       RegCloseKey( pm_hkey );\r
+\r
+       reg_status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_EVENTLOG_PATH, 0, NULL,\r
+               REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pm_hkey, NULL );\r
+\r
+       if( reg_status != ERROR_SUCCESS )\r
+       {\r
+               fprintf(stderr, "Create EventLog Key failed with %d\n", reg_status );\r
+               return reg_status;\r
+       }\r
+\r
+       /* create/assign values to the key */\r
+       RegSetValueExW( pm_hkey, L"EventMessageFile", 0, REG_EXPAND_SZ,\\r
+               (LPBYTE)provider_path, sizeof(provider_path) );\r
+\r
+       RegSetValueEx( pm_hkey, TEXT("TypesSupported"), 0, REG_DWORD,\r
+               (LPBYTE)&typesSupp, sizeof(typesSupp) );\r
+\r
+       RegFlushKey( pm_hkey );\r
+       RegCloseKey( pm_hkey );\r
+\r
+       return reg_status;\r
+}\r
+\r
+\r
+/* Try to destroy IB WSD Performance Register Keys */\r
+static LONG\r
+_IBSPPerfmonDeregisterKeys( void )\r
+{\r
+       LONG    reg_status;\r
+\r
+       reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF,\r
+               (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
+\r
+       if( reg_status != ERROR_SUCCESS )\r
+       {\r
+               fprintf( stderr,\r
+                       "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
+                       GetLastError() );\r
+       }\r
+\r
+       reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_REGISTRY_PATH, (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
+\r
+       if( reg_status != ERROR_SUCCESS )\r
+       {\r
+               fprintf( stderr,\r
+                       "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
+                       GetLastError() );\r
+       }\r
+\r
+       reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_EVENTLOG_PATH, (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
+\r
+       if( reg_status != ERROR_SUCCESS )\r
+       {\r
+               fprintf( stderr,\r
+                       "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
+                       GetLastError() );\r
+       }\r
+\r
+       return reg_status;\r
+}\r
+\r
+\r
+/*\r
+ * functions will try to register performance counters\r
+ * definitions with PerfMon application.\r
+ * API externally called by lodctr.exe/unlodctr.exe utilities.\r
+ */\r
+static DWORD\r
+_IBSPPerfmonRegisterCounters( void )\r
+{\r
+       DWORD status;\r
+       /*\r
+        * format commandline string, as per SDK :\r
+        *      Pointer to a null-terminated string that consists of one or more \r
+        *      arbitrary letters, a space, and then the name of the initialization\r
+        *      file.\r
+        */\r
+       status = LoadPerfCounterTextStrings(\r
+               TEXT("unused ") TEXT(IBSP_PM_INI_FILE), TRUE );\r
+       if( status != ERROR_SUCCESS )\r
+       {\r
+               status = GetLastError();\r
+               fprintf( stderr,\r
+                       "IBSPPerfmonRegisterCounters install failed status %d\n", status );\r
+       }\r
+\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * functions will try to unregister performance counters\r
+ * definitions with PerfMon application.\r
+ * API externally called by lodctr.exe/unlodctr.exe utilities.\r
+ */\r
+static DWORD\r
+_IBSPPerfmonDeregisterCounters( void )\r
+{\r
+       DWORD status;\r
+\r
+       /*\r
+        * format commandline string, as per SDK :\r
+        *      Pointer to a null-terminated string that consists of one or more \r
+        *      arbitrary letters, a space, and then the name of the initialization\r
+        *      file.\r
+        */\r
+       status = UnloadPerfCounterTextStrings(\r
+               TEXT("unused ") TEXT(IBSP_PM_SUBKEY_NAME), TRUE );\r
+       if( status != ERROR_SUCCESS )\r
+       {\r
+               fprintf( stderr,\r
+                       "IBSPPerfmonDeregisterCounters remove failed status %d\n",\r
+                       status );\r
+       }\r
+       return status;\r
+}\r
+\r
+#endif /* PERFMON_ENABLED */\r
+\r
+\r
 /*\r
  * Function: usage\r
  *   Description: Prints usage information.\r
@@ -67,7 +378,7 @@ static GUID provider_guid = {
 static void\r
 usage (char *progname)\r
 {\r
-       printf ("usage: %s [-i/-r]\n", progname);\r
+       printf ("usage: %s [-i/-r [-p]]\n", progname);\r
        printf ("    -i   Install the service provider\n"\r
                        "    -r   Remove the OpenIB service provider\n"\r
                        "    -r <name>   Remove the specified service provider\n"\r
@@ -144,11 +455,12 @@ static void install_provider(void)
        HKEY hkey;\r
 \r
        /* Now setup the key. */\r
-       reg_error = RegCreateKeyEx( HKEY_LOCAL_MACHINE, winsock_key_path, 0, NULL,\r
-               REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hkey, NULL );\r
+       reg_error = RegCreateKeyExA( HKEY_LOCAL_MACHINE, winsock_key_path,\r
+               0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL,\r
+               &hkey, NULL );\r
        if( reg_error == ERROR_SUCCESS )\r
        {\r
-               reg_error = RegSetValueEx( hkey, openib_key_name, 0, REG_BINARY,\r
+               reg_error = RegSetValueExA( hkey, openib_key_name, 0, REG_BINARY,\r
                        (PBYTE)&provider_guid, sizeof(GUID) );\r
                if( reg_error == ERROR_SUCCESS )\r
                {\r
@@ -216,14 +528,14 @@ static void remove_provider( const char* const provider_name )
        HKEY hkey;\r
 \r
        /* Remove our key */\r
-       reg_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,\r
+       reg_error = RegOpenKeyExA(HKEY_LOCAL_MACHINE,\r
                                                         winsock_key_path,\r
                                                         0,\r
                                                         (KEY_WRITE | KEY_READ),\r
                                                         &hkey);\r
        if (reg_error == ERROR_SUCCESS) {\r
 \r
-               reg_error = RegDeleteValue(hkey, provider_name);\r
+               reg_error = RegDeleteValueA(hkey, provider_name);\r
                if (reg_error == ERROR_SUCCESS) {\r
                        /* Force the system to remove the key now. */\r
                        RegFlushKey(hkey);\r
@@ -291,6 +603,11 @@ int __cdecl main (int argc, char *argv[])
        case 'i':\r
                /* Install the Infiniband Service Provider */\r
                install_provider ();\r
+#ifdef PERFMON_ENABLED\r
+               _IBSPPerfmonIniFilesGenerate();\r
+               if ( _IBSPPerfmonRegisterKeys() == ERROR_SUCCESS )\r
+                               _IBSPPerfmonRegisterCounters();\r
+#endif\r
                break;\r
 \r
        case 'r':\r
@@ -299,13 +616,18 @@ int __cdecl main (int argc, char *argv[])
                        remove_provider( openib_key_name );\r
                else\r
                        remove_provider( argv[2] );\r
+#ifdef PERFMON_ENABLED\r
+               _IBSPPerfmonIniFilesRemove();\r
+               if ( _IBSPPerfmonDeregisterCounters() == ERROR_SUCCESS )\r
+                       _IBSPPerfmonDeregisterKeys();\r
+#endif\r
                break;\r
 \r
        case 'l':\r
                /* List existing providers */\r
                print_providers();\r
                break;\r
-\r
+       \r
        default:\r
                usage (argv[0]);\r
                break;\r
index 3238302..c844ae6 100644 (file)
@@ -17,16 +17,19 @@ SOURCES=\
        ibspdll.c               \\r
        misc.c                  \\r
        sockinfo.c              \\r
-       ibsp_duplicate.c\r
+       ibsp_duplicate.c \\r
+       ibsp_perfmon.c\r
 \r
 INCLUDES=..\..\..\inc;..\..\..\inc\user;$(DDK_INC_PATH);\r
 \r
-USER_C_FLAGS=$(USER_C_FLAGS) -DCL_NO_TRACK_MEM\r
+USER_C_FLAGS=$(USER_C_FLAGS) -DCL_NO_TRACK_MEM -DPERFMON_ENABLED\r
 \r
 TARGETLIBS=\\r
                        $(SDK_LIB_PATH)\kernel32.lib \\r
                        $(SDK_LIB_PATH)\ws2_32.lib \\r
                        $(SDK_LIB_PATH)\rpcrt4.lib \\r
+                       $(SDK_LIB_PATH)\Advapi32.lib \\r
+                       $(SDK_LIB_PATH)\LoadPerf.lib \\r
 !if $(FREEBUILD)\r
                        $(TARGETPATH)\*\complib.lib \\r
                        $(TARGETPATH)\*\ibal.lib\r
index 87c318e..191b9a2 100644 (file)
 \r
 #include "ibspdll.h"\r
 \r
+#ifdef PERFMON_ENABLED\r
+#include "ibsp_perfmon.h"\r
+#endif\r
+\r
 \r
 typedef struct _io_comp_info\r
 {\r
@@ -89,10 +93,10 @@ complete_wq(
                 * NOTE: Without a valid length, the switch doesn't seem to call \r
                 * GetOverlappedResult() even if we call lpWPUCompleteOverlappedRequest()\r
                 */\r
-               if( wc->wc_type == IB_WC_RECV )\r
+               switch ( wc->wc_type ) \r
                {\r
+               case IB_WC_RECV:\r
                        lpOverlapped->InternalHigh = wc->length;\r
-\r
 #ifdef IBSP_LOGGING\r
                        cl_spinlock_acquire( &socket_info->recv_lock );\r
                        DataLogger_WriteData(&socket_info->RecvDataLogger,\r
@@ -100,8 +104,37 @@ complete_wq(
                                wc->length);\r
                        cl_spinlock_release( &socket_info->recv_lock );\r
 #endif\r
+#ifdef PERFMON_ENABLED\r
+                       InterlockedIncrement64( &g_pm_stat.pdata[COMP_RECV] );\r
+                       InterlockedExchangeAdd64( &g_pm_stat.pdata[BYTES_RECV],\r
+                               lpOverlapped->InternalHigh );\r
+#endif\r
+                       break;\r
+#ifdef PERFMON_ENABLED\r
+\r
+               case IB_WC_RDMA_READ:\r
+                       lpOverlapped->InternalHigh = wc->length;\r
+                       InterlockedIncrement64( &g_pm_stat.pdata[COMP_RECV] );\r
+                       InterlockedExchangeAdd64( &g_pm_stat.pdata[BYTES_READ],\r
+                               lpOverlapped->InternalHigh );\r
+                       break;\r
+\r
+               case IB_WC_SEND:\r
+                       InterlockedIncrement64( &g_pm_stat.pdata[COMP_SEND] );\r
+                       InterlockedExchangeAdd64( &g_pm_stat.pdata[BYTES_SEND],\r
+                               lpOverlapped->InternalHigh );\r
+                       break;\r
+\r
+               case IB_WC_RDMA_WRITE:\r
+                       InterlockedIncrement64( &g_pm_stat.pdata[COMP_SEND] );\r
+                       InterlockedExchangeAdd64( &g_pm_stat.pdata[BYTES_WRITE],\r
+                               lpOverlapped->InternalHigh );\r
+               default:\r
+                       break;\r
                }\r
 \r
+#endif /* PERFMON_ENABLED */\r
+\r
                lpOverlapped->OffsetHigh = 0;\r
                break;\r
 \r
@@ -173,6 +206,10 @@ complete_wq(
                break;\r
        }\r
 \r
+#ifdef PERFMON_ENABLED\r
+       InterlockedIncrement64( &g_pm_stat.pdata[COMP_TOTAL] );\r
+#endif\r
+\r
 #ifdef _DEBUG_\r
        if( wc->wc_type == IB_WC_RECV )\r
        {\r
@@ -285,9 +322,13 @@ complete_wq(
        }\r
 \r
        if( wc->wc_type == IB_WC_RECV )\r
+       {\r
                cl_atomic_dec( &socket_info->recv_cnt );\r
+       }\r
        else\r
+       {\r
                cl_atomic_dec( &socket_info->send_cnt );\r
+       }\r
 \r
        IBSP_EXIT( IBSP_DBG_IO );\r
 }\r
@@ -432,7 +473,6 @@ ib_cq_thread(
 \r
        IBSP_ENTER( IBSP_DBG_HW );\r
 \r
-\r
        fzprint(("%s():%d:0x%x:0x%x: cq_tinfo=0x%p\n", __FUNCTION__,\r
                         __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), cq_tinfo));\r
 \r
@@ -454,6 +494,9 @@ ib_cq_thread(
                        fzprint(("%s():%d:0x%x:0x%x: Calling ib_cq_comp().\n", __FUNCTION__,\r
                                         __LINE__, GetCurrentProcessId(), GetCurrentThreadId()));\r
 \r
+#ifdef PERFMON_ENABLED\r
+                       InterlockedIncrement64( &g_pm_stat.pdata[INTR_TOTAL] );\r
+#endif\r
                        i = g_max_poll;\r
                        do\r
                        {\r
diff --git a/ulp/wsd/user/ibsp_perfmon.c b/ulp/wsd/user/ibsp_perfmon.c
new file mode 100644 (file)
index 0000000..3626a28
--- /dev/null
@@ -0,0 +1,557 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+\r
+#include <string.h>\r
+#include "ibspdebug.h"\r
+#include "ibsp_perfmon.h"\r
+\r
+\r
+struct _ibsp_pm_definition     g_ibsp_pm_def; /* IB WSD performance object */\r
+\r
+\r
+void\r
+IBSPPmInit( void )\r
+{\r
+       HANDLE                          h_mapping;\r
+       BOOL                            just_created;\r
+       SECURITY_ATTRIBUTES     sec_attr;\r
+\r
+       IBSP_ENTER( IBSP_DBG_PERFMON );\r
+\r
+       g_pm_stat.idx = INVALID_IDX;\r
+       g_pm_stat.p_shmem = NULL;\r
+\r
+       sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);\r
+       sec_attr.bInheritHandle = FALSE;\r
+\r
+       if( !ConvertStringSecurityDescriptorToSecurityDescriptor(\r
+               IBSP_PM_SEC_STRING, SDDL_REVISION_1,\r
+               &(sec_attr.lpSecurityDescriptor), NULL ) )\r
+       {\r
+               IBSP_ERROR( ("SecurityDescriptor error %d\n", GetLastError()) );\r
+               return;\r
+       }\r
+\r
+       h_mapping = CreateFileMapping(\r
+               INVALID_HANDLE_VALUE,   // use paging file\r
+               &sec_attr,                              // security attributes\r
+               PAGE_READWRITE,                 // read/write access\r
+               0,                                              // size: high 32-bits\r
+               sizeof(pm_shmem_t),             // size: low 32-bits\r
+               IBSP_PM_MAPPED_OBJ_NAME );\r
+\r
+       LocalFree( sec_attr.lpSecurityDescriptor );\r
+\r
+       if( h_mapping == NULL )\r
+       {\r
+               IBSP_ERROR_EXIT( ("CreateFileMapping error %d\n", GetLastError()) );\r
+               return;\r
+       }\r
+\r
+       just_created = (GetLastError() != ERROR_ALREADY_EXISTS);\r
+\r
+       /* Get a pointer to the shared memory. */\r
+       g_pm_stat.p_shmem = MapViewOfFile(\r
+                                               h_mapping,     // object handle\r
+                                               FILE_MAP_ALL_ACCESS,\r
+                                               0,              // high offset:  map from\r
+                                               0,              // low offset:   beginning\r
+                                               0);             // num bytes to map\r
+\r
+       /* Now that we have the view mapped, we don't need the mapping handle. */\r
+       g_pm_stat.h_mapping = h_mapping;\r
+\r
+       if( g_pm_stat.p_shmem == NULL )\r
+       {\r
+               IBSP_ERROR( ("MapViewOfFile returned %d\n", GetLastError()) );\r
+               return;\r
+       }\r
+       \r
+       if( just_created )\r
+       {\r
+               /*\r
+                * Reserve instance 0 for fallback counters\r
+                * Apps that can't get a dedicated slot will share this one.\r
+                */\r
+               wcscpy( g_pm_stat.p_shmem->obj[0].app_name,\r
+                       IBSP_PM_TOTAL_COUNTER_NAME );\r
+               g_pm_stat.p_shmem->obj[0].taken = 1;\r
+       }\r
+\r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+}\r
+\r
+\r
+/*\r
+ * We always get a slot - either an individual one, or fall back on the \r
+ * common one.\r
+ */\r
+void\r
+IBSPPmGetSlot( void )\r
+{\r
+       WCHAR           mod_path[MAX_PATH];\r
+       WCHAR*          buf;\r
+       int                     idx;\r
+       size_t          name_len;\r
+       WCHAR           id_str[12];\r
+       mem_obj_t       *p_slot;\r
+       pm_shmem_t* p_mem = g_pm_stat.p_shmem;\r
+\r
+       IBSP_ENTER( IBSP_DBG_PERFMON );\r
+\r
+       if( g_pm_stat.p_shmem == NULL )\r
+       {\r
+               g_pm_stat.pdata = g_pm_stat.fall_back_data;\r
+               return;\r
+       }\r
+\r
+       GetModuleFileNameW( NULL, mod_path, MAX_PATH );\r
+\r
+       buf = wcsrchr( mod_path, L'\\' );\r
+       if( !buf )\r
+               buf = mod_path;\r
+       else\r
+               buf++;\r
+\r
+       /* The max length is 11, one for the ':', and 10 for the process ID. */\r
+       id_str[0] = ':';\r
+       _ultow( GetCurrentProcessId(), &id_str[1], 10 );\r
+\r
+       /* Cap the length of the application. */\r
+       name_len = min( wcslen( buf ),\r
+               IBSP_PM_APP_NAME_SIZE - 1 - wcslen( id_str ) );\r
+\r
+       /* instance 0 is taken for "Total" counters, so don't try it */\r
+       for( idx = 1; idx < IBSP_PM_NUM_INSTANCES; idx++)\r
+       {\r
+               /* Compare with 0, exchange with 1 */\r
+               if( InterlockedCompareExchange(\r
+                       &g_pm_stat.p_shmem->obj[idx].taken, 1, 0 ) )\r
+               {\r
+                       continue;\r
+               }\r
+\r
+               p_slot = &g_pm_stat.p_shmem->obj[idx];\r
+\r
+               /* Copy the app name. */\r
+               CopyMemory( p_slot->app_name, buf, name_len * sizeof(WCHAR) );\r
+               CopyMemory( &p_slot->app_name[name_len], id_str,\r
+                       (wcslen( id_str ) + 1) * sizeof(WCHAR) );\r
+\r
+               g_pm_stat.idx = idx;\r
+               g_pm_stat.pdata = g_pm_stat.p_shmem->obj[idx].data;\r
+               IBSP_TRACE2( IBSP_DBG_PERFMON,\r
+                       ("%S got slot %d\n", p_slot->app_name, idx) );\r
+               break;\r
+       }\r
+       \r
+       if( idx == IBSP_PM_NUM_INSTANCES )\r
+       {\r
+               /*\r
+                * Assign "Total" slot for this process to avoid loosing precious\r
+                * statistic.  Keep saved idx INVALID so data won't be flushed during\r
+                * process closeout.\r
+                */\r
+               g_pm_stat.pdata = p_mem->obj[0].data;\r
+       }\r
+               \r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+}\r
+\r
+\r
+void\r
+IBSPPmReleaseSlot( void )\r
+{\r
+       mem_obj_t       *p_slot;\r
+       int                     idx;\r
+\r
+       /* perfmon never get registered itself in shared mem buffer */\r
+       if ( g_pm_stat.idx == INVALID_IDX )\r
+               return;\r
+\r
+       if( g_pm_stat.p_shmem == NULL )\r
+               return;\r
+\r
+       p_slot = &g_pm_stat.p_shmem->obj[g_pm_stat.idx];\r
+\r
+       /* Add all the data to the "Total" bin (0) */\r
+       for( idx = 0; idx < IBSP_PM_NUM_COUNTERS; idx++ )\r
+       {\r
+               InterlockedExchangeAdd64( &g_pm_stat.p_shmem->obj[0].data[idx],\r
+                       InterlockedExchange64( &g_pm_stat.pdata[idx], 0 ) );\r
+       }\r
+       ZeroMemory( p_slot->app_name, sizeof(p_slot->app_name) );\r
+       InterlockedExchange( &p_slot->taken, 0 );\r
+\r
+       g_pm_stat.idx = INVALID_IDX;\r
+\r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+}\r
+\r
+\r
+static BOOL\r
+__PmIsQuerySupported(\r
+       IN                              WCHAR*                                  p_query_str )\r
+{\r
+       if( p_query_str == NULL )\r
+               return TRUE;\r
+\r
+       if( *p_query_str == 0 )\r
+               return TRUE;\r
+\r
+       if( wcsstr( p_query_str, L"Global" ) != NULL )\r
+               return TRUE;\r
+\r
+       if( wcsstr( p_query_str, L"Foreign" ) != NULL )\r
+               return FALSE;\r
+\r
+       if( wcsstr( p_query_str, L"Costly" ) != NULL )\r
+               return FALSE;\r
+\r
+       else\r
+               return TRUE;\r
+}\r
+\r
+\r
+/*\r
+ * http://msdn.microsoft.com/library/en-us/perfctrs/perf/openperformancedata.asp\r
+ */\r
+DWORD APIENTRY\r
+IBSPPmOpen(\r
+       IN                              LPWSTR                                          lpDeviceNames )\r
+{\r
+       DWORD status = ERROR_SUCCESS;\r
+       HKEY  pm_hkey = NULL;\r
+       DWORD data_size;\r
+       DWORD data_type;\r
+       DWORD first_counter = 0;\r
+       DWORD first_help = 0;\r
+       int num         = 0;\r
+       int num_offset;\r
+\r
+       IBSP_ENTER( IBSP_DBG_PERFMON );\r
+\r
+       UNUSED_PARAM(lpDeviceNames);\r
+\r
+       if( g_pm_stat.threads++ )\r
+       {\r
+               IBSP_EXIT( IBSP_DBG_PERFMON );\r
+               return ERROR_SUCCESS;\r
+       }\r
+\r
+       /* open Registry and query for the first and last keys */\r
+       status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,\r
+               IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF,\r
+               0L, KEY_READ, &pm_hkey);\r
+\r
+       if( status != ERROR_SUCCESS )\r
+       {\r
+               g_pm_stat.threads--;\r
+               IBSP_ERROR_EXIT(\r
+                       ("RegOpenKeyEx for perf information returned %d.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       data_size = sizeof(DWORD);\r
+       status = RegQueryValueEx( pm_hkey, "First Counter", 0L,\r
+               &data_type, (LPBYTE)&first_counter, &data_size );\r
+\r
+       if( status != ERROR_SUCCESS )\r
+       {\r
+               RegCloseKey(pm_hkey);\r
+               g_pm_stat.threads--;\r
+               IBSP_ERROR_EXIT(\r
+                       ("RegQueryValueEx for \"First Counter\" returned %d.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       data_size = sizeof(DWORD);\r
+       status = RegQueryValueEx( pm_hkey, "First Help", 0L,\r
+               &data_type, (LPBYTE)&first_help, &data_size );\r
+\r
+       RegCloseKey( pm_hkey );\r
+\r
+       if( status != ERROR_SUCCESS )\r
+       {\r
+               g_pm_stat.threads--;\r
+               IBSP_ERROR_EXIT(\r
+                       ("RegQueryValueEx for \"First Help\" returned %d.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       /* perf_obj */          \r
+       g_ibsp_pm_def.perf_obj.ObjectNameTitleIndex  = IBSP_PM_OBJ + first_counter;\r
+       g_ibsp_pm_def.perf_obj.ObjectHelpTitleIndex  = IBSP_PM_OBJ + first_help;\r
+       g_ibsp_pm_def.perf_obj.TotalByteLength  =\r
+               sizeof(ibsp_pm_definition_t) + sizeof(ibsp_pm_counters_t);\r
+       g_ibsp_pm_def.perf_obj.DefinitionLength = sizeof(ibsp_pm_definition_t);\r
+       g_ibsp_pm_def.perf_obj.HeaderLength     = sizeof(PERF_OBJECT_TYPE);\r
+\r
+       g_ibsp_pm_def.perf_obj.ObjectNameTitle = 0;\r
+       g_ibsp_pm_def.perf_obj.ObjectHelpTitle = 0;\r
+\r
+       g_ibsp_pm_def.perf_obj.DetailLevel = PERF_DETAIL_NOVICE;\r
+       g_ibsp_pm_def.perf_obj.NumCounters = IBSP_PM_NUM_COUNTERS;\r
+       g_ibsp_pm_def.perf_obj.DefaultCounter = 0;\r
+       g_ibsp_pm_def.perf_obj.NumInstances = 0;\r
+       g_ibsp_pm_def.perf_obj.CodePage = 0;\r
+\r
+       QueryPerformanceFrequency( &g_ibsp_pm_def.perf_obj.PerfFreq );\r
+\r
+       /* initialize all counter definitions */\r
+       num_offset = IBSP_PM_OBJ + 2;\r
+       for ( num = 0; num <  IBSP_PM_NUM_COUNTERS ; num++, num_offset += 2)\r
+       {\r
+               g_ibsp_pm_def.counter[num].CounterNameTitleIndex = num_offset + first_counter;\r
+               g_ibsp_pm_def.counter[num].CounterHelpTitleIndex = num_offset + first_help;\r
+               g_ibsp_pm_def.counter[num].ByteLength = sizeof(PERF_COUNTER_DEFINITION);\r
+               g_ibsp_pm_def.counter[num].CounterNameTitle = 0;\r
+               g_ibsp_pm_def.counter[num].CounterHelpTitle = 0;\r
+               g_ibsp_pm_def.counter[num].DefaultScale = 0;\r
+               g_ibsp_pm_def.counter[num].DetailLevel = PERF_DETAIL_NOVICE;\r
+               g_ibsp_pm_def.counter[num].CounterType = PERF_COUNTER_BULK_COUNT;\r
+               /* All counters should be kept to 64-bits for consistency and simplicity. */\r
+               g_ibsp_pm_def.counter[num].CounterSize = sizeof(LONG64);\r
+               g_ibsp_pm_def.counter[num].CounterOffset =\r
+                       (DWORD)offsetof( ibsp_pm_counters_t, data[num] );\r
+       }\r
+\r
+       g_pm_stat.h_evlog = RegisterEventSource( NULL, IBSP_PM_SUBKEY_NAME );\r
+       if( !g_pm_stat.h_evlog )\r
+       {\r
+               g_pm_stat.threads--;\r
+               status = GetLastError();\r
+               IBSP_ERROR_EXIT( ("RegisterEventSource failed with %d\n", status) );\r
+               return status;\r
+       }\r
+\r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+       return ERROR_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * http://msdn.microsoft.com/library/en-us/perfctrs/perf/closeperformancedata.asp\r
+ */\r
+DWORD APIENTRY\r
+IBSPPmClose( void )\r
+{\r
+       BOOL status;\r
+\r
+       IBSP_ENTER( IBSP_DBG_PERFMON );\r
+\r
+       if( --g_pm_stat.threads )\r
+       {\r
+               IBSP_EXIT( IBSP_DBG_PERFMON );\r
+               return ERROR_SUCCESS;\r
+       }\r
+\r
+       IBSPPmReleaseSlot();\r
+\r
+       /* avoid double closing */\r
+       if( g_pm_stat.p_shmem != NULL )\r
+       {\r
+               status = UnmapViewOfFile( g_pm_stat.p_shmem );\r
+               g_pm_stat.p_shmem = NULL;\r
+       }\r
+       \r
+       if( g_pm_stat.h_evlog != NULL )\r
+       {\r
+               DeregisterEventSource( g_pm_stat.h_evlog );\r
+               g_pm_stat.h_evlog = NULL;\r
+       }\r
+\r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+       return ERROR_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * http://msdn.microsoft.com/library/en-us/perfctrs/perf/collectperformancedata.asp\r
+ */\r
+DWORD WINAPI\r
+IBSPPmCollectData(\r
+       IN                              LPWSTR                                          lpValueName,\r
+       IN      OUT                     LPVOID*                                         lppData,\r
+       IN      OUT                     LPDWORD                                         lpcbTotalBytes,\r
+       IN      OUT                     LPDWORD                                         lpNumObjectTypes )\r
+{\r
+       int32_t                                         sh_num;\r
+       int32_t                                         num_instances, max_instances;\r
+       uint32_t                                        use_bytes;\r
+       ibsp_pm_definition_t            *p_obj_def;\r
+       ibsp_pm_counters_t                      *p_count_def;\r
+       PERF_INSTANCE_DEFINITION        *p_inst_def;\r
+       pm_shmem_t                                      *p_mem;\r
+       LONG64                                          total_data[IBSP_PM_NUM_COUNTERS];\r
+       \r
+       IBSP_ENTER( IBSP_DBG_PERFMON );\r
+\r
+       p_mem = (pm_shmem_t * __ptr64 )g_pm_stat.p_shmem;\r
+       \r
+       if( p_mem == NULL )\r
+       {\r
+               IBSP_ERROR( ("No shared memory object\n") );\r
+               goto done;\r
+       }\r
+\r
+       if( !__PmIsQuerySupported(lpValueName ) )\r
+       {\r
+               IBSP_TRACE1( IBSP_DBG_PERFMON, ("Unsupported query\n") );\r
+               goto done;\r
+       }\r
+\r
+       if( !g_pm_stat.threads )\r
+       {\r
+               IBSP_ERROR( ("Initialization was not completed\n") );\r
+done:\r
+               *lpcbTotalBytes   = 0;\r
+               *lpNumObjectTypes = 0;\r
+\r
+               IBSP_EXIT( IBSP_DBG_PERFMON );\r
+               return ERROR_SUCCESS;\r
+       }\r
+\r
+       ZeroMemory( &total_data, sizeof(total_data) );\r
+       num_instances = 0;\r
+       /* sum total counters that were not filled in completion routine */\r
+       for( sh_num = 0; sh_num < IBSP_PM_NUM_INSTANCES; sh_num++ )\r
+       {\r
+               if( !InterlockedCompareExchange( &p_mem->obj[sh_num].taken, 1, 1 ) )\r
+                       continue;\r
+\r
+               total_data[BYTES_SEND] += p_mem->obj[sh_num].data[BYTES_SEND];\r
+               total_data[BYTES_RECV] += p_mem->obj[sh_num].data[BYTES_RECV];\r
+               total_data[BYTES_WRITE] += p_mem->obj[sh_num].data[BYTES_WRITE];\r
+               total_data[BYTES_READ] += p_mem->obj[sh_num].data[BYTES_READ];\r
+               /* Update total for current slot. */\r
+               p_mem->obj[sh_num].data[BYTES_TOTAL] =\r
+                       p_mem->obj[sh_num].data[BYTES_SEND] +\r
+                       p_mem->obj[sh_num].data[BYTES_RECV] +\r
+                       p_mem->obj[sh_num].data[BYTES_WRITE] +\r
+                       p_mem->obj[sh_num].data[BYTES_READ];\r
+               total_data[BYTES_TOTAL] += p_mem->obj[sh_num].data[BYTES_TOTAL];\r
+               total_data[COMP_SEND] += p_mem->obj[sh_num].data[COMP_SEND];\r
+               total_data[COMP_RECV] += p_mem->obj[sh_num].data[COMP_RECV];\r
+               total_data[COMP_TOTAL] += p_mem->obj[sh_num].data[COMP_TOTAL];\r
+               total_data[INTR_TOTAL] += p_mem->obj[sh_num].data[INTR_TOTAL];\r
+\r
+               num_instances++;\r
+       }\r
+\r
+       IBSP_TRACE1( IBSP_DBG_PERFMON, ("%d instances.\n", num_instances) );\r
+\r
+       /* calc buffer size required for data return */\r
+       use_bytes = sizeof(ibsp_pm_definition_t) + \\r
+                               (sizeof(PERF_INSTANCE_DEFINITION) + \\r
+                               sizeof(ibsp_pm_counters_t) + \\r
+                               (sizeof(WCHAR) * IBSP_PM_APP_NAME_SIZE)) * num_instances;\r
+\r
+       if( *lpcbTotalBytes < use_bytes )\r
+       {\r
+               *lpcbTotalBytes   = 0;\r
+               *lpNumObjectTypes = 0;\r
+               return ERROR_MORE_DATA;\r
+       }\r
+\r
+       p_obj_def = (ibsp_pm_definition_t*)*lppData;\r
+       use_bytes = sizeof(ibsp_pm_definition_t);\r
+\r
+       /* Copy counter definition */\r
+       CopyMemory( p_obj_def, &g_ibsp_pm_def, sizeof(ibsp_pm_definition_t) );\r
+\r
+       p_obj_def->perf_obj.NumInstances = num_instances;\r
+       QueryPerformanceCounter( &p_obj_def->perf_obj.PerfTime );\r
+\r
+       max_instances = num_instances;\r
+\r
+       /* Assign pointers for the first instance */\r
+       p_inst_def = (PERF_INSTANCE_DEFINITION*)(p_obj_def + 1);\r
+\r
+       for( sh_num = 0; sh_num < IBSP_PM_NUM_INSTANCES; sh_num++ )\r
+       {\r
+               if( !InterlockedCompareExchange( &p_mem->obj[sh_num].taken, 1, 1 ) )\r
+                       continue;\r
+\r
+               /* Make sure we don't overrun the buffer! */\r
+               if( max_instances-- == 0 )\r
+                       break;\r
+\r
+               p_inst_def->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) + \r
+                       (sizeof(WCHAR) * IBSP_PM_APP_NAME_SIZE);\r
+               p_inst_def->ParentObjectTitleIndex = 0;\r
+               p_inst_def->ParentObjectInstance = 0;\r
+               p_inst_def->UniqueID = -1;  /* using module names */\r
+               p_inst_def->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);\r
+\r
+               /* Length in bytes of Unicode name string, including terminating NULL */\r
+               p_inst_def->NameLength =\r
+                       (DWORD)wcslen( p_mem->obj[sh_num].app_name ) + 1;\r
+               p_inst_def->NameLength *= sizeof(WCHAR);\r
+\r
+               CopyMemory( (WCHAR*)(p_inst_def + 1),\r
+                       p_mem->obj[sh_num].app_name, p_inst_def->NameLength );\r
+\r
+               use_bytes += p_inst_def->ByteLength;\r
+\r
+               /* advance to counter definition */\r
+               p_count_def = (ibsp_pm_counters_t*)\r
+                       (((BYTE*)p_inst_def) + p_inst_def->ByteLength);\r
+\r
+               p_count_def->pm_block.ByteLength = sizeof(ibsp_pm_counters_t);\r
+               use_bytes += sizeof(ibsp_pm_counters_t);\r
+\r
+               /* Here we report actual counter values. */\r
+               if( sh_num == 0 )\r
+               {\r
+                       CopyMemory( p_count_def->data, total_data, sizeof(total_data) );\r
+               }\r
+               else\r
+               {\r
+                       CopyMemory( p_count_def->data, p_mem->obj[sh_num].data,\r
+                               sizeof(p_mem->obj[sh_num].data) );\r
+               }\r
+\r
+               /* Advance pointers for the next instance definition */\r
+               p_inst_def = (PERF_INSTANCE_DEFINITION*)(p_count_def + 1);\r
+       }\r
+\r
+       p_obj_def->perf_obj.TotalByteLength = (DWORD)use_bytes;\r
+\r
+       *lppData = ((BYTE*)*lppData) + use_bytes;\r
+       *lpNumObjectTypes = 1;\r
+       *lpcbTotalBytes = (DWORD)use_bytes;\r
+\r
+       IBSP_EXIT( IBSP_DBG_PERFMON );\r
+       return ERROR_SUCCESS;\r
+}\r
diff --git a/ulp/wsd/user/ibsp_perfmon.h b/ulp/wsd/user/ibsp_perfmon.h
new file mode 100644 (file)
index 0000000..03afb53
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+#ifndef _IBSP_PERFMON_H_\r
+#define _IBSP_PERFMON_H_\r
+\r
+\r
+#include <sddl.h>\r
+#include <winperf.h>\r
+#include "wsd/ibsp_regpath.h"\r
+\r
+\r
+/* invalid instance index value to initialize */\r
+#define INVALID_IDX                    0xffffffff\r
+\r
+#define IBSP_PM_SEC_STRING \\r
+       TEXT("D:(A;CIOI;GAFA;;;SY)"             /* SDDL_LOCAL_SYSTEM */ \\r
+                       "(A;CIOI;GAFA;;;DA)"    /* SDDL_DOMAIN_ADMIN */ \\r
+                       "(A;CIOI;GAFA;;;BA)"    /* SDDL_BUILTIN_ADMIN */ \\r
+                       "(A;CIOI;GAFA;;;NS)"    /* SDDL_NETWORK_SERVICE */ \\r
+                       "(A;CIOI;GAFA;;;LS)"    /* SDDL_LOCAL_SERVICE */ \\r
+                       "(A;CIOI;GAFA;;;SU)"    /* SDDL_SERVICE */ \\r
+                       "(A;CIOI;GAFA;;;MU)"    /* SDDL_PERFMON_USERS */ \\r
+                       "(A;CIOI;GAFA;;;LU)")   /* SDDL_PERFLOG_USERS */\r
+\r
+#define IBSP_PM_NUM_OBJECT_TYPES       1\r
+#define IBSP_PM_NUM_INSTANCES          100     /* how many processes we can handle */\r
+\r
+#define IBSP_PM_APP_NAME_SIZE          24      /* Must be multiple of 8 */\r
+#define IBSP_PM_TOTAL_COUNTER_NAME     L"_Total"\r
+#define IBSP_PM_MAPPED_OBJ_NAME                TEXT("Global\\ibwsd_perfmon_data")\r
+\r
+\r
+/* Structures used to report counter information to perfmon. */\r
+typedef struct _ibsp_pm_definition\r
+{\r
+       PERF_OBJECT_TYPE                        perf_obj;\r
+       PERF_COUNTER_DEFINITION         counter[IBSP_PM_NUM_COUNTERS];\r
+\r
+}      ibsp_pm_definition_t;\r
+\r
+typedef struct _ibsp_pm_counters\r
+{\r
+       PERF_COUNTER_BLOCK      pm_block;\r
+       LONG64                          data[IBSP_PM_NUM_COUNTERS];\r
+\r
+}      ibsp_pm_counters_t;\r
+\r
+\r
+/* Structures used to manage counters internally */\r
+typedef struct _mem_obj\r
+{\r
+       volatile LONG   taken;\r
+       WCHAR                   app_name[IBSP_PM_APP_NAME_SIZE];\r
+       LONG64                  data[IBSP_PM_NUM_COUNTERS];\r
+\r
+}      mem_obj_t;\r
+\r
+typedef struct _pm_shmem\r
+{\r
+       mem_obj_t               obj[IBSP_PM_NUM_INSTANCES];\r
+\r
+}      pm_shmem_t;\r
+\r
+\r
+/* global data for every process linked to this DLL */\r
+struct _pm_stat\r
+{\r
+       struct _pm_shmem*               p_shmem;                /* base pointer to shared memory for this process */\r
+       volatile LONG64*                pdata;                  /* pointer to data collected */\r
+       HANDLE                                  h_mapping;\r
+       HANDLE                                  h_evlog;                /* event log handle */\r
+       DWORD                                   threads;                /* number of threads open */\r
+       DWORD                                   idx;                    /* slot index assigned for this process */\r
+       LONG64                                  fall_back_data[IBSP_PM_NUM_COUNTERS];\r
+\r
+}      g_pm_stat;\r
+\r
+\r
+void\r
+IBSPPmInit( void );\r
+\r
+DWORD APIENTRY\r
+IBSPPmClose( void );\r
+\r
+void\r
+IBSPPmGetSlot( void );\r
+\r
+void\r
+IBSPPmReleaseSlot( void );\r
+\r
+#endif /* _IBSP_PERFMON_H_ */\r
index 5fed257..2b02051 100644 (file)
@@ -49,6 +49,7 @@ extern uint32_t gdbg_lvl;
 #define IBSP_DBG_HW                    0x00000800      /* Hardware */\r
 #define IBSP_DBG_IO                    0x00001000      /* Overlapped I/O request */\r
 #define IBSP_DBG_DUP           0x00002000      /* Socket Duplication */\r
+#define IBSP_DBG_PERFMON       0x00004000      /* Performance Monitoring */\r
 \r
 #define IBSP_DBG_LEVEL4                0x01000000      /* debug use */\r
 #define IBSP_DBG_LEVEL3                0x02000000      /* debug use */\r
index 177b735..08bf8a1 100644 (file)
  *\r
  * $Id$\r
  */\r
-\r
 #include <tchar.h>\r
 #include <stdlib.h>\r
 #include "ibspdll.h"\r
 \r
+#ifdef PERFMON_ENABLED\r
+#include "ibsp_perfmon.h"\r
+#endif /* PERFMON_ENABLED */\r
+\r
 /* Globals */\r
 struct ibspdll_globals g_ibsp;\r
 \r
@@ -50,6 +53,7 @@ static DWORD  no_read = 0;
 uint32_t               g_max_inline = 0xFFFFFFFF;\r
 uint32_t               g_max_poll = 0;\r
 \r
+\r
 /*\r
  * Function: DllMain\r
  * \r
@@ -118,6 +122,10 @@ _DllMain(
 \r
                if( init_globals() )\r
                        return FALSE;\r
+\r
+#ifdef PERFMON_ENABLED\r
+               IBSPPmInit();\r
+#endif\r
                break;\r
 \r
        case DLL_THREAD_ATTACH:\r
@@ -187,6 +195,9 @@ _DllMain(
                }\r
 #endif\r
                release_globals();\r
+#ifdef PERFMON_ENABLED\r
+               IBSPPmClose();\r
+#endif\r
                break;\r
        }\r
 \r
@@ -2107,6 +2118,10 @@ IBSPCleanup(
        {\r
                IBSP_TRACE( IBSP_DBG_INIT, ("entry_count is 0 => cleaning up\n") );\r
                ib_release();\r
+\r
+#ifdef PERFMON_ENABLED\r
+               IBSPPmReleaseSlot();\r
+#endif\r
        }\r
 \r
        cl_spinlock_release( &g_ibsp.mutex );\r
@@ -2215,5 +2230,12 @@ WSPStartupEx(
 \r
        IBSP_EXIT( IBSP_DBG_INIT );\r
 \r
+#ifdef PERFMON_ENABLED\r
+       /* Socket application register with perfmon */\r
+       IBSPPmGetSlot();\r
+#endif /* PERFMON_ENABLED */\r
+\r
        return 0;\r
 }\r
+\r
+\r
index dcb7a83..8932928 100644 (file)
@@ -1,3 +1,6 @@
 LIBRARY        ibwsd\r
-EXPORTS   \r
+EXPORTS\r
 WSPStartupEx\r
+IBSPPmOpen\r
+IBSPPmCollectData\r
+IBSPPmClose\r
diff --git a/ulp/wsd/user/ibspdll.sln b/ulp/wsd/user/ibspdll.sln
deleted file mode 100644 (file)
index f80e956..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 8.00\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ibspdll", "ibspdll.vcproj", "{414811DF-737C-43C0-BF6C-3D5B4EF416A9}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstallSP", "..\InstallSP\InstallSP.vcproj", "{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1", "..\unittest\test1\test1.vcproj", "{4FE83165-7E2D-4375-906B-0D2927DC4F8A}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ttcp", "..\unittest\ttcp\ttcp.vcproj", "{BB697350-4EF7-45AD-A25D-8411E21E516D}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test2", "..\unittest\test2\test2.vcproj", "{FAE22AE2-151A-4C26-A598-8440B3603DA7}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test3", "..\unittest\test3\test3.vcproj", "{8C3B680E-31D3-4A1C-AF19-51A17A50C439}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "contest", "..\unittest\contest\contest.vcproj", "{FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockdupc", "..\..\..\..\..\Program Files\Microsoft SDK\Samples\netds\WinSock\Sockdup\sockdupc.vcproj", "{45F064C2-606E-494C-9961-A0BDF7BC7D78}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockdups", "..\..\..\..\..\Program Files\Microsoft SDK\Samples\netds\WinSock\Sockdup\sockdups.vcproj", "{45F064C2-606E-494C-9961-A0BDF7BC7D78}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-       EndProjectSection\r
-EndProject\r
-Global\r
-       GlobalSection(SolutionConfiguration) = preSolution\r
-               Debug = Debug\r
-               Pre32_RETAIL = Pre32_RETAIL\r
-               Release = Release\r
-       EndGlobalSection\r
-       GlobalSection(ProjectConfiguration) = postSolution\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Debug.ActiveCfg = Debug|Win32\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Debug.Build.0 = Debug|Win32\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Release.ActiveCfg = Release|Win32\r
-               {414811DF-737C-43C0-BF6C-3D5B4EF416A9}.Release.Build.0 = Release|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Debug.ActiveCfg = Debug|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Debug.Build.0 = Debug|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Release.ActiveCfg = Release|Win32\r
-               {B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Release.Build.0 = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Debug.ActiveCfg = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Debug.Build.0 = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Release.ActiveCfg = Release|Win32\r
-               {4FE83165-7E2D-4375-906B-0D2927DC4F8A}.Release.Build.0 = Release|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Debug.ActiveCfg = Debug|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Debug.Build.0 = Debug|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Release.ActiveCfg = Release|Win32\r
-               {BB697350-4EF7-45AD-A25D-8411E21E516D}.Release.Build.0 = Release|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Debug.ActiveCfg = Debug|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Debug.Build.0 = Debug|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Release.ActiveCfg = Release|Win32\r
-               {FAE22AE2-151A-4C26-A598-8440B3603DA7}.Release.Build.0 = Release|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Debug.ActiveCfg = Debug|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Debug.Build.0 = Debug|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Release.ActiveCfg = Release|Win32\r
-               {8C3B680E-31D3-4A1C-AF19-51A17A50C439}.Release.Build.0 = Release|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Debug.ActiveCfg = Debug|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Debug.Build.0 = Debug|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Pre32_RETAIL.ActiveCfg = Release|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Pre32_RETAIL.Build.0 = Release|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Release.ActiveCfg = Debug|Win32\r
-               {FE720CBD-A6BD-493C-9A65-F18B1ABE3DEC}.Release.Build.0 = Debug|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Debug.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Debug.Build.0 = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Pre32_RETAIL.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Pre32_RETAIL.Build.0 = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Release.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Release.Build.0 = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Debug.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Debug.Build.0 = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Pre32_RETAIL.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Pre32_RETAIL.Build.0 = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Release.ActiveCfg = Pre32_RETAIL|Win32\r
-               {45F064C2-606E-494C-9961-A0BDF7BC7D78}.Release.Build.0 = Pre32_RETAIL|Win32\r
-       EndGlobalSection\r
-       GlobalSection(ExtensibilityGlobals) = postSolution\r
-       EndGlobalSection\r
-       GlobalSection(ExtensibilityAddIns) = postSolution\r
-       EndGlobalSection\r
-EndGlobal\r