Implemented thread and (partial) module snapshots, based on the work

of Andreas Mohr <amohr@student.ei.uni-stuttgart.de>.
This commit is contained in:
Alexandre Julliard 2000-04-16 19:45:05 +00:00
parent c970904c2c
commit 07d8446918
11 changed files with 449 additions and 99 deletions

View File

@ -789,6 +789,7 @@ struct create_snapshot_request
{
IN int inherit; /* inherit flag */
IN int flags; /* snapshot flags (TH32CS_*) */
IN void* pid; /* process id */
OUT int handle; /* handle to the snapshot */
};
@ -798,12 +799,36 @@ struct next_process_request
{
IN int handle; /* handle to the snapshot */
IN int reset; /* reset snapshot position? */
OUT int count; /* process usage count */
OUT void* pid; /* process id */
OUT int threads; /* number of threads */
OUT int priority; /* process priority */
};
/* Get the next thread from a snapshot */
struct next_thread_request
{
IN int handle; /* handle to the snapshot */
IN int reset; /* reset snapshot position? */
OUT int count; /* thread usage count */
OUT void* pid; /* process id */
OUT void* tid; /* thread id */
OUT int base_pri; /* base priority */
OUT int delta_pri; /* delta priority */
};
/* Get the next module from a snapshot */
struct next_module_request
{
IN int handle; /* handle to the snapshot */
IN int reset; /* reset snapshot position? */
OUT void* pid; /* process id */
OUT void* base; /* module base address */
};
/* Wait for a debug event */
struct wait_debug_event_request
{
@ -1184,6 +1209,8 @@ enum request
REQ_CREATE_DEVICE,
REQ_CREATE_SNAPSHOT,
REQ_NEXT_PROCESS,
REQ_NEXT_THREAD,
REQ_NEXT_MODULE,
REQ_WAIT_DEBUG_EVENT,
REQ_EXCEPTION_EVENT,
REQ_OUTPUT_DEBUG_STRING,
@ -1219,7 +1246,7 @@ enum request
REQ_NB_REQUESTS
};
#define SERVER_PROTOCOL_VERSION 8
#define SERVER_PROTOCOL_VERSION 9
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */

View File

