refactor: break out buffers

mmap-opt
Sean McBride 4 years ago
parent 64e35f767e
commit a9d3b3199f

@ -65,11 +65,12 @@ client_socket_send(int client_socket, int status_code)
while (total_sent < to_send) {
ssize_t sent = write(client_socket, &response[total_sent], to_send - total_sent);
if (sent < 0) {
if (errno == EAGAIN) { debuglog("Unexpectedly blocking on write of %s\n", response); }
debuglog("Error with %s\n", strerror(errno));
goto send_err;
if (errno == EAGAIN) {
debuglog("Unexpectedly blocking on write of %s\n", response);
} else {
debuglog("Error with %s\n", strerror(errno));
goto send_err;
}
}
total_sent += sent;
};

@ -0,0 +1,88 @@
#pragma once
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "current_sandbox.h"
#include "http.h"
#include "http_total.h"
#include "likely.h"
#include "sandbox_types.h"
#include "scheduler.h"
#include "panic.h"
/**
* Sends Response Back to Client
* @return RC. -1 on Failure
*/
static inline int
current_sandbox_send_response()
{
struct sandbox *sandbox = current_sandbox_get();
assert(sandbox != NULL);
int rc;
ssize_t sent = 0;
/* Determine values to template into our HTTP response */
ssize_t response_body_size = sandbox->response.length;
char * module_content_type = sandbox->module->response_content_type;
const char *content_type = strlen(module_content_type) > 0 ? module_content_type : "text/plain";
/* Capture Timekeeping data for end-to-end latency */
uint64_t end_time = __getcycles();
sandbox->total_time = end_time - sandbox->timestamp_of.request_arrival;
/* Send HTTP Response Headers */
ssize_t response_size = http_response_200_size(content_type, response_body_size);
char header_buffer[response_size + 1];
rc = sprintf(header_buffer, HTTP_RESPONSE_200_TEMPLATE, content_type, response_body_size);
if (rc <= 0) {
perror("sprintf");
goto err;
}
while (sent < response_size) {
rc = write(sandbox->client_socket_descriptor, &header_buffer[sent], response_size - sent);
if (rc < 0) {
if (errno == EAGAIN)
current_sandbox_sleep();
else {
perror("write");
goto err;
}
}
sent += rc;
}
/* Send HTTP Response Body */
sent = 0;
response_size = response_body_size;
while (sent < response_size) {
rc = write(sandbox->client_socket_descriptor, &sandbox->response.base[sent], response_size - sent);
if (rc < 0) {
if (errno == EAGAIN)
current_sandbox_sleep();
else {
perror("write");
goto err;
}
}
sent += rc;
}
http_total_increment_2xx();
rc = 0;
done:
return rc;
err:
debuglog("Error sending to client: %s", strerror(errno));
rc = -1;
goto done;
}

@ -30,46 +30,27 @@
"Server: SLEdge\r\n" \
"Connection: close\r\n" \
"Content-Type: %s\r\n" \
"Content-Length: %s\r\n" \
"Content-Length: %lu\r\n" \
"\r\n"
/* The sum of format specifier characters in the template above */
#define HTTP_RESPONSE_200_TEMPLATE_FORMAT_SPECIFIER_LENGTH 4
#define HTTP_RESPONSE_200_TEMPLATE_FORMAT_SPECIFIER_LENGTH 5
/**
* Calculates the number of bytes of the HTTP response containing the passed header values
* @return total size in bytes
*/
static inline size_t
http_response_200_size(char *content_type, char *content_length)
http_response_200_size(const char *content_type, ssize_t content_length)
{
size_t size = 0;
size += strlen(HTTP_RESPONSE_200_TEMPLATE) - HTTP_RESPONSE_200_TEMPLATE_FORMAT_SPECIFIER_LENGTH;
size += strlen(content_type);
size += strlen(content_length);
return size;
}
/**
* Writes the HTTP response header to the destination. This is assumed to have been sized
* using the value returned by http_response_200_size. We have to use an intermediate buffer
* in order to truncate off the null terminator
* @return 0 on success, -1 otherwise
*/
static inline int
http_response_200(char *destination, char *content_type, char *content_length)
{
size_t response_size = http_response_200_size(content_type, content_length);
char buffer[response_size + 1];
int rc = 0;
rc = sprintf(buffer, HTTP_RESPONSE_200_TEMPLATE, content_type, content_length);
if (rc <= 0) goto err;
memmove(destination, buffer, response_size);
rc = 0;
while (content_length > 0) {
content_length /= 10;
size++;
}
done:
return rc;
err:
rc = -1;
goto done;
return size;
}

@ -1,74 +0,0 @@
#pragma once
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "current_sandbox.h"
#include "http.h"
#include "http_total.h"
#include "likely.h"
#include "sandbox_types.h"
#include "scheduler.h"
#include "panic.h"
/**
* Sends Response Back to Client
* @return RC. -1 on Failure
*/
static inline int
sandbox_send_response(struct sandbox *sandbox)
{
assert(sandbox != NULL);
/* Assumption: The HTTP Request Buffer immediately precedes the HTTP Response Buffer,
* meaning that when we prepend, we are overwritting the tail of the HTTP request buffer */
assert(sandbox->request.base + sandbox->module->max_request_size == sandbox->response.base);
int rc;
/* Determine values to template into our HTTP response */
ssize_t response_body_size = sandbox->response.length;
char content_length[20] = { 0 };
sprintf(content_length, "%zu", response_body_size);
char *module_content_type = sandbox->module->response_content_type;
char *content_type = strlen(module_content_type) > 0 ? module_content_type : "text/plain";
/* Prepend HTTP Response Headers */
size_t response_header_size = http_response_200_size(content_type, content_length);
char * response_header = sandbox->response.base - response_header_size;
rc = http_response_200(response_header, content_type, content_length);
if (rc < 0) goto err;
/* Capture Timekeeping data for end-to-end latency */
uint64_t end_time = __getcycles();
sandbox->total_time = end_time - sandbox->timestamp_of.request_arrival;
/* Send HTTP Response */
int sent = 0;
size_t response_size = response_header_size + response_body_size;
while (sent < response_size) {
rc = write(sandbox->client_socket_descriptor, response_header, response_size - sent);
if (rc < 0) {
if (errno == EAGAIN)
current_sandbox_sleep();
else {
perror("write");
goto err;
}
}
sent += rc;
}
http_total_increment_2xx();
rc = 0;
done:
return rc;
err:
rc = -1;
goto done;
}

@ -87,7 +87,6 @@ struct sandbox {
int client_socket_descriptor;
http_parser http_parser;
struct http_request http_request;
ssize_t http_request_length; /* TODO: Get rid of me */
struct sandbox_buffer request;
struct sandbox_buffer response;

@ -1,9 +1,9 @@
#include <threads.h>
#include "current_sandbox.h"
#include "current_sandbox_send_response.h"
#include "sandbox_functions.h"
#include "sandbox_receive_request.h"
#include "sandbox_send_response.h"
#include "sandbox_set_as_asleep.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_returned.h"
@ -148,7 +148,7 @@ current_sandbox_fini()
sandbox->timestamp_of.completion = __getcycles();
/* Retrieve the result, construct the HTTP response, and send to client */
if (sandbox_send_response(sandbox) < 0) {
if (current_sandbox_send_response() < 0) {
error_message = "Unable to build and send client response\n";
goto err;
};

@ -26,10 +26,8 @@ sandbox_allocate_memory(struct module *module)
struct sandbox *sandbox = NULL;
unsigned long page_aligned_sandbox_size = round_up_to_page(sizeof(struct sandbox));
unsigned long size_to_alloc = page_aligned_sandbox_size + module->max_request_size + module->max_request_size
+ memory_max + /* guard page */ PAGE_SIZE;
unsigned long size_to_read_write = page_aligned_sandbox_size + module->max_request_size
+ module->max_request_size + memory_size;
unsigned long size_to_alloc = memory_max + /* guard page */ PAGE_SIZE;
unsigned long size_to_read_write = memory_size;
/*
* Control information should be page-aligned
@ -55,23 +53,22 @@ sandbox_allocate_memory(struct module *module)
goto set_rw_failed;
}
sandbox = (struct sandbox *)addr_rw;
sandbox = calloc(1, page_aligned_sandbox_size);
/* Populate Sandbox members */
sandbox->state = SANDBOX_UNINITIALIZED;
sandbox->module = module;
module_acquire(module);
sandbox->request.base = (char *)addr + page_aligned_sandbox_size;
sandbox->request.base = calloc(1, module->max_request_size);
sandbox->request.length = 0;
sandbox->response.base = (char *)addr + page_aligned_sandbox_size + module->max_request_size;
sandbox->request.length = 0;
sandbox->response.base = calloc(1, module->max_response_size);
sandbox->response.length = 0;
sandbox->memory.start = (char *)addr + page_aligned_sandbox_size + module->max_request_size
+ module->max_request_size;
sandbox->memory.size = memory_size;
sandbox->memory.max = memory_max;
sandbox->memory.start = addr_rw;
sandbox->memory.size = memory_size;
sandbox->memory.max = memory_max;
memset(&sandbox->duration_of_state, 0, SANDBOX_STATE_COUNT * sizeof(uint64_t));
@ -96,7 +93,7 @@ sandbox_allocate_stack(struct sandbox *sandbox)
int rc = 0;
char *addr = mmap(NULL, sandbox->module->stack_size + /* guard page */ PAGE_SIZE, PROT_NONE,
char *addr = mmap(NULL, /* guard page */ PAGE_SIZE + sandbox->module->stack_size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (unlikely(addr == MAP_FAILED)) {
perror("sandbox allocate stack");
@ -222,16 +219,10 @@ sandbox_free(struct sandbox *sandbox)
/* Linear Memory and Guard Page should already have been munmaped and set to NULL */
assert(sandbox->memory.start == NULL);
errno = 0;
unsigned long size_to_unmap = round_up_to_page(sizeof(struct sandbox)) + sandbox->module->max_request_size
+ sandbox->module->max_response_size;
munmap(sandbox, size_to_unmap);
if (rc == -1) {
debuglog("Failed to unmap Sandbox %lu\n", sandbox->id);
goto err_free_sandbox_failed;
};
free(sandbox->request.base);
free(sandbox->response.base);
free(sandbox);
done:
return;
err_free_sandbox_failed:

Loading…
Cancel
Save