From: Rémi Bernon rbernon@codeweavers.com
--- server/class.c | 2 +- server/file.h | 2 +- server/mapping.c | 28 ++++++++++++++++++++-------- server/queue.c | 8 ++++++-- server/window.c | 2 +- server/winstation.c | 2 +- 6 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/server/class.c b/server/class.c index 53dd5b5509b..a5cd765bc2b 100644 --- a/server/class.c +++ b/server/class.c @@ -66,7 +66,7 @@ static struct window_class *create_class( struct process *process, int extra_byt class->nb_extra_bytes = extra_bytes; memset( class->extra_bytes, 0, extra_bytes );
- if (!(class->shared = alloc_shared_object())) goto failed; + if (!(class->shared = alloc_shared_object( sizeof(*class->shared) ))) goto failed; SHARED_WRITE_BEGIN( class->shared, class_shm_t ) { memcpy( (void *)shared->name, name->str, name->len ); diff --git a/server/file.h b/server/file.h index 567194bf00a..db89602441f 100644 --- a/server/file.h +++ b/server/file.h @@ -195,7 +195,7 @@ extern struct mapping *create_session_mapping( struct object *root, const struct extern void set_session_mapping( struct mapping *mapping );
extern session_shm_t *shared_session; -extern volatile void *alloc_shared_object(void); +extern volatile void *alloc_shared_object( mem_size_t shm_size ); extern void free_shared_object( volatile void *object_shm ); extern void invalidate_shared_object( volatile void *object_shm ); extern struct obj_locator get_shared_object_locator( volatile void *object_shm ); diff --git a/server/mapping.c b/server/mapping.c index c3f57b6394c..937ba95b9a0 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -242,6 +242,7 @@ struct session_object { struct list entry; /* entry in the session free object list */ mem_size_t offset; /* offset of obj in the session shared mapping */ + mem_size_t size; /* size of obj in the session shared mapping */ shared_object_t obj; /* object actually shared with the client */ };
@@ -1380,31 +1381,41 @@ static struct session_block *find_free_session_block( mem_size_t size ) return grow_session_mapping( size ); }
-volatile void *alloc_shared_object(void) +static struct session_object *find_free_session_object( mem_size_t size ) { struct session_object *object; - struct list *ptr;
- if ((ptr = list_head( &session.free_objects ))) + LIST_FOR_EACH_ENTRY( object, &session.free_objects, struct session_object, entry ) { - object = CONTAINING_RECORD( ptr, struct session_object, entry ); - list_remove( &object->entry ); + if (size == sizeof(*object) && object->size == size) return object; + if (size > sizeof(*object) && size <= object->size) return object; } + + return NULL; +} + +volatile void *alloc_shared_object( mem_size_t shm_size ) +{ + struct session_object *object; + mem_size_t size = sizeof(*object) - sizeof(object_shm_t) + max(shm_size, sizeof(object_shm_t)); + + if ((object = find_free_session_object( size ))) + list_remove( &object->entry ); else { - mem_size_t size = sizeof(*object); struct session_block *block;
if (!(block = find_free_session_block( size ))) return NULL; object = (struct session_object *)(block->data + block->used_size); object->offset = block->offset + (char *)&object->obj - block->data; + object->size = size; block->used_size += size; }
SHARED_WRITE_BEGIN( &object->obj.shm, object_shm_t ) { /* mark the object data as uninitialized */ - mark_block_uninitialized( (void *)shared, sizeof(*shared) ); + mark_block_uninitialized( (void *)shared, shm_size ); CONTAINING_RECORD( shared, shared_object_t, shm )->id = ++session.last_object_id; } SHARED_WRITE_END; @@ -1415,10 +1426,11 @@ volatile void *alloc_shared_object(void) void free_shared_object( volatile void *object_shm ) { struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm ); + mem_size_t shm_size = object->size - sizeof(*object) + sizeof(object_shm_t);
SHARED_WRITE_BEGIN( &object->obj.shm, object_shm_t ) { - mark_block_noaccess( (void *)shared, sizeof(*shared) ); + mark_block_noaccess( (void *)shared, shm_size ); CONTAINING_RECORD( shared, shared_object_t, shm )->id = 0; } SHARED_WRITE_END; diff --git a/server/queue.c b/server/queue.c index 596742bc64c..90710722c80 100644 --- a/server/queue.c +++ b/server/queue.c @@ -265,7 +265,7 @@ static struct thread_input *create_thread_input( struct thread *thread ) memcpy( input->desktop_keystate, (const void *)input->desktop->shared->keystate, sizeof(input->desktop_keystate) );
- if (!(input->shared = alloc_shared_object())) + if (!(input->shared = alloc_shared_object( sizeof(*input->shared) ))) { release_object( input ); return NULL; @@ -329,7 +329,11 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_event_sync( 1, 0 ))) goto error; - if (!(queue->shared = alloc_shared_object())) goto error; + if (!(queue->shared = alloc_shared_object( sizeof(*queue->shared) ))) + { + release_object( queue ); + return NULL; + }
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) { diff --git a/server/window.c b/server/window.c index 9f871ed9494..d9a2689ae5a 100644 --- a/server/window.c +++ b/server/window.c @@ -681,7 +681,7 @@ static struct window *create_window( struct window *parent, struct window *owner list_init( &win->children ); list_init( &win->unlinked );
- if (!(win->shared = alloc_shared_object())) goto failed; + if (!(win->shared = alloc_shared_object( sizeof(*win->shared) ))) goto failed; SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { shared->class = class_locator; diff --git a/server/winstation.c b/server/winstation.c index bfcd4a53613..52c3f1ce1eb 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -308,7 +308,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned list_init( &desktop->hotkeys ); list_init( &desktop->pointers );
- if (!(desktop->shared = alloc_shared_object())) + if (!(desktop->shared = alloc_shared_object( sizeof(*desktop->shared) ))) { release_object( desktop ); return NULL;