#include #include #include #include /* Non standard include */ #include #include void *create_comm_channel(void) { struct channel *channel; if (!posix_memalign((void *) &channel, CACHE_LINE_SIZE, sizeof(struct channel))) { if (!posix_memalign((void *) &channel->shared_space, CACHE_LINE_SIZE, SHARED_SPACE_SIZE)) { int i; channel->head = 0; channel->tail = 0; for (i = 0; i < SHARED_SPACE_VOIDPTR; i++) channel->shared_space[i] = NULL; return channel; } else free(channel); } return NULL; } int destroy_comm_channel(void *channel) { free((void *) ((struct channel *) channel)->shared_space); free(channel); return 0; } int adjust_slip(struct channel *channel) { int dist, dist_old, unused; puts("adjust_slip is called"); /* Must be removed after calibration */ unused = 0; dist = (channel->head + SHARED_SPACE_VOIDPTR - channel->tail) % SHARED_SPACE_VOIDPTR; if (dist < DANGER) { dist_old = 0; do { int i; dist_old = dist; /* * I consider 20 as being the number of ++ which could * be done while one data is sent by the producer */ for (i = 0; i < 20 * ((GOOD + 1) - dist); i++) unused++; dist = (channel->head + SHARED_SPACE_VOIDPTR - channel->tail) % SHARED_SPACE_VOIDPTR; } while (dist < GOOD && dist_old < dist); } return unused; } void *recv_one_data(struct channel *channel) { void *result; static __thread int nb_iter = 0; if (nb_iter == ADJUST_FREQ) { adjust_slip(channel); nb_iter = 0; } while (1) { result = channel->shared_space[channel->tail]; if (NULL == result) continue; channel->shared_space[channel->tail] = NULL; channel->tail = (channel->tail + 1) % SHARED_SPACE_VOIDPTR; break; } return result; } ssize_t recv_some_data(struct channel *channel, void **buf, size_t count) { int n, next_adjust; static __thread int nb_iter = 0; next_adjust = ADJUST_FREQ - nb_iter; for(n = 0; n < count; n++) { /* if ((nb_iter + n) % ADJUST_FREQ == 0) */ if (n && (n % next_adjust == ADJUST_FREQ)) { adjust_slip(channel); nb_iter = 0; } /* * The behaviour of this is not documented but we know * the values inside buf won't change during this affectation */ *buf = channel->shared_space[channel->tail]; if (NULL == *buf) break; buf++; channel->shared_space[channel->tail] = NULL; channel->tail = (channel->tail + 1) % SHARED_SPACE_VOIDPTR; } nb_iter = (nb_iter + n) % ADJUST_FREQ; return n; }