@ -1,17 +1,11 @@
#ifndef __WINE_TLHELP32_H
#define __WINE_TLHELP32_H
#include "windef.h"
#ifdef __cplusplus
extern "C" {
#endif
/*===================================================================
* Arguments for Toolhelp routines
*/
/*
/*
* CreateToolhelp32Snapshot
*/
@ -22,6 +16,118 @@ extern "C" {
#define TH32CS_SNAPALL (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
#define TH32CS_INHERIT 0x80000000
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD,DWORD);
/*
* thread entry list as created by CreateToolHelp32Snapshot
*/
typedef struct tagTHREADENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
LONG tbBasePri;
LONG tbDeltaPri;
DWORD dwFlags;
} THREADENTRY32, *PTHREADENTRY32, *LPTHREADENTRY32;
BOOL WINAPI Thread32First(HANDLE,LPTHREADENTRY32);
BOOL WINAPI Thread32Next(HANDLE,LPTHREADENTRY32);
/*
* Process entry list as created by CreateToolHelp32Snapshot
*/
typedef struct tagPROCESSENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
char szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32, *LPPROCESSENTRY32;
typedef struct tagPROCESSENTRY32W
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
WCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32W, *PPROCESSENTRY32W, *LPPROCESSENTRY32W;
BOOL WINAPI Process32First(HANDLE,LPPROCESSENTRY32);
BOOL WINAPI Process32FirstW(HANDLE,LPPROCESSENTRY32W);
BOOL WINAPI Process32Next(HANDLE,LPPROCESSENTRY32);
BOOL WINAPI Process32NextW(HANDLE,LPPROCESSENTRY32W);
#ifdef UNICODE
#define Process32First Process32FirstW
#define Process32Next Process32NextW
#define PROCESSENTRY32 PROCESSENTRY32W
#define PPROCESSENTRY32 PPROCESSENTRY32W
#define LPPROCESSENTRY32 LPPROCESSENTRY32W
#endif
/*
* Module entry list as created by CreateToolHelp32Snapshot
*/
#define MAX_MODULE_NAME32 255
typedef struct tagMODULEENTRY32
{
DWORD dwSize;
DWORD th32ModuleID;
DWORD th32ProcessID;
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE *modBaseAddr;
DWORD modBaseSize;
DWORD hModule;
char szModule[MAX_MODULE_NAME32 + 1];
char szExePath[MAX_PATH];
} MODULEENTRY32, *PMODULEENTRY32, *LPMODULEENTRY32;
typedef struct tagMODULEENTRY32W
{
DWORD dwSize;
DWORD th32ModuleID;
DWORD th32ProcessID;
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE *modBaseAddr;
DWORD modBaseSize;
DWORD hModule;
WCHAR szModule[MAX_MODULE_NAME32 + 1];
WCHAR szExePath[MAX_PATH];
} MODULEENTRY32W, *PMODULEENTRY32W, *LPMODULEENTRY32W;
BOOL WINAPI Module32First(HANDLE,LPMODULEENTRY32);
BOOL WINAPI Module32FirstW(HANDLE,LPMODULEENTRY32W);
BOOL WINAPI Module32Next(HANDLE,LPMODULEENTRY32);
BOOL WINAPI Module32NextW(HANDLE,LPMODULEENTRY32W);
#ifdef UNICODE
#define Module32First Module32FirstW
#define Module32Next Module32NextW
#define MODULEENTRY32 MODULEENTRY32W
#define PMODULEENTRY32 PMODULEENTRY32W
#define LPMODULEENTRY32 LPMODULEENTRY32W
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -2,7 +2,6 @@
#define __WINE_TOOLHELP_H
#include "windef.h"
#include "tlhelp32.h"
#define MAX_DATA 11
#define MAX_MODULE_NAME 9
@ -397,44 +396,4 @@ typedef struct {
#include "poppack.h"
/*
* Thread entry list as created by CreateToolHelp32Snapshot
*/
typedef struct tagTHREADENTRY {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
DWORD tbBasePri;
DWORD tbDeltaPri;
DWORD dwFlags;
DWORD th32AccessKey;
DWORD th32CurrentProcessID;
} THREADENTRY, *PTHREADENTRY, *LPTHREADENTRY;
BOOL WINAPI Thread32First(HANDLE,LPTHREADENTRY);
BOOL WINAPI Thread32Next(HANDLE,LPTHREADENTRY);
/*
* Process entry list as created by CreateToolHelp32Snapshot
*/
typedef struct tagPROCESSENTRY {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
char szExeFile[MAX_PATH];
} PROCESSENTRY, *PPROCESSENTRY, *LPPROCESSENTRY;
BOOL WINAPI Process32First(HANDLE,LPPROCESSENTRY);
BOOL WINAPI Process32Next(HANDLE,LPPROCESSENTRY);
#endif /* __WINE_TOOLHELP_H */

View File

@ -19,7 +19,7 @@
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(toolhelp)
DEFAULT_DEBUG_CHANNEL(toolhelp);
/* FIXME: to make this working, we have to callback all these registered
@ -150,10 +150,9 @@ HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
struct create_snapshot_request *req = get_req_buffer();
TRACE("%lx,%lx\n", flags, process );
if (flags & (TH32CS_SNAPHEAPLIST|TH32CS_SNAPMODULE|TH32CS_SNAPTHREAD))
FIXME("flags %lx not implemented\n", flags );
if (!(flags & TH32CS_SNAPPROCESS))
if (!(flags & (TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)))
{
FIXME("flags %lx not implemented\n", flags );
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return INVALID_HANDLE_VALUE;
}
@ -161,23 +160,47 @@ HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
/* Now do the snapshot */
req->flags = flags & ~TH32CS_INHERIT;
req->inherit = (flags & TH32CS_INHERIT) != 0;
req->pid = (void *)process;
server_call( REQ_CREATE_SNAPSHOT );
return req->handle;
}
/***********************************************************************
* TOOLHELP_Thread32Next
*
* Implementation of Thread32First/Next
*/
static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL first )
{
struct next_thread_request *req = get_req_buffer();
if (lpte->dwSize < sizeof(THREADENTRY32))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(THREADENTRY32), lpte->dwSize);
return FALSE;
}
req->handle = handle;
req->reset = first;
if (server_call( REQ_NEXT_THREAD )) return FALSE;
lpte->cntUsage = req->count;
lpte->th32ThreadID = (DWORD)req->tid;
lpte->th32OwnerProcessID = (DWORD)req->pid;
lpte->tbBasePri = req->base_pri;
lpte->tbDeltaPri = req->delta_pri;
lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
return TRUE;
}
/***********************************************************************
* Thread32First (KERNEL32.686)
*
* Return info about the first thread in a toolhelp32 snapshot
*/
BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY lpte)
BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
{
if (!lpte)
return FALSE;
FIXME("(%d,%p),stub!\n",hSnapshot,lpte);
return FALSE;
return TOOLHELP_Thread32Next(hSnapshot, lpte, TRUE);
}
/***********************************************************************
@ -185,13 +208,9 @@ BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY lpte)
*
* Return info about the "next" thread in a toolhelp32 snapshot
*/
BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY lpte)
BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
{
if (!lpte)
return FALSE;
FIXME("(%d,%p),stub!\n",hSnapshot,lpte);
return FALSE;
return TOOLHELP_Thread32Next(hSnapshot, lpte, FALSE);
}
/***********************************************************************
@ -199,20 +218,20 @@ BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY lpte)
*
* Implementation of Process32First/Next
*/
static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY lppe, BOOL first )
static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first )
{
struct next_process_request *req = get_req_buffer();
if (lppe->dwSize < sizeof (PROCESSENTRY))
if (lppe->dwSize < sizeof(PROCESSENTRY32))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ERR("Result buffer too small\n");
ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize);
return FALSE;
}
req->handle = handle;
req->reset = first;
if (server_call( REQ_NEXT_PROCESS )) return FALSE;
lppe->cntUsage = 1;
lppe->cntUsage = req->count;
lppe->th32ProcessID = (DWORD)req->pid;
lppe->th32DefaultHeapID = 0; /* FIXME */
lppe->th32ModuleID = 0; /* FIXME */
@ -230,7 +249,7 @@ static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY lppe, BOOL fir
*
* Return info about the first process in a toolhelp32 snapshot
*/
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY lppe)
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE );
}
@ -240,20 +259,50 @@ BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY lppe)
*
* Return info about the "next" process in a toolhelp32 snapshot
*/
BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY lppe)
BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE );
}
/***********************************************************************
* TOOLHELP_Module32Next
*
* Implementation of Module32First/Next
*/
static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL first )
{
struct next_module_request *req = get_req_buffer();
if (lpme->dwSize < sizeof (MODULEENTRY32))
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(MODULEENTRY32), lpme->dwSize);
return FALSE;
}
req->handle = handle;
req->reset = first;
if (server_call( REQ_NEXT_MODULE )) return FALSE;
lpme->th32ModuleID = 0; /* toolhelp internal id, never used */
lpme->th32ProcessID = (DWORD)req->pid;
lpme->GlblcntUsage = 0; /* FIXME */
lpme->ProccntUsage = 0; /* FIXME */
lpme->modBaseAddr = req->base;
lpme->modBaseSize = 0; /* FIXME */
lpme->hModule = (DWORD)req->base;
lpme->szModule[0] = 0; /* FIXME */
lpme->szExePath[0] = 0; /* FIXME */
return TRUE;
}
/***********************************************************************
* Module32First (KERNEL32.527)
*
* Return info about the "first" module in a toolhelp32 snapshot
*/
BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY lpme)
BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
FIXME("(%d,%p),stub!\n",hSnapshot,lpme);
return FALSE;
return TOOLHELP_Module32Next( hSnapshot, lpme, TRUE );
}
/***********************************************************************
@ -261,10 +310,9 @@ BOOL WINAPI Module32First(HANDLE hSnapshot, LPMODULEENTRY lpme)
*
* Return info about the "next" module in a toolhelp32 snapshot
*/
BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY lpme)
BOOL WINAPI Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
FIXME("(%d,%p),stub!\n",hSnapshot,lpme);
return FALSE;
return TOOLHELP_Module32Next( hSnapshot, lpme, FALSE );
}
/************************************************************************

View File

@ -563,6 +563,7 @@ struct process_snapshot *process_snap( int *count )
if (!process->running_threads) continue;
ptr->process = process;
ptr->threads = process->running_threads;
ptr->count = process->obj.refcount;
ptr->priority = process->priority;
grab_object( process );
ptr++;
@ -571,6 +572,25 @@ struct process_snapshot *process_snap( int *count )
return snapshot;
}
/* take a snapshot of the modules of a process */
struct module_snapshot *module_snap( struct process *process, int *count )
{
struct module_snapshot *snapshot, *ptr;
struct process_dll *dll;
int total = 0;
for (dll = &process->exe; dll; dll = dll->next) total++;
if (!(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
for (ptr = snapshot, dll = &process->exe; dll; dll = dll->next, ptr++)
{
ptr->base = dll->base;
}
*count = total;
return snapshot;
}
/* create a new process */
DECL_HANDLER(new_process)
{

View File

@ -55,10 +55,16 @@ struct process_snapshot
{
struct process *process; /* process ptr */
struct process *parent; /* process parent */
int count; /* process refcount */
int threads; /* number of threads */
int priority; /* priority class */
};
struct module_snapshot
{
void *base; /* module base addr */
};
/* process functions */
extern struct thread *create_process( int fd, struct process *parent,
@ -75,6 +81,7 @@ extern void suspend_process( struct process *process );
extern void resume_process( struct process *process );
extern void kill_debugged_processes( struct thread *debugger, int exit_code );
extern struct process_snapshot *process_snap( int *count );
extern struct module_snapshot *module_snap( struct process *process, int *count );
static inline void *get_process_id( struct process *process ) { return process; }

View File

@ -138,6 +138,8 @@ DECL_HANDLER(get_mapping_info);
DECL_HANDLER(create_device);
DECL_HANDLER(create_snapshot);
DECL_HANDLER(next_process);
DECL_HANDLER(next_thread);
DECL_HANDLER(next_module);
DECL_HANDLER(wait_debug_event);
DECL_HANDLER(exception_event);
DECL_HANDLER(output_debug_string);
@ -244,6 +246,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_create_device,
(req_handler)req_create_snapshot,
(req_handler)req_next_process,
(req_handler)req_next_thread,
(req_handler)req_next_module,
(req_handler)req_wait_debug_event,
(req_handler)req_exception_event,
(req_handler)req_output_debug_string,

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Alexandre Julliard
*
* FIXME: only process snapshots implemented for now
* FIXME: heap snapshots not implemented
*/
#include <assert.h>
@ -22,9 +22,16 @@
struct snapshot
{
struct object obj; /* object header */
struct process_snapshot *process; /* processes snapshot */
struct process *process; /* process of this snapshot (for modules and heaps) */
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 */
struct module_snapshot *modules; /* modules snapshot */
int module_count; /* count of modules */
int module_pos; /* current position in module snapshot */
};
static void snapshot_dump( struct object *obj, int verbose );
@ -49,18 +56,41 @@ static const struct object_ops snapshot_ops =
/* create a new snapshot */
static struct snapshot *create_snapshot( int flags )
static struct snapshot *create_snapshot( void *pid, int flags )
{
struct process *process = NULL;
struct snapshot *snapshot;
if ((snapshot = alloc_object( &snapshot_ops, -1 )))
/* need a process for modules and heaps */
if (flags & (TH32CS_SNAPMODULE|TH32CS_SNAPHEAPLIST))
{
if (flags & TH32CS_SNAPPROCESS)
snapshot->process = process_snap( &snapshot->process_count );
else
snapshot->process_count = 0;
snapshot->process_pos = 0;
if (!pid) process = (struct process *)grab_object( current->process );
else if (!(process = get_process_from_id( pid ))) return NULL;
}
if (!(snapshot = alloc_object( &snapshot_ops, -1 )))
{
if (process) release_object( process );
return NULL;
}
snapshot->process = process;
snapshot->process_pos = 0;
snapshot->process_count = 0;
if (flags & TH32CS_SNAPPROCESS)
snapshot->processes = process_snap( &snapshot->process_count );
snapshot->thread_pos = 0;
snapshot->thread_count = 0;
if (flags & TH32CS_SNAPTHREAD)
snapshot->threads = thread_snap( &snapshot->thread_count );
snapshot->module_pos = 0;
snapshot->module_count = 0;
if (flags & TH32CS_SNAPMODULE)
snapshot->modules = module_snap( process, &snapshot->module_count );
return snapshot;
}
@ -80,19 +110,67 @@ static int snapshot_next_process( struct snapshot *snapshot, struct next_process
set_error( STATUS_NO_MORE_FILES );
return 0;
}
ptr = &snapshot->process[snapshot->process_pos++];
req->pid = ptr->process;
ptr = &snapshot->processes[snapshot->process_pos++];
req->count = ptr->count;
req->pid = get_process_id( ptr->process );
req->threads = ptr->threads;
req->priority = ptr->priority;
return 1;
}
/* get the next thread in the snapshot */
static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_request *req )
{
struct thread_snapshot *ptr;
if (!snapshot->thread_count)
{
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
return 0;
}
if (req->reset) snapshot->thread_pos = 0;
else if (snapshot->thread_pos >= snapshot->thread_count)
{
set_error( STATUS_NO_MORE_FILES );
return 0;
}
ptr = &snapshot->threads[snapshot->thread_pos++];
req->count = ptr->count;
req->pid = get_process_id( ptr->thread->process );
req->tid = get_thread_id( ptr->thread );
req->base_pri = ptr->priority;
req->delta_pri = 0; /* FIXME */
return 1;
}
/* get the next module in the snapshot */
static int snapshot_next_module( struct snapshot *snapshot, struct next_module_request *req )
{
struct module_snapshot *ptr;
if (!snapshot->module_count)
{
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
return 0;
}
if (req->reset) snapshot->module_pos = 0;
else if (snapshot->module_pos >= snapshot->module_count)
{
set_error( STATUS_NO_MORE_FILES );
return 0;
}
ptr = &snapshot->modules[snapshot->module_pos++];
req->pid = get_process_id( snapshot->process );
req->base = ptr->base;
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 processes\n",
snapshot->process_count );
fprintf( stderr, "Snapshot: %d procs %d threads %d modules\n",
snapshot->process_count, snapshot->thread_count, snapshot->module_count );
}
static void snapshot_destroy( struct object *obj )
@ -103,9 +181,17 @@ static void snapshot_destroy( struct object *obj )
if (snapshot->process_count)
{
for (i = 0; i < snapshot->process_count; i++)
release_object( snapshot->process[i].process );
free( snapshot->process );
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 );
}
if (snapshot->module_count) free( snapshot->modules );
if (snapshot->process) release_object( snapshot->process );
}
/* create a snapshot */
@ -114,7 +200,7 @@ DECL_HANDLER(create_snapshot)
struct snapshot *snapshot;
req->handle = -1;
if ((snapshot = create_snapshot( req->flags )))
if ((snapshot = create_snapshot( req->pid, req->flags )))
{
req->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
release_object( snapshot );
@ -133,3 +219,29 @@ DECL_HANDLER(next_process)
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 )))
{
snapshot_next_thread( snapshot, req );
release_object( snapshot );
}
}
/* get the next module from a snapshot */
DECL_HANDLER(next_module)
{
struct snapshot *snapshot;
if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
0, &snapshot_ops )))
{
snapshot_next_module( snapshot, req );
release_object( snapshot );
}
}

