server: Update the active hooks bitmaps when hooks are added / removed.

This commit is contained in:
Rémi Bernon 2024-06-24 23:35:06 +02:00 committed by Alexandre Julliard
parent cd8bbea138
commit ae5a02e808
6 changed files with 89 additions and 33 deletions

View file

@ -899,7 +899,7 @@ typedef volatile struct
typedef volatile struct
{
int placeholder;
int hooks_count[WH_MAX - WH_MIN + 2];
} queue_shm_t;
typedef volatile union
@ -6575,7 +6575,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 816
#define SERVER_PROTOCOL_VERSION 817
/* ### protocol_version end ### */

View file

@ -173,6 +173,15 @@ static struct hook *add_hook( struct desktop *desktop, struct process *process,
hook->module_size = module_size;
list_add_head( &table->hooks[index], &hook->chain );
if (thread) thread->desktop_users++;
if (!global)
add_queue_hook_count( hook->thread, index, 1 );
else LIST_FOR_EACH_ENTRY( thread, &desktop->threads, struct thread, desktop_entry )
{
if (!run_hook_in_thread( hook, thread )) continue;
add_queue_hook_count( thread, index, 1 );
}
return hook;
}
@ -315,12 +324,43 @@ static void hook_table_destroy( struct object *obj )
/* remove a hook, freeing it if the chain is not in use */
static void remove_hook( struct hook *hook )
{
struct desktop *desktop = hook->desktop;
int global = hook->table == desktop->global_hooks;
struct thread *thread;
if (!global)
add_queue_hook_count( hook->thread, hook->index, -1 );
else LIST_FOR_EACH_ENTRY( thread, &desktop->threads, struct thread, desktop_entry )
{
if (!run_hook_in_thread( hook, thread )) continue;
add_queue_hook_count( thread, hook->index, -1 );
}
if (hook->table->counts[hook->index])
hook->proc = 0; /* chain is in use, just mark it and return */
else
free_hook( hook );
}
/* update the thread message queue hooks counters from the desktop global hooks */
void add_desktop_hook_count( struct desktop *desktop, struct thread *thread, int count )
{
struct hook_table *table;
struct hook *hook;
int index;
if (!(table = desktop->global_hooks)) return;
for (index = 0; index < ARRAY_SIZE(table->hooks); index++)
{
LIST_FOR_EACH_ENTRY( hook, &table->hooks[index], struct hook, chain )
{
if (!run_hook_in_thread( hook, thread )) continue;
add_queue_hook_count( thread, hook->index, count );
}
}
}
/* release a hook chain, removing deleted hooks if the use count drops to 0 */
static void release_hook_chain( struct hook_table *table, int index )
{
@ -362,36 +402,6 @@ void remove_thread_hooks( struct thread *thread )
}
}
/* get a bitmap of active hooks in a hook table */
static int is_hook_active( struct hook_table *table, int index )
{
struct hook *hook = get_first_hook( table, index );
while (hook)
{
if (hook->proc && run_hook_in_current_thread( hook )) return 1;
hook = HOOK_ENTRY( list_next( &table->hooks[index], &hook->chain ) );
}
return 0;
}
/* get a bitmap of all active hooks for the current thread */
unsigned int get_active_hooks(void)
{
struct hook_table *table = get_queue_hooks( current );
struct hook_table *global_hooks = get_global_hooks( current );
unsigned int ret = 1u << 31; /* set high bit to indicate that the bitmap is valid */
int id;
for (id = WH_MINHOOK; id <= WH_WINEVENT; id++)
{
if ((table && is_hook_active( table, id - WH_MINHOOK )) ||
(global_hooks && is_hook_active( global_hooks, id - WH_MINHOOK )))
ret |= 1 << (id - WH_MINHOOK);
}
return ret;
}
/* return the thread that owns the first global hook */
struct thread *get_first_global_hook( struct desktop *desktop, int id )
{

View file

@ -915,7 +915,7 @@ typedef volatile struct
typedef volatile struct
{
int placeholder;
int hooks_count[WH_MAX - WH_MIN + 2]; /* active hooks count */
} queue_shm_t;
typedef volatile union

View file

@ -290,6 +290,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
{
struct thread_input *new_input = NULL;
struct msg_queue *queue;
struct desktop *desktop;
int i;
if (!input)
@ -328,7 +329,19 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
return NULL;
}
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t )
{
memset( (void *)shared->hooks_count, 0, sizeof(shared->hooks_count) );
}
SHARED_WRITE_END;
thread->queue = queue;
if ((desktop = get_thread_desktop( thread, 0 )))
{
add_desktop_hook_count( desktop, thread, 1 );
release_object( desktop );
}
}
if (new_input) release_object( new_input );
return queue;
@ -612,6 +625,35 @@ void set_queue_hooks( struct thread *thread, struct hook_table *hooks )
queue->hooks = hooks;
}
/* get the thread message queue active hooks bitmap */
unsigned int get_active_hooks(void)
{
unsigned int ret = 1u << 31; /* set high bit to indicate that the bitmap is valid */
struct msg_queue *queue;
int bit;
if (!(queue = current->queue)) return ret;
for (bit = 0; bit < ARRAY_SIZE(queue->shared->hooks_count); bit++)
if (queue->shared->hooks_count[bit]) ret |= 1 << bit;
return ret;
}
/* update the thread message queue hooks counters */
void add_queue_hook_count( struct thread *thread, unsigned int index, int count )
{
if (!thread->queue) return;
SHARED_WRITE_BEGIN( thread->queue->shared, queue_shm_t )
{
shared->hooks_count[index] += count;
}
SHARED_WRITE_END;
assert( thread->queue->shared->hooks_count[index] >= 0 );
}
/* check the queue status */
static inline int is_signaled( struct msg_queue *queue )
{

View file

@ -108,12 +108,14 @@ extern void cleanup_clipboard_thread( struct thread *thread );
extern void remove_thread_hooks( struct thread *thread );
extern unsigned int get_active_hooks(void);
extern struct thread *get_first_global_hook( struct desktop *desktop, int id );
extern void add_desktop_hook_count( struct desktop *desktop, struct thread *thread, int count );
/* queue functions */
extern void free_msg_queue( struct thread *thread );
extern struct hook_table *get_queue_hooks( struct thread *thread );
extern void set_queue_hooks( struct thread *thread, struct hook_table *hooks );
extern void add_queue_hook_count( struct thread *thread, unsigned int index, int count );
extern void inc_queue_paint_count( struct thread *thread, int incr );
extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
extern int init_thread_queue( struct thread *thread );

View file

@ -410,6 +410,7 @@ static void close_desktop_timeout( void *private )
static void add_desktop_thread( struct desktop *desktop, struct thread *thread )
{
list_add_tail( &desktop->threads, &thread->desktop_entry );
add_desktop_hook_count( desktop, thread, 1 );
if (!thread->process->is_system)
{
@ -441,6 +442,7 @@ static void remove_desktop_user( struct desktop *desktop, struct thread *thread
/* remove a thread from the list of threads attached to a desktop */
static void remove_desktop_thread( struct desktop *desktop, struct thread *thread )
{
add_desktop_hook_count( desktop, thread, -1 );
list_remove( &thread->desktop_entry );
if (!thread->process->is_system) remove_desktop_user( desktop, thread );