cavatools: initialize repository
[cavatools.git] / caveat / shmfifo.c
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <assert.h>
9 #include <string.h>
10 #include <sys/mman.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13
14
15 #include "shmfifo.h"
16 #include "caveat.h"
17
18
19
20 #define DEFAULT_BUFSIZE 12
21
22
23 /* Producer side fifo initialization.
24 bufid - number = file descriptor (already opened)
25 $name = shared memory segment /dev/shm/name
26 otherwise = trace file path name
27 bufsize - log-base-2 number of bytes
28 */
29 struct fifo_t* fifo_create( const char* bufid, int bufsize )
30 {
31 // assert(sizeof(struct fifo_t) == 2*64);
32 if (bufsize == 0)
33 bufsize = DEFAULT_BUFSIZE;
34 assert(bufsize > 3);
35 int fd = shm_open(bufid, O_CREAT|O_TRUNC|O_RDWR, S_IRWXU);
36 dieif(fd<0, "shm_open() failed in fifo_create");
37 size_t fsize = (1<<bufsize) + sizeof(struct fifo_t);
38 dieif(ftruncate(fd, fsize)<0, "ftruncate() failed in fifo_create");
39 struct fifo_t* fifo = (struct fifo_t*)mmap(NULL, fsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
40 dieif(fifo==0, "mmap() failed in fifo_create");
41 assert(((uint64_t)fifo & 0x3fL) == 0L);
42 memset((char*)fifo, 0, fsize);
43 fifo->size = bufsize;
44 fifo->fd = fd;
45 fifo->get_mask = fifo->put_mask = (1<<(bufsize-3))-1;
46 fifo->id = bufid;
47 return fifo;
48 }
49
50
51 /* Consumer side fifo initialization.
52 bufid - number = file descriptor (already opened)
53 $name = shared memory segment /dev/shm/name
54 otherwise = trace file path name
55 */
56 struct fifo_t* fifo_open( const char* bufid )
57 {
58 int fd = shm_open(bufid, O_RDWR, 0);
59 dieif(fd<0, "shm_open() failed in fifo_open");
60 struct fifo_t* fifo = (struct fifo_t*)mmap(NULL, sizeof(struct fifo_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
61 dieif(fifo==0, "first mmap() failed in fifo_open");
62 size_t fsize = (1<<fifo->size) + sizeof(struct fifo_t);
63 dieif(munmap(fifo, sizeof(struct fifo_t))<0, "munmap() failed in fifo_open");
64 fifo = (struct fifo_t*)mmap(NULL, fsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
65 dieif(fifo==0, "second mmap() failed in fifo_open");
66 assert(((uint64_t)fifo & 0x3fL) == 0L);
67 return fifo;
68 }
69
70
71 /* Consumer side fifo termination. */
72 void fifo_close( struct fifo_t* fifo )
73 {
74 fifo->finished = 1;
75 futex_wake(&fifo->finished);
76 size_t fsize = (1<<fifo->size) + sizeof(struct fifo_t);
77 dieif(munmap(fifo, fsize)<0, "munmap() failed in fifo_close");
78 }
79
80
81 /* Producer side fifo termination. */
82 void fifo_finish( struct fifo_t* fifo )
83 {
84 fifo_flush(fifo);
85 /* wait for consumer to finish */
86 futex_hibernate(&fifo->finished, 0);
87 size_t fsize = (1<<fifo->size) + sizeof(struct fifo_t);
88 dieif(munmap(fifo, fsize)<0, "munmap() failed in fifo_finish");
89 }
90
91
92 void fifo_debug( struct fifo_t* fifo, const char* msg )
93 {
94 fprintf(stderr, "%s: HEAD=%d, head=%d, TAIL=%d, tail=%d\n",
95 msg, fifo->HEAD, fifo->head, fifo->TAIL, fifo->tail);
96 }