mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-01 22:58:40 -04:00
connection: Always malloc closure
This lets us allocate the closure just big enough and is a first step towards a message queue.
This commit is contained in:
parent
1432bd62df
commit
46f9745c10
4 changed files with 62 additions and 65 deletions
|
|
@ -403,12 +403,12 @@ wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct wl_closure *
|
||||||
wl_closure_vmarshal(struct wl_closure *closure,
|
wl_closure_vmarshal(struct wl_object *sender,
|
||||||
struct wl_object *sender,
|
|
||||||
uint32_t opcode, va_list ap,
|
uint32_t opcode, va_list ap,
|
||||||
const struct wl_message *message)
|
const struct wl_message *message)
|
||||||
{
|
{
|
||||||
|
struct wl_closure *closure;
|
||||||
struct wl_object **objectp, *object;
|
struct wl_object **objectp, *object;
|
||||||
uint32_t length, *p, *start, size, *end;
|
uint32_t length, *p, *start, size, *end;
|
||||||
int dup_fd;
|
int dup_fd;
|
||||||
|
|
@ -417,11 +417,16 @@ wl_closure_vmarshal(struct wl_closure *closure,
|
||||||
char *extra;
|
char *extra;
|
||||||
int i, count, fd, extra_size, *fd_ptr;
|
int i, count, fd, extra_size, *fd_ptr;
|
||||||
|
|
||||||
|
/* FIXME: Match old fixed allocation for now */
|
||||||
|
closure = malloc(sizeof *closure + 1024);
|
||||||
|
if (closure == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
extra_size = wl_message_size_extra(message);
|
extra_size = wl_message_size_extra(message);
|
||||||
count = strlen(message->signature) + 2;
|
count = strlen(message->signature) + 2;
|
||||||
extra = (char *) closure->buffer;
|
extra = (char *) closure->buffer;
|
||||||
start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
|
start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
|
||||||
end = &closure->buffer[ARRAY_LENGTH(closure->buffer)];
|
end = &closure->buffer[256];
|
||||||
p = &start[2];
|
p = &start[2];
|
||||||
|
|
||||||
closure->types[0] = &ffi_type_pointer;
|
closure->types[0] = &ffi_type_pointer;
|
||||||
|
|
@ -553,18 +558,18 @@ wl_closure_vmarshal(struct wl_closure *closure,
|
||||||
ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
|
ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI,
|
||||||
closure->count, &ffi_type_void, closure->types);
|
closure->count, &ffi_type_void, closure->types);
|
||||||
|
|
||||||
return 0;
|
return closure;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
printf("request too big to marshal, maximum size is %zu\n",
|
printf("request too big to marshal, maximum size is %zu\n",
|
||||||
sizeof closure->buffer);
|
sizeof closure->buffer);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct wl_closure *
|
||||||
wl_connection_demarshal(struct wl_connection *connection,
|
wl_connection_demarshal(struct wl_connection *connection,
|
||||||
struct wl_closure *closure,
|
|
||||||
uint32_t size,
|
uint32_t size,
|
||||||
struct wl_map *objects,
|
struct wl_map *objects,
|
||||||
const struct wl_message *message)
|
const struct wl_message *message)
|
||||||
|
|
@ -575,23 +580,20 @@ wl_connection_demarshal(struct wl_connection *connection,
|
||||||
unsigned int i, count, extra_space;
|
unsigned int i, count, extra_space;
|
||||||
struct wl_object **object;
|
struct wl_object **object;
|
||||||
struct wl_array **array;
|
struct wl_array **array;
|
||||||
|
struct wl_closure *closure;
|
||||||
|
|
||||||
count = strlen(message->signature) + 2;
|
count = strlen(message->signature) + 2;
|
||||||
if (count > ARRAY_LENGTH(closure->types)) {
|
if (count > ARRAY_LENGTH(closure->types)) {
|
||||||
printf("too many args (%d)\n", count);
|
printf("too many args (%d)\n", count);
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
wl_connection_consume(connection, size);
|
wl_connection_consume(connection, size);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extra_space = wl_message_size_extra(message);
|
extra_space = wl_message_size_extra(message);
|
||||||
if (sizeof closure->buffer < size + extra_space) {
|
closure = malloc(sizeof *closure + 8 + size + extra_space);
|
||||||
printf("request too big to demarshal, maximum %zu actual %d\n",
|
if (closure == NULL)
|
||||||
sizeof closure->buffer, size + extra_space);
|
return NULL;
|
||||||
errno = ENOMEM;
|
|
||||||
wl_connection_consume(connection, size);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
closure->message = message;
|
closure->message = message;
|
||||||
closure->types[0] = &ffi_type_pointer;
|
closure->types[0] = &ffi_type_pointer;
|
||||||
|
|
@ -748,14 +750,14 @@ wl_connection_demarshal(struct wl_connection *connection,
|
||||||
|
|
||||||
wl_connection_consume(connection, size);
|
wl_connection_consume(connection, size);
|
||||||
|
|
||||||
return 0;
|
return closure;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
closure->count = i;
|
closure->count = i;
|
||||||
wl_closure_destroy(closure);
|
wl_closure_destroy(closure);
|
||||||
wl_connection_consume(connection, size);
|
wl_connection_consume(connection, size);
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -884,4 +886,5 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
|
||||||
void
|
void
|
||||||
wl_closure_destroy(struct wl_closure *closure)
|
wl_closure_destroy(struct wl_closure *closure)
|
||||||
{
|
{
|
||||||
|
free(closure);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,29 +190,28 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
|
wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
|
||||||
{
|
{
|
||||||
struct wl_closure closure;
|
struct wl_closure *closure;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
|
||||||
|
|
||||||
va_start(ap, opcode);
|
va_start(ap, opcode);
|
||||||
ret = wl_closure_vmarshal(&closure, &proxy->object, opcode, ap,
|
closure = wl_closure_vmarshal(&proxy->object, opcode, ap,
|
||||||
&proxy->object.interface->methods[opcode]);
|
&proxy->object.interface->methods[opcode]);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (ret) {
|
if (closure == NULL) {
|
||||||
fprintf(stderr, "Error marshalling request\n");
|
fprintf(stderr, "Error marshalling request\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_closure_send(&closure, proxy->display->connection)) {
|
if (wl_closure_send(closure, proxy->display->connection)) {
|
||||||
fprintf(stderr, "Error sending request: %m\n");
|
fprintf(stderr, "Error sending request: %m\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_debug)
|
if (wl_debug)
|
||||||
wl_closure_print(&closure, &proxy->object, true);
|
wl_closure_print(closure, &proxy->object, true);
|
||||||
|
|
||||||
wl_closure_destroy(&closure);
|
wl_closure_destroy(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can't do this, there may be more than one instance of an
|
/* Can't do this, there may be more than one instance of an
|
||||||
|
|
@ -468,9 +467,8 @@ handle_event(struct wl_display *display,
|
||||||
uint32_t id, uint32_t opcode, uint32_t size)
|
uint32_t id, uint32_t opcode, uint32_t size)
|
||||||
{
|
{
|
||||||
struct wl_proxy *proxy;
|
struct wl_proxy *proxy;
|
||||||
struct wl_closure closure;
|
struct wl_closure *closure;
|
||||||
const struct wl_message *message;
|
const struct wl_message *message;
|
||||||
int ret;
|
|
||||||
|
|
||||||
proxy = wl_map_lookup(&display->objects, id);
|
proxy = wl_map_lookup(&display->objects, id);
|
||||||
|
|
||||||
|
|
@ -483,22 +481,22 @@ handle_event(struct wl_display *display,
|
||||||
}
|
}
|
||||||
|
|
||||||
message = &proxy->object.interface->events[opcode];
|
message = &proxy->object.interface->events[opcode];
|
||||||
ret = wl_connection_demarshal(display->connection, &closure,
|
closure = wl_connection_demarshal(display->connection, size,
|
||||||
size, &display->objects, message);
|
&display->objects, message);
|
||||||
|
|
||||||
if (ret) {
|
if (closure == NULL) {
|
||||||
fprintf(stderr, "Error demarshalling event\n");
|
fprintf(stderr, "Error demarshalling event\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_debug)
|
if (wl_debug)
|
||||||
wl_closure_print(&closure, &proxy->object, false);
|
wl_closure_print(closure, &proxy->object, false);
|
||||||
|
|
||||||
wl_closure_invoke(&closure, &proxy->object,
|
wl_closure_invoke(closure, &proxy->object,
|
||||||
proxy->object.implementation[opcode],
|
proxy->object.implementation[opcode],
|
||||||
proxy->user_data);
|
proxy->user_data);
|
||||||
|
|
||||||
wl_closure_destroy(&closure);
|
wl_closure_destroy(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
|
|
|
||||||
|
|
@ -76,19 +76,17 @@ struct wl_closure {
|
||||||
ffi_type *types[20];
|
ffi_type *types[20];
|
||||||
ffi_cif cif;
|
ffi_cif cif;
|
||||||
void *args[20];
|
void *args[20];
|
||||||
uint32_t buffer[256];
|
|
||||||
uint32_t *start;
|
uint32_t *start;
|
||||||
|
uint32_t buffer[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
struct wl_closure *
|
||||||
wl_closure_vmarshal(struct wl_closure *closure,
|
wl_closure_vmarshal(struct wl_object *sender,
|
||||||
struct wl_object *sender,
|
|
||||||
uint32_t opcode, va_list ap,
|
uint32_t opcode, va_list ap,
|
||||||
const struct wl_message *message);
|
const struct wl_message *message);
|
||||||
|
|
||||||
int
|
struct wl_closure *
|
||||||
wl_connection_demarshal(struct wl_connection *connection,
|
wl_connection_demarshal(struct wl_connection *connection,
|
||||||
struct wl_closure *closure,
|
|
||||||
uint32_t size,
|
uint32_t size,
|
||||||
struct wl_map *objects,
|
struct wl_map *objects,
|
||||||
const struct wl_message *message);
|
const struct wl_message *message);
|
||||||
|
|
|
||||||
|
|
@ -102,54 +102,52 @@ destroy_client(void *data)
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
|
wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
|
||||||
{
|
{
|
||||||
struct wl_closure closure;
|
struct wl_closure *closure;
|
||||||
struct wl_object *object = &resource->object;
|
struct wl_object *object = &resource->object;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
|
||||||
|
|
||||||
va_start(ap, opcode);
|
va_start(ap, opcode);
|
||||||
ret = wl_closure_vmarshal(&closure, object, opcode, ap,
|
closure = wl_closure_vmarshal(object, opcode, ap,
|
||||||
&object->interface->events[opcode]);
|
&object->interface->events[opcode]);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (ret)
|
if (closure == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wl_closure_send(&closure, resource->client->connection))
|
if (wl_closure_send(closure, resource->client->connection))
|
||||||
wl_event_loop_add_idle(resource->client->display->loop,
|
wl_event_loop_add_idle(resource->client->display->loop,
|
||||||
destroy_client, resource->client);
|
destroy_client, resource->client);
|
||||||
|
|
||||||
if (wl_debug)
|
if (wl_debug)
|
||||||
wl_closure_print(&closure, object, true);
|
wl_closure_print(closure, object, true);
|
||||||
|
|
||||||
wl_closure_destroy(&closure);
|
wl_closure_destroy(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
|
wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
|
||||||
{
|
{
|
||||||
struct wl_closure closure;
|
struct wl_closure *closure;
|
||||||
struct wl_object *object = &resource->object;
|
struct wl_object *object = &resource->object;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
|
||||||
|
|
||||||
va_start(ap, opcode);
|
va_start(ap, opcode);
|
||||||
ret = wl_closure_vmarshal(&closure, object, opcode, ap,
|
closure = wl_closure_vmarshal(object, opcode, ap,
|
||||||
&object->interface->events[opcode]);
|
&object->interface->events[opcode]);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (ret)
|
if (closure == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wl_closure_queue(&closure, resource->client->connection))
|
if (wl_closure_queue(closure, resource->client->connection))
|
||||||
wl_event_loop_add_idle(resource->client->display->loop,
|
wl_event_loop_add_idle(resource->client->display->loop,
|
||||||
destroy_client, resource->client);
|
destroy_client, resource->client);
|
||||||
|
|
||||||
if (wl_debug)
|
if (wl_debug)
|
||||||
wl_closure_print(&closure, object, true);
|
wl_closure_print(closure, object, true);
|
||||||
|
|
||||||
wl_closure_destroy(&closure);
|
wl_closure_destroy(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
|
|
@ -187,12 +185,12 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||||
struct wl_connection *connection = client->connection;
|
struct wl_connection *connection = client->connection;
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
struct wl_object *object;
|
struct wl_object *object;
|
||||||
struct wl_closure closure;
|
struct wl_closure *closure;
|
||||||
const struct wl_message *message;
|
const struct wl_message *message;
|
||||||
uint32_t p[2];
|
uint32_t p[2];
|
||||||
int opcode, size;
|
int opcode, size;
|
||||||
uint32_t cmask = 0;
|
uint32_t cmask = 0;
|
||||||
int len, ret;
|
int len;
|
||||||
|
|
||||||
if (mask & WL_EVENT_READABLE)
|
if (mask & WL_EVENT_READABLE)
|
||||||
cmask |= WL_CONNECTION_READABLE;
|
cmask |= WL_CONNECTION_READABLE;
|
||||||
|
|
@ -232,11 +230,11 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
message = &object->interface->methods[opcode];
|
message = &object->interface->methods[opcode];
|
||||||
ret = wl_connection_demarshal(client->connection, &closure,
|
closure = wl_connection_demarshal(client->connection, size,
|
||||||
size, &client->objects, message);
|
&client->objects, message);
|
||||||
len -= size;
|
len -= size;
|
||||||
|
|
||||||
if (ret && errno == EINVAL) {
|
if (closure == NULL && errno == EINVAL) {
|
||||||
wl_resource_post_error(client->display_resource,
|
wl_resource_post_error(client->display_resource,
|
||||||
WL_DISPLAY_ERROR_INVALID_METHOD,
|
WL_DISPLAY_ERROR_INVALID_METHOD,
|
||||||
"invalid arguments for %s@%d.%s",
|
"invalid arguments for %s@%d.%s",
|
||||||
|
|
@ -244,18 +242,18 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||||
object->id,
|
object->id,
|
||||||
message->name);
|
message->name);
|
||||||
break;
|
break;
|
||||||
} else if (ret && errno == ENOMEM) {
|
} else if (closure == NULL && errno == ENOMEM) {
|
||||||
wl_resource_post_no_memory(resource);
|
wl_resource_post_no_memory(resource);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_debug)
|
if (wl_debug)
|
||||||
wl_closure_print(&closure, object, false);
|
wl_closure_print(closure, object, false);
|
||||||
|
|
||||||
wl_closure_invoke(&closure, object,
|
wl_closure_invoke(closure, object,
|
||||||
object->implementation[opcode], client);
|
object->implementation[opcode], client);
|
||||||
|
|
||||||
wl_closure_destroy(&closure);
|
wl_closure_destroy(closure);
|
||||||
|
|
||||||
if (client->error)
|
if (client->error)
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue