#include <string.h>
#include "rtltypes.h"
#include "rts.h"
extern void __cause_ex1 (char *ex, char *file, int lineno);
EXCEPTION (bufferinconsistency)
#define CAUSE_BUFFINCONS __cause_ex1 ("bufferinconsistency", filename, lineno)
EXCEPTION (spacefail);
#define CAUSE_SPACEFAIL __cause_ex1 ("spacefail", filename, lineno)
int
__wait_buffer (buf_got, nbuf, bufptr, datap, datalen, ins,
else_clause, to, filename, lineno)
void **buf_got;
int nbuf;
Buffer_Descr *bufptr[];
void *datap;
int datalen;
INSTANCE *ins;
int else_clause;
void *to;
char *filename;
int lineno;
{
int i;
Buffer_Wait_Queue *start_list;
Buffer_Queue **retval;
Buffer_Queue **highprio;
int timed_out;
highprio = 0;
for (i = 0; i < nbuf; i++)
{
Buffer_Queue *bq;
memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
if (bq != 0 && bq->sendqueue != 0)
{
if (highprio != 0)
{
Buffer_Queue *bsq = *highprio;
if (bq->sendqueue->priority > bsq->sendqueue->priority)
highprio = bufptr[i]->buf;
}
else
highprio = bufptr[i]->buf;
}
}
if (highprio != 0)
{
Buffer_Queue *bq;
memcpy (&bq, highprio, sizeof (Buffer_Queue *));
if (bq != 0 && bq->sendqueue != 0)
{
Buffer_Send_Queue *bsq = bq->sendqueue;
Buffer_Send_Queue *tmp;
if (datalen < bsq->datalen)
CAUSE_SPACEFAIL;
memcpy (datap, bsq->dataptr, bsq->datalen);
if (ins != 0)
memcpy (ins, &bsq->this, sizeof (INSTANCE));
tmp = bsq;
bq->sendqueue = tmp->forward;
if (tmp->is_delayed)
{
__continue_that (tmp->this, tmp->priority, filename, lineno);
FREE (tmp);
*buf_got = (void *)highprio;
return 0;
}
bq->sendqueuelength--;
FREE (tmp);
bsq = bq->sendqueue;
while (bsq != 0)
{
if (bsq->is_delayed)
{
bq->sendqueuelength++;
bsq->is_delayed = 0;
__continue_that (bsq->this, bsq->priority, filename, lineno);
break;
}
bsq = bsq->forward;
}
*buf_got = (void *)highprio;
return 0;
}
}
if (else_clause != 0)
{
*buf_got = 0;
return 0;
}
start_list = 0;
for (i = 0; i < nbuf; i++)
{
Buffer_Queue *bq;
Buffer_Wait_Queue *wrk;
Buffer_Wait_Queue *bwq;
Buffer_Wait_Queue *prev_queue_entry = 0;
Buffer_Wait_Queue *prev_list_entry;
int j, have_done = 0;
for (j = 0; j < i; j++)
{
if (bufptr[i]->buf == bufptr[j]->buf)
{
have_done = 1;
break;
}
}
if (have_done)
continue;
memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
if (bq == 0)
{
MALLOC (bq, sizeof (Buffer_Queue));
memset (bq, 0, sizeof (Buffer_Queue));
memcpy (bufptr[i]->buf, &bq, sizeof (Buffer_Queue *));
}
MALLOC (wrk, sizeof (Buffer_Wait_Queue));
memset (wrk, 0, sizeof (Buffer_Wait_Queue));
bwq = (Buffer_Wait_Queue *)&bq->waitqueue;
wrk->this = THIS;
wrk->datalen = datalen;
wrk->dataptr = datap;
wrk->bufferaddr = bufptr[i]->buf;
while (bwq->forward != 0)
bwq = bwq->forward;
wrk->forward = bwq->forward;
bwq->forward = wrk;
wrk->startlist = start_list;
if (! start_list)
{
start_list = wrk;
prev_list_entry = wrk;
wrk->startlist = start_list;
}
else
{
prev_list_entry->chain = wrk;
prev_list_entry = wrk;
}
bq->waitqueuelength++;
}
timed_out = __delay_this (wait_buffer_receive, to, filename, lineno);
if (timed_out)
{
Buffer_Wait_Queue *listentry = start_list;
while (listentry != 0)
{
Buffer_Queue *bq = *(listentry->bufferaddr);
Buffer_Wait_Queue *prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue;
Buffer_Wait_Queue *bwq = bq->waitqueue;
while (bwq != listentry)
{
prev_entry = bwq;
bwq = bwq->forward;
}
prev_entry->forward = bwq->forward;
bq->waitqueuelength--;
listentry = listentry->chain;
}
}
retval = 0;
while (start_list != 0)
{
Buffer_Wait_Queue *tmp = start_list->chain;
if (start_list->is_sent)
{
if (retval == 0)
retval = start_list->bufferaddr;
else
CAUSE_BUFFINCONS;
if (ins != 0)
memcpy (ins, &start_list->who_sent, sizeof (INSTANCE));
}
FREE (start_list);
start_list = tmp;
}
if (retval == 0 && !timed_out)
CAUSE_BUFFINCONS;
if (!timed_out)
*buf_got = (void *)retval;
return timed_out;
}
extern void __print_buffer ();
static EntryPoint pev = __print_buffer;