diff --git a/examples/simple/example_decoder.c b/examples/simple/example_decoder.c index 2b1f746bcd0fc0ce9279fde3d34d549648eb9153..122745d62aebe4ea9831dfbf4280d4f267e40425 100644 --- a/examples/simple/example_decoder.c +++ b/examples/simple/example_decoder.c @@ -2,6 +2,9 @@ #include <sys/stat.h> #include <fcntl.h> #include <labcomm_fd_reader.h> +#include <labcomm_default_error_handler.h> +#include <labcomm_default_memory.h> +#include <labcomm_default_scheduler.h> #include "gen/simple.h" #include <stdio.h> @@ -58,7 +61,9 @@ int main(int argc, char *argv[]) { fd = open(filename, O_RDONLY); decoder = labcomm_decoder_new(labcomm_fd_reader_new( labcomm_default_memory, fd, 1), - NULL, labcomm_default_memory); + labcomm_default_error_handler, + labcomm_default_memory, + labcomm_default_scheduler); 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 67beb4c369c80f1437ce601a800f83968f43a660..174694237cfeb83c05093a73bbdf56e8f513a4ad 100644 --- a/examples/simple/example_encoder.c +++ b/examples/simple/example_encoder.c @@ -2,6 +2,9 @@ #include <sys/stat.h> #include <fcntl.h> #include <labcomm_fd_writer.h> +#include <labcomm_default_error_handler.h> +#include <labcomm_default_memory.h> +#include <labcomm_default_scheduler.h> #include "gen/simple.h" #include <stdio.h> @@ -14,7 +17,9 @@ int main(int argc, char *argv[]) { fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); encoder = labcomm_encoder_new(labcomm_fd_writer_new( labcomm_default_memory, fd, 1), - NULL, labcomm_default_memory); + labcomm_default_error_handler, + labcomm_default_memory, + labcomm_default_scheduler); labcomm_encoder_register_simple_theTwoInts(encoder); labcomm_encoder_register_simple_anotherTwoInts(encoder); labcomm_encoder_register_simple_IntString(encoder); diff --git a/examples/twoway/client.c b/examples/twoway/client.c index 401a7a55aadbe720a016924bbae2c62eaeed3740..656a71fae03d65232f217fd51387dfe27566e3c3 100644 --- a/examples/twoway/client.c +++ b/examples/twoway/client.c @@ -33,7 +33,9 @@ #include <labcomm.h> #include <labcomm_fd_reader.h> #include <labcomm_fd_writer.h> -#include <labcomm_pthread_mutex_lock.h> +#include <labcomm_default_error_handler.h> +#include <labcomm_default_memory.h> +#include <labcomm_pthread_scheduler.h> #include "decimating.h" #include "introspecting.h" #include "gen/types.h" @@ -74,7 +76,7 @@ int main(int argc, char *argv[]) struct introspecting *introspecting; char *hostname; int port; - struct labcomm_lock *lock; + struct labcomm_scheduler *scheduler; struct labcomm_decoder *decoder; struct labcomm_encoder *encoder; int32_t i, j; @@ -114,29 +116,35 @@ int main(int argc, char *argv[]) nodelay = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); - lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory); + scheduler = labcomm_pthread_scheduler_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); + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); if (decimating == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } introspecting = introspecting_new(decimating->reader, decimating->writer, - lock, - labcomm_default_memory); + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); if (introspecting == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } - decoder = labcomm_decoder_new(introspecting->reader, lock, - labcomm_default_memory); - encoder = labcomm_encoder_new(introspecting->writer, lock, - labcomm_default_memory); + decoder = labcomm_decoder_new(introspecting->reader, + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); + encoder = labcomm_encoder_new(introspecting->writer, + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); pthread_t rdt; pthread_create(&rdt, NULL, run_decoder, decoder); labcomm_encoder_register_types_A(encoder); diff --git a/examples/twoway/decimating.c b/examples/twoway/decimating.c index 52b2329d6b2e4726c2dba1d970fafb5f9e79e1d2..717a8e75017cce81a92fe08689fd2d2d3ca4452e 100644 --- a/examples/twoway/decimating.c +++ b/examples/twoway/decimating.c @@ -29,8 +29,9 @@ struct decimating_private { struct decimating decimating; + struct labcomm_error_handler *error; struct labcomm_memory *memory; - struct labcomm_lock *lock; + struct labcomm_scheduler *scheduler; int encoder_initialized; struct labcomm_reader_action_context reader_action_context; struct labcomm_writer_action_context writer_action_context; @@ -59,19 +60,19 @@ static void set_decimation( static int wrap_reader_alloc( struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *labcomm_version) { int result; struct decimating_private *decimating = action_context->context; - fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__); + fprintf(stderr, "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); /* Stash away decoder for later use */ - result = labcomm_reader_alloc(r, action_context->next, - decoder, labcomm_version); + result = labcomm_reader_alloc(r, action_context->next, labcomm_version); + fprintf(stderr, "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); labcomm_decoder_register_decimating_messages_set_decimation( - decoder, set_decimation, decimating); + r->decoder, set_decimation, decimating); + fprintf(stderr, "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); return result; } @@ -110,25 +111,26 @@ struct labcomm_reader_action decimating_reader_action = { .ioctl = wrap_reader_ioctl }; -static void register_signatures(struct labcomm_encoder *encoder, - void *context) +static void register_signatures(void *context) { + struct decimating_private *decimating = context; + labcomm_encoder_register_decimating_messages_set_decimation( - encoder); + decimating->decimating.writer->encoder); } static int wrap_writer_alloc( struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, char *labcomm_version, - labcomm_encoder_enqueue enqueue) + char *labcomm_version) { + struct decimating_private *decimating = action_context->context; int result; fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__); - result = labcomm_writer_alloc(w, action_context->next, - encoder, labcomm_version, enqueue); - enqueue(encoder, register_signatures, NULL); + result = labcomm_writer_alloc(w, action_context->next, labcomm_version); + labcomm_scheduler_enqueue(decimating->scheduler, + 0, register_signatures, decimating); return result; } @@ -164,11 +166,12 @@ struct labcomm_writer_action decimating_writer_action = { .ioctl = NULL }; -extern struct decimating *decimating_new( +struct decimating *decimating_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock, - struct labcomm_memory *memory) + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler) { struct decimating_private *result; @@ -193,8 +196,9 @@ extern struct decimating *decimating_new( result->decimating.writer = writer; /* Init other fields */ - result->lock = lock; + result->error = error; result->memory = memory; + result->scheduler = scheduler; LABCOMM_SIGNATURE_ARRAY_INIT(result->decimation, struct decimation); goto out_ok; diff --git a/examples/twoway/decimating.h b/examples/twoway/decimating.h index df926efad1cf1a927a67aad36b79d597ac57e5eb..cdfedd7a5417dab9360d96add30e01b14ca13c9e 100644 --- a/examples/twoway/decimating.h +++ b/examples/twoway/decimating.h @@ -12,8 +12,9 @@ struct decimating { extern struct decimating *decimating_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock, - struct labcomm_memory *memory); + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler); #define SET_DECIMATION LABCOMM_IOSW('d',0,int) diff --git a/examples/twoway/introspecting.c b/examples/twoway/introspecting.c index 8123988b3218b72e98f5a20b5b1f0cf31b541022..cb17246b44fd7737da53794ac92e21f6d7565643 100644 --- a/examples/twoway/introspecting.c +++ b/examples/twoway/introspecting.c @@ -30,13 +30,10 @@ enum status {unknown, unhandled, unregistered, registered}; struct introspecting_private { struct introspecting introspecting; - struct labcomm_lock *lock; + struct labcomm_error_handler *error; struct labcomm_memory *memory; + struct labcomm_scheduler *scheduler; - struct labcomm_encoder *encoder; - int encoder_initialized; - struct labcomm_decoder *decoder; - int decoder_initialized; struct labcomm_reader_action_context reader_action_context; struct labcomm_writer_action_context writer_action_context; LABCOMM_SIGNATURE_ARRAY_DEF(remote, @@ -93,51 +90,60 @@ static void handles_signature( static int wrap_reader_alloc( struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *labcomm_version) { int result; struct introspecting_private *introspecting = action_context->context; fprintf(stderr, "%s %s\n", __FILE__, __FUNCTION__); - /* Stash away decoder for later use */ - introspecting->decoder = decoder; - result = labcomm_reader_alloc(r, action_context->next, - decoder, labcomm_version); + result = labcomm_reader_alloc(r, action_context->next, labcomm_version); labcomm_decoder_register_introspecting_messages_handles_signature( - introspecting->decoder, handles_signature, introspecting); - introspecting->decoder_initialized = 1; + introspecting->introspecting.reader->decoder, + handles_signature, introspecting); return result; } +struct handles_signature { + struct introspecting_private *introspecting; + int index; + struct labcomm_signature *signature; +}; + +static void send_handles_signature(void *arg) +{ + struct handles_signature *h = arg; + + introspecting_messages_handles_signature handles_signature; + handles_signature.index = h->index; + handles_signature.name = h->signature->name; + handles_signature.signature.n_0 = h->signature->size; + handles_signature.signature.a = h->signature->signature; + labcomm_encode_introspecting_messages_handles_signature( + h->introspecting->introspecting.writer->encoder, &handles_signature); +} + static int wrap_reader_start( struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - int index, struct labcomm_signature *signature, + int local_index, int remote_index, struct labcomm_signature *signature, void *value) { struct introspecting_private *introspecting = action_context->context; - int result; - result = labcomm_reader_start(r, action_context->next, index, - signature, value); if (value == NULL) { - introspecting_messages_handles_signature handles_signature; + struct handles_signature *handles_signature; + + handles_signature = labcomm_memory_alloc(introspecting->memory, 1, + sizeof(*handles_signature)); + handles_signature->introspecting = introspecting; + handles_signature->index = local_index; + handles_signature->signature = signature; + labcomm_scheduler_enqueue(introspecting->scheduler, + 0, send_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; - handles_signature.signature.a = signature->signature; - labcomm_encode_introspecting_messages_handles_signature( - introspecting->encoder, &handles_signature); } - return result; + return labcomm_reader_start(r, action_context->next, + local_index, remote_index, signature, value); } void encode_handles_signature( @@ -167,32 +173,25 @@ struct labcomm_reader_action introspecting_reader_action = { .ioctl = NULL }; -static void register_signatures(struct labcomm_encoder *encoder, - void *context) +static void register_encoder_signatures(void *context) { + struct introspecting_private *introspecting = context; + labcomm_encoder_register_introspecting_messages_handles_signature( - encoder); + introspecting->introspecting.writer->encoder); } static int wrap_writer_alloc( struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, char *labcomm_version, - labcomm_encoder_enqueue enqueue) + char *labcomm_version) { - int result; struct introspecting_private *introspecting = action_context->context; 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); - return result; + labcomm_scheduler_enqueue(introspecting->scheduler, + 0, register_encoder_signatures, introspecting); + return labcomm_writer_alloc(w, action_context->next, labcomm_version); } static int wrap_writer_start( @@ -249,8 +248,9 @@ 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_memory *memory) + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler) { struct introspecting_private *result; @@ -275,12 +275,9 @@ extern struct introspecting *introspecting_new( result->introspecting.writer = writer; /* Init other fields */ - result->lock = lock; + result->error = error; result->memory = memory; - result->encoder = NULL; - result->encoder_initialized = 0; - result->decoder = NULL; - result->decoder_initialized = 0; + result->scheduler = scheduler; LABCOMM_SIGNATURE_ARRAY_INIT(result->remote, struct remote); LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct local); diff --git a/examples/twoway/introspecting.h b/examples/twoway/introspecting.h index 7eea00e1855013999cb8936400719a2fccd36f8b..894b9988d48379f359fa83663791b3ba8426dd17 100644 --- a/examples/twoway/introspecting.h +++ b/examples/twoway/introspecting.h @@ -36,8 +36,9 @@ struct introspecting { extern struct introspecting *introspecting_new( struct labcomm_reader *reader, struct labcomm_writer *writer, - struct labcomm_lock *lock, - struct labcomm_memory *memory); + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler); #define HAS_SIGNATURE LABCOMM_IOS('i',2) diff --git a/examples/twoway/server.c b/examples/twoway/server.c index 58a8ae0e39eb8fb7cc8fe480c0de266e336b6a74..66c7c6a3d61f85a92b36f721da082ad9416cad77 100644 --- a/examples/twoway/server.c +++ b/examples/twoway/server.c @@ -27,7 +27,9 @@ #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> -#include <labcomm_pthread_mutex_lock.h> +#include <labcomm_default_error_handler.h> +#include <labcomm_default_memory.h> +#include <labcomm_pthread_scheduler.h> #include <labcomm_fd_reader.h> #include <labcomm_fd_writer.h> #include "decimating.h" @@ -89,34 +91,40 @@ static void *run_client(void *arg) struct client *client = arg; struct decimating *decimating; struct introspecting *introspecting; - struct labcomm_lock *lock; + struct labcomm_scheduler *scheduler; printf("Client start\n"); client->A = 0; client->B = 0; - lock = labcomm_pthread_mutex_lock_new(labcomm_default_memory); + scheduler = labcomm_pthread_scheduler_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); + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); if (decimating == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } introspecting = introspecting_new(decimating->reader, decimating->writer, - lock, - labcomm_default_memory); + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); if (introspecting == NULL) { /* Warning: might leak reader and writer at this point */ goto out; } - client->decoder = labcomm_decoder_new(introspecting->reader, lock, - labcomm_default_memory); - client->encoder = labcomm_encoder_new(introspecting->writer, lock, - labcomm_default_memory); + client->decoder = labcomm_decoder_new(introspecting->reader, + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); + client->encoder = labcomm_encoder_new(introspecting->writer, + labcomm_default_error_handler, + labcomm_default_memory, + scheduler); pthread_t rdt; pthread_create(&rdt, NULL, run_decoder, client); labcomm_encoder_register_types_Sum(client->encoder); diff --git a/lib/c/Makefile b/lib/c/Makefile index 043eaf067f23d35e927a0f9867161d37dd44d0d2..979b9899e68c0ca446a39da503394ff395b75a92 100644 --- a/lib/c/Makefile +++ b/lib/c/Makefile @@ -7,12 +7,16 @@ LDFLAGS=-L. #LDLIBS_TEST=-Tlabcomm.linkscript -lcunit -llabcomm LDLIBS_TEST=-lcunit -llabcomm -Tlabcomm.linkscript -lrt -OBJS=labcomm_memory.o labcomm_default_memory.o \ +OBJS=labcomm_memory.o \ + labcomm_default_error_handler.o \ + labcomm_default_memory.o \ + labcomm_default_scheduler.o \ labcomm_time.o labcomm_scheduler.o \ + labcomm_encoder.o labcomm_decoder.o \ labcomm.o \ labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o \ labcomm_pthread_scheduler.o \ - labcomm_pthread_mutex_lock.o + labcomm_signature_gnu_ld_tricks.o #FIXME: labcomm_mem_reader.o labcomm_mem_writer.o LABCOMM_JAR=../../compiler/labComm.jar diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c index 582d5aa2b345ba32922285d386bfb87f1345dd6e..1721289e4b7b7451f57e0d8dda8c50ffdb7e1d38 100644 --- a/lib/c/labcomm.c +++ b/lib/c/labcomm.c @@ -39,90 +39,6 @@ #define LABCOMM_VERSION "LabComm2013" -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); - LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int); -}; - -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; - struct encoder_alloc_action { - struct encoder_alloc_action *next; - void (*action)(struct labcomm_encoder *encoder, void *context); - void *context; - } *alloc_action; - labcomm_error_handler_callback on_error; - LABCOMM_SIGNATURE_ARRAY_DEF(registered, int); -}; - -struct labcomm_sample_entry { - struct labcomm_sample_entry *next; - int index; - struct labcomm_signature *signature; - labcomm_decoder_function decoder; - labcomm_handler_function handler; - labcomm_encoder_function encode; - void *context; -}; - -extern struct labcomm_signature labcomm_first_signature; -extern struct labcomm_signature labcomm_last_signature; - -struct labcomm_encoder_context { - struct labcomm_sample_entry *by_section; -}; - -struct labcomm_decoder_context { - struct labcomm_sample_entry *sample; -}; - -/* Lock wrappers */ -#define CONDCALL_lock(lock, ...) lock -#define CONDCALL(func, ...) \ - if (CONDCALL_lock(__VA_ARGS__) && \ - CONDCALL_lock(__VA_ARGS__)->action->func) { \ - return CONDCALL_lock(__VA_ARGS__)->action->func(__VA_ARGS__); \ - } \ - return -ENOSYS; - -int labcomm_lock_free(struct labcomm_lock *lock) { - CONDCALL(free, lock); -} - -int labcomm_lock_acquire(struct labcomm_lock *lock) -{ - CONDCALL(acquire, lock); -} - -int labcomm_lock_release(struct labcomm_lock *lock) -{ - CONDCALL(release, lock); -} - -int labcomm_lock_wait(struct labcomm_lock *lock, useconds_t usec){ - CONDCALL(wait, lock, usec); -} - -int labcomm_lock_notify(struct labcomm_lock *lock) -{ - CONDCALL(notify, lock); -} - -#undef CONDCALL -#undef CONDCALL_lock - /* Unwrapping reader/writer functions */ #define UNWRAP_ac(rw, ac, ...) ac #define UNWRAP(func, ...) \ @@ -135,10 +51,9 @@ int labcomm_lock_notify(struct labcomm_lock *lock) int labcomm_reader_alloc(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *labcomm_version) { - UNWRAP(alloc, r, action_context, decoder, labcomm_version); + UNWRAP(alloc, r, action_context, labcomm_version); } int labcomm_reader_free(struct labcomm_reader *r, @@ -149,10 +64,11 @@ int labcomm_reader_free(struct labcomm_reader *r, int labcomm_reader_start(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - int index, struct labcomm_signature *signature, + int local_index, int remote_index, + struct labcomm_signature *signature, void *value) { - UNWRAP(start, r, action_context, index, signature, value); + UNWRAP(start, r, action_context, local_index, remote_index, signature, value); } int labcomm_reader_end(struct labcomm_reader *r, @@ -178,11 +94,9 @@ int labcomm_reader_ioctl(struct labcomm_reader *r, int labcomm_writer_alloc(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, - char *labcomm_version, - labcomm_encoder_enqueue enqueue) + char *labcomm_version) { - UNWRAP(alloc, w, action_context, encoder, labcomm_version, enqueue); + UNWRAP(alloc, w, action_context, labcomm_version); } int labcomm_writer_free(struct labcomm_writer *w, @@ -225,15 +139,6 @@ int labcomm_writer_ioctl(struct labcomm_writer *w, -void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback) -{ - encoder->on_error = callback; -} - -void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback) -{ - decoder->on_error = callback; -} static const char *labcomm_error_string[] = { #define LABCOMM_ERROR(name, description) description , @@ -254,17 +159,6 @@ const char *labcomm_error_get_str(enum labcomm_error error_id) return error_str; } -void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d, labcomm_handle_new_datatype_callback on_new_datatype) -{ - d->on_new_datatype = on_new_datatype; -} - -int on_new_datatype(struct labcomm_decoder *d, struct labcomm_signature *sig) -{ - d->on_error(LABCOMM_ERROR_DEC_UNKNOWN_DATATYPE, 4, "%s(): unknown datatype '%s'\n", __FUNCTION__, sig->name); - return 0; -} - void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...) { #ifndef LABCOMM_NO_STDIO @@ -291,644 +185,6 @@ void on_error_fprintf(enum labcomm_error error_id, size_t nbr_va_args, ...) } -static struct labcomm_sample_entry *get_sample_by_signature_address( - struct labcomm_sample_entry *head, - struct labcomm_signature *signature) -{ - struct labcomm_sample_entry *p; - for (p = head ; p && p->signature != signature ; p = p->next) { - - } - return p; -} - -static struct labcomm_sample_entry *get_sample_by_signature_value( - struct labcomm_sample_entry *head, - struct labcomm_signature *signature) -{ - struct labcomm_sample_entry *p; - for (p = head ; p ; p = p->next) { - if (p->signature->type == signature->type && - p->signature->size == signature->size && - strcmp(p->signature->name, signature->name) == 0 && - bcmp((void*)p->signature->signature, (void*)signature->signature, - signature->size) == 0) { - break; - } - } - return p; -} - -static struct labcomm_sample_entry *get_sample_by_index( - struct labcomm_sample_entry *head, - int index) -{ - struct labcomm_sample_entry *p; - for (p = head ; p && p->index != index ; p = p->next) { - } - return p; -} - -static int get_local_index( - struct labcomm_signature *s) -{ - int result = -ENOENT; - - if (&labcomm_first_signature <= s && s < &labcomm_last_signature) { - result = (int)(s - &labcomm_first_signature) + LABCOMM_USER; - } - return result; -} - -static int get_encoder_index( - struct labcomm_encoder *e, - struct labcomm_signature *s) -{ - return get_local_index(s); -} - -struct labcomm_encoder *labcomm_encoder_new( - struct labcomm_writer *writer, - struct labcomm_lock *lock, - struct labcomm_memory *memory) -{ - struct labcomm_encoder *result; - - result = labcomm_memory_alloc(memory, 0, sizeof(*result)); - if (result) { - struct labcomm_encoder_context *context; - - context = labcomm_memory_alloc(memory, 0, sizeof(*context)); -#ifdef LABCOMM_ENCODER_LINEAR_SEARCH - context->sample = NULL; - context->index = LABCOMM_USER; -#else - context->by_section = NULL; -#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; - result->alloc_action = NULL; - result->on_error = on_error_fprintf; - LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int); - } - return result; -} - -static int encoder_enqueue_action( - struct labcomm_encoder *encoder, - void (*action)(struct labcomm_encoder *encoder, void *context), - void *context) -{ - int result; - struct encoder_alloc_action *element, **next; - - element = labcomm_memory_alloc(encoder->memory, 0, sizeof(*action)); - if (element == NULL) { - result = -ENOMEM; - goto out; - } - element->next = NULL; - element->action = action; - element->context = context; - for (next = &encoder->alloc_action ; *next ; next = &(*next)->next) { - } - *next = element; - result = 0; -out: - return result; -} - -static struct labcomm_encoder *enter_encoder(struct labcomm_encoder *e) -{ - if (e->is_deferred) { - return e->is_deferred; - } else { - labcomm_lock_acquire(e->lock); - e->waiting++; - while (e->busy) { labcomm_lock_wait(e->lock, 10000000); } - e->busy = 1; - labcomm_lock_release(e->lock); - - if (e->writer->data == NULL) { - labcomm_writer_alloc(e->writer,e->writer->action_context, - e, LABCOMM_VERSION, encoder_enqueue_action); - if (e->alloc_action) { - struct labcomm_encoder deferred; - struct encoder_alloc_action *p; - - deferred.is_deferred = e; - p = e->alloc_action; - e->alloc_action = NULL; - while (p) { - struct encoder_alloc_action *tmp; - - p->action(&deferred, p->context); - tmp = p; - p = p->next; - labcomm_memory_free(e->memory, 1, tmp); - } - } - } - } - return e; -} -static void leave_encoder(struct labcomm_encoder *e) -{ - if (!e->is_deferred) { - labcomm_lock_acquire(e->lock); { - e->busy = 0; - e->waiting--; - if (e->waiting) { - labcomm_lock_notify(e->lock); - } - } labcomm_lock_release(e->lock); - } -} - -int labcomm_internal_encoder_register( - struct labcomm_encoder *encoder, - struct labcomm_signature *signature, - labcomm_encoder_function encode) -{ - int result = -EINVAL; - struct labcomm_encoder *e; - int index; - - e = enter_encoder(encoder); - index = get_encoder_index(e, signature); - if (signature->type == LABCOMM_SAMPLE) { - if (index > 0) { - int *registered = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, - int, index); - if (! *registered) { - int err; - - *registered = 1; - err = labcomm_writer_start(e->writer, e->writer->action_context, - index, signature, NULL); - if (err == -EALREADY) { - result = 0; - } else if (err != 0) { - result = err; - } else if (err == 0) { - int i; - - labcomm_write_packed32(e->writer, signature->type); - labcomm_write_packed32(e->writer, index); - labcomm_write_string(e->writer, signature->name); - for (i = 0 ; i < signature->size ; i++) { - if (e->writer->pos >= e->writer->count) { - labcomm_writer_flush(e->writer, e->writer->action_context); - } - e->writer->data[e->writer->pos] = signature->signature[i]; - e->writer->pos++; - } - labcomm_writer_end(e->writer, e->writer->action_context); - result = e->writer->error; - } - } - } - } - leave_encoder(encoder); - return result; -} - -int labcomm_internal_encode( - struct labcomm_encoder *encoder, - struct labcomm_signature *signature, - labcomm_encoder_function encode, - void *value) -{ - int result; - struct labcomm_encoder *e; - int index; - - e = enter_encoder(encoder); - index = get_encoder_index(e, signature); - result = labcomm_writer_start(e->writer, e->writer->action_context, - index, signature, value); - if (result == -EALREADY) { result = 0; goto no_end; } - if (result != 0) { goto out; } - result = labcomm_write_packed32(e->writer, index); - if (result != 0) { goto out; } - result = encode(e->writer, value); -out: - labcomm_writer_end(e->writer, e->writer->action_context); -no_end: - leave_encoder(encoder); - return result; -} - -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->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; - labcomm_memory_free(memory, 0, entry); - entry = entry_next; - } -#else - labcomm_memory_free(memory, 0, context->by_section); -#endif - labcomm_memory_free(memory, 0, e->context); - labcomm_memory_free(memory, 0, e); -} - -int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, - uint32_t action, - ...) -{ - int result; - va_list va; - - if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) { - result = -EINVAL; - goto out; - } - - va_start(va, action); - result = labcomm_writer_ioctl(encoder->writer, - encoder->writer->action_context, - 0, NULL, action, va); - va_end(va); - -out: - return result; -} - -static int writer_ioctl(struct labcomm_writer *writer, - uint32_t action, - ...) -{ - int result; - va_list va; - - if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) { - result = -EINVAL; - goto out; - } - - va_start(va, action); - result = labcomm_writer_ioctl(writer, writer->action_context, - 0, NULL, action, va); - va_end(va); -out: - return result; -} - -int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, - struct labcomm_signature *signature, - uint32_t action, va_list va) -{ - int result = -ENOTSUP; - - result = labcomm_writer_ioctl(encoder->writer, - encoder->writer->action_context, - -1, signature, action, va); - return result; -} - -static void collect_flat_signature( - struct labcomm_decoder *decoder, - struct labcomm_writer *writer) -{ - int type = labcomm_read_packed32(decoder->reader); - if (type >= LABCOMM_USER) { - decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3, - "Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type); - } else { - labcomm_write_packed32(writer, type); - switch (type) { - case LABCOMM_ARRAY: { - int dimensions, i; - - dimensions = labcomm_read_packed32(decoder->reader); - labcomm_write_packed32(writer, dimensions); - for (i = 0 ; i < dimensions ; i++) { - int n = labcomm_read_packed32(decoder->reader); - labcomm_write_packed32(writer, n); - } - collect_flat_signature(decoder, writer); - } break; - case LABCOMM_STRUCT: { - int fields, i; - - fields = labcomm_read_packed32(decoder->reader); - labcomm_write_packed32(writer, fields); - for (i = 0 ; i < fields ; i++) { - char *name = labcomm_read_string(decoder->reader); - labcomm_write_string(writer, name); - labcomm_memory_free(decoder->memory, 1, name); - collect_flat_signature(decoder, writer); - } - } break; - case LABCOMM_BOOLEAN: - case LABCOMM_BYTE: - case LABCOMM_SHORT: - case LABCOMM_INT: - case LABCOMM_LONG: - case LABCOMM_FLOAT: - case LABCOMM_DOUBLE: - case LABCOMM_STRING: { - } break; - default: { - decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3, - "Implement %s (2) for type 0x%x...\n", __FUNCTION__, type); - } break; - } - } -} - -struct labcomm_decoder *labcomm_decoder_new( - struct labcomm_reader *reader, - struct labcomm_lock *lock, - struct labcomm_memory *memory) -{ - struct labcomm_decoder *result; - - result = labcomm_memory_alloc(memory, 0, sizeof(*result)); - if (result) { - 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); - LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int); - } - return result; -} - -int labcomm_internal_decoder_register( - struct labcomm_decoder *d, - struct labcomm_signature *signature, - labcomm_decoder_function type_decoder, - labcomm_handler_function handler, - void *handler_context) -{ - struct labcomm_decoder_context *context = d->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; -} - -static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind) -{ - int result; - struct labcomm_decoder_context *context = d->context; - - /* TODO: should the labcomm_dynamic_buffer_writer be - a permanent part of labcomm_decoder? */ - struct labcomm_writer_action_context action_context = { - .next = NULL, - .action = labcomm_dynamic_buffer_writer_action, - .context = NULL - }; - struct labcomm_writer writer = { - .action_context = &action_context, - .memory = d->memory, - .data = NULL, - .data_size = 0, - .count = 0, - .pos = 0, - .error = 0, - }; - struct labcomm_signature signature; - struct labcomm_sample_entry *entry = NULL; - int remote_index, err; - - labcomm_writer_alloc(&writer, writer.action_context, NULL, "", NULL); - labcomm_writer_start(&writer, writer.action_context, 0, NULL, NULL); - remote_index = labcomm_read_packed32(d->reader); //int - signature.name = labcomm_read_string(d->reader); - signature.type = kind; - collect_flat_signature(d, &writer); - labcomm_writer_end(&writer, writer.action_context); - err = writer_ioctl(&writer, - LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN, - &signature.size); - if (err < 0) { - printf("Failed to get size: %s\n", strerror(-err)); - result = -ENOENT; - goto free_signature_name; - } - err = writer_ioctl(&writer, - LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER, - &signature.signature); - if (err < 0) { - printf("Failed to get pointer: %s\n", strerror(-err)); - result = -ENOENT; - goto free_signature_name; - } - entry = get_sample_by_signature_value(context->sample, &signature); - if (! entry) { - /* Unknown datatype, bail out */ - d->on_new_datatype(d, &signature); - result = -ENOENT; - } else if (entry->index && entry->index != remote_index) { - d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5, - "%s(): index mismatch '%s' (id=0x%x != 0x%x)\n", - __FUNCTION__, signature.name, entry->index, remote_index); - result = -ENOENT; - } else { - int local_index; - int *local_to_remote, *remote_to_local; - // 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->memory, - d->local_to_remote, int, - local_index); - *local_to_remote = remote_index; - remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, - d->remote_to_local, int, - remote_index); - *remote_to_local = local_index; - result = remote_index; - } -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) - result = -ENOENT; - } - return result; -} - -struct call_handler_context { - struct labcomm_sample_entry *entry; - struct labcomm_reader *reader; -}; - -static void call_handler(void *value, void *context) -{ - struct call_handler_context *wrap = context; - - labcomm_reader_start(wrap->reader, wrap->reader->action_context, - wrap->entry->index, wrap->entry->signature, - value); - wrap->entry->handler(value, wrap->entry->context); - labcomm_reader_end(wrap->reader, wrap->reader->action_context); -} - -int labcomm_decoder_decode_one(struct labcomm_decoder *d) -{ - int result, index; - struct labcomm_decoder_context *context = d->context; - - if (d->reader->data == NULL) { - result = labcomm_reader_alloc(d->reader, d->reader->action_context, - d, LABCOMM_VERSION); - if (result <= 0) { - goto out; - } - } - index = labcomm_read_packed32(d->reader); - if (d->reader->error < 0) { - result = d->reader->error; - goto out; - } - if (index == LABCOMM_TYPEDEF || index == LABCOMM_SAMPLE) { - result = decode_typedef_or_sample(d, index); - } else { - struct labcomm_sample_entry *entry; - - entry = get_sample_by_index(context->sample, index); - if (!entry) { - // printf("Error: %s: type not found (id=0x%x)\n", - //__FUNCTION__, result); - d->on_error(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND, 3, - "%s(): type not found (id=0x%x)\n", - __FUNCTION__, index); - result = -ENOENT; - } else { - struct call_handler_context wrap = { - .entry = entry, - .reader = d->reader - }; - entry->decoder(d->reader, call_handler, &wrap); - result = index; - } - } -out: - return result; -} - -void labcomm_decoder_run(struct labcomm_decoder *d) -{ - while (labcomm_decoder_decode_one(d) > 0) { - } -} - -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(memory, d->local_to_remote, int); - LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int); - while (entry != NULL) { - entry_next = entry->next; - labcomm_memory_free(memory, 0, entry); - entry = entry_next; - } - - labcomm_memory_free(memory, 0, d->context); - labcomm_memory_free(memory, 0, d); -} - -int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, - uint32_t action, - ...) -{ - int result; - va_list va; - - va_start(va, action); - result = labcomm_reader_ioctl(decoder->reader, - decoder->reader->action_context, - 0, NULL, action, va); - va_end(va); - return result; -} - -int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder, - struct labcomm_signature *signature, - uint32_t action, va_list va) -{ - int result; - int local_index, *remote_index; - - local_index = get_local_index(signature); - remote_index = LABCOMM_SIGNATURE_ARRAY_REF(decoder->memory, - decoder->local_to_remote, int, - local_index); - if (*remote_index == 0) { - result = -EAGAIN; - } else { - result = labcomm_reader_ioctl(decoder->reader, - decoder->reader->action_context, - *remote_index, signature, - action, va); - } - return result; -} #if 0 static void dump(void *p, int size, int first, int last) diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h index e4d3fc89254872c7e8ddc76667dbd8df76beb263..12df1a20b0a944798b72cbe41853e97624da06d1 100644 --- a/lib/c/labcomm.h +++ b/lib/c/labcomm.h @@ -26,7 +26,8 @@ #include <stdarg.h> #include <stdint.h> #include <unistd.h> -#include <labcomm_error.h> +#include "labcomm_error.h" +#include "labcomm_scheduler.h" /* Forward declaration */ struct labcomm_encoder; @@ -79,21 +80,6 @@ typedef int (*labcomm_handle_new_datatype_callback)( void labcomm_decoder_register_new_datatype_handler(struct labcomm_decoder *d, labcomm_handle_new_datatype_callback on_new_datatype); -/* - * 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_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(struct labcomm_lock *lock); -int labcomm_lock_sleep_epoch(struct labcomm_lock *lock); -int labcomm_lock_sleep_add(struct labcomm_lock *lock, useconds_t usec); -int labcomm_lock_sleep(struct labcomm_lock *lock); - /* * Dynamic memory handling * lifetime == 0 memory that will live for as long as the @@ -109,8 +95,6 @@ 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 */ @@ -118,14 +102,15 @@ struct labcomm_reader; struct labcomm_decoder *labcomm_decoder_new( struct labcomm_reader *reader, - struct labcomm_lock *lock, - struct labcomm_memory *memory); + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler); +void labcomm_decoder_free( + struct labcomm_decoder *decoder); int labcomm_decoder_decode_one( struct labcomm_decoder *decoder); void labcomm_decoder_run( struct labcomm_decoder *decoder); -void labcomm_decoder_free( - struct labcomm_decoder *decoder); /* See labcomm_ioctl.h for predefined ioctl_action values */ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder, @@ -139,8 +124,9 @@ struct labcomm_writer; struct labcomm_encoder *labcomm_encoder_new( struct labcomm_writer *writer, - struct labcomm_lock *lock, - struct labcomm_memory *memory); + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler); void labcomm_encoder_free( struct labcomm_encoder *encoder); diff --git a/lib/c/labcomm_decoder.c b/lib/c/labcomm_decoder.c new file mode 100644 index 0000000000000000000000000000000000000000..175a382440e0840ac2fb2450f6163154cc09d342 --- /dev/null +++ b/lib/c/labcomm_decoder.c @@ -0,0 +1,403 @@ +/* + labcomm_decoder.c -- runtime for handling decoding of labcomm samples. + + 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/>. +*/ +#define LABCOMM_VERSION "LabComm2013" + +#include <errno.h> +#include "labcomm.h" +#include "labcomm_private.h" +#include "labcomm_signature.h" +#include "labcomm_ioctl.h" +#include "labcomm_dynamic_buffer_writer.h" + +struct sample_entry { + int remote_index; + struct labcomm_signature *signature; + labcomm_decoder_function decode; + labcomm_handler_function handler; + void *context; +}; + +struct labcomm_decoder { + struct labcomm_reader *reader; + struct labcomm_error_handler *error; + struct labcomm_memory *memory; + struct labcomm_scheduler *scheduler; + labcomm_error_handler_callback on_error; + labcomm_handle_new_datatype_callback on_new_datatype; + LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry); + LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int); +}; + +struct labcomm_decoder *labcomm_decoder_new( + struct labcomm_reader *reader, + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler) +{ + struct labcomm_decoder *result; + + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); + if (result) { + 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->error = error; + result->memory = memory; + result->scheduler = scheduler; + LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry); + LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int); + } + return result; +} + +void labcomm_decoder_free(struct labcomm_decoder* d) +{ + struct labcomm_memory *memory = d->memory; + + labcomm_reader_free(d->reader, d->reader->action_context); + LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->local, struct sample_entry); + LABCOMM_SIGNATURE_ARRAY_FREE(memory, d->remote_to_local, int); + labcomm_memory_free(memory, 0, d); +} + +static void collect_flat_signature( + struct labcomm_decoder *decoder, + struct labcomm_writer *writer) +{ + int type = labcomm_read_packed32(decoder->reader); + if (type >= LABCOMM_USER) { + decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3, + "Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type); + } else { + labcomm_write_packed32(writer, type); + switch (type) { + case LABCOMM_ARRAY: { + int dimensions, i; + + dimensions = labcomm_read_packed32(decoder->reader); + labcomm_write_packed32(writer, dimensions); + for (i = 0 ; i < dimensions ; i++) { + int n = labcomm_read_packed32(decoder->reader); + labcomm_write_packed32(writer, n); + } + collect_flat_signature(decoder, writer); + } break; + case LABCOMM_STRUCT: { + int fields, i; + + fields = labcomm_read_packed32(decoder->reader); + labcomm_write_packed32(writer, fields); + for (i = 0 ; i < fields ; i++) { + char *name = labcomm_read_string(decoder->reader); + labcomm_write_string(writer, name); + labcomm_memory_free(decoder->memory, 1, name); + collect_flat_signature(decoder, writer); + } + } break; + case LABCOMM_BOOLEAN: + case LABCOMM_BYTE: + case LABCOMM_SHORT: + case LABCOMM_INT: + case LABCOMM_LONG: + case LABCOMM_FLOAT: + case LABCOMM_DOUBLE: + case LABCOMM_STRING: { + } break; + default: { + decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3, + "Implement %s (2) for type 0x%x...\n", __FUNCTION__, type); + } break; + } + } +} + +static int writer_ioctl(struct labcomm_writer *writer, + uint32_t action, + ...) +{ + int result; + va_list va; + + if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) { + result = -EINVAL; + goto out; + } + + va_start(va, action); + result = labcomm_writer_ioctl(writer, writer->action_context, + 0, NULL, action, va); + va_end(va); +out: + return result; +} + +static int decode_typedef_or_sample(struct labcomm_decoder *d, int kind) +{ + int result; + + /* TODO: should the labcomm_dynamic_buffer_writer be + a permanent part of labcomm_decoder? */ + struct labcomm_writer_action_context action_context = { + .next = NULL, + .action = labcomm_dynamic_buffer_writer_action, + .context = NULL + }; + struct labcomm_writer writer = { + .action_context = &action_context, + .memory = d->memory, + .data = NULL, + .data_size = 0, + .count = 0, + .pos = 0, + .error = 0, + }; + struct labcomm_signature signature; + int remote_index, err; + + labcomm_writer_alloc(&writer, writer.action_context, ""); + labcomm_writer_start(&writer, writer.action_context, 0, NULL, NULL); + remote_index = labcomm_read_packed32(d->reader); //int + signature.name = labcomm_read_string(d->reader); + signature.type = kind; + collect_flat_signature(d, &writer); + labcomm_writer_end(&writer, writer.action_context); + err = writer_ioctl(&writer, + LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN, + &signature.size); + if (err < 0) { + fprintf(stderr, "Failed to get size: %s\n", strerror(-err)); + result = -ENOENT; + goto free_signature_name; + } + err = writer_ioctl(&writer, + LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER, + &signature.signature); + if (err < 0) { + fprintf(stderr, "Failed to get pointer: %s\n", strerror(-err)); + result = -ENOENT; + goto free_signature_name; + } + { + int i; + + labcomm_scheduler_data_lock(d->scheduler); + LABCOMM_SIGNATURE_ARRAY_FOREACH(d->local, struct sample_entry, i) { + struct sample_entry *s; + int *remote_to_local; + + result = -ENOENT; + s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->local, struct sample_entry, i); + if (s->signature && + s->signature->type == signature.type && + s->signature->size == signature.size && + strcmp(s->signature->name, signature.name) == 0 && + bcmp((void*)s->signature->signature, (void*)signature.signature, + signature.size) == 0) { + s->remote_index = remote_index; + remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->remote_to_local, int, + remote_index); + *remote_to_local = i; + result = remote_index; + break; + } + } + labcomm_scheduler_data_unlock(d->scheduler); + } +#if 0 + if (! entry) { + /* Unknown datatype, bail out */ + d->on_new_datatype(d, &signature); + result = -ENOENT; + } else if (entry->index && entry->index != remote_index) { + d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5, + "%s(): index mismatch '%s' (id=0x%x != 0x%x)\n", + __FUNCTION__, signature.name, entry->index, remote_index); + result = -ENOENT; +#endif +free_signature_name: + labcomm_memory_free(d->memory, 0, signature.name); + labcomm_writer_free(&writer, writer.action_context); + return result; +} + +struct call_handler_context { + struct labcomm_reader *reader; + int local_index; + int remote_index; + struct labcomm_signature *signature; + labcomm_handler_function handler; + void *context; +}; + +static void call_handler(void *value, void *context) +{ + struct call_handler_context *wrap = context; + + labcomm_reader_start(wrap->reader, wrap->reader->action_context, + wrap->local_index, wrap->remote_index, wrap->signature, + value); + wrap->handler(value, wrap->context); + labcomm_reader_end(wrap->reader, wrap->reader->action_context); +} + +static void reader_alloc(struct labcomm_reader *reader) +{ + if (reader->data == NULL) { + labcomm_reader_alloc(reader, reader->action_context, + LABCOMM_VERSION); + } +} + +int labcomm_decoder_decode_one(struct labcomm_decoder *d) +{ + int result, remote_index; + + reader_alloc(d->reader); + remote_index = labcomm_read_packed32(d->reader); + if (d->reader->error < 0) { + result = d->reader->error; + goto out; + } + if (remote_index == LABCOMM_TYPEDEF || remote_index == LABCOMM_SAMPLE) { + result = decode_typedef_or_sample(d, remote_index); + } else { + int *local_index; + struct call_handler_context wrap = { + .reader = d->reader, + .remote_index = remote_index, + .signature = NULL, + .handler = NULL, + .context = NULL, + }; + labcomm_decoder_function do_decode = NULL; + + labcomm_scheduler_data_lock(d->scheduler); + local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->remote_to_local, int, + remote_index); + if (*local_index != 0) { + struct sample_entry *entry; + + entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->local, struct sample_entry, + *local_index); + wrap.local_index = *local_index; + wrap.signature = entry->signature; + wrap.handler = entry->handler; + wrap.context = entry->context; + do_decode = entry->decode; + result = *local_index; + } + labcomm_scheduler_data_unlock(d->scheduler); + if (do_decode) { + do_decode(d->reader, call_handler, &wrap); + } else { + result = -ENOENT; + } + } +out: + return result; +} + +void labcomm_decoder_run(struct labcomm_decoder *d) +{ + while (labcomm_decoder_decode_one(d) > 0) { + } +} + +int labcomm_decoder_ioctl(struct labcomm_decoder *d, + uint32_t action, + ...) +{ + int result; + va_list va; + + va_start(va, action); + result = labcomm_reader_ioctl(d->reader, + d->reader->action_context, + 0, NULL, action, va); + va_end(va); + return result; +} + +int labcomm_internal_decoder_ioctl(struct labcomm_decoder *d, + struct labcomm_signature *signature, + uint32_t action, va_list va) +{ + int result; + int local_index, remote_index; + + local_index = labcomm_signature_local_index(signature); + labcomm_scheduler_data_lock(d->scheduler); + remote_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->local, + struct sample_entry, + local_index)->remote_index; + labcomm_scheduler_data_unlock(d->scheduler); + if (remote_index == 0) { + result = -EAGAIN; + } else { + result = labcomm_reader_ioctl(d->reader, d->reader->action_context, + remote_index, signature, action, va); + } + return result; +} + +int labcomm_internal_decoder_register( + struct labcomm_decoder *d, + struct labcomm_signature *signature, + labcomm_decoder_function decode, + labcomm_handler_function handler, + void *context) +{ + int local_index; + struct sample_entry *entry; + + reader_alloc(d->reader); + local_index = labcomm_signature_local_index(signature); + if (local_index <= 0) { goto out; } + labcomm_reader_start(d->reader, d->reader->action_context, + local_index, 0, signature, + NULL); + labcomm_reader_end(d->reader, d->reader->action_context); + + labcomm_scheduler_data_lock(d->scheduler); + entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, + d->local, struct sample_entry, + local_index); + if (entry == NULL) { local_index = -ENOMEM; goto unlock; } + entry->remote_index = 0; + entry->signature = signature; + entry->decode = decode; + entry->handler = handler; + entry->context = context; +unlock: + labcomm_scheduler_data_unlock(d->scheduler); +out: + return local_index; +} + diff --git a/lib/c/labcomm_default_error_handler.c b/lib/c/labcomm_default_error_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..61e04dd6d5153f360b4564364c3b37ee67a171af --- /dev/null +++ b/lib/c/labcomm_default_error_handler.c @@ -0,0 +1,24 @@ +/* + test_default_error_handler.c -- LabComm default error handler + + 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.h" + +struct labcomm_error_handler *labcomm_default_error_handler = NULL; diff --git a/lib/c/labcomm_default_error_handler.h b/lib/c/labcomm_default_error_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..4cd642a9e2f986f31ce085d6fc775fa8d7312fb2 --- /dev/null +++ b/lib/c/labcomm_default_error_handler.h @@ -0,0 +1,24 @@ +/* + test_default_error_handler.h -- LabComm default error handler + + 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.h" + +extern struct labcomm_error_handler *labcomm_default_error_handler; diff --git a/lib/c/labcomm_pthread_mutex_lock.h b/lib/c/labcomm_default_memory.h similarity index 75% rename from lib/c/labcomm_pthread_mutex_lock.h rename to lib/c/labcomm_default_memory.h index e67b16a24fe5b4b4a2997add53a3479cd6ef99fe..09112099de57360fccb9897ab1a7926830df60b8 100644 --- a/lib/c/labcomm_pthread_mutex_lock.h +++ b/lib/c/labcomm_default_memory.h @@ -1,5 +1,5 @@ /* - labcomm_pthread_mutex_lock.h -- a labcomm_lock on top of pthread_mutex. + test_default_memory.h -- LabComm default memory allocator Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se> @@ -19,12 +19,9 @@ 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 <stdlib.h> #include "labcomm.h" +#include "labcomm_private.h" -struct labcomm_lock *labcomm_pthread_mutex_lock_new( - struct labcomm_memory *memory); +extern struct labcomm_memory *labcomm_default_memory; -#endif diff --git a/lib/c/labcomm_default_scheduler.c b/lib/c/labcomm_default_scheduler.c new file mode 100644 index 0000000000000000000000000000000000000000..cbc46400a489ec2ac6362515a82efa6342af417e --- /dev/null +++ b/lib/c/labcomm_default_scheduler.c @@ -0,0 +1,109 @@ +/* + test_default_scheduler.c -- LabComm default scheduler + + 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 <stdio.h> +#include <stdlib.h> +#include "labcomm_default_scheduler.h" +#include "labcomm_scheduler.h" +#include "labcomm_scheduler_private.h" + +static int scheduler_free(struct labcomm_scheduler *s) +{ + fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__, + "not implemented"); + exit(1); + return 0; +} + +static int scheduler_writer_lock(struct labcomm_scheduler *s) +{ + return 0; +} + +static int scheduler_writer_unlock(struct labcomm_scheduler *s) +{ + return 0; +} + +static int scheduler_data_lock(struct labcomm_scheduler *s) +{ + return 0; +} + +static int scheduler_data_unlock(struct labcomm_scheduler *s) +{ + return 0; +} + +static struct labcomm_time *scheduler_now(struct labcomm_scheduler *s) +{ + fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__, + "not implemented"); + exit(1); + return NULL; +} + +static int scheduler_sleep(struct labcomm_scheduler *s, + struct labcomm_time *t) +{ + fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__, + "not implemented"); + exit(1); + return 0; +} + +static int scheduler_wakeup(struct labcomm_scheduler *s) +{ + fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__, + "not implemented"); + exit(1); + return 0; +} + +static int scheduler_enqueue(struct labcomm_scheduler *s, + useconds_t delay, + void (*deferred)(void *context), + void *context) +{ + fprintf(stderr, "%s:%d %s %s", __FILE__, __LINE__, __FUNCTION__, + "not implemented"); + exit(1); + return 0; +} + +static const struct labcomm_scheduler_action scheduler_action = { + .free = scheduler_free, + .writer_lock = scheduler_writer_lock, + .writer_unlock = scheduler_writer_unlock, + .data_lock = scheduler_data_lock, + .data_unlock = scheduler_data_unlock, + .now = scheduler_now, + .sleep = scheduler_sleep, + .wakeup = scheduler_wakeup, + .enqueue = scheduler_enqueue +}; + +static struct labcomm_scheduler scheduler = { + .action = &scheduler_action, + .context = NULL +}; + +struct labcomm_scheduler *labcomm_default_scheduler = &scheduler; diff --git a/lib/c/labcomm_default_scheduler.h b/lib/c/labcomm_default_scheduler.h new file mode 100644 index 0000000000000000000000000000000000000000..923ea20f26fe8c587dc0c97447592b738a4b0b8b --- /dev/null +++ b/lib/c/labcomm_default_scheduler.h @@ -0,0 +1,24 @@ +/* + test_default_scheduler.h -- LabComm default scheduler + + 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.h" + +extern struct labcomm_scheduler *labcomm_default_scheduler; diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c index fb61f2349a98556610c5af67836dc4758cf787ff..3a7425d9643cd1b24d71ccb4804cdfd6bdbddd3e 100644 --- a/lib/c/labcomm_dynamic_buffer_writer.c +++ b/lib/c/labcomm_dynamic_buffer_writer.c @@ -29,9 +29,7 @@ static int dyn_alloc(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, - char *labcomm_version, - labcomm_encoder_enqueue enqueue) + char *labcomm_version) { w->data_size = 1000; w->count = w->data_size; diff --git a/lib/c/labcomm_encoder.c b/lib/c/labcomm_encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..ba02ff1b93bc48b82555e6a0e41df61080c858a2 --- /dev/null +++ b/lib/c/labcomm_encoder.c @@ -0,0 +1,222 @@ +/* + labcomm_encoder.c -- handling encoding of labcomm samples. + + 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/>. +*/ +#define LABCOMM_VERSION "LabComm2013" + +#include <errno.h> +#include "labcomm.h" +#include "labcomm_signature.h" +#include "labcomm_private.h" +#include "labcomm_ioctl.h" + +struct labcomm_encoder { + struct labcomm_writer *writer; + struct labcomm_error_handler *error; + struct labcomm_memory *memory; + struct labcomm_scheduler *scheduler; + LABCOMM_SIGNATURE_ARRAY_DEF(registered, int); +}; + +struct labcomm_encoder *labcomm_encoder_new( + struct labcomm_writer *writer, + struct labcomm_error_handler *error, + struct labcomm_memory *memory, + struct labcomm_scheduler *scheduler) +{ + struct labcomm_encoder *result; + + result = labcomm_memory_alloc(memory, 0, sizeof(*result)); + if (result) { + 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->error = error; + result->memory = memory; + result->scheduler = scheduler; + LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int); + } + return result; +} + +void labcomm_encoder_free(struct labcomm_encoder* e) +{ + struct labcomm_memory *memory = e->memory; + + labcomm_writer_free(e->writer, e->writer->action_context); + LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int); + labcomm_memory_free(memory, 0, e); +} + +int labcomm_internal_encoder_register( + struct labcomm_encoder *e, + struct labcomm_signature *signature, + labcomm_encoder_function encode) +{ + int result = -EINVAL; + int index, *done, err, i; + + index = labcomm_signature_local_index(signature); + labcomm_scheduler_writer_lock(e->scheduler); + if (e->writer->data == NULL) { + labcomm_writer_alloc(e->writer,e->writer->action_context, LABCOMM_VERSION); + } + if (signature->type != LABCOMM_SAMPLE) { goto out; } + if (index <= 0) { goto out; } + done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, int, index); + if (*done) { goto out; } + *done = 1; + err = labcomm_writer_start(e->writer, e->writer->action_context, + index, signature, NULL); + if (err == -EALREADY) { result = 0; goto out; } + if (err != 0) { result = err; goto out; } + labcomm_write_packed32(e->writer, signature->type); + labcomm_write_packed32(e->writer, index); + labcomm_write_string(e->writer, signature->name); + for (i = 0 ; i < signature->size ; i++) { + if (e->writer->pos >= e->writer->count) { + labcomm_writer_flush(e->writer, e->writer->action_context); + } + e->writer->data[e->writer->pos] = signature->signature[i]; + e->writer->pos++; + } + labcomm_writer_end(e->writer, e->writer->action_context); + result = e->writer->error; +out: + labcomm_scheduler_writer_unlock(e->scheduler); + return result; +} + +int labcomm_internal_encode( + struct labcomm_encoder *e, + struct labcomm_signature *signature, + labcomm_encoder_function encode, + void *value) +{ + int result; + int index; + + index = labcomm_signature_local_index(signature); + labcomm_scheduler_writer_lock(e->scheduler); + if (e->writer->data == NULL) { + labcomm_writer_alloc(e->writer,e->writer->action_context, LABCOMM_VERSION); + } + result = labcomm_writer_start(e->writer, e->writer->action_context, + index, signature, value); + if (result == -EALREADY) { result = 0; goto no_end; } + if (result != 0) { goto out; } + result = labcomm_write_packed32(e->writer, index); + if (result != 0) { goto out; } + result = encode(e->writer, value); +out: + labcomm_writer_end(e->writer, e->writer->action_context); +no_end: + labcomm_scheduler_writer_unlock(e->scheduler); + return result; +} + +int labcomm_encoder_ioctl(struct labcomm_encoder *encoder, + uint32_t action, + ...) +{ + int result; + va_list va; + + if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) { + result = -EINVAL; + goto out; + } + + va_start(va, action); + result = labcomm_writer_ioctl(encoder->writer, + encoder->writer->action_context, + 0, NULL, action, va); + va_end(va); + +out: + return result; +} + +int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, + struct labcomm_signature *signature, + uint32_t action, va_list va) +{ + int result = -ENOTSUP; + + result = labcomm_writer_ioctl(encoder->writer, + encoder->writer->action_context, + -1, signature, action, va); + return result; +} + + + +#if 0 +static struct labcomm_encoder *enter_encoder(struct labcomm_encoder *e) +{ + if (e->is_deferred) { + return e->is_deferred; + } else { + labcomm_lock_acquire(e->lock); + e->waiting++; + while (e->busy) { labcomm_lock_wait(e->lock, 10000000); } + e->busy = 1; + labcomm_lock_release(e->lock); + + if (e->writer->data == NULL) { + labcomm_writer_alloc(e->writer,e->writer->action_context, + e, LABCOMM_VERSION, encoder_enqueue_action); + if (e->alloc_action) { + struct labcomm_encoder deferred; + struct encoder_alloc_action *p; + + deferred.is_deferred = e; + p = e->alloc_action; + e->alloc_action = NULL; + while (p) { + struct encoder_alloc_action *tmp; + + p->action(&deferred, p->context); + tmp = p; + p = p->next; + labcomm_memory_free(e->memory, 1, tmp); + } + } + } + } + return e; +} +static void leave_encoder(struct labcomm_encoder *e) +{ + if (!e->is_deferred) { + labcomm_lock_acquire(e->lock); { + e->busy = 0; + e->waiting--; + if (e->waiting) { + labcomm_lock_notify(e->lock); + } + } labcomm_lock_release(e->lock); + } +} + +#endif diff --git a/lib/c/labcomm_error.h b/lib/c/labcomm_error.h index 79f4647f810f74f862e82781e7a9f41d6bc974e0..d83cd619d52d4357d51d3046f52b73139699c475 100644 --- a/lib/c/labcomm_error.h +++ b/lib/c/labcomm_error.h @@ -7,6 +7,8 @@ enum labcomm_error { #undef LABCOMM_ERROR }; +struct labcomm_error_handler; + #endif #ifdef LABCOMM_ERROR diff --git a/lib/c/labcomm_fd_reader.c b/lib/c/labcomm_fd_reader.c index 6cae2aeff014952c99844f079d9928e7a05224e1..e397c84401a27a59aec74da39e37cedbf111e7f5 100644 --- a/lib/c/labcomm_fd_reader.c +++ b/lib/c/labcomm_fd_reader.c @@ -37,7 +37,6 @@ struct labcomm_fd_reader { static int fd_alloc(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *version) { int result = 0; diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c index d21e047c63fc6bc1cf95ea7a3f55d292676af8d0..acf6934ad7c50eec43dba087b8d863e045ac4703 100644 --- a/lib/c/labcomm_fd_writer.c +++ b/lib/c/labcomm_fd_writer.c @@ -41,9 +41,7 @@ static int fd_flush(struct labcomm_writer *w, static int fd_alloc(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, - char *version, - labcomm_encoder_enqueue enqueue) + char *version) { w->data = labcomm_memory_alloc(w->memory, 0, BUFFER_SIZE); if (! w->data) { diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h index a19ec2af031be2e061165afab604059564eeeb64..e953f02a03e117645fbce7642042e079f58ee88b 100644 --- a/lib/c/labcomm_private.h +++ b/lib/c/labcomm_private.h @@ -67,25 +67,6 @@ #define LABCOMM_DECLARE_SIGNATURE(name) \ struct labcomm_signature __attribute__((section("labcomm"),aligned(1))) name -/* - * Semi private lock declarations - */ -struct labcomm_lock; - -struct labcomm_lock_action { - int (*free)(struct labcomm_lock *lock); - int (*acquire)(struct labcomm_lock *lock); - int (*release)(struct labcomm_lock *lock); - int (*wait)(struct labcomm_lock *lock, useconds_t usec); - int (*notify)(struct labcomm_lock *lock); -}; - -struct labcomm_lock { - const struct labcomm_lock_action *action; - struct labcomm_memory *memory; - void *context; -}; - /* * Semi private dynamic memory declarations */ @@ -122,7 +103,7 @@ struct labcomm_reader_action { */ int (*alloc)(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *labcomm_version); + char *labcomm_version); /* 'free' returns the resources claimed by 'alloc' and might have other reader specific side-effects as well. @@ -137,7 +118,8 @@ struct labcomm_reader_action { */ int (*start)(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - int index, struct labcomm_signature *signature, + int local_index, int remote_index, + struct labcomm_signature *signature, void *value); int (*end)(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context); @@ -169,13 +151,13 @@ struct labcomm_reader { int labcomm_reader_alloc(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - struct labcomm_decoder *decoder, char *labcomm_version); int labcomm_reader_free(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context); int labcomm_reader_start(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context, - int index, struct labcomm_signature *signature, + int local_index, int remote_index, + struct labcomm_signature *signature, void *value); int labcomm_reader_end(struct labcomm_reader *r, struct labcomm_reader_action_context *action_context); @@ -286,21 +268,14 @@ static inline char *labcomm_read_string(struct labcomm_reader *r) /* * Semi private encoder declarations */ -typedef int (*labcomm_encoder_function)( - struct labcomm_writer *, - void *value); -typedef int (*labcomm_encoder_enqueue)( - struct labcomm_encoder *encoder, - void (*action)(struct labcomm_encoder *encoder, - void *context), - void *context); +typedef int (*labcomm_encoder_function)(struct labcomm_writer *, + void *value); struct labcomm_writer_action_context; struct labcomm_writer_action { int (*alloc)(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, char *labcomm_version, - labcomm_encoder_enqueue enqueue); + char *labcomm_version); int (*free)(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context); /* 'start' is called right before a sample is to be sent. In the @@ -346,9 +321,7 @@ struct labcomm_writer { int labcomm_writer_alloc(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, - char *labcomm_version, - labcomm_encoder_enqueue enqueue); + char *labcomm_version); int labcomm_writer_free(struct labcomm_writer *w, struct labcomm_writer_action_context *action_context); int labcomm_writer_start(struct labcomm_writer *w, diff --git a/lib/c/labcomm_pthread_mutex_lock.c b/lib/c/labcomm_pthread_mutex_lock.c deleted file mode 100644 index 548a3e6916433aaebd1bbcef09f85a643fba7459..0000000000000000000000000000000000000000 --- a/lib/c/labcomm_pthread_mutex_lock.c +++ /dev/null @@ -1,114 +0,0 @@ -#include <errno.h> -#include <pthread.h> -#include "labcomm.h" -#include "labcomm_private.h" - -struct labcomm_pthread_mutex_lock { - struct labcomm_lock lock; - - pthread_mutex_t mutex; - pthread_cond_t cond; -}; - -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); - labcomm_memory_free(memory, 0, lock); - return 0; -} - -int do_acquire(struct labcomm_lock *l) -{ - struct labcomm_pthread_mutex_lock *lock = l->context; - - if (pthread_mutex_lock(&lock->mutex) != 0) { - return -errno; - } - return 0; -} - -int do_release(struct labcomm_lock *l) -{ - struct labcomm_pthread_mutex_lock *lock = l->context; - - if (pthread_mutex_unlock(&lock->mutex) != 0) { - return -errno; - } - return 0; -} - -int do_wait(struct labcomm_lock *l, useconds_t usec) -{ - struct labcomm_pthread_mutex_lock *lock = l->context; - - if (usec <= 0) { - if (pthread_cond_wait(&lock->cond, &lock->mutex) != 0) { - return -errno; - } - } else { - struct timespec abstime; - time_t sec = usec / 1000000; - long nsec = (usec % 1000000) * 1000; - - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec += nsec; - abstime.tv_sec += sec + abstime.tv_nsec / 1000000000; - abstime.tv_nsec %= 1000000000; - if (pthread_cond_timedwait(&lock->cond, &lock->mutex, &abstime) != 0) { - return -errno; - } - } - return 0; -} - -int do_notify(struct labcomm_lock *l) -{ - struct labcomm_pthread_mutex_lock *lock = l->context; - if (pthread_cond_broadcast(&lock->cond) != 0) { - return -errno; - } - return 0; -} - -static struct labcomm_lock_action action = { - .free = do_free, - .acquire = do_acquire, - .release = do_release, - .wait = do_wait, - .notify = do_notify -}; - -struct labcomm_lock *labcomm_pthread_mutex_lock_new( - struct labcomm_memory *memory) -{ - struct labcomm_lock *result = NULL; - struct labcomm_pthread_mutex_lock *lock; - - lock = labcomm_memory_alloc(memory, 0, sizeof(*lock)); - if (lock == NULL) { - goto out; - } - if (pthread_mutex_init(&lock->mutex, NULL) != 0) { - goto free_lock; - } - 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; - goto out; -destroy_mutex: - pthread_mutex_destroy(&lock->mutex); -free_lock: - labcomm_memory_free(memory, 0, lock); -out: - return result; - -} - diff --git a/lib/c/labcomm_pthread_scheduler.c b/lib/c/labcomm_pthread_scheduler.c index 809236748306a4db040341abcb161fe233b24444..52ebed5dd05f717b5238ba876e2cb01b40bf7b5f 100644 --- a/lib/c/labcomm_pthread_scheduler.c +++ b/lib/c/labcomm_pthread_scheduler.c @@ -324,7 +324,7 @@ out: return result; } -const struct labcomm_scheduler_action scheduler_action = { +static const struct labcomm_scheduler_action scheduler_action = { .free = scheduler_free, .writer_lock = scheduler_writer_lock, .writer_unlock = scheduler_writer_unlock, diff --git a/lib/c/labcomm_signature.h b/lib/c/labcomm_signature.h new file mode 100644 index 0000000000000000000000000000000000000000..d68c579de094db0f71a6e2180afe4f5d416160cb --- /dev/null +++ b/lib/c/labcomm_signature.h @@ -0,0 +1,23 @@ +/* + labcomm_signature.h -- signature handling. + + 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.h" +int labcomm_signature_local_index(struct labcomm_signature *s); diff --git a/lib/c/labcomm_signature_gnu_ld_tricks.c b/lib/c/labcomm_signature_gnu_ld_tricks.c new file mode 100644 index 0000000000000000000000000000000000000000..7ce21ee5f6497c7e60e7a0da468e7724dc60d956 --- /dev/null +++ b/lib/c/labcomm_signature_gnu_ld_tricks.c @@ -0,0 +1,38 @@ +/* + labcomm_signature_gnu_ld_tricks.h -- signature handling. + + 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 <errno.h> +#include "labcomm.h" +#include "labcomm_signature.h" +#include "labcomm_private.h" + +extern struct labcomm_signature labcomm_first_signature; +extern struct labcomm_signature labcomm_last_signature; + +int labcomm_signature_local_index(struct labcomm_signature *s) +{ + int result = -ENOENT; + + if (&labcomm_first_signature <= s && s < &labcomm_last_signature) { + result = (int)(s - &labcomm_first_signature) + LABCOMM_USER; + } + return result; +} diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c index bf81d0b3ad0494c586d85ddb6f08d0ae2cea5343..79aeb4307575f6d6d98f6c9a2215e80eb340e05d 100644 --- a/lib/c/test/test_labcomm_generated_encoding.c +++ b/lib/c/test/test_labcomm_generated_encoding.c @@ -24,6 +24,9 @@ #include <string.h> #include <errno.h> #include "labcomm_private.h" +#include "labcomm_default_error_handler.h" +#include "labcomm_default_memory.h" +#include "labcomm_pthread_scheduler.h" #include "test/gen/generated_encoding.h" #define IOCTL_WRITER_ASSERT_BYTES 4096 @@ -35,9 +38,7 @@ struct labcomm_writer *writer; static int buf_writer_alloc( struct labcomm_writer *w, struct labcomm_writer_action_context *action_context, - struct labcomm_encoder *encoder, - char *labcomm_version, - labcomm_encoder_enqueue enqueue) + char *labcomm_version) { writer = w; /* Hack */ w->data_size = sizeof(buffer); @@ -181,9 +182,11 @@ int main(void) generated_encoding_V V; generated_encoding_B B = 1; - struct labcomm_encoder *encoder = labcomm_encoder_new(&buffer_writer, - NULL, - labcomm_default_memory); + struct labcomm_encoder *encoder = labcomm_encoder_new( + &buffer_writer, + labcomm_default_error_handler, + labcomm_default_memory, + labcomm_pthread_scheduler_new(labcomm_default_memory)); labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET); labcomm_encoder_register_generated_encoding_V(encoder); diff --git a/lib/c/test/test_labcomm_pthread_scheduler.c b/lib/c/test/test_labcomm_pthread_scheduler.c index 20709672ae03c20fd9c87124a0787d231012d165..718293d58af7cf51c6215d2e226343c3cd14d9b2 100644 --- a/lib/c/test/test_labcomm_pthread_scheduler.c +++ b/lib/c/test/test_labcomm_pthread_scheduler.c @@ -22,9 +22,11 @@ #include <stdio.h> #include <stdlib.h> +#include "labcomm_default_memory.h" #include "labcomm_scheduler.h" #include "labcomm_pthread_scheduler.h" +#define TICK 100000 struct func_arg { struct labcomm_scheduler *scheduler; int i; @@ -50,7 +52,7 @@ void enqueue(struct labcomm_scheduler *scheduler, tmp->scheduler = scheduler; tmp->i = i; - labcomm_scheduler_enqueue(scheduler, i*1000000, func, tmp); + labcomm_scheduler_enqueue(scheduler, i*TICK, func, tmp); } } @@ -69,10 +71,10 @@ int main(int argc, char *argv[]) tmp->scheduler = scheduler; tmp->i = 999; - labcomm_scheduler_enqueue(scheduler, 6000000, func, tmp); + labcomm_scheduler_enqueue(scheduler, 6*TICK, func, tmp); } time = labcomm_scheduler_now(scheduler); - labcomm_time_add_usec(time, 12*1000000); + labcomm_time_add_usec(time, 12*TICK); labcomm_scheduler_sleep(scheduler, NULL); labcomm_scheduler_sleep(scheduler, time); diff --git a/test/relay_gen_c.py b/test/relay_gen_c.py index 30a081ae0ff6f8b3bd390982f5731d1a86bfdcf8..6f4da2ca1b7e1d621a5e52d0e7e1052c33edbb3b 100755 --- a/test/relay_gen_c.py +++ b/test/relay_gen_c.py @@ -27,6 +27,9 @@ if __name__ == '__main__': |#include <sys/stat.h> |#include <fcntl.h> |#include <labcomm.h> + |#include <labcomm_default_error_handler.h> + |#include <labcomm_default_memory.h> + |#include <labcomm_default_scheduler.h> |#include <labcomm_fd_reader.h> |#include <labcomm_fd_writer.h> |#include "c_code.h" @@ -52,10 +55,14 @@ if __name__ == '__main__': | if (out < 0) { return 1; } | e = labcomm_encoder_new(labcomm_fd_writer_new( | labcomm_default_memory, out, 1), - | NULL, labcomm_default_memory); + | labcomm_default_error_handler, + | labcomm_default_memory, + | labcomm_default_scheduler); | d = labcomm_decoder_new(labcomm_fd_reader_new( - | labcomm_default_memory, in, 1), - | NULL, labcomm_default_memory); + | labcomm_default_memory, in, 1), + | labcomm_default_error_handler, + | labcomm_default_memory, + | labcomm_default_scheduler); """)) for func,arg in sample: result.extend(split_match('^[^|]*\|(.*)$', """