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:
Kristian Høgsberg 2012-06-12 17:45:25 -04:00
parent 1432bd62df
commit 46f9745c10
4 changed files with 62 additions and 65 deletions

View file

@ -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);
} }

View file

@ -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

View file

@ -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);

View file

@ -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;