#ifndef _BATCH_QUEUE_COMMON_COMM_H_ #define _BATCH_QUEUE_COMMON_COMM_H_ 1 #include #include /* Non standard include */ #include #ifndef BUF_SIZE #define BUF_SIZE (32 * CACHE_LINE_SIZE) #endif struct channel { /* buf must be the first field to allow the buf_mask test */ void * volatile buf[2][BUF_SIZE / sizeof(void *)] __attribute__ ((aligned (CACHE_LINE_SIZE))); struct channel *mapping1; /* accesses to buf[0] and state */ struct channel *mapping2; /* accesses to buf[1] */ uintptr_t buf_mask; int unused[20] __attribute__ ((aligned (CACHE_LINE_SIZE))); volatile unsigned int state:1 __attribute__ ((aligned (CACHE_LINE_SIZE))); void * volatile *sender_ptr __attribute__ ((aligned (CACHE_LINE_SIZE))); void * volatile *receiver_ptr __attribute__ ((aligned (CACHE_LINE_SIZE))); }; void send1(struct channel *channel, void **addr) __attribute__ ((visibility ("hidden"))); void send2(struct channel *channel, void **addr) __attribute__ ((visibility ("hidden"))); #ifndef _BATCH_QUEUE_C_ #ifndef PAGE_SIZE_HELPER #define PAGE_SIZE_HELPER 1 void * volatile *_bq_end_buf1; void * volatile *_bq_end_buf2; void (*send_ptr)(struct channel *, void **); void *create_comm_channel_internal(void); static void *create_comm_channel_helper(void) __attribute__ ((unused)); static void *create_comm_channel_helper(void) { struct channel *channel; send_ptr = &send1; channel = create_comm_channel_internal(); _bq_end_buf1 = channel->buf[0] + (sizeof channel->buf[0] / sizeof channel->buf[0][0]); _bq_end_buf2 = channel->mapping2->buf[1] + (sizeof channel->buf[1] / sizeof channel->buf[1][0]); return channel; } #else extern uintptr_t _bq_end_buf1; extern uintptr_t _bq_end_buf2; extern void (*send_ptr)(struct channel *, void **); #endif /* PAGE_SIZE_HELPER */ #define create_comm_channel() create_comm_channel_helper() __BEGIN_DECLS static inline void send(struct channel *channel, void **addr) { (*send_ptr)(channel, addr); } void send1(struct channel *channel, void **addr) { *channel->sender_ptr++ = addr; if (unlikely(channel->sender_ptr == _bq_end_buf1)) { while (channel->state); channel->state = 1; channel->sender_ptr = channel->mapping2->buf[1]; send_ptr = &send2; } } void send2(struct channel *channel, void **addr) { *channel->sender_ptr++ = addr; if (unlikely(channel->sender_ptr == _bq_end_buf2)) { while (channel->state); channel->state = 1; channel->sender_ptr = channel->buf[0]; send_ptr = &send1; } } __END_DECLS #endif /* _BATCH_QUEUE_C_ */ #endif