|
|
|
@ -68,11 +68,12 @@ typedef struct shmem
|
|
|
|
|
size_t size; |
|
|
|
|
uint32_t sent; |
|
|
|
|
uint32_t read; |
|
|
|
|
size_t* a; |
|
|
|
|
char* a; |
|
|
|
|
uint32_t pos; |
|
|
|
|
|
|
|
|
|
} Shmem; |
|
|
|
|
|
|
|
|
|
Shmem* s; |
|
|
|
|
Shmem s; |
|
|
|
|
|
|
|
|
|
#else // SHMEM
|
|
|
|
|
|
|
|
|
@ -90,10 +91,8 @@ typedef union size
|
|
|
|
|
#endif // SHMEM
|
|
|
|
|
|
|
|
|
|
#ifdef SHMEM |
|
|
|
|
static Shmem* shmem_create(void) |
|
|
|
|
static void shmem_create(void) |
|
|
|
|
{ |
|
|
|
|
Shmem* s; |
|
|
|
|
|
|
|
|
|
// Our memory buffer will be readable and writable:
|
|
|
|
|
int protection = PROT_READ | PROT_WRITE; |
|
|
|
|
|
|
|
|
@ -104,27 +103,18 @@ static Shmem* shmem_create(void)
|
|
|
|
|
|
|
|
|
|
// The remaining parameters to `mmap()` are not important for this use case,
|
|
|
|
|
// but the manpage for `mmap` explains their purpose.
|
|
|
|
|
s = mmap(NULL, SIZE, protection, visibility, -1, 0); |
|
|
|
|
if (s == NULL) err("mmap of Shmem failed", 5); |
|
|
|
|
|
|
|
|
|
s->a = mmap(NULL, SIZE, protection, visibility, -1, 0); |
|
|
|
|
if (s->a == NULL) err("mmap of array failed", 5); |
|
|
|
|
s.a = mmap(NULL, SIZE, protection, visibility, -1, 0); |
|
|
|
|
if (s.a == NULL) err("mmap of array failed", 5); |
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG |
|
|
|
|
printf("s: %p, %p\n", s, s + sizeof(Shmem)); |
|
|
|
|
#endif // NDEBUG
|
|
|
|
|
|
|
|
|
|
s->size = SIZE; |
|
|
|
|
s->sent = 0; |
|
|
|
|
s->read = 0; |
|
|
|
|
|
|
|
|
|
return s; |
|
|
|
|
s.size = SIZE; |
|
|
|
|
s.sent = 0; |
|
|
|
|
s.read = 0; |
|
|
|
|
s.pos = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void shmem_destroy(Shmem* s) |
|
|
|
|
{ |
|
|
|
|
if (munmap(s->a, SIZE)) err("could not unmap memory", 1); |
|
|
|
|
if (munmap(s, SIZE)) err("could not unmap memory", 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline long futex(uint32_t* uaddr, int futex_op, uint32_t val, |
|
|
|
@ -163,13 +153,31 @@ static inline void do_wake(uint32_t* f, uint32_t val)
|
|
|
|
|
__attribute__((always_inline)) |
|
|
|
|
static inline uint32_t get_val(bool read, uint32_t val) |
|
|
|
|
{ |
|
|
|
|
return do_wait(read ? &s->read : &s->sent, val); |
|
|
|
|
return do_wait(read ? &s.read : &s.sent, val); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute__((always_inline)) |
|
|
|
|
static inline void set_val(unsigned int val, bool read) |
|
|
|
|
{ |
|
|
|
|
do_wake(read ? &s->read : &s->sent, val); |
|
|
|
|
do_wake(read ? &s.read : &s.sent, val); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute__((always_inline)) |
|
|
|
|
static inline uint32_t* get_write_ptr(void) |
|
|
|
|
{ |
|
|
|
|
return ((uint32_t*) s.a + ((s.pos + sizeof(uint32_t)) & MASK)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute__((always_inline)) |
|
|
|
|
static inline uint32_t* get_read_ptr(void) |
|
|
|
|
{ |
|
|
|
|
return ((uint32_t*) s.a + (s.pos & MASK)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute__((always_inline)) |
|
|
|
|
static inline size_t* get_data_ptr(void) |
|
|
|
|
{ |
|
|
|
|
return ((size_t*) s.a + ((s.pos + 2 * sizeof(uint32_t)) & MASK)); |
|
|
|
|
} |
|
|
|
|
#endif // SHMEM
|
|
|
|
|
|
|
|
|
@ -191,13 +199,24 @@ static size_t receive(unsigned int* rd)
|
|
|
|
|
|
|
|
|
|
unsigned int val; |
|
|
|
|
|
|
|
|
|
val = get_val(false, *rd); |
|
|
|
|
uint32_t* read_ptr; |
|
|
|
|
uint32_t* read_ptr2; |
|
|
|
|
uint32_t* write_ptr; |
|
|
|
|
size_t* data_ptr; |
|
|
|
|
|
|
|
|
|
read_ptr = get_read_ptr(); |
|
|
|
|
write_ptr = get_write_ptr(); |
|
|
|
|
data_ptr = get_data_ptr(); |
|
|
|
|
|
|
|
|
|
s.pos += 2 * sizeof(uint32_t) + sizeof(size_t); |
|
|
|
|
|
|
|
|
|
do_wait(write_ptr, 0); |
|
|
|
|
|
|
|
|
|
idx = s->a[val & MASK]; |
|
|
|
|
idx = *data_ptr; |
|
|
|
|
|
|
|
|
|
*rd += 1; |
|
|
|
|
|
|
|
|
|
set_val(*rd, true); |
|
|
|
|
do_wake(read_ptr, 8); |
|
|
|
|
|
|
|
|
|
#endif // KERNEL
|
|
|
|
|
|
|
|
|
@ -221,15 +240,30 @@ static void send(size_t idx, unsigned int* st)
|
|
|
|
|
|
|
|
|
|
#else // KERNEL
|
|
|
|
|
|
|
|
|
|
unsigned int val; |
|
|
|
|
uint32_t* read_ptr; |
|
|
|
|
uint32_t* read_ptr2; |
|
|
|
|
uint32_t* write_ptr; |
|
|
|
|
uint32_t* write_ptr2; |
|
|
|
|
size_t* data_ptr; |
|
|
|
|
|
|
|
|
|
s->a[(*st) & MASK] = idx + 1; |
|
|
|
|
read_ptr = get_read_ptr(); |
|
|
|
|
write_ptr = get_write_ptr(); |
|
|
|
|
data_ptr = get_data_ptr(); |
|
|
|
|
|
|
|
|
|
*st += 1; |
|
|
|
|
*data_ptr = idx + 1; |
|
|
|
|
|
|
|
|
|
s.pos += 2 * sizeof(uint32_t) + sizeof(size_t); |
|
|
|
|
|
|
|
|
|
set_val(*st, false); |
|
|
|
|
read_ptr2 = get_read_ptr(); |
|
|
|
|
write_ptr2 = get_write_ptr(); |
|
|
|
|
|
|
|
|
|
*read_ptr2 = 0; |
|
|
|
|
*write_ptr2 = 0; |
|
|
|
|
|
|
|
|
|
*st += 1; |
|
|
|
|
|
|
|
|
|
val = get_val(true, *st - 1); |
|
|
|
|
do_wake(write_ptr, 8); |
|
|
|
|
do_wait(read_ptr, 0); |
|
|
|
|
|
|
|
|
|
#endif // KERNEL
|
|
|
|
|
} |
|
|
|
@ -248,7 +282,7 @@ int main(int argc, char* argv[])
|
|
|
|
|
|
|
|
|
|
#ifdef SHMEM |
|
|
|
|
|
|
|
|
|
s = shmem_create(); |
|
|
|
|
shmem_create(); |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
@ -347,7 +381,7 @@ int main(int argc, char* argv[])
|
|
|
|
|
if (CONSUMER(pid)) close(in); |
|
|
|
|
else close(out); |
|
|
|
|
#else // KERNEL
|
|
|
|
|
shmem_destroy(s); |
|
|
|
|
shmem_destroy(&s); |
|
|
|
|
#endif // KERNEL
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|