1
0
Files
irix-657m-src/irix/cmd/tk/mbox.c
2022-09-29 17:59:04 +03:00

198 lines
2.8 KiB
C

#include "mbox.h"
#include "ulocks.h"
#include "stdlib.h"
#include "memory.h"
#include "sys/prctl.h"
/*
* Mailbox
*/
#define NMSGS 50
struct mbox {
usema_t *full;
int fwaiting;
int isfull;
usema_t *empty;
int ewaiting;
usema_t *reply;
mesg_t *msgs[NMSGS];
int rmsg;
int wmsg;
int nodeup;
ulock_t lock;
};
static usptr_t *mus;
void
initmbox(char *f)
{
if ((mus = usinit(f)) == NULL)
abort();
}
struct mbox *
allocmbox(void)
{
struct mbox *mbox;
mbox = usmalloc(sizeof(*mbox), mus);
mbox->full = usnewsema(mus, 0);
mbox->isfull = 0;
mbox->empty = usnewsema(mus, 0);
mbox->lock = usnewlock(mus);
mbox->reply = usnewsema(mus, 0);
mbox->rmsg = mbox->wmsg = 0;
mbox->ewaiting = mbox->fwaiting = 0;
return mbox;
}
void
freembox(struct mbox *mb)
{
usfreesema(mb->empty, mus);
usfreesema(mb->full, mus);
usfreesema(mb->reply, mus);
usfreelock(mb->lock, mus);
usfree(mb, mus);
}
/*
* allocate a mesg
*/
mesg_t *
getmesg(void)
{
mesg_t *a;
a = usmalloc(sizeof(mesg_t), mus);
a->flags = 0;
return a;
}
void
freemesg(mesg_t *a)
{
usfree(a, mus);
}
/*
* write into a mailbox
*/
int
writembox(struct mbox *mb, mesg_t *msg)
{
if (mb->nodeup == 0)
return ENOSEND;
ussetlock(mb->lock);
while (mb->isfull) {
/* full */
mb->fwaiting++;
usunsetlock(mb->lock);
uspsema(mb->full);
ussetlock(mb->lock);
}
mb->msgs[mb->wmsg] = msg;
if (++mb->wmsg >= NMSGS)
mb->wmsg = 0;
if (mb->wmsg == mb->rmsg)
mb->isfull = 1;
if (mb->ewaiting) {
usvsema(mb->empty);
mb->ewaiting--;
}
usunsetlock(mb->lock);
return 0;
}
int
readmbox(struct mbox *mb, mesg_t **msg)
{
ussetlock(mb->lock);
while (mb->rmsg == mb->wmsg && !mb->isfull) {
/* empty */
mb->ewaiting++;
usunsetlock(mb->lock);
uspsema(mb->empty);
ussetlock(mb->lock);
}
*msg = mb->msgs[mb->rmsg];
if (++mb->rmsg >= NMSGS)
mb->rmsg = 0;
if (mb->fwaiting) {
usvsema(mb->full);
mb->fwaiting--;
}
usunsetlock(mb->lock);
return 0;
}
/*
* RPC to a mailbox
*/
int
callmbox(struct mbox *mb, mesg_t *mesg)
{
mesg->flags = MESG_RPC;
if (writembox(mb, mesg))
return ENOSEND;
for (;;) {
uspsema(mb->reply);
if (mesg->flags & MESG_DONE)
break;
usvsema(mb->reply);
}
return (mesg->flags & MESG_ERROR) ? ENOREPLY : 0;
}
/*
* reply to an RPC
*/
void
replymbox(struct mbox *mb, mesg_t *mesg)
{
assert(mesg->flags & MESG_RPC);
mesg->flags |= MESG_DONE;
usvsema(mb->reply);
}
void
freemboxmsg(void *m)
{
usfree(m, mus);
}
static struct mbox *nodes[64];
struct mbox *
ntombox(int nodenum)
{
return nodes[nodenum];
}
void
setmbox(int nodenum, struct mbox *mb)
{
nodes[nodenum] = mb;
mb->nodeup = 1;
}
/*
* XXX how do we reclaim mbox memory??
*/
void
nodedownmbox(int nodenum)
{
struct mbox *mb;
if (mb = nodes[nodenum]) {
mb->nodeup = 0;
ussetlock(mb->lock);
while (mb->ewaiting) {
usvsema(mb->empty);
mb->ewaiting--;
}
usunsetlock(mb->lock);
}
}