Created
October 28, 2015 04:53
-
-
Save dvyukov/93c2d1775625a684cc11 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
struct shm_t { | |
uint32_t head; | |
uint32_t alloc; | |
char data[0]; | |
}; | |
#define SHM_HEADER_SIZE 8 | |
#define SHM_BLOCK_SIZE 8 | |
#define SHM_BLOCK_ALIGNMENT 8 | |
#define SHM_SIZE (1<<20) | |
void *shm_alloc(struct shm_t *shm, uint32_t size) | |
{ | |
uint32_t alloc, new; | |
size = ((size+SHM_BLOCK_ALIGNMENT-1)&~(SHM_BLOCK_ALIGNMENT-1)) + SHM_BLOCK_SIZE; | |
alloc = __atomic_load_n(&shm->alloc, __ATOMIC_RELAXED); | |
for (;;) { | |
new = alloc + size; | |
if (new > SHM_SIZE-SHM_HEADER_SIZE) | |
return 0; | |
if (__atomic_compare_exchange_n(&shm->alloc, &alloc, new, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) | |
return &shm->data[alloc + SHM_BLOCK_SIZE]; | |
} | |
} | |
void shm_commit(struct shm_t *shm, void *block) | |
{ | |
uint32_t *hdr; | |
hdr = (uint32_t*)((char*)block-SHM_BLOCK_SIZE); | |
*hdr = __atomic_load_n(&shm->head, __ATOMIC_ACQUIRE); | |
while (!__atomic_compare_exchange_n(&shm->head, hdr, (char*)block - &shm->data[0], 1, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)); | |
} | |
void shm_foreach(struct shm_t *shm, void (*f)(void*, void*), void *ctx) | |
{ | |
uint32_t pos; | |
pos = __atomic_load_n(&shm->head, __ATOMIC_ACQUIRE); | |
while (pos) { | |
f(ctx, &shm->data[pos]); | |
pos = *(uint32_t*)&shm->data[pos-SHM_BLOCK_SIZE]; | |
} | |
} | |
void print(void *ctx, void *b); | |
int main() | |
{ | |
struct shm_t *shm; | |
void *b0, *b1, *b2; | |
shm = calloc(SHM_SIZE, 1); | |
b0 = shm_alloc(shm, 8); | |
b1 = shm_alloc(shm, 12); | |
b2 = shm_alloc(shm, 12); | |
((uint32_t*)b0)[0] = 1; | |
((uint32_t*)b0)[1] = 11; | |
((uint32_t*)b1)[0] = 2; | |
((uint32_t*)b1)[1] = 21; | |
((uint32_t*)b1)[2] = 22; | |
((uint32_t*)b2)[0] = 2; | |
((uint32_t*)b2)[1] = 31; | |
((uint32_t*)b2)[2] = 32; | |
shm_commit(shm, b1); | |
shm_commit(shm, b0); | |
shm_commit(shm, b2); | |
shm_foreach(shm, print, 0); | |
return 0; | |
} | |
void print(void *ctx, void *b) | |
{ | |
uint32_t i, n; | |
n = *(uint32_t*)b; | |
printf("size=%d:", n); | |
for (i = 0; i < n; i++) | |
printf(" %d", ((uint32_t*)b)[i+1]); | |
printf("\n"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment