aboutsummaryrefslogtreecommitdiff
path: root/src/ui_ipc.c
blob: cce7825d29efea98e21786483451b9cde02b972e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <semaphore.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <alloca.h>
#include <errno.h>

#include "ui_ipc.h"

#define JMP_IF(cmd, retval, jmplabel) if ( (cmd) == retval ) {  printf("(%s) == %p\n", #cmd, (void*)retval);  goto jmplabel; }


static sem_t *sems[SEM_NUM];
static mqd_t msqs[MSQ_NUM];


int
ui_ipc_init(int is_master)
{
  volatile int sp_oflags, mq_oflags;
  mode_t crt_flags;
  struct mq_attr m_attr;

  bzero(sems, sizeof(sem_t*)*SEM_NUM);
  bzero(msqs, sizeof(mqd_t)*MSQ_NUM);
  m_attr.mq_flags = 0;
  m_attr.mq_msgsize = IPC_MQSIZ;
  m_attr.mq_maxmsg = 3;
  m_attr.mq_curmsgs = 0;
  if (is_master) {
    sp_oflags = O_CREAT | O_EXCL;
    mq_oflags = O_NONBLOCK | O_CREAT | O_EXCL;
    crt_flags = S_IRUSR | S_IWUSR;
    JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error );
    JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error );
  } else {
    sp_oflags = 0;
    mq_oflags = 0;
    crt_flags = 0;
    JMP_IF( msqs[MQ_PW] = mq_open(MSQ_PWD, mq_oflags | O_WRONLY, crt_flags, &m_attr), (mqd_t)-1, error );
    JMP_IF( msqs[MQ_IF] = mq_open(MSQ_INF, mq_oflags | O_RDONLY, crt_flags, &m_attr), (mqd_t)-1, error );
  }
  JMP_IF( sems[SEM_UI] = sem_open(SEM_GUI, sp_oflags, crt_flags, 0), SEM_FAILED, error );
  JMP_IF( sems[SEM_IN] = sem_open(SEM_INP, sp_oflags, crt_flags, 0), SEM_FAILED, error );
  return 0;
error:
  return errno;
}

void
ui_ipc_free(int is_master)
{
  int i;

  for (i = 0; i < SEM_NUM; i++) {
    if (sems[i]) sem_close(sems[i]);
  }
  for (i = 0; i < MSQ_NUM; i++) {
    if (msqs[i]) mq_close(msqs[i]);
  }
  if (is_master > 0) {
    sem_unlink(SEM_GUI);
    sem_unlink(SEM_INP);
    mq_unlink(MSQ_PWD);
    mq_unlink(MSQ_INF);
  }
}

int
ui_ipc_sempost(enum UI_IPC_SEM e_sp)
{
  return ( sem_post(sems[e_sp]) );
}

int
ui_ipc_semwait(enum UI_IPC_SEM e_sp)
{
  return ( sem_wait(sems[e_sp]) );
}

int
ui_ipc_semtrywait(enum UI_IPC_SEM e_sp)
{
  return ( sem_trywait(sems[e_sp]) );
}

int
ui_ipc_getvalue(enum UI_IPC_SEM e_sp)
{
  int sp_val = 0;

  if (sem_getvalue(sems[e_sp], &sp_val) != 0) {
    return -1;
  }
  return sp_val;
}

int
ui_ipc_semtimedwait(enum UI_IPC_SEM e_sp, time_t tmout)
{
  struct timespec ts;
  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
    return -1;
  }
  ts.tv_sec += tmout;
  return ( sem_timedwait(sems[e_sp], &ts) );
}

int
ui_ipc_msgsend(enum UI_IPC_MSQ e_mq, const char *msg_ptr)
{
  char *tmp = alloca(IPC_MQSIZ);
  memset(tmp, '\0', IPC_MQSIZ);
  strncpy(tmp, msg_ptr, IPC_MQSIZ);
  return ( mq_send(msqs[e_mq], tmp, IPC_MQSIZ, 0) );
}

ssize_t
ui_ipc_msgrecv(enum UI_IPC_MSQ e_mq, char *msg_ptr, time_t tmout)
{
  if (tmout > 0) {
    struct timespec tm;
    clock_gettime(CLOCK_REALTIME, &tm);
    tm.tv_sec += tmout;
    return mq_timedreceive(msqs[e_mq], msg_ptr, IPC_MQSIZ, NULL, &tm);
  } else
    return mq_receive(msqs[e_mq], msg_ptr, IPC_MQSIZ, NULL);
}

long
ui_ipc_msgcount(enum UI_IPC_MSQ e_mq)
{
  struct mq_attr m_attr;
  bzero(&m_attr, sizeof(struct mq_attr));
  if (mq_getattr(msqs[e_mq], &m_attr) != 0) return -1;
  return m_attr.mq_curmsgs;
}

void
ui_ipc_msgclear(enum UI_IPC_MSQ e_mq)
{
  char ipc_buf[IPC_MQSIZ+1];
  while (ui_ipc_msgcount(e_mq) > 0) {
    ui_ipc_msgrecv(e_mq, ipc_buf, 0);
  }
}