Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v2: Properly align variables (thanks Alexandre); adjust variable names a bit.
This decreases CPU usage by wineserver from about 65% to about 45% for me in Street Fighter V, which for some reason calls this 15-20 times per second.
dlls/ntdll/unix/system.c | 182 +++++++++++++++++---------------------- server/process.c | 68 +++++++++++++++ server/protocol.def | 30 +++++++ server/trace.c | 39 +++++++++ 4 files changed, 215 insertions(+), 104 deletions(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 7045bc1550b..3a53a764d03 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -1998,6 +1998,11 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) RtlLeaveCriticalSection( &TIME_tz_section ); }
+static unsigned int align_offset(unsigned int offset, unsigned int alignment) +{ + return (offset + (alignment - 1)) & ~(alignment - 1); +} +
/****************************************************************************** * NtQuerySystemInformation (NTDLL.@) @@ -2083,132 +2088,101 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
case SystemProcessInformation: { - SYSTEM_PROCESS_INFORMATION *spi = info; - SYSTEM_PROCESS_INFORMATION *last = NULL; - HANDLE handle = 0; - WCHAR procname[1024]; - WCHAR* exename; - DWORD wlen = 0; - DWORD procstructlen = 0; + unsigned int process_count, i, j; + char *buffer = NULL; + unsigned int pos = 0;
- SERVER_START_REQ( create_snapshot ) + if (size && !(buffer = RtlAllocateHeap( GetProcessHeap(), 0, size ))) { - req->flags = SNAP_PROCESS | SNAP_THREAD; - if (!(ret = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle ); + ret = STATUS_NO_MEMORY; + break; } - SERVER_END_REQ;
- len = 0; - while (ret == STATUS_SUCCESS) + SERVER_START_REQ( list_processes ) { - int unix_pid = -1; - SERVER_START_REQ( next_process ) - { - req->handle = wine_server_obj_handle( handle ); - req->reset = (len == 0); - wine_server_set_reply( req, procname, sizeof(procname) - sizeof(WCHAR) ); - if (!(ret = wine_server_call( req ))) - { - unix_pid = reply->unix_pid; - - /* Make sure procname is 0 terminated */ - procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0; - - /* Get only the executable name, not the path */ - if ((exename = wcsrchr(procname, '\')) != NULL) exename++; - else exename = procname; + wine_server_set_reply( req, buffer, size ); + ret = wine_server_call( req ); + len = reply->info_size; + process_count = reply->process_count; + } + SERVER_END_REQ;
- wlen = (wcslen(exename) + 1) * sizeof(WCHAR); - procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION)); + if (ret) + { + RtlFreeHeap( GetProcessHeap(), 0, buffer ); + break; + }
- if (size >= len + procstructlen) - { - /* ftCreationTime, ftUserTime, ftKernelTime; - * vmCounters, ioCounters - */ - memset(spi, 0, sizeof(*spi)); + len = 0;
- spi->NextEntryOffset = procstructlen - wlen; - spi->dwThreadCount = reply->threads; + for (i = 0; i < process_count; i++) + { + SYSTEM_PROCESS_INFORMATION *nt_process = (SYSTEM_PROCESS_INFORMATION *)((char *)info + len); + const struct process_info *server_process; + const WCHAR *server_name, *file_part; + ULONG proc_len; + ULONG name_len = 0;
- /* spi->pszProcessName will be set later on */ + pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) ); + server_process = (const struct process_info *)(buffer + pos); + pos += sizeof(*server_process);
- spi->dwBasePriority = reply->priority; - spi->UniqueProcessId = UlongToHandle(reply->pid); - spi->ParentProcessId = UlongToHandle(reply->ppid); - spi->HandleCount = reply->handles; + server_name = (const WCHAR *)(buffer + pos); + file_part = server_name + (server_process->name_len / sizeof(WCHAR)); + pos += server_process->name_len; + while (file_part > server_name && file_part[-1] != '\') + { + file_part--; + name_len++; + }
- /* spi->ti will be set later on */ + proc_len = sizeof(*nt_process) + server_process->thread_count * sizeof(SYSTEM_THREAD_INFORMATION) + + (name_len + 1) * sizeof(WCHAR); + len += proc_len;
- } - len += procstructlen; - } - } - SERVER_END_REQ; - if (ret != STATUS_SUCCESS) + if (len <= size) { - if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS; - break; + memset(nt_process, 0, sizeof(*nt_process)); + if (i < process_count - 1) + nt_process->NextEntryOffset = proc_len; + nt_process->dwThreadCount = server_process->thread_count; + nt_process->dwBasePriority = server_process->priority; + nt_process->UniqueProcessId = UlongToHandle(server_process->pid); + nt_process->ParentProcessId = UlongToHandle(server_process->parent_pid); + nt_process->HandleCount = server_process->handle_count; + get_thread_times( server_process->unix_pid, -1, &nt_process->KernelTime, &nt_process->UserTime ); }
- if (size >= len) + pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) ); + for (j = 0; j < server_process->thread_count; j++) { - int i, j; + const struct thread_info *server_thread = (const struct thread_info *)(buffer + pos);
- get_thread_times(unix_pid, -1, &spi->KernelTime, &spi->UserTime); - - /* set thread info */ - i = j = 0; - while (ret == STATUS_SUCCESS) + if (len <= size) { - int unix_tid, pid, tid, base_pri, delta_pri; - SERVER_START_REQ( next_thread ) - { - req->handle = wine_server_obj_handle( handle ); - req->reset = (j == 0); - if (!(ret = wine_server_call( req ))) - { - unix_tid = reply->unix_tid; - pid = reply->pid; - tid = reply->tid; - base_pri = reply->base_pri; - delta_pri = reply->delta_pri; - j++; - } - } - SERVER_END_REQ; - - if (!ret) - { - if (UlongToHandle(pid) == spi->UniqueProcessId) - { - memset(&spi->ti[i], 0, sizeof(spi->ti)); - - spi->ti[i].CreateTime.QuadPart = 0xdeadbeef; - spi->ti[i].ClientId.UniqueProcess = UlongToHandle(pid); - spi->ti[i].ClientId.UniqueThread = UlongToHandle(tid); - spi->ti[i].dwCurrentPriority = base_pri + delta_pri; - spi->ti[i].dwBasePriority = base_pri; - get_thread_times(unix_pid, unix_tid, &spi->ti[i].KernelTime, &spi->ti[i].UserTime); - i++; - } - } + nt_process->ti[j].CreateTime.QuadPart = 0xdeadbeef; + nt_process->ti[j].ClientId.UniqueProcess = UlongToHandle(server_process->pid); + nt_process->ti[j].ClientId.UniqueThread = UlongToHandle(server_thread->tid); + nt_process->ti[j].dwCurrentPriority = server_thread->current_priority; + nt_process->ti[j].dwBasePriority = server_thread->base_priority; + get_thread_times( server_process->unix_pid, server_thread->unix_tid, + &nt_process->ti[j].KernelTime, &nt_process->ti[j].UserTime ); } - if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS; - - /* now append process name */ - spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->NextEntryOffset); - spi->ProcessName.Length = wlen - sizeof(WCHAR); - spi->ProcessName.MaximumLength = wlen; - memcpy( spi->ProcessName.Buffer, exename, wlen ); - spi->NextEntryOffset += wlen; - last = spi; - spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->NextEntryOffset); + + pos += sizeof(*server_thread); + } + + if (len <= size) + { + nt_process->ProcessName.Buffer = (WCHAR *)&nt_process->ti[server_process->thread_count]; + nt_process->ProcessName.Length = name_len * sizeof(WCHAR); + nt_process->ProcessName.MaximumLength = (name_len + 1) * sizeof(WCHAR); + memcpy(nt_process->ProcessName.Buffer, file_part, name_len * sizeof(WCHAR)); + nt_process->ProcessName.Buffer[name_len] = 0; } } - if (ret == STATUS_SUCCESS && last) last->NextEntryOffset = 0; + if (len > size) ret = STATUS_INFO_LENGTH_MISMATCH; - if (handle) NtClose( handle ); break; }
diff --git a/server/process.c b/server/process.c index 283edc09c5e..6b9557ceb60 100644 --- a/server/process.c +++ b/server/process.c @@ -22,6 +22,7 @@ #include "wine/port.h"
#include <assert.h> +#include <errno.h> #include <limits.h> #include <signal.h> #include <string.h> @@ -1819,3 +1820,70 @@ DECL_HANDLER(resume_process) release_object( process ); } } + +static unsigned int align_offset(unsigned int offset, unsigned int alignment) +{ + return (offset + (alignment - 1)) & ~(alignment - 1); +} + +/* Get a list of processes and threads currently running */ +DECL_HANDLER(list_processes) +{ + struct process *process; + struct thread *thread; + unsigned int pos = 0; + char *buffer; + + reply->process_count = 0; + reply->info_size = 0; + + LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry ) + { + struct process_dll *exe = get_process_exe_module( process ); + reply->info_size = align_offset( reply->info_size, TYPE_ALIGNMENT(struct process_info) ); + reply->info_size += sizeof(struct process_info) + exe->namelen; + reply->info_size = align_offset( reply->info_size, TYPE_ALIGNMENT(struct thread_info) ); + reply->info_size += process->running_threads * sizeof(struct thread_info); + reply->process_count++; + } + + if (reply->info_size > get_reply_max_size()) + { + set_error( STATUS_INFO_LENGTH_MISMATCH ); + return; + } + + if (!(buffer = set_reply_data_size( reply->info_size ))) return; + + LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry ) + { + struct process_info *process_info; + struct process_dll *exe = get_process_exe_module( process ); + + pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) ); + process_info = (struct process_info *)(buffer + pos); + process_info->name_len = exe->namelen; + process_info->thread_count = process->running_threads; + process_info->priority = process->priority; + process_info->pid = process->id; + process_info->parent_pid = process->parent_id; + process_info->handle_count = get_handle_table_count(process); + process_info->unix_pid = process->unix_pid; + pos += sizeof(*process_info); + + memcpy( buffer + pos, exe->filename, exe->namelen ); + pos += exe->namelen; + + pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) ); + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) + { + struct thread_info *thread_info = (struct thread_info *)(buffer + pos); + + thread_info->tid = thread->id; + thread_info->base_priority = thread->priority; + thread_info->current_priority = thread->priority; /* FIXME */ + thread_info->unix_tid = thread->unix_tid; + pos += sizeof(*thread_info); + } + } +} diff --git a/server/protocol.def b/server/protocol.def index 6416306c0a1..2737cd6fddd 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1919,6 +1919,36 @@ enum char_info_mode @END
+struct thread_info +{ + thread_id_t tid; + int base_priority; + int current_priority; + int unix_tid; +}; + +struct process_info +{ + data_size_t name_len; + unsigned int thread_count; + int priority; + process_id_t pid; + process_id_t parent_pid; + unsigned int handle_count; + int unix_pid; + /* VARARG(name,unicode_str,name_len); */ + /* VARARG(threads,struct thread_info,thread_count); */ +}; + +/* Get a list of processes and threads currently running */ +@REQ(list_processes) +@REPLY + data_size_t info_size; + unsigned int process_count; + VARARG(data,process_info,info_size); +@END + + /* Wait for a debug event */ @REQ(wait_debug_event) int get_handle; /* should we alloc a handle for waiting? */ diff --git a/server/trace.c b/server/trace.c index 2fb5afd5ef1..d47e1260255 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1115,6 +1115,45 @@ static void dump_varargs_token_groups( const char *prefix, data_size_t size ) fputc( '}', stderr ); }
+static unsigned int align_offset(unsigned int offset, unsigned int alignment) +{ + return (offset + (alignment - 1)) & ~(alignment - 1); +} + +static void dump_varargs_process_info( const char *prefix, data_size_t size ) +{ + data_size_t pos = 0; + unsigned int i; + + fprintf( stderr,"%s{", prefix ); + + while (size - pos >= sizeof(struct process_info)) + { + const struct process_info *process = (const struct process_info *)((const char *)cur_data + pos); + pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) ); + fprintf( stderr, "[thread_count=%u,priority=%d,pid=%04x,parent_pid=%04x,handle_count=%08x,unix_pid=%d,", + process->thread_count, process->priority, process->pid, + process->parent_pid, process->handle_count, process->unix_pid ); + pos += sizeof(*process); + + pos = dump_inline_unicode_string( "name=L"", pos, process->name_len, size ); + + pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) ); + fprintf( stderr, "",threads={" ); + for (i = 0; i < process->thread_count; i++) + { + const struct thread_info *thread = (const struct thread_info *)((const char *)cur_data + pos); + if (size - pos < sizeof(*thread)) break; + fprintf( stderr, "[tid=%04x,base_priority=%d,current_priority=%d,unix_tid=%d],", + thread->tid, thread->base_priority, thread->current_priority, thread->unix_tid ); + pos += sizeof(*thread); + } + fprintf( stderr, "}," ); + } + + fputc( '}', stderr ); +} + static void dump_varargs_object_attributes( const char *prefix, data_size_t size ) { const struct object_attributes *objattr = cur_data;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/iphlpapi/ipstats.c | 90 ++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 36 deletions(-)
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index 11d52d4d651..58a02010124 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -1885,58 +1885,76 @@ struct pid_map unsigned int unix_pid; };
+static unsigned int align_offset(unsigned int offset, unsigned int alignment) +{ + return (offset + (alignment - 1)) & ~(alignment - 1); +} + static struct pid_map *get_pid_map( unsigned int *num_entries ) { - HANDLE snapshot = NULL; struct pid_map *map; - unsigned int i = 0, count = 16, size = count * sizeof(*map); + unsigned int i = 0, map_count = 16, buffer_len = 4096, process_count, pos = 0; NTSTATUS ret; + char *buffer = NULL, *new_buffer;
- if (!(map = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL; + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;
- SERVER_START_REQ( create_snapshot ) + for (;;) { - req->flags = SNAP_PROCESS; - req->attributes = 0; - if (!(ret = wine_server_call( req ))) - snapshot = wine_server_ptr_handle( reply->handle ); + SERVER_START_REQ( list_processes ) + { + wine_server_set_reply( req, buffer, buffer_len ); + ret = wine_server_call( req ); + buffer_len = reply->info_size; + process_count = reply->process_count; + } + SERVER_END_REQ; + + if (ret != STATUS_INFO_LENGTH_MISMATCH) break; + + if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, buffer_len ))) + { + HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; + } } - SERVER_END_REQ;
- *num_entries = 0; - while (ret == STATUS_SUCCESS) + if (!(map = HeapAlloc( GetProcessHeap(), 0, map_count * sizeof(*map) ))) { - SERVER_START_REQ( next_process ) + HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; + } + + for (i = 0; i < process_count; ++i) + { + const struct process_info *process; + + pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) ); + process = (const struct process_info *)(buffer + pos); + + if (i >= map_count) { - req->handle = wine_server_obj_handle( snapshot ); - req->reset = (i == 0); - if (!(ret = wine_server_call( req ))) + struct pid_map *new_map; + map_count *= 2; + if (!(new_map = HeapReAlloc( GetProcessHeap(), 0, map, map_count * sizeof(*map)))) { - if (i >= count) - { - struct pid_map *new_map; - count *= 2; - size = count * sizeof(*new_map); - - if (!(new_map = HeapReAlloc( GetProcessHeap(), 0, map, size ))) - { - HeapFree( GetProcessHeap(), 0, map ); - map = NULL; - goto done; - } - map = new_map; - } - map[i].pid = reply->pid; - map[i].unix_pid = reply->unix_pid; - (*num_entries)++; - i++; + HeapFree( GetProcessHeap(), 0, map ); + HeapFree( GetProcessHeap(), 0, buffer ); + return NULL; } + map = new_map; } - SERVER_END_REQ; + + map[i].pid = process->pid; + map[i].unix_pid = process->unix_pid; + + pos += sizeof(struct process_info) + process->name_len; + pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) ); + pos += process->thread_count * sizeof(struct thread_info); }
-done: - NtClose( snapshot ); + HeapFree( GetProcessHeap(), 0, buffer ); + *num_entries = process_count; return map; }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/Makefile.in | 1 - server/process.c | 30 ------ server/process.h | 10 -- server/protocol.def | 41 -------- server/snapshot.c | 223 -------------------------------------------- server/thread.c | 24 ----- server/thread.h | 8 -- 7 files changed, 337 deletions(-) delete mode 100644 server/snapshot.c
diff --git a/server/Makefile.in b/server/Makefile.in index 3f3761faab6..e90c5d1336c 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -33,7 +33,6 @@ C_SRCS = \ semaphore.c \ serial.c \ signal.c \ - snapshot.c \ sock.c \ symlink.c \ thread.c \ diff --git a/server/process.c b/server/process.c index 6b9557ceb60..96389eed4fe 100644 --- a/server/process.c +++ b/server/process.c @@ -1086,36 +1086,6 @@ int set_process_debug_flag( struct process *process, int flag ) return write_process_memory( process, process->peb + 2, 1, &data ); }
-/* take a snapshot of currently running processes */ -struct process_snapshot *process_snap( int *count ) -{ - struct process_snapshot *snapshot, *ptr; - struct process *process; - - if (!running_processes) return NULL; - if (!(snapshot = mem_alloc( sizeof(*snapshot) * running_processes ))) - return NULL; - ptr = snapshot; - LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry ) - { - if (!process->running_threads) continue; - ptr->process = process; - ptr->threads = process->running_threads; - ptr->count = process->obj.refcount; - ptr->priority = process->priority; - ptr->handles = get_handle_table_count(process); - grab_object( process ); - ptr++; - } - - if (!(*count = ptr - snapshot)) - { - free( snapshot ); - snapshot = NULL; - } - return snapshot; -} - /* create a new process */ DECL_HANDLER(new_process) { diff --git a/server/process.h b/server/process.h index 5b83e111a6f..fb29f21cb12 100644 --- a/server/process.h +++ b/server/process.h @@ -100,15 +100,6 @@ struct process struct list kernel_object; /* list of kernel object pointers */ };
-struct process_snapshot -{ - struct process *process; /* process ptr */ - int count; /* process refcount */ - int threads; /* number of threads */ - int priority; /* priority class */ - int handles; /* number of handles */ -}; - #define CPU_FLAG(cpu) (1 << (cpu)) #define CPU_64BIT_MASK (CPU_FLAG(CPU_x86_64) | CPU_FLAG(CPU_ARM64))
@@ -137,7 +128,6 @@ extern void kill_process( struct process *process, int violent_death ); extern void kill_console_processes( struct thread *renderer, int exit_code ); extern void kill_debugged_processes( struct thread *debugger, int exit_code ); extern void detach_debugged_processes( struct thread *debugger ); -extern struct process_snapshot *process_snap( int *count ); extern void enum_processes( int (*cb)(struct process*, void*), void *user);
/* console functions */ diff --git a/server/protocol.def b/server/protocol.def index 2737cd6fddd..7f0202c2b00 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1878,47 +1878,6 @@ enum char_info_mode @END
-#define SNAP_PROCESS 0x00000001 -#define SNAP_THREAD 0x00000002 -/* Create a snapshot */ -@REQ(create_snapshot) - unsigned int attributes; /* object attributes */ - unsigned int flags; /* snapshot flags (SNAP_*) */ -@REPLY - obj_handle_t handle; /* handle to the snapshot */ -@END - - -/* Get the next process from a snapshot */ -@REQ(next_process) - obj_handle_t handle; /* handle to the snapshot */ - int reset; /* reset snapshot position? */ -@REPLY - int count; /* process usage count */ - process_id_t pid; /* process id */ - process_id_t ppid; /* parent process id */ - int threads; /* number of threads */ - int priority; /* process priority */ - int handles; /* number of handles */ - int unix_pid; /* Unix pid */ - VARARG(filename,unicode_str); /* file name of main exe */ -@END - - -/* Get the next thread from a snapshot */ -@REQ(next_thread) - obj_handle_t handle; /* handle to the snapshot */ - int reset; /* reset snapshot position? */ -@REPLY - int count; /* thread usage count */ - process_id_t pid; /* process id */ - thread_id_t tid; /* thread id */ - int base_pri; /* base priority */ - int delta_pri; /* delta priority */ - int unix_tid; /* thread native pid */ -@END - - struct thread_info { thread_id_t tid; diff --git a/server/snapshot.c b/server/snapshot.c deleted file mode 100644 index bdceaef5302..00000000000 --- a/server/snapshot.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Server-side snapshots - * - * Copyright (C) 1999 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * FIXME: heap snapshots not implemented - */ - -#include "config.h" -#include "wine/port.h" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winternl.h" - -#include "handle.h" -#include "process.h" -#include "thread.h" -#include "request.h" - - -struct snapshot -{ - struct object obj; /* object header */ - struct process_snapshot *processes; /* processes snapshot */ - int process_count; /* count of processes */ - int process_pos; /* current position in proc snapshot */ - struct thread_snapshot *threads; /* threads snapshot */ - int thread_count; /* count of threads */ - int thread_pos; /* current position in thread snapshot */ -}; - -static void snapshot_dump( struct object *obj, int verbose ); -static void snapshot_destroy( struct object *obj ); - -static const struct object_ops snapshot_ops = -{ - sizeof(struct snapshot), /* size */ - snapshot_dump, /* dump */ - no_get_type, /* get_type */ - no_add_queue, /* add_queue */ - NULL, /* remove_queue */ - NULL, /* signaled */ - NULL, /* satisfied */ - no_signal, /* signal */ - no_get_fd, /* get_fd */ - no_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ - no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ - no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ - no_close_handle, /* close_handle */ - snapshot_destroy /* destroy */ -}; - - -/* create a new snapshot */ -static struct snapshot *create_snapshot( unsigned int flags ) -{ - struct snapshot *snapshot; - - if (!(snapshot = alloc_object( &snapshot_ops ))) return NULL; - - snapshot->process_pos = 0; - snapshot->process_count = 0; - if (flags & SNAP_PROCESS) - snapshot->processes = process_snap( &snapshot->process_count ); - - snapshot->thread_pos = 0; - snapshot->thread_count = 0; - if (flags & SNAP_THREAD) - snapshot->threads = thread_snap( &snapshot->thread_count ); - - return snapshot; -} - -/* get the next process in the snapshot */ -static int snapshot_next_process( struct snapshot *snapshot, struct next_process_reply *reply ) -{ - struct process_snapshot *ptr; - struct process_dll *exe_module; - - if (!snapshot->process_count) - { - set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ - return 0; - } - if (snapshot->process_pos >= snapshot->process_count) - { - set_error( STATUS_NO_MORE_FILES ); - return 0; - } - ptr = &snapshot->processes[snapshot->process_pos++]; - reply->count = ptr->count; - reply->pid = get_process_id( ptr->process ); - reply->ppid = ptr->process->parent_id; - reply->threads = ptr->threads; - reply->priority = ptr->priority; - reply->handles = ptr->handles; - reply->unix_pid = ptr->process->unix_pid; - if ((exe_module = get_process_exe_module( ptr->process )) && exe_module->filename) - { - data_size_t len = min( exe_module->namelen, get_reply_max_size() ); - set_reply_data( exe_module->filename, len ); - } - return 1; -} - -/* get the next thread in the snapshot */ -static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_reply *reply ) -{ - struct thread_snapshot *ptr; - - if (!snapshot->thread_count) - { - set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ - return 0; - } - if (snapshot->thread_pos >= snapshot->thread_count) - { - set_error( STATUS_NO_MORE_FILES ); - return 0; - } - ptr = &snapshot->threads[snapshot->thread_pos++]; - reply->count = ptr->count; - reply->pid = get_process_id( ptr->thread->process ); - reply->tid = get_thread_id( ptr->thread ); - reply->base_pri = ptr->priority; - reply->delta_pri = 0; /* FIXME */ - reply->unix_tid = ptr->thread->unix_tid; - return 1; -} - -static void snapshot_dump( struct object *obj, int verbose ) -{ - struct snapshot *snapshot = (struct snapshot *)obj; - assert( obj->ops == &snapshot_ops ); - fprintf( stderr, "Snapshot: %d procs %d threads\n", - snapshot->process_count, snapshot->thread_count ); -} - -static void snapshot_destroy( struct object *obj ) -{ - int i; - struct snapshot *snapshot = (struct snapshot *)obj; - assert( obj->ops == &snapshot_ops ); - if (snapshot->process_count) - { - for (i = 0; i < snapshot->process_count; i++) - release_object( snapshot->processes[i].process ); - free( snapshot->processes ); - } - if (snapshot->thread_count) - { - for (i = 0; i < snapshot->thread_count; i++) - release_object( snapshot->threads[i].thread ); - free( snapshot->threads ); - } -} - -/* create a snapshot */ -DECL_HANDLER(create_snapshot) -{ - struct snapshot *snapshot; - - reply->handle = 0; - if ((snapshot = create_snapshot( req->flags ))) - { - reply->handle = alloc_handle( current->process, snapshot, 0, req->attributes ); - release_object( snapshot ); - } -} - -/* get the next process from a snapshot */ -DECL_HANDLER(next_process) -{ - struct snapshot *snapshot; - - if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle, - 0, &snapshot_ops ))) - { - if (req->reset) snapshot->process_pos = 0; - snapshot_next_process( snapshot, reply ); - release_object( snapshot ); - } -} - -/* get the next thread from a snapshot */ -DECL_HANDLER(next_thread) -{ - struct snapshot *snapshot; - - if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle, - 0, &snapshot_ops ))) - { - if (req->reset) snapshot->thread_pos = 0; - snapshot_next_thread( snapshot, reply ); - release_object( snapshot ); - } -} diff --git a/server/thread.c b/server/thread.c index d55af204bda..9b14174578e 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1299,30 +1299,6 @@ static unsigned int get_context_system_regs( enum cpu_type cpu ) return 0; }
-/* take a snapshot of currently running threads */ -struct thread_snapshot *thread_snap( int *count ) -{ - struct thread_snapshot *snapshot, *ptr; - struct thread *thread; - int total = 0; - - LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry ) - if (thread->state != TERMINATED) total++; - if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL; - ptr = snapshot; - LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry ) - { - if (thread->state == TERMINATED) continue; - ptr->thread = thread; - ptr->count = thread->obj.refcount; - ptr->priority = thread->priority; - grab_object( thread ); - ptr++; - } - *count = total; - return snapshot; -} - /* gets the current impersonation token */ struct token *thread_get_impersonation_token( struct thread *thread ) { diff --git a/server/thread.h b/server/thread.h index 183f6baa0f2..650bc44628d 100644 --- a/server/thread.h +++ b/server/thread.h @@ -93,13 +93,6 @@ struct thread WCHAR *desc; /* thread description string */ };
-struct thread_snapshot -{ - struct thread *thread; /* thread ptr */ - int count; /* thread refcount */ - int priority; /* priority class */ -}; - extern struct thread *current;
/* thread functions */ @@ -125,7 +118,6 @@ extern int thread_queue_apc( struct process *process, struct thread *thread, str extern void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_type type ); extern int thread_add_inflight_fd( struct thread *thread, int client, int server ); extern int thread_get_inflight_fd( struct thread *thread, int client ); -extern struct thread_snapshot *thread_snap( int *count ); extern struct token *thread_get_impersonation_token( struct thread *thread ); extern int set_thread_affinity( struct thread *thread, affinity_t affinity ); extern int is_cpu_supported( enum cpu_type cpu );
Zebediah Figura z.figura12@gmail.com writes:
- LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
- {
struct process_info *process_info;
struct process_dll *exe = get_process_exe_module( process );
pos = align_offset( pos, TYPE_ALIGNMENT(struct process_info) );
process_info = (struct process_info *)(buffer + pos);
process_info->name_len = exe->namelen;
process_info->thread_count = process->running_threads;
process_info->priority = process->priority;
process_info->pid = process->id;
process_info->parent_pid = process->parent_id;
process_info->handle_count = get_handle_table_count(process);
process_info->unix_pid = process->unix_pid;
pos += sizeof(*process_info);
memcpy( buffer + pos, exe->filename, exe->namelen );
pos += exe->namelen;
pos = align_offset( pos, TYPE_ALIGNMENT(struct thread_info) );
You also need to fill the alignment with zeros to avoid sending uninitialized data.