Skip to content

Instantly share code, notes, and snippets.

@bnoordhuis
Created July 6, 2012 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bnoordhuis/40d9c0316c083f1366ac to your computer and use it in GitHub Desktop.
Save bnoordhuis/40d9c0316c083f1366ac to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
#define E(expr) \
do { \
errno = 0; \
expr; \
if (errno) perror(#expr), exit(42); \
} \
while (0)
struct mq
{
sem_t producer_sem_;
sem_t consumer_sem_;
char data[1];
};
struct msg
{
char cmd[64];
};
struct shared
{
struct mq mq;
struct msg msg;
};
int mq_init(struct mq *mq)
{
if (sem_init(&mq->producer_sem_, 1, 1))
return -1;
if (sem_init(&mq->consumer_sem_, 1, 0)) {
sem_destroy(&mq->producer_sem_);
return -1;
}
return 0;
}
int mq_send(struct mq *mq, const void *data, size_t size)
{
if (sem_wait(&mq->producer_sem_))
return -1;
memcpy(mq->data, data, size);
if (sem_post(&mq->consumer_sem_))
return -1;
return 0;
}
int mq_recv(struct mq *mq, void *data, size_t size)
{
if (sem_wait(&mq->consumer_sem_))
return -1;
memcpy(data, mq->data, size);
if (sem_post(&mq->producer_sem_))
return -1;
return 0;
}
static void *do_mmap(size_t size)
{
void *addr;
E(addr = mmap(NULL, size,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS,
-1, 0));
return addr;
}
static uint64_t gettime(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
return 0;
return (ts.tv_sec * 1e9) + ts.tv_nsec;
}
static void init(struct shared *s)
{
if (mq_init(&s->mq))
abort();
}
static void do_parent(struct shared *s)
{
struct msg msg;
int status;
while (1) {
mq_recv(&s->mq, &msg, sizeof msg);
//printf("RECV -> %s\n", msg.cmd);
int t = gettime() % (1000*1000);
printf("[%d] RECV -> %s\n", t, msg.cmd);
if (strcmp(msg.cmd, "QUIT") == 0)
break;
}
E(wait(&status));
}
static void do_child(struct shared *s)
{
struct msg msg;
int cid;
#define MAX_CMDS 32
for (cid = 1; cid <= MAX_CMDS; cid++) {
if (cid == MAX_CMDS)
snprintf(msg.cmd, sizeof msg.cmd, "QUIT");
else
snprintf(msg.cmd, sizeof msg.cmd, "CMD %d", cid);
mq_send(&s->mq, &msg, sizeof msg);
int t = gettime() % (1000*1000);
printf("[%d] SEND -> %s\n", t, msg.cmd);
//printf("SEND -> %s\n", msg.cmd);
}
}
int main(void)
{
struct shared *s;
pid_t pid;
s = do_mmap(sizeof *s);
init(s);
E(pid = fork());
if (pid)
do_parent(s);
else
do_child(s);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment