diff --git a/compiler/C_CodeGen.jrag b/compiler/C_CodeGen.jrag index 786f5ccc2db674177682fc50cce52eb382692877..551e14d77b0e0c332338d7ec86871756ce1425e7 100644 --- a/compiler/C_CodeGen.jrag +++ b/compiler/C_CodeGen.jrag @@ -538,7 +538,9 @@ aspect C_Decoder { } public void VariableArrayType.C_emitDecoderArrayAllocate(C_env env) { - env.print(env.qualid + ".a = malloc(sizeof(" + env.qualid + ".a[0])"); + env.print(env.qualid + + ".a = labcomm_memory_alloc(r->memory, 1, sizeof(" + + env.qualid + ".a[0])"); for (int i = 0 ; i < getNumExp() ; i++) { env.print(" * " + getExp(i).C_getLimit(env, i)); } @@ -555,7 +557,8 @@ aspect C_Decoder { public void PrimType.C_emitDecoderDeallocation(C_env env) { if (C_isDynamic()) { - env.println("free(" + env.qualid + ");"); + env.println("labcomm_memory_free(r->memory, 1, " + + env.qualid + ");"); } } @@ -600,7 +603,8 @@ aspect C_Decoder { public void VariableArrayType.C_emitDecoderDeallocation(C_env env) { super.C_emitDecoderDeallocation(env); - env.println("free(" + env.qualid + ".a);"); + env.println("labcomm_memory_free(r->memory, 1, " + + env.qualid + ".a);"); } public void Field.C_emitDecoderDeallocation(C_env env) { diff --git a/examples/simple/example_decoder.c b/examples/simple/example_decoder.c index d79bc7aa5c5e468aa720e3966ba4120a1f671f71..2b1f746bcd0fc0ce9279fde3d34d549648eb9153 100644 --- a/examples/simple/example_decoder.c +++ b/examples/simple/example_decoder.c @@ -56,7 +56,9 @@ int main(int argc, char *argv[]) { char *filename = argv[1]; printf("C decoder reading from %s\n", filename); fd = open(filename, O_RDONLY); - decoder = labcomm_decoder_new(labcomm_fd_reader_new(fd, 1), NULL); + decoder = labcomm_decoder_new(labcomm_fd_reader_new( + labcomm_default_memory, fd, 1), + NULL, labcomm_default_memory); if (!decoder) { printf("Failed to allocate decoder %s:%d\n", __FUNCTION__, __LINE__); return 1; diff --git a/examples/simple/example_encoder.c b/examples/simple/example_encoder.c index b4f392176970b24c7984552060a2007a73adfa7f..67beb4c369c80f1437ce601a800f83968f43a660 100644 --- a/examples/simple/example_encoder.c +++ b/examples/simple/example_encoder.c @@ -12,7 +12,9 @@ int main(int argc, char *argv[]) { char *filename = argv[1]; printf("C encoder writing to %s\n", filename); fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); - encoder = labcomm_encoder_new(labcomm_fd_writer_new(fd, 1), NULL); + encoder = labcomm_encoder_new(labcomm_fd_writer_new( + labcomm_default_memory, fd, 1), + NULL, labcomm_default_memory); labcomm_encoder_register_simple_theTwoInts(encoder); labcomm_encoder_register_simple_anotherTwoInts(encoder); labcomm_encoder_register_simple_IntString(encoder); diff --git a/examples/twoway/Makefile b/examples/twoway/Makefile index 5689df1d9fd0b482a3fd671b6fe59f7c869da813..76da45e3412d153c37ed286cf342a2a347c16348 100644 --- a/examples/twoway/Makefile +++ b/examples/twoway/Makefile @@ -42,11 +42,11 @@ gen/introspecting.o: introspecting.h gen/introspecting.o: gen/introspecting_messages.h gen/client.o: decimating.h gen/client.o: gen/types.h -gen/client: gen/types.o gen/client: gen/decimating.o gen/client: gen/decimating_messages.o gen/client: gen/introspecting.o gen/client: gen/introspecting_messages.o +gen/client: gen/types.o gen/server: gen/types.o gen/server: gen/decimating.o gen/server: gen/decimating_messages.o diff --git a/examples/twoway/client.c b/examples/twoway/client.c index ec373b1ca8db7eb161094c89eb8c02c47841637e..401a7a55aadbe720a016924bbae2c62eaeed3740 100644 --- a/examples/twoway/client.c +++ b/examples/twoway/client.c @@ -53,6 +53,8 @@ static void *run_decoder(void *context) struct labcomm_decoder *decoder = context; int result; + labcomm_decoder_register_types_Sum(decoder, handle_Sum, NULL); + labcomm_decoder_register_types_Diff(decoder, handle_Diff, NULL); do { result = labcomm_decoder_decode_one(decoder); } while (result >= 0); @@ -112,34 +114,35 @@ int main(int argc, char *argv[]) nodelay = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); - lock = labcomm_pthread_mutex_lock_new(); - decimating = decimating_new(labcomm_fd_reader_new(fd, 1), - labcomm_fd_writer_new(fd, 0), - lock); + lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory); + decimating = decimating_new(labcomm_fd_reader_new(labcomm_default_memory, + fd, 1), + labcomm_fd_writer_new(labcomm_default_memory, + fd, 0), + lock, + labcomm_default_memory); if (decimating == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } introspecting = introspecting_new(decimating->reader, decimating->writer, - lock); + lock, + labcomm_default_memory); if (introspecting == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } - decoder = labcomm_decoder_new(introspecting->reader, lock); - encoder = labcomm_encoder_new(introspecting->writer, lock); + decoder = labcomm_decoder_new(introspecting->reader, lock, + labcomm_default_memory); + encoder = labcomm_encoder_new(introspecting->writer, lock, + labcomm_default_memory); pthread_t rdt; - - labcomm_decoder_register_types_Sum(decoder, handle_Sum, NULL); - labcomm_decoder_register_types_Diff(decoder, handle_Diff, NULL); pthread_create(&rdt, NULL, run_decoder, decoder); labcomm_encoder_register_types_A(encoder); labcomm_encoder_register_types_B(encoder); labcomm_encoder_register_types_Terminate(encoder); - usleep(100000); - err = labcomm_decoder_ioctl_types_Sum(decoder, SET_DECIMATION, 2); err = labcomm_decoder_ioctl_types_Diff(decoder, SET_DECIMATION, 4); @@ -151,7 +154,7 @@ int main(int argc, char *argv[]) sleep(1); } } - labcomm_encode_types_Terminate(encoder, NULL); + labcomm_encode_types_Terminate(encoder, LABCOMM_VOID); out: return 0; diff --git a/examples/twoway/decimating.c b/examples/twoway/decimating.c index 9ce2b34bd584c3b82355269e5e8088ecf7ff170f..52b2329d6b2e4726c2dba1d970fafb5f9e79e1d2 100644 --- a/examples/twoway/decimating.c +++ b/examples/twoway/decimating.c @@ -29,8 +29,8 @@ struct decimating_private { struct decimating decimating; + struct labcomm_memory *memory; struct labcomm_lock *lock; - struct labcomm_encoder *encoder; int encoder_initialized; struct labcomm_reader_action_context reader_action_context; struct labcomm_writer_action_context writer_action_context; @@ -48,7 +48,8 @@ static void set_decimation( struct decimating_private *decimating = context; struct decimation *decimation; - decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->decimation, + decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->memory, + decimating->decimation, struct decimation, value->signature_index); decimation->n = value->decimation; @@ -92,7 +93,7 @@ static int wrap_reader_ioctl( decimation.signature_index = signature_index; va_end(va); return labcomm_encode_decimating_messages_set_decimation( - decimating->encoder, &decimation); + decimating->decimating.writer->encoder, &decimation); } else { return labcomm_reader_ioctl(r, action_context->next, signature_index, signature, action, args); @@ -123,11 +124,8 @@ static int wrap_writer_alloc( labcomm_encoder_enqueue enqueue) { int result; - struct decimating_private *decimating = action_context->context; fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__); - /* Stash away encoder for later use */ - decimating->encoder = encoder; result = labcomm_writer_alloc(w, action_context->next, encoder, labcomm_version, enqueue); enqueue(encoder, register_signatures, NULL); @@ -144,7 +142,8 @@ static int wrap_writer_start( struct decimating_private *decimating = action_context->context; struct decimation *decimation; - decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->decimation, + decimation = LABCOMM_SIGNATURE_ARRAY_REF(decimating->memory, + decimating->decimation, struct decimation, index); decimation->current++; if (decimation->current < decimation->n) { @@ -168,7 +167,8 @@ struct labcomm_writer_action decimating_writer_action = { extern struct decimating *decimating_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock) + struct labcomm_lock *lock, + struct labcomm_memory *memory) { struct decimating_private *result; @@ -194,8 +194,7 @@ extern struct decimating *decimating_new( /* Init other fields */ result->lock = lock; - result->encoder = NULL; - result->encoder_initialized = 0; + result->memory = memory; LABCOMM_SIGNATURE_ARRAY_INIT(result->decimation, struct decimation); goto out_ok; diff --git a/examples/twoway/decimating.h b/examples/twoway/decimating.h index ca539c0d18d90643c977a7e9f9ad3ae95d7506bd..df926efad1cf1a927a67aad36b79d597ac57e5eb 100644 --- a/examples/twoway/decimating.h +++ b/examples/twoway/decimating.h @@ -12,7 +12,8 @@ struct decimating { extern struct decimating *decimating_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock); + struct labcomm_lock *lock, + struct labcomm_memory *memory); #define SET_DECIMATION LABCOMM_IOSW('d',0,int) diff --git a/examples/twoway/introspecting.c b/examples/twoway/introspecting.c index 85c29191bf05583c66b6b5b71a80b06f7dcb4faf..8123988b3218b72e98f5a20b5b1f0cf31b541022 100644 --- a/examples/twoway/introspecting.c +++ b/examples/twoway/introspecting.c @@ -27,19 +27,28 @@ #include "introspecting.h" #include "gen/introspecting_messages.h" +enum status {unknown, unhandled, unregistered, registered}; struct introspecting_private { struct introspecting introspecting; + struct labcomm_lock *lock; + struct labcomm_memory *memory; + struct labcomm_encoder *encoder; int encoder_initialized; struct labcomm_decoder *decoder; int decoder_initialized; - struct labcomm_lock *lock; struct labcomm_reader_action_context reader_action_context; struct labcomm_writer_action_context writer_action_context; - LABCOMM_SIGNATURE_ARRAY_DEF(introspection, - struct introspection { - int has_got_response; - int has_handler; + LABCOMM_SIGNATURE_ARRAY_DEF(remote, + struct remote { + char *name; + int size; + uint8_t *signature; + }); + LABCOMM_SIGNATURE_ARRAY_DEF(local, + struct local { + enum status status; + struct labcomm_signature *signature; }); }; @@ -48,16 +57,37 @@ static void handles_signature( void * context) { fprintf(stderr, "### %s %x %s\n", __FUNCTION__, value->index, value->name); -/* struct introspecting_private *introspecting = context; - struct introspection *introspection; - - introspection = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->introspection, - struct introspection, - value->index); - - introspection->has_handler = value->has_handler; -*/ + struct remote *remote; + + remote = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory, + introspecting->remote, + struct remote, + value->index); + remote->name = strdup(value->name); + remote->signature = malloc(value->signature.n_0); + if (remote->signature) { + int i; + + memcpy(remote->signature, value->signature.a, value->signature.n_0); + remote->size = value->signature.n_0; + LABCOMM_SIGNATURE_ARRAY_FOREACH(introspecting->local, struct local, i) { + struct local *l; + + l = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory, + introspecting->local, struct local, i); + if (l->signature && + l->status == unhandled && + l->signature->name && + strcmp(remote->name, l->signature->name) == 0 && + remote->size == l->signature->size && + memcmp(l->signature->signature, remote->signature, + l->signature->size) == 0) { + fprintf(stderr, "OK %s %x %x\n", __FUNCTION__, value->index, i); + l->status = unregistered; + } + } + } } static int wrap_reader_alloc( @@ -87,10 +117,19 @@ static int wrap_reader_start( void *value) { struct introspecting_private *introspecting = action_context->context; - - if (value == NULL && introspecting->decoder_initialized) { + int result; + + result = labcomm_reader_start(r, action_context->next, index, + signature, value); + if (value == NULL) { introspecting_messages_handles_signature handles_signature; + labcomm_lock_acquire(introspecting->lock); + while (introspecting->encoder == NULL) { + /* Wait for the encoder to become functional */ + labcomm_lock_wait(introspecting->lock, 1000000); + } + labcomm_lock_release(introspecting->lock); handles_signature.index = index; handles_signature.name = signature->name; handles_signature.signature.n_0 = signature->size; @@ -98,7 +137,7 @@ static int wrap_reader_start( labcomm_encode_introspecting_messages_handles_signature( introspecting->encoder, &handles_signature); } - return labcomm_reader_start(r, action_context->next, index, signature, value); + return result; } void encode_handles_signature( @@ -146,7 +185,10 @@ static int wrap_writer_alloc( fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__); /* Stash away encoder for later use */ + labcomm_lock_acquire(introspecting->lock); introspecting->encoder = encoder; + labcomm_lock_notify(introspecting->lock); + labcomm_lock_release(introspecting->lock); result = labcomm_writer_alloc(w, action_context->next, encoder, labcomm_version, enqueue); enqueue(encoder, register_signatures, NULL); @@ -159,9 +201,39 @@ static int wrap_writer_start( int index, struct labcomm_signature *signature, void *value) { -// struct introspecting_private *introspecting = action_context->context; - - fprintf(stderr, "%s %p\n", __FUNCTION__, value); + struct introspecting_private *introspecting = action_context->context; + struct local *local; + + fprintf(stderr, "%s %x %s\n", __FUNCTION__, index, signature->name); + local = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory, + introspecting->local, + struct local, + index); + if (local->signature == NULL) { + local->signature = signature; + } + if (local->status == unknown) { + int i; + int found = 0; + + LABCOMM_SIGNATURE_ARRAY_FOREACH(introspecting->remote, struct remote, i) { + struct remote *r; + + r = LABCOMM_SIGNATURE_ARRAY_REF(introspecting->memory, + introspecting->remote, struct remote, i); + if (r->name && + strcmp(signature->name, r->name) == 0 && + r->size == signature->size && + memcmp(signature->signature, r->signature, signature->size) == 0) { + fprintf(stderr, "OK %s %x %x\n", __FUNCTION__, index, i); + found = i; + } + } + if (found == 0) { + local->status = unhandled; + } + fprintf(stderr, "Found: %d\n", found); + } return labcomm_writer_start(w, action_context->next, index, signature, value); } @@ -177,7 +249,8 @@ struct labcomm_writer_action introspecting_writer_action = { extern struct introspecting *introspecting_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock) + struct labcomm_lock *lock, + struct labcomm_memory *memory) { struct introspecting_private *result; @@ -202,12 +275,14 @@ extern struct introspecting *introspecting_new( result->introspecting.writer = writer; /* Init other fields */ + result->lock = lock; + result->memory = memory; result->encoder = NULL; result->encoder_initialized = 0; result->decoder = NULL; result->decoder_initialized = 0; - result->lock = lock; - LABCOMM_SIGNATURE_ARRAY_INIT(result->introspection, struct introspection); + LABCOMM_SIGNATURE_ARRAY_INIT(result->remote, struct remote); + LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct local); goto out_ok; diff --git a/examples/twoway/introspecting.h b/examples/twoway/introspecting.h index 9c168274d41c626250e16e2615e974991262417d..7eea00e1855013999cb8936400719a2fccd36f8b 100644 --- a/examples/twoway/introspecting.h +++ b/examples/twoway/introspecting.h @@ -36,7 +36,8 @@ struct introspecting { extern struct introspecting *introspecting_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock); + struct labcomm_lock *lock, + struct labcomm_memory *memory); #define HAS_SIGNATURE LABCOMM_IOS('i',2) diff --git a/examples/twoway/server.c b/examples/twoway/server.c index 9a980cb4f08187e0d3a47406c91f9b298b911d19..58a8ae0e39eb8fb7cc8fe480c0de266e336b6a74 100644 --- a/examples/twoway/server.c +++ b/examples/twoway/server.c @@ -68,13 +68,18 @@ static void handle_Terminate(types_Terminate *value, void *context) exit(0); } -static void *run_decoder(void *context) +static void *run_decoder(void *arg) { - struct labcomm_decoder *decoder = context; + struct client *client = arg; int result; + + labcomm_decoder_register_types_A(client->decoder, handle_A, client); + labcomm_decoder_register_types_B(client->decoder, handle_B, client); + labcomm_decoder_register_types_Terminate(client->decoder, handle_Terminate, + NULL); do { - result = labcomm_decoder_decode_one(decoder); + result = labcomm_decoder_decode_one(client->decoder); } while (result >= 0); return NULL; } @@ -89,30 +94,31 @@ static void *run_client(void *arg) printf("Client start\n"); client->A = 0; client->B = 0; - lock = labcomm_pthread_mutex_lock_new(); - decimating = decimating_new(labcomm_fd_reader_new(client->fd, 1), - labcomm_fd_writer_new(client->fd, 0), - lock); + lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory); + decimating = decimating_new(labcomm_fd_reader_new(labcomm_default_memory, + client->fd, 1), + labcomm_fd_writer_new(labcomm_default_memory, + client->fd, 0), + lock, + labcomm_default_memory); if (decimating == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } introspecting = introspecting_new(decimating->reader, decimating->writer, - lock); + lock, + labcomm_default_memory); if (introspecting == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } - client->decoder = labcomm_decoder_new(introspecting->reader, lock); - client->encoder = labcomm_encoder_new(introspecting->writer, lock); + client->decoder = labcomm_decoder_new(introspecting->reader, lock, + labcomm_default_memory); + client->encoder = labcomm_encoder_new(introspecting->writer, lock, + labcomm_default_memory); pthread_t rdt; - - labcomm_decoder_register_types_A(client->decoder, handle_A, client); - labcomm_decoder_register_types_B(client->decoder, handle_B, client); - labcomm_decoder_register_types_Terminate(client->decoder, handle_Terminate, - NULL); - pthread_create(&rdt, NULL, run_decoder, client->decoder); + pthread_create(&rdt, NULL, run_decoder, client); labcomm_encoder_register_types_Sum(client->encoder); labcomm_encoder_register_types_Diff(client->encoder); pthread_join(rdt, NULL); diff --git a/lib/c/Makefile b/lib/c/Makefile index bb68b640cb91505b75d218578f5b35a8f4e48e3a..348e8c3b799a60d9295330c20335bc912803aef3 100644 --- a/lib/c/Makefile +++ b/lib/c/Makefile @@ -8,6 +8,7 @@ LDFLAGS=-L. LDLIBS_TEST=-lcunit -llabcomm -Tlabcomm.linkscript OBJS= labcomm.o \ + labcomm_memory.o labcomm_default_memory.o \ labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o \ labcomm_pthread_mutex_lock.o diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c index c5e7bfb230c710dc0d617dbbb43036dd6b1cb6ce..582d5aa2b345ba32922285d386bfb87f1345dd6e 100644 --- a/lib/c/labcomm.c +++ b/lib/c/labcomm.c @@ -43,6 +43,7 @@ struct labcomm_decoder { void *context; struct labcomm_reader *reader; struct labcomm_lock *lock; + struct labcomm_memory *memory; labcomm_error_handler_callback on_error; labcomm_handle_new_datatype_callback on_new_datatype; LABCOMM_SIGNATURE_ARRAY_DEF(local_to_remote, int); @@ -53,6 +54,7 @@ struct labcomm_encoder { void *context; struct labcomm_writer *writer; struct labcomm_lock *lock; + struct labcomm_memory *memory; struct labcomm_encoder *is_deferred; int busy; int waiting; @@ -347,13 +349,16 @@ static int get_encoder_index( struct labcomm_encoder *labcomm_encoder_new( struct labcomm_writer *writer, - struct labcomm_lock *lock) + struct labcomm_lock *lock, + struct labcomm_memory *memory) { - struct labcomm_encoder *result = malloc(sizeof(*result)); + struct labcomm_encoder *result; + + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); if (result) { struct labcomm_encoder_context *context; - context = malloc(sizeof(*context)); + context = labcomm_memory_alloc(memory, 0, sizeof(*context)); #ifdef LABCOMM_ENCODER_LINEAR_SEARCH context->sample = NULL; context->index = LABCOMM_USER; @@ -362,12 +367,14 @@ struct labcomm_encoder *labcomm_encoder_new( #endif result->context = context; result->writer = writer; + result->writer->encoder = result; result->writer->data = NULL; result->writer->data_size = 0; result->writer->count = 0; result->writer->pos = 0; result->writer->error = 0; result->lock = lock; + result->memory = memory; result->is_deferred = NULL; result->busy = 0; result->waiting = 0; @@ -386,8 +393,7 @@ static int encoder_enqueue_action( int result; struct encoder_alloc_action *element, **next; - fprintf(stderr, "%s %p\n", __FUNCTION__, action); - element = malloc(sizeof(*action)); + element = labcomm_memory_alloc(encoder->memory, 0, sizeof(*action)); if (element == NULL) { result = -ENOMEM; goto out; @@ -427,11 +433,10 @@ static struct labcomm_encoder *enter_encoder(struct labcomm_encoder *e) while (p) { struct encoder_alloc_action *tmp; - fprintf(stderr, "RUN %p", p->action); p->action(&deferred, p->context); tmp = p; p = p->next; - free(tmp); + labcomm_memory_free(e->memory, 1, tmp); } } } @@ -464,7 +469,8 @@ int labcomm_internal_encoder_register( index = get_encoder_index(e, signature); if (signature->type == LABCOMM_SAMPLE) { if (index > 0) { - int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->registered, int, index); + int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, + int, index); if (! *registered) { int err; @@ -473,6 +479,8 @@ int labcomm_internal_encoder_register( index, signature, NULL); if (err == -EALREADY) { result = 0; + } else if (err != 0) { + result = err; } else if (err == 0) { int i; @@ -525,24 +533,25 @@ no_end: void labcomm_encoder_free(struct labcomm_encoder* e) { struct labcomm_encoder_context *context; + struct labcomm_memory * memory = e->memory; context = (struct labcomm_encoder_context *) e->context; labcomm_writer_free(e->writer, e->writer->action_context); - LABCOMM_SIGNATURE_ARRAY_FREE(e->registered, int); + LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int); #ifdef LABCOMM_ENCODER_LINEAR_SEARCH struct labcomm_sample_entry *entry = context->sample; struct labcomm_sample_entry *entry_next; while (entry != NULL) { entry_next = entry->next; - free(entry); + labcomm_memory_free(memory, 0, entry); entry = entry_next; } #else - free(context->by_section); + labcomm_memory_free(memory, 0, context->by_section); #endif - free(e->context); - free(e); + labcomm_memory_free(memory, 0, e->context); + labcomm_memory_free(memory, 0, e); } int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, @@ -629,7 +638,7 @@ static void collect_flat_signature( for (i = 0 ; i < fields ; i++) { char *name = labcomm_read_string(decoder->reader); labcomm_write_string(writer, name); - free(name); + labcomm_memory_free(decoder->memory, 1, name); collect_flat_signature(decoder, writer); } } break; @@ -652,21 +661,27 @@ static void collect_flat_signature( struct labcomm_decoder *labcomm_decoder_new( struct labcomm_reader *reader, - struct labcomm_lock *lock) + struct labcomm_lock *lock, + struct labcomm_memory *memory) { - struct labcomm_decoder *result = malloc(sizeof(*result)); + struct labcomm_decoder *result; + + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); if (result) { - struct labcomm_decoder_context *context = - (struct labcomm_decoder_context *)malloc(sizeof(*context)); + struct labcomm_decoder_context *context; + + context = labcomm_memory_alloc(memory, 0, sizeof(*context)); context->sample = 0; result->context = context; result->reader = reader; + result->reader->decoder = result; result->reader->data = 0; result->reader->data_size = 0; result->reader->count = 0; result->reader->pos = 0; result->reader->error = 0; result->lock = lock; + result->memory = memory; result->on_error = on_error_fprintf; result->on_new_datatype = on_new_datatype; LABCOMM_SIGNATURE_ARRAY_INIT(result->local_to_remote, int); @@ -683,20 +698,29 @@ int labcomm_internal_decoder_register( void *handler_context) { struct labcomm_decoder_context *context = d->context; - struct labcomm_sample_entry *sample; - sample = get_sample_by_signature_address(context->sample, - signature); - if (!sample) { - sample = (struct labcomm_sample_entry *)malloc(sizeof(*sample)); - sample->next = context->sample; - context->sample = sample; - sample->index = 0; - sample->signature = signature; - } - sample->decoder = type_decoder; - sample->handler = handler; - sample->context = handler_context; + int index; + + index = get_local_index(signature); + if (index >= 0) { + struct labcomm_sample_entry *sample; + labcomm_reader_start(d->reader, d->reader->action_context, + index, signature, + NULL); + labcomm_reader_end(d->reader, d->reader->action_context); + sample = get_sample_by_signature_address(context->sample, + signature); + if (!sample) { + sample = labcomm_memory_alloc(d->memory, 0, sizeof(*sample)); + sample->next = context->sample; + context->sample = sample; + sample->index = 0; + sample->signature = signature; + } + sample->decoder = type_decoder; + sample->handler = handler; + sample->context = handler_context; + } return 0; } @@ -714,6 +738,7 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind) }; struct labcomm_writer writer = { .action_context = &action_context, + .memory = d->memory, .data = NULL, .data_size = 0, .count = 0, @@ -749,7 +774,6 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind) } entry = get_sample_by_signature_value(context->sample, &signature); if (! entry) { - fprintf(stderr, "%d %s\n", remote_index, signature.name); /* Unknown datatype, bail out */ d->on_new_datatype(d, &signature); result = -ENOENT; @@ -764,20 +788,18 @@ static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind) // TODO unnessesary, since entry->index == index in above if statement entry->index = remote_index; local_index = get_local_index(entry->signature); - local_to_remote = LABCOMM_SIGNATURE_ARRAY_REF(d->local_to_remote, int, + local_to_remote = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->local_to_remote, int, local_index); *local_to_remote = remote_index; - remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->remote_to_local, int, + remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->remote_to_local, int, remote_index); *remote_to_local = local_index; result = remote_index; - labcomm_reader_start(d->reader, d->reader->action_context, - entry->index, entry->signature, - NULL); - labcomm_reader_end(d->reader, d->reader->action_context); } free_signature_name: - free(signature.name); + labcomm_memory_free(d->memory, 0, signature.name); labcomm_writer_free(&writer, writer.action_context); if (!entry) { // No handler for found type, bail out (after cleanup) @@ -856,18 +878,19 @@ void labcomm_decoder_free(struct labcomm_decoder* d) struct labcomm_decoder_context *context = (struct labcomm_decoder_context *) d->context; struct labcomm_sample_entry *entry = context->sample; struct labcomm_sample_entry *entry_next; + struct labcomm_memory *memory = d->memory; labcomm_reader_free(d->reader, d->reader->action_context); - LABCOMM_SIGNATURE_ARRAY_FREE(d->local_to_remote, int); - LABCOMM_SIGNATURE_ARRAY_FREE(d->remote_to_local, int); + LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local_to_remote, int); + LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int); while (entry != NULL) { entry_next = entry->next; - free(entry); + labcomm_memory_free(memory, 0, entry); entry = entry_next; } - free(d->context); - free(d); + labcomm_memory_free(memory, 0, d->context); + labcomm_memory_free(memory, 0, d); } int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, @@ -893,7 +916,8 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, int local_index, *remote_index; local_index = get_local_index(signature); - remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->local_to_remote, int, + remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->memory, + decoder->local_to_remote, int, local_index); if (*remote_index == 0) { result = -EAGAIN; @@ -922,13 +946,14 @@ static void dump(void *p, int size, int first, int last) } #endif -void *labcomm_signature_array_ref(int *first, int *last, void **data, +void *labcomm_signature_array_ref(struct labcomm_memory *memory, + int *first, int *last, void **data, int size, int index) { if (*first == 0 && *last == 0) { *first = index; *last = index + 1; - *data = malloc(size); + *data = labcomm_memory_alloc(memory, 0, size); if (*data) { memset(*data, 0, size); } @@ -940,7 +965,7 @@ void *labcomm_signature_array_ref(int *first, int *last, void **data, *first = (index<old_first)?index:old_first; *last = (old_last<=index)?index+1:old_last; n = (*last - *first); - *data = malloc(n * size); + *data = labcomm_memory_alloc(memory, 0, n * size); if (*data) { memset(*data, 0, n * size); memcpy(*data + (old_first - *first) * size, @@ -948,7 +973,7 @@ void *labcomm_signature_array_ref(int *first, int *last, void **data, (old_last - old_first) * size); } // dump(old_data, size, old_first, old_last); - free(old_data); + labcomm_memory_free(memory, 0, old_data); } if (*data) { // dump(*data, size, *first, *last); diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h index 1e4f3033d5b88f72d894147e93cd92612a16a023..42bdbce765c941fe8f06e680ad725f326903cf27 100644 --- a/lib/c/labcomm.h +++ b/lib/c/labcomm.h @@ -80,15 +80,33 @@ void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d, labcomm_handle_new_datatype_callback on_new_datatype); /* - * Locking support (optional) + * Locking support (optional), if not used only a single thread + * may access an encoder or decoder at the same time. */ struct labcomm_lock; int labcomm_lock_free(struct labcomm_lock *lock); -int labcomm_lock_lock(struct labcomm_lock *lock); -int labcomm_lock_unlock(struct labcomm_lock *lock); +int labcomm_lock_acquire(struct labcomm_lock *lock); +int labcomm_lock_release(struct labcomm_lock *lock); int labcomm_lock_wait(struct labcomm_lock *lock, useconds_t usec); -int labcomm_lock_notify_all(struct labcomm_lock *lock); +int labcomm_lock_notify(struct labcomm_lock *lock); + +/* + * Dynamic memory handling + * lifetime == 0 memory that will live for as long as the + * encoder/decoder or that are allocated/deallocated + * during the communication setup phase + * otherwise memory will live for approximately this number of + * sent/received samples + */ +struct labcomm_memory; + +void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, size_t size); +void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, + void *ptr, size_t size); +void labcomm_memory_free(struct labcomm_memory *m, int lifetime, void *ptr); + +extern struct labcomm_memory *labcomm_default_memory; /* * Decoder @@ -97,7 +115,8 @@ struct labcomm_reader; struct labcomm_decoder *labcomm_decoder_new( struct labcomm_reader *reader, - struct labcomm_lock *lock); + struct labcomm_lock *lock, + struct labcomm_memory *memory); int labcomm_decoder_decode_one( struct labcomm_decoder *decoder); void labcomm_decoder_run( @@ -117,7 +136,8 @@ struct labcomm_writer; struct labcomm_encoder *labcomm_encoder_new( struct labcomm_writer *writer, - struct labcomm_lock *lock); + struct labcomm_lock *lock, + struct labcomm_memory *memory); void labcomm_encoder_free( struct labcomm_encoder *encoder); @@ -126,4 +146,6 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, uint32_t ioctl_action, ...); +#define LABCOMM_VOID ((void*)1) + #endif diff --git a/lib/c/labcomm_default_memory.c b/lib/c/labcomm_default_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..d6b13c52621352a3658e2ce51d20b9e4d92b7274 --- /dev/null +++ b/lib/c/labcomm_default_memory.c @@ -0,0 +1,49 @@ +/* + test_default_memory.c -- LabComm default memory allocator + + Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "labcomm.h" +#include "labcomm_private.h" + +void *default_alloc(struct labcomm_memory *m, int lifetime, size_t size) +{ + return malloc(size); +} + +void *default_realloc(struct labcomm_memory *m, int lifetime, + void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void default_free(struct labcomm_memory *m, int lifetime, void *ptr) +{ + free(ptr); +} + +struct labcomm_memory memory = { + .alloc = default_alloc, + .realloc = default_realloc, + .free = default_free, + .context = NULL +}; + +struct labcomm_memory *labcomm_default_memory = &memory; diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c index f3619b02cc31a127ad00f74b36691c99a2292b62..fb61f2349a98556610c5af67836dc4758cf787ff 100644 --- a/lib/c/labcomm_dynamic_buffer_writer.c +++ b/lib/c/labcomm_dynamic_buffer_writer.c @@ -35,7 +35,7 @@ static int dyn_alloc(struct labcomm_writer *w, { w->data_size = 1000; w->count = w->data_size; - w->data = malloc(w->data_size); + w->data = labcomm_memory_alloc(w->memory, 1, w->data_size); if (w->data == NULL) { w->error = -ENOMEM; } @@ -47,14 +47,12 @@ static int dyn_alloc(struct labcomm_writer *w, static int dyn_free(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context) { - free(w->data); + labcomm_memory_free(w->memory, 1, w->data); w->data = 0; w->data_size = 0; w->count = 0; w->pos = 0; - if (action_context->context) { - free(action_context->context); - } + labcomm_memory_free(w->memory, 0, action_context->context); return 0; } @@ -68,7 +66,7 @@ static int dyn_start(struct labcomm_writer *w, w->data_size = 1000; w->count = w->data_size; - tmp = realloc(w->data, w->data_size); + tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size); if (tmp != NULL) { w->data = tmp; w->error = 0; @@ -93,11 +91,12 @@ static int dyn_flush(struct labcomm_writer *w, w->data_size += 1000; w->count = w->data_size; - tmp = realloc(w->data, w->data_size); + tmp = labcomm_memory_realloc(w->memory, 1, w->data, w->data_size); if (tmp != NULL) { w->data = tmp; w->error = 0; } else { + /* Old pointer in w->data still valid */ w->error = -ENOMEM; } @@ -137,19 +136,21 @@ static const struct labcomm_writer_action action = { const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action = &action; -struct labcomm_writer *labcomm_dynamic_buffer_writer_new() +struct labcomm_writer *labcomm_dynamic_buffer_writer_new( + struct labcomm_memory *memory) { struct result { struct labcomm_writer writer; struct labcomm_writer_action_context action_context; } *result; - result = malloc(sizeof(*result)); + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); if (result != NULL) { result->action_context.next = NULL; result->action_context.context = result; result->action_context.action = &action; result->writer.action_context = &result->action_context; + result->writer.memory = memory; return &result->writer; } return NULL; diff --git a/lib/c/labcomm_dynamic_buffer_writer.h b/lib/c/labcomm_dynamic_buffer_writer.h index 7f01a1dfd0eda72722d0cff97902617f523d70f6..53a65d42c878dea278f78f7572774658c86d6fe0 100644 --- a/lib/c/labcomm_dynamic_buffer_writer.h +++ b/lib/c/labcomm_dynamic_buffer_writer.h @@ -1,3 +1,24 @@ +/* + labcomm_dynamic_buffer_writer.h -- LabComm dynamic memory writer. + + Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_ #define _LABCOMM_DYNAMIC_BUFFER_READER_WRITER_H_ @@ -5,4 +26,7 @@ extern const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action; +struct labcomm_writer *labcomm_dynamic_buffer_writer_new( + struct labcomm_memory *memory); + #endif diff --git a/lib/c/labcomm_fd_reader.c b/lib/c/labcomm_fd_reader.c index 70c1df999edeedaddde3165ca98cce444259b4f5..6cae2aeff014952c99844f079d9928e7a05224e1 100644 --- a/lib/c/labcomm_fd_reader.c +++ b/lib/c/labcomm_fd_reader.c @@ -44,7 +44,7 @@ static int fd_alloc(struct labcomm_reader *r, r->count = 0; r->pos = 0; - r->data = malloc(BUFFER_SIZE); + r->data = labcomm_memory_alloc(r->memory, 0, BUFFER_SIZE); if (! r->data) { r->data_size = 0; result = -ENOMEM; @@ -61,7 +61,7 @@ static int fd_alloc(struct labcomm_reader *r, } else { result = r->data_size; } - free(tmp); + labcomm_memory_free(r->memory, 1, tmp); } } return result; @@ -70,18 +70,19 @@ static int fd_alloc(struct labcomm_reader *r, static int fd_free(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context) { - struct labcomm_fd_reader *fd_context = action_context->context; + struct labcomm_fd_reader *fd_reader = action_context->context; + struct labcomm_memory *memory = r->memory; - free(r->data); + labcomm_memory_free(memory, 0, r->data); r->data = 0; r->data_size = 0; r->count = 0; r->pos = 0; - if (fd_context->close_fd_on_free) { - close(fd_context->fd); + if (fd_reader->close_fd_on_free) { + close(fd_reader->fd); } - free(fd_context); + labcomm_memory_free(memory, 0, fd_reader); return 0; } @@ -90,7 +91,7 @@ static int fd_fill(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context) { int result = 0; - struct labcomm_fd_reader *fd_context = action_context->context; + struct labcomm_fd_reader *fd_reader = action_context->context; if (r->pos < r->count) { result = r->count - r->pos; @@ -98,7 +99,7 @@ static int fd_fill(struct labcomm_reader *r, int err; r->pos = 0; - err = read(fd_context->fd, r->data, r->data_size); + err = read(fd_reader->fd, r->data, r->data_size); if (err <= 0) { r->count = 0; r->error = -EPIPE; @@ -111,51 +112,29 @@ static int fd_fill(struct labcomm_reader *r, return result; } -static int fd_start(struct labcomm_reader *r, - struct labcomm_reader_action_context *action_context, - int index, struct labcomm_signature *signature, - void *value) -{ - return 0; -} - -static int fd_end(struct labcomm_reader *r, - struct labcomm_reader_action_context *action_context) -{ - return 0; -} - -static int fd_ioctl(struct labcomm_reader *r, - struct labcomm_reader_action_context *action_context, - int signature_index, - struct labcomm_signature *signature, - uint32_t action, va_list args) -{ - return -ENOTSUP; -} - - static const struct labcomm_reader_action action = { .alloc = fd_alloc, .free = fd_free, - .start = fd_start, + .start = NULL, .fill = fd_fill, - .end = fd_end, - .ioctl = fd_ioctl + .end = NULL, + .ioctl = NULL }; -struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free) +struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory, + int fd, int close_fd_on_free) { struct labcomm_fd_reader *result; - result = malloc(sizeof(*result)); + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); if (result == NULL) { return NULL; } else { - result->reader.action_context = &result->action_context; result->action_context.next = NULL; result->action_context.action = &action; result->action_context.context = result; + result->reader.action_context = &result->action_context; + result->reader.memory = memory; result->fd = fd; result->close_fd_on_free = close_fd_on_free; return &result->reader; diff --git a/lib/c/labcomm_fd_reader.h b/lib/c/labcomm_fd_reader.h index 8f526fa3d9f828b77f4838f1fdee12bd62160a6f..b04aa8ed5515ccb5caf3571fd05adf0fdfc294f0 100644 --- a/lib/c/labcomm_fd_reader.h +++ b/lib/c/labcomm_fd_reader.h @@ -1,9 +1,31 @@ +/* + labcomm_fd_reader.c -- a reader for unix style file-descriptors + + Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _LABCOMM_FD_READER_H_ #define _LABCOMM_FD_READER_H_ #include "labcomm.h" -struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free); +struct labcomm_reader *labcomm_fd_reader_new(struct labcomm_memory *memory, + int fd, int close_fd_on_free); #endif diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c index 476052c6cf79a4cb495d9efb3774a89ccd6fb769..d21e047c63fc6bc1cf95ea7a3f55d292676af8d0 100644 --- a/lib/c/labcomm_fd_writer.c +++ b/lib/c/labcomm_fd_writer.c @@ -45,7 +45,7 @@ static int fd_alloc(struct labcomm_writer *w, char *version, labcomm_encoder_enqueue enqueue) { - w->data = malloc(BUFFER_SIZE); + w->data = labcomm_memory_alloc(w->memory, 0, BUFFER_SIZE); if (! w->data) { w->error = -ENOMEM; w->data_size = 0; @@ -67,17 +67,19 @@ static int fd_alloc(struct labcomm_writer *w, static int fd_free(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context) { - struct labcomm_fd_writer *fd_context = action_context->context; + struct labcomm_fd_writer *fd_writer = action_context->context; + struct labcomm_memory *memory = w->memory; - free(w->data); + labcomm_memory_free(memory, 0, w->data); w->data = 0; w->data_size = 0; w->count = 0; w->pos = 0; - if (fd_context->close_fd_on_free) { - close(fd_context->fd); + if (fd_writer->close_fd_on_free) { + close(fd_writer->fd); } + labcomm_memory_free(memory, 0, fd_writer); return 0; } @@ -117,35 +119,29 @@ static int fd_flush(struct labcomm_writer *w, return w->error; } -static int fd_ioctl(struct labcomm_writer *w, - struct labcomm_writer_action_context *action_context, - int signature_index, struct labcomm_signature *signature, - uint32_t action, va_list args) -{ - return -ENOTSUP; -} - static const struct labcomm_writer_action action = { .alloc = fd_alloc, .free = fd_free, .start = fd_start, .end = fd_flush, .flush = fd_flush, - .ioctl = fd_ioctl + .ioctl = NULL }; -struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_fd_on_free) +struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory, + int fd, int close_fd_on_free) { struct labcomm_fd_writer *result; - result = malloc(sizeof(*result)); + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); if (result == NULL) { return NULL; } else { - result->writer.action_context = &result->action_context; result->action_context.next = NULL; result->action_context.action = &action; result->action_context.context = result; + result->writer.action_context = &result->action_context; + result->writer.memory = memory; result->fd = fd; result->close_fd_on_free = close_fd_on_free; return &result->writer; diff --git a/lib/c/labcomm_fd_writer.h b/lib/c/labcomm_fd_writer.h index e1c976a390c96ea3afc534b5f8a3543de3a1cd3c..e89b5e7198c1d7822f276d23801baf9a889ce4f2 100644 --- a/lib/c/labcomm_fd_writer.h +++ b/lib/c/labcomm_fd_writer.h @@ -1,9 +1,31 @@ +/* + labcomm_fd_writer.c -- a writer for unix style file-descriptors + + Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _LABCOMM_FD_WRITER_H_ #define _LABCOMM_FD_WRITER_H_ #include "labcomm.h" -struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_on_free); +struct labcomm_writer *labcomm_fd_writer_new(struct labcomm_memory *memory, + int fd, int close_on_free); #endif diff --git a/lib/c/labcomm_memory.c b/lib/c/labcomm_memory.c new file mode 100644 index 0000000000000000000000000000000000000000..62bc9ac5a3f81ef496f836509cf4e7f8e8bb81cf --- /dev/null +++ b/lib/c/labcomm_memory.c @@ -0,0 +1,40 @@ +/* + labcomm_memory.c -- dynamic memory handlig dispatcher + + Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "labcomm_private.h" + +void *labcomm_memory_alloc(struct labcomm_memory *m, int lifetime, + size_t size) +{ + return m->alloc(m, lifetime, size); +} + +void *labcomm_memory_realloc(struct labcomm_memory *m, int lifetime, + void *ptr, size_t size) +{ + return m->realloc(m, lifetime, ptr, size); +} + +void labcomm_memory_free(struct labcomm_memory *m, int lifetime, + void *ptr) +{ + m->free(m, lifetime, ptr); +} diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h index 8632dc0d423e7c08279e31585b5fa67d69e346ee..a19ec2af031be2e061165afab604059564eeeb64 100644 --- a/lib/c/labcomm_private.h +++ b/lib/c/labcomm_private.h @@ -31,7 +31,7 @@ #endif #include <stdint.h> -#include <stdlib.h> +//#include <stdlib.h> #include <string.h> #include <unistd.h> #include "labcomm.h" @@ -82,6 +82,19 @@ struct labcomm_lock_action { struct labcomm_lock { const struct labcomm_lock_action *action; + struct labcomm_memory *memory; + void *context; +}; + +/* + * Semi private dynamic memory declarations + */ + +struct labcomm_memory { + void *(*alloc)(struct labcomm_memory *m, int lifetime, size_t size); + void *(*realloc)(struct labcomm_memory *m, int lifetime, + void *ptr, size_t size); + void (*free)(struct labcomm_memory *m, int lifetime, void *ptr); void *context; }; @@ -144,6 +157,9 @@ struct labcomm_reader_action_context { struct labcomm_reader { struct labcomm_reader_action_context *action_context; + struct labcomm_memory *memory; + /* The following fields are initialized by labcomm_decoder_new */ + struct labcomm_decoder *decoder; unsigned char *data; int data_size; int count; @@ -255,7 +271,7 @@ static inline char *labcomm_read_string(struct labcomm_reader *r) int length, i; length = labcomm_read_packed32(r); - result = malloc(length + 1); + result = labcomm_memory_alloc(r->memory, 1, length + 1); for (i = 0 ; i < length ; i++) { if (r->pos >= r->count) { labcomm_reader_fill(r, r->action_context); @@ -318,6 +334,9 @@ struct labcomm_writer_action_context { struct labcomm_writer { struct labcomm_writer_action_context *action_context; + struct labcomm_memory *memory; + /* The following fields are initialized by labcomm_encoder_new */ + struct labcomm_encoder *encoder; unsigned char *data; int data_size; int count; @@ -461,18 +480,29 @@ static inline int labcomm_write_string(struct labcomm_writer *w, char *s) name.first = 0; name.last = 0; name.data = NULL; \ name.data = (kind *)name.data; /* typechecking no-op */ -#define LABCOMM_SIGNATURE_ARRAY_FREE(name, kind) \ - if (name.data) { free(name.data); } \ +#define LABCOMM_SIGNATURE_ARRAY_FREE(memory, name, kind) \ + if (name.data) { labcomm_memory_free(memory, 0, name.data); } \ name.data = (kind *)NULL; /* typechecking */ -#define LABCOMM_SIGNATURE_ARRAY_REF(name, kind, index) \ +void *labcomm_signature_array_ref(struct labcomm_memory * memory, + int *first, int *last, void **data, + int size, int index); +/* + * NB: the pointer returned by LABCOMM_SIGNATURE_ARRAY_REF might be + * rendered invalid by a subsequent call to LABCOMM_SIGNATURE_ARRAY_REF + * on the same SIGNATURE_ARRAY, so make sure not to use the result if + * any other code might have made a call to LABCOMM_SIGNATURE_ARRAY_REF + * on the same SIGNATURE_ARRAY. + */ +#define LABCOMM_SIGNATURE_ARRAY_REF(memory, name, kind, index) \ (name.data = (kind *)name.data, /* typechecking no-op */ \ - (kind *)(labcomm_signature_array_ref(&name.first, &name.last, \ + (kind *)(labcomm_signature_array_ref(memory, \ + &name.first, &name.last, \ (void **)&name.data, \ sizeof(kind), index))) -void *labcomm_signature_array_ref(int *first, int *last, void **data, - int size, int index); - +#define LABCOMM_SIGNATURE_ARRAY_FOREACH(name, kind, var) \ + for (name.data = (kind *)name.data, /* typechecking no-op */ \ + var = name.first ; var < name.last ; var++) #endif diff --git a/lib/c/labcomm_pthread_mutex_lock.c b/lib/c/labcomm_pthread_mutex_lock.c index 66c8ac34da228e50c97b74d471c1cc3041985850..548a3e6916433aaebd1bbcef09f85a643fba7459 100644 --- a/lib/c/labcomm_pthread_mutex_lock.c +++ b/lib/c/labcomm_pthread_mutex_lock.c @@ -5,6 +5,7 @@ struct labcomm_pthread_mutex_lock { struct labcomm_lock lock; + pthread_mutex_t mutex; pthread_cond_t cond; }; @@ -12,10 +13,11 @@ struct labcomm_pthread_mutex_lock { int do_free(struct labcomm_lock *l) { struct labcomm_pthread_mutex_lock *lock = l->context; - + struct labcomm_memory *memory = l->memory; + pthread_cond_destroy(&lock->cond); pthread_mutex_destroy(&lock->mutex); - free(lock); + labcomm_memory_free(memory, 0, lock); return 0; } @@ -80,12 +82,13 @@ static struct labcomm_lock_action action = { .notify = do_notify }; -struct labcomm_lock *labcomm_pthread_mutex_lock_new() +struct labcomm_lock *labcomm_pthread_mutex_lock_new( + struct labcomm_memory *memory) { struct labcomm_lock *result = NULL; struct labcomm_pthread_mutex_lock *lock; - lock = malloc(sizeof(*lock)); + lock = labcomm_memory_alloc(memory, 0, sizeof(*lock)); if (lock == NULL) { goto out; } @@ -95,6 +98,7 @@ struct labcomm_lock *labcomm_pthread_mutex_lock_new() if (pthread_cond_init(&lock->cond, NULL) != 0) { goto destroy_mutex; } + lock->lock.memory = memory; lock->lock.action = &action; lock->lock.context = lock; result = &lock->lock; @@ -102,7 +106,7 @@ struct labcomm_lock *labcomm_pthread_mutex_lock_new() destroy_mutex: pthread_mutex_destroy(&lock->mutex); free_lock: - free(lock); + labcomm_memory_free(memory, 0, lock); out: return result; diff --git a/lib/c/labcomm_pthread_mutex_lock.h b/lib/c/labcomm_pthread_mutex_lock.h index d4ff9f714f5a7ab8b848f806653e29ec07eb8754..e67b16a24fe5b4b4a2997add53a3479cd6ef99fe 100644 --- a/lib/c/labcomm_pthread_mutex_lock.h +++ b/lib/c/labcomm_pthread_mutex_lock.h @@ -1,8 +1,30 @@ +/* + labcomm_pthread_mutex_lock.h -- a labcomm_lock on top of pthread_mutex. + + Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se> + + This file is part of LabComm. + + LabComm is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LabComm is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + #ifndef _LABCOMM_PTHREAD_MUTEX_LOCK_H_ #define _LABCOMM_PTHREAD_MUTEX_LOCK_H_ #include "labcomm.h" -struct labcomm_lock *labcomm_pthread_mutex_lock_new(); +struct labcomm_lock *labcomm_pthread_mutex_lock_new( + struct labcomm_memory *memory); #endif diff --git a/lib/c/test/test_labcomm_basic_type_encoding.c b/lib/c/test/test_labcomm_basic_type_encoding.c index 9151b9b630da228e59fb3065e2791e5b9cee6bd5..b964c9890b4cef2ad1d89d43198f1bd4ebdc8a54 100644 --- a/lib/c/test/test_labcomm_basic_type_encoding.c +++ b/lib/c/test/test_labcomm_basic_type_encoding.c @@ -22,6 +22,7 @@ #include <stdint.h> #include <inttypes.h> #include <string.h> +#include <stdlib.h> #include "labcomm_private.h" static int line; diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c index 32a5a99bcaefe497661816acc23ebdc53f82b713..bf81d0b3ad0494c586d85ddb6f08d0ae2cea5343 100644 --- a/lib/c/test/test_labcomm_generated_encoding.c +++ b/lib/c/test/test_labcomm_generated_encoding.c @@ -20,10 +20,10 @@ */ #include <stdint.h> +#include <stdlib.h> #include <string.h> #include <errno.h> #include "labcomm_private.h" -#include "labcomm_private.h" #include "test/gen/generated_encoding.h" #define IOCTL_WRITER_ASSERT_BYTES 4096 @@ -182,7 +182,8 @@ int main(void) generated_encoding_B B = 1; struct labcomm_encoder *encoder = labcomm_encoder_new(&buffer_writer, - NULL); + NULL, + labcomm_default_memory); labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encoder_register_generated_encoding_V(encoder); diff --git a/test/nested.lc b/test/nested.lc index 26f0ac82d09b9fdd851454f0079b4913778be6da..58d45ee9f1d81c12a40e6533217a55d173f88208 100644 --- a/test/nested.lc +++ b/test/nested.lc @@ -21,3 +21,5 @@ sample struct_t struct_t_s; sample struct_array_t struct_array_t_s; sample struct_struct_t struct_struct_t_s; +sample string string_array[_]; +sample struct { string s[_]; } string_struct_array; diff --git a/test/relay_gen_c.py b/test/relay_gen_c.py index 9e2a3a7d61f42ed8f5e928c11b3ab22840ac7914..30a081ae0ff6f8b3bd390982f5731d1a86bfdcf8 100755 --- a/test/relay_gen_c.py +++ b/test/relay_gen_c.py @@ -50,8 +50,12 @@ if __name__ == '__main__': | if (in < 0) { return 1; } | out = open(argv[2], O_WRONLY); | if (out < 0) { return 1; } - | e = labcomm_encoder_new(labcomm_fd_writer_new(out, 1), NULL); - | d = labcomm_decoder_new(labcomm_fd_reader_new(in, 1), NULL); + | e = labcomm_encoder_new(labcomm_fd_writer_new( + | labcomm_default_memory, out, 1), + | NULL, labcomm_default_memory); + | d = labcomm_decoder_new(labcomm_fd_reader_new( + | labcomm_default_memory, in, 1), + | NULL, labcomm_default_memory); """)) for func,arg in sample: result.extend(split_match('^[^|]*\|(.*)$', """