diff --git a/ChangeLog b/ChangeLog index f864b07f..982a1d0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-09-08 Doug MacEachern + + * [SIGAR-13] Use EnumProcesses for sigar_proc_list_get on Win32 + 2006-09-07 Doug MacEachern * [SIGAR-14] Fix sigar_cpu_t.total on Linux and Solaris with multi-core CPUs diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index c33bfca3..78b0b2ec 100644 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -372,6 +372,10 @@ typedef DWORD (CALLBACK *psapi_get_module_name)(HANDLE, LPTSTR, DWORD); +typedef BOOL (CALLBACK *psapi_enum_processes)(DWORD *, + DWORD, + DWORD *); + /* winsta.dll */ typedef BOOLEAN (CALLBACK *winsta_query_info)(HANDLE, ULONG, @@ -436,6 +440,7 @@ typedef struct { sigar_dll_handle_t handle; SIGAR_DLLFUNC(psapi, enum_modules); + SIGAR_DLLFUNC(psapi, enum_processes); SIGAR_DLLFUNC(psapi, get_module_name); sigar_dll_func_t end; diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index 459a1c4c..610c374d 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -110,6 +110,26 @@ typedef enum { #define PERF_VAL_CPU(ix) \ NS100_2SEC(PERF_VAL(ix)) +static DWORD perfbuf_init(sigar_t *sigar) +{ + if (!sigar->perfbuf) { + sigar->perfbuf = malloc(PERFBUF_SIZE); + sigar->perfbuf_size = PERFBUF_SIZE; + } + + return sigar->perfbuf_size; +} + +static DWORD perfbuf_grow(sigar_t *sigar) +{ + sigar->perfbuf_size += PERFBUF_SIZE; + + sigar->perfbuf = + realloc(sigar->perfbuf, sigar->perfbuf_size); + + return sigar->perfbuf_size; +} + static PERF_OBJECT_TYPE *get_perf_object(sigar_t *sigar, char *counter_key, DWORD *err) { @@ -120,22 +140,15 @@ static PERF_OBJECT_TYPE *get_perf_object(sigar_t *sigar, char *counter_key, *err = SIGAR_OK; - if (!sigar->perfbuf) { - sigar->perfbuf = malloc(PERFBUF_SIZE); - sigar->perfbuf_size = PERFBUF_SIZE; - } - if (USING_WIDE()) { SIGAR_A2W(counter_key, wcounter_key, sizeof(wcounter_key)); } - bytes = sigar->perfbuf_size; + bytes = perfbuf_init(sigar); + while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) { if (retval == ERROR_MORE_DATA) { - sigar->perfbuf_size += PERFBUF_SIZE; - bytes = sigar->perfbuf_size; - sigar->perfbuf = - realloc(sigar->perfbuf, sigar->perfbuf_size); + bytes = perfbuf_grow(sigar); } else { *err = retval; @@ -230,6 +243,7 @@ static sigar_psapi_t sigar_psapi = { "psapi.dll", NULL, { "EnumProcessModules", NULL }, + { "EnumProcesses", NULL }, { "GetModuleFileNameExA", NULL }, { NULL, NULL } }; @@ -798,9 +812,10 @@ SIGAR_DECLARE(int) sigar_loadavg_get(sigar_t *sigar, #define get_process_object(sigar, err) \ get_perf_object(sigar, PERF_TITLE_PROC_KEY, err) -SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, - sigar_proc_list_t *proclist) +static int sigar_proc_list_get_perf(sigar_t *sigar, + sigar_proc_list_t *proclist) { + PERF_OBJECT_TYPE *object; PERF_INSTANCE_DEFINITION *inst; PERF_COUNTER_DEFINITION *counter; @@ -857,6 +872,57 @@ SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, return SIGAR_OK; } +#define sigar_EnumProcesses \ + sigar->psapi.enum_processes.func + +SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, + sigar_proc_list_t *proclist) +{ + DLLMOD_INIT(psapi, FALSE); + + if (sigar_EnumProcesses) { + DWORD retval, *pids; + DWORD size = 0, i; + + do { + /* re-use the perfbuf */ + if (size == 0) { + size = perfbuf_init(sigar); + } + else { + size = perfbuf_grow(sigar); + } + + if (!sigar_EnumProcesses((DWORD *)sigar->perfbuf, + sigar->perfbuf_size, + &retval)) + { + return GetLastError(); + } + } while (retval == sigar->perfbuf_size); //unlikely + + pids = (DWORD *)sigar->perfbuf; + + proclist->number = 0; + proclist->size = retval / sizeof(DWORD); + proclist->data = + malloc(sizeof(*(proclist->data)) * proclist->size); + + for (i=0; isize; i++) { + DWORD pid = pids[i]; + if (pid == 0) { + continue; /* dont include the system Idle process */ + } + proclist->data[proclist->number++] = pid; + } + + return SIGAR_OK; + } + else { + return sigar_proc_list_get_perf(sigar, proclist); + } +} + SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar, sigar_proc_stat_t *procstat) {