View File

@ -580,6 +580,30 @@ void kill_thread( struct thread *thread, int violent_death )
release_object( thread );
}
/* 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;
for (thread = first_thread; thread; thread = thread->next)
if (thread->state != TERMINATED) total++;
if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
ptr = snapshot;
for (thread = first_thread; thread; thread = thread->next)
{
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;
}
/* signal that we are finished booting on the client side */
DECL_HANDLER(boot_done)
{

View File

@ -58,6 +58,13 @@ struct thread
enum request last_req; /* last request received (for debugging) */
};
struct thread_snapshot
{
struct thread *thread; /* thread ptr */
int count; /* thread refcount */
int priority; /* priority class */
};
/* callback function for building the thread reply when sleep_on is finished */
typedef void (*sleep_reply)( struct thread *thread, struct object *obj, int signaled );
@ -79,6 +86,7 @@ extern void kill_thread( struct thread *thread, int violent_death );
extern void wake_up( struct object *obj, int max );
extern int sleep_on( int count, struct object *objects[], int flags,
int timeout, sleep_reply func );
extern struct thread_snapshot *thread_snap( int *count );
/* ptrace functions */

View File

@ -929,7 +929,8 @@ static void dump_create_device_reply( const struct create_device_request *req )
static void dump_create_snapshot_request( const struct create_snapshot_request *req )
{
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " flags=%d", req->flags );
fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " pid=%p", req->pid );
}
static void dump_create_snapshot_reply( const struct create_snapshot_request *req )
@ -945,11 +946,39 @@ static void dump_next_process_request( const struct next_process_request *req )
static void dump_next_process_reply( const struct next_process_request *req )
{
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " threads=%d,", req->threads );
fprintf( stderr, " priority=%d", req->priority );
}
static void dump_next_thread_request( const struct next_thread_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " reset=%d", req->reset );
}
static void dump_next_thread_reply( const struct next_thread_request *req )
{
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " tid=%p,", req->tid );
fprintf( stderr, " base_pri=%d,", req->base_pri );
fprintf( stderr, " delta_pri=%d", req->delta_pri );
}
static void dump_next_module_request( const struct next_module_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " reset=%d", req->reset );
}
static void dump_next_module_reply( const struct next_module_request *req )
{
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " base=%p", req->base );
}
static void dump_wait_debug_event_request( const struct wait_debug_event_request *req )
{
fprintf( stderr, " timeout=%d", req->timeout );
@ -1364,6 +1393,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_device_request,
(dump_func)dump_create_snapshot_request,
(dump_func)dump_next_process_request,
(dump_func)dump_next_thread_request,
(dump_func)dump_next_module_request,
(dump_func)dump_wait_debug_event_request,
(dump_func)dump_exception_event_request,
(dump_func)dump_output_debug_string_request,
@ -1467,6 +1498,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_device_reply,
(dump_func)dump_create_snapshot_reply,
(dump_func)dump_next_process_reply,
(dump_func)dump_next_thread_reply,
(dump_func)dump_next_module_reply,
(dump_func)dump_wait_debug_event_reply,
(dump_func)dump_exception_event_reply,
(dump_func)0,
@ -1570,6 +1603,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_device",
"create_snapshot",
"next_process",
"next_thread",
"next_module",
"wait_debug_event",
"exception_event",
"output_debug_string",