#include #include #include /* Non standard include */ #include #include __thread union comm comm; int init_library(void) { return 0; } int finalize_library(void) { return 0; } void *create_comm_channel(void) { struct cons *cons; if (!posix_memalign((void **) &cons, CACHE_LINE_SIZE, sizeof(struct cons))) { cons->receiver_idx = 0; if (!posix_memalign((void **) &cons->channel, CACHE_LINE_SIZE, sizeof(struct channel))) { cons->channel->state = 0; cons->channel->idx = 0; return cons; } else free(cons); } return NULL; } int destroy_comm_channel(void *cons) { free(((struct cons *) cons)->channel); free(cons); return 0; } int init_producer_thread(void *cons) { comm.channel = ((struct cons *) cons)->channel; return 0; } int finalize_producer_thread(void *cons) { comm.channel = NULL; return 0; } int init_consumer_thread(void *cons) { comm.cons = (struct cons *) cons; return 0; } int finalize_consumer_thread(void *cons) { comm.cons = NULL; return 0; } /* * Copy at max count received data into buf * @param buf The buffer in which received data must be copied into * @return Number of data received and copied into buf * * @warning recv_one_data should not be used in conjonction of * recv_some_data */ void *recv_one_data(void) { static __thread int i; void *result; if (unlikely(i % (BUF_SIZE / sizeof(void *)))) while (!comm.cons->channel->state); result = (void *) comm.cons->channel->buf[i++]; i %= (2 * BUF_SIZE) / sizeof(void *); if (unlikely(i % (BUF_SIZE / sizeof(void *)))) comm.cons->channel->state = 0; return result; } /* * Copy at max count received data into buf * @param buf The buffer in which received data must be copied into * @return Number of data received and copied into buf * * @warning recv_some_data should not be used in conjonction of * recv_one_data * @warning count must be a multiple of BUF_SIZE */ ssize_t recv_some_data(void **buf, size_t count) { int nb_read; nb_read = 0; while (comm.cons->channel->state && nb_read < count) { int i, n; /* * cur->receiver_idx point to the last buffer we have read. * We go to the next cache line "+ (BUF_SIZE / sizeof(void *))" * (because the line is full of void * and then if we are after * the second cache line we correct the pointer to point to the * first one (this is done by the modulo). */ i = comm.cons->receiver_idx; n = comm.cons->receiver_idx + (BUF_SIZE / sizeof(void *)); comm.cons->receiver_idx = n % ((2 * BUF_SIZE) / sizeof(void *)); for(; i < n; i++) { /* * The behaviour of this is not documented but we know * the values inside buf won't change during this affectation */ *buf++ = (void *) comm.cons->channel->buf[i]; } nb_read += BUF_SIZE / sizeof(void *); comm.cons->channel->state = 0; } return nb_read; }