#include #include #include #include typedef uint32_t cliptr_t; #define MEMORY_LIMIT (1<<30) // 1GB typedef struct client_s { void* memory; cliptr_t /* some_object* */ some_data; } client; #define cliptr(T,C,P) ((T)(((char*)((C)->memory))+(P))) #define cliptr_safe(T,C,P) (((P)memory)) #define PTRCLI(P) ptrcli(cli, P) client* client_create(void){ client* cli = malloc(sizeof(client)); if(!cli) return 0; cli->memory = mmap(0, MEMORY_LIMIT, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(cli->memory == MAP_FAILED){ free(cli); return 0; } return cli; } void client_destroy(client* cli){ munmap(cli->memory, MEMORY_LIMIT); free(cli); } void* cli_malloc(client* cli, size_t s){ // TODO: mmap if necessary and return some memory within cli->memory } #define CLI_MALLOC(X) cli_malloc(cli, (X)) void cli_free(client* cli, cliptr_t object){ // TODO: mmap if possible the freed pages as PROT_NONE and mark them as freed } #define CLI_FREE(X) cli_malloc(cli, (X)) // These objects store the state of a client typedef struct some_object_s { cliptr_t /* some_object* */ next; // Always points to an object belonging to the same client as the containing object } some_object; // RPC functions, called by the client void client_add_something(client* cli){ some_object* new_thing = CLI_MALLOC(sizeof(*new_thing)); if(!new_thing) return; new_thing->next = cli->some_data; cli->some_data = PTRCLI(new_thing); } void client_remove_stuff(client* cli, cliptr_t ptr){ // RPC call from client if(ptr >= MEMORY_LIMIT) // Verify object is owned by client return; for(cliptr_t* it=&cli->some_data; *it < MEMORY_LIMIT; it=&CLIPTR(some_object*, *it)->next){ if(*it == ptr){ *it = CLIPTR(some_object*, *it)->next; cli_free(cli, ptr); break; } } }