mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:48:36 +00:00
server: Update the active hooks bitmaps when hooks are added / removed.
This commit is contained in:
parent
cd8bbea138
commit
ae5a02e808
|
@ -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 ### */
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue