#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))); }; #ifndef _BATCH_QUEUE_C_ #ifndef PAGE_SIZE_HELPER #define PAGE_SIZE_HELPER 1 uintptr_t _bq_page_mask; void *create_comm_channel_internal(void); static void *create_comm_channel_helper(void) __attribute__ ((unused)); static void *create_comm_channel_helper(void) { int ret; struct channel *channel; ret = sysconf(_SC_PAGESIZE); if (ret == -1) return NULL; _bq_page_mask = ~(ret - 1); channel = create_comm_channel_internal(); channel->buf_mask = sizeof channel->buf[0] - 1; return channel; } #else extern unsigned int _bq_page_mask; #endif /* PAGE_SIZE_HELPER */ #define create_comm_channel() create_comm_channel_helper() __BEGIN_DECLS static inline void send(struct channel *channel, void **addr) { uintptr_t sender_ptr_high; *channel->sender_ptr++ = addr; if (unlikely(!((uintptr_t) channel->sender_ptr & channel->buf_mask))) { while (channel->state); channel->state = 1; sender_ptr_high = (uintptr_t) channel->sender_ptr & _bq_page_mask; if ((void *) sender_ptr_high == channel->mapping1) channel->sender_ptr = channel->mapping2->buf[1]; else channel->sender_ptr = channel->mapping1->buf[0]; } } __END_DECLS #endif /* _BATCH_QUEUE_C_ */ #endif