Commit fdc92bae authored by Alexandre Julliard's avatar Alexandre Julliard

Added server snapshot support (processes only for now).

parent 068a26e8
......@@ -596,6 +596,32 @@ struct create_device_reply
};
/* Create a snapshot */
struct create_snapshot_request
{
int inherit; /* inherit flag */
int flags; /* snapshot flags (TH32CS_*) */
};
struct create_snapshot_reply
{
int handle; /* handle to the snapshot */
};
/* Get the next process from a snapshot */
struct next_process_request
{
int handle; /* handle to the snapshot */
int reset; /* reset snapshot position? */
};
struct next_process_reply
{
void* pid; /* process id */
int threads; /* number of threads */
int priority; /* process priority */
};
/* client-side functions */
#ifndef __WINE_SERVER__
......
......@@ -20,6 +20,7 @@
struct object;
struct object_name;
struct thread;
struct process;
struct file;
struct wait_queue_entry;
......@@ -119,42 +120,6 @@ extern void set_timeout( int client_fd, struct timeval *when );
extern int send_reply_v( int client_fd, int type, int pass_fd,
struct iovec *vec, int veclen );
/* process functions */
struct process;
extern struct process *create_process(void);
extern struct process *get_process_from_id( void *id );
extern struct process *get_process_from_handle( int handle, unsigned int access );
extern void add_process_thread( struct process *process,
struct thread *thread );
extern void remove_process_thread( struct process *process,
struct thread *thread );
extern void kill_process( struct process *process, int exit_code );
extern void get_process_info( struct process *process,
struct get_process_info_reply *reply );
extern void set_process_info( struct process *process,
struct set_process_info_request *req );
extern int alloc_console( struct process *process );
extern int free_console( struct process *process );
extern struct object *get_console( struct process *process, int output );
/* handle functions */
/* alloc_handle takes a void *obj for convenience, but you better make sure */
/* that the thing pointed to starts with a struct object... */
extern int alloc_handle( struct process *process, void *obj,
unsigned int access, int inherit );
extern int close_handle( struct process *process, int handle );
extern int set_handle_info( struct process *process, int handle,
int mask, int flags );
extern struct object *get_handle_obj( struct process *process, int handle,
unsigned int access, const struct object_ops *ops );
extern int duplicate_handle( struct process *src, int src_handle, struct process *dst,
int dst_handle, unsigned int access, int inherit, int options );
extern int open_object( const char *name, const struct object_ops *ops,
unsigned int access, int inherit );
/* event functions */
extern struct object *create_event( const char *name, int manual_reset, int initial_state );
......@@ -232,6 +197,10 @@ extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply );
extern struct object *create_device( int id );
/* snapshot functions */
extern struct object *create_snapshot( int flags );
extern int snapshot_next_process( int handle, int reset, struct next_process_reply *reply );
extern int debug_level;
#endif /* __WINE_SERVER_OBJECT_H */
......@@ -53,6 +53,8 @@ enum request
REQ_CREATE_MAPPING,
REQ_GET_MAPPING_INFO,
REQ_CREATE_DEVICE,
REQ_CREATE_SNAPSHOT,
REQ_NEXT_PROCESS,
REQ_NB_REQUESTS
};
......@@ -109,6 +111,8 @@ DECL_HANDLER(create_change_notification);
DECL_HANDLER(create_mapping);
DECL_HANDLER(get_mapping_info);
DECL_HANDLER(create_device);
DECL_HANDLER(create_snapshot);
DECL_HANDLER(next_process);
static const struct handler {
void (*handler)();
......@@ -162,6 +166,8 @@ static const struct handler {
{ (void(*)())req_create_mapping, sizeof(struct create_mapping_request) },
{ (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
{ (void(*)())req_create_device, sizeof(struct create_device_request) },
{ (void(*)())req_create_snapshot, sizeof(struct create_snapshot_request) },
{ (void(*)())req_next_process, sizeof(struct next_process_request) },
};
#endif /* WANT_REQUEST_HANDLERS */
......
......@@ -17,6 +17,7 @@ C_SRCS = \
pipe.c \
process.c \
request.c \
snapshot.c \
select.c \
semaphore.c \
socket.c \
......
......@@ -17,6 +17,7 @@
#include "winnt.h"
#include "server.h"
#include "server/process.h"
#include "server/thread.h"
/* reserved handle access rights */
......@@ -60,6 +61,7 @@ struct process
static struct process *first_process;
static struct process *initial_process;
static int running_processes;
#define MIN_HANDLE_ENTRIES 32
......@@ -214,7 +216,7 @@ void add_process_thread( struct process *process, struct thread *thread )
thread->proc_prev = NULL;
if (thread->proc_next) thread->proc_next->proc_prev = thread;
process->thread_list = thread;
process->running_threads++;
if (!process->running_threads++) running_processes++;
grab_object( thread );
}
......@@ -231,6 +233,7 @@ void remove_process_thread( struct process *process, struct thread *thread )
if (!--process->running_threads)
{
/* we have removed the last running thread, exit the process */
running_processes--;
process_killed( process, thread->exit_code );
}
release_object( thread );
......@@ -573,3 +576,25 @@ struct object *get_console( struct process *process, int output )
return NULL;
return grab_object( obj );
}
/* 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;
for (process = first_process; process; process = process->next)
{
if (!process->running_threads) continue;
ptr->process = process;
ptr->threads = process->running_threads;
ptr->priority = process->priority;
grab_object( process );
ptr++;
}
*count = running_processes;
return snapshot;
}
......@@ -19,6 +19,7 @@
#define WANT_REQUEST_HANDLERS
#include "server.h"
#include "server/request.h"
#include "server/process.h"
#include "server/thread.h"
/* check that the string is NULL-terminated and that the len is correct */
......@@ -754,3 +755,26 @@ DECL_HANDLER(create_device)
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* create a snapshot */
DECL_HANDLER(create_snapshot)
{
struct object *obj;
struct create_snapshot_reply reply = { -1 };
if ((obj = create_snapshot( req->flags )))
{
reply.handle = alloc_handle( current->process, obj, 0, req->inherit );
release_object( obj );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* get the next process from a snapshot */
DECL_HANDLER(next_process)
{
struct next_process_reply reply;
snapshot_next_process( req->handle, req->reset, &reply );
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/*
* Server-side snapshots
*
* Copyright (C) 1999 Alexandre Julliard
*
* FIXME: only process snapshots implemented for now
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "winerror.h"
#include "winnt.h"
#include "tlhelp32.h"
#include "server/process.h"
#include "server/thread.h"
struct snapshot
{
struct object obj; /* object header */
struct process_snapshot *process; /* processes snapshot */
int process_count; /* count of processes */
int process_pos; /* current position in proc snapshot */
};
static void snapshot_dump( struct object *obj, int verbose );
static void snapshot_destroy( struct object *obj );
static const struct object_ops snapshot_ops =
{
snapshot_dump,
no_add_queue,
NULL, /* should never get called */
NULL, /* should never get called */
NULL, /* should never get called */
no_read_fd,
no_write_fd,
no_flush,
no_get_file_info,
snapshot_destroy
};
/* create a new snapshot */
struct object *create_snapshot( int flags )
{
struct snapshot *snapshot;
if (!(snapshot = mem_alloc( sizeof(*snapshot) ))) return NULL;
init_object( &snapshot->obj, &snapshot_ops, NULL );
if (flags & TH32CS_SNAPPROCESS)
snapshot->process = process_snap( &snapshot->process_count );
else
snapshot->process_count = 0;
snapshot->process_pos = 0;
return &snapshot->obj;
}
/* get the next process in the snapshot */
int snapshot_next_process( int handle, int reset, struct next_process_reply *reply )
{
struct snapshot *snapshot;
struct process_snapshot *ptr;
if (!(snapshot = (struct snapshot *)get_handle_obj( current->process, handle,
0, &snapshot_ops )))
return 0;
if (!snapshot->process_count)
{
SET_ERROR( ERROR_INVALID_PARAMETER ); /* FIXME */
release_object( snapshot );
return 0;
}
if (reset) snapshot->process_pos = 0;
else if (snapshot->process_pos >= snapshot->process_count)
{
SET_ERROR( ERROR_NO_MORE_FILES );
release_object( snapshot );
return 0;
}
ptr = &snapshot->process[snapshot->process_pos++];
reply->pid = ptr->process;
reply->threads = ptr->threads;
reply->priority = ptr->priority;
release_object( snapshot );
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 );
}
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->process[i].process );
free( snapshot->process );
}
free( snapshot );
}
......@@ -541,6 +541,34 @@ static int dump_create_device_reply( struct create_device_reply *req, int len )
return (int)sizeof(*req);
}
static int dump_create_snapshot_request( struct create_snapshot_request *req, int len )
{
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " flags=%d", req->flags );
return (int)sizeof(*req);
}
static int dump_create_snapshot_reply( struct create_snapshot_reply *req, int len )
{
fprintf( stderr, " handle=%d", req->handle );
return (int)sizeof(*req);
}
static int dump_next_process_request( struct next_process_request *req, int len )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " reset=%d", req->reset );
return (int)sizeof(*req);
}
static int dump_next_process_reply( struct next_process_reply *req, int len )
{
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " threads=%d,", req->threads );
fprintf( stderr, " priority=%d", req->priority );
return (int)sizeof(*req);
}
struct dumper
{
int (*dump_req)( void *data, int len );
......@@ -645,6 +673,10 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
(void(*)())dump_get_mapping_info_reply },
{ (int(*)(void *,int))dump_create_device_request,
(void(*)())dump_create_device_reply },
{ (int(*)(void *,int))dump_create_snapshot_request,
(void(*)())dump_create_snapshot_reply },
{ (int(*)(void *,int))dump_next_process_request,
(void(*)())dump_next_process_reply },
};
static const char * const req_names[REQ_NB_REQUESTS] =
......@@ -697,6 +729,8 @@ static const char * const req_names[REQ_NB_REQUESTS] =
"create_mapping",
"get_mapping_info",
"create_device",
"create_snapshot",
"next_process",
};
void trace_request( enum request req, void *data, int len, int fd )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment