/* Implement tasking-related runtime actions for CHILL. Copyright (C) 1992,1993 Free Software Foundation, Inc. Author: Wilfried Moser This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rtltypes.h" #include "rts.h" EXCEPTION (sendfail); extern void __cause_ex1 (char *ex, char *file, int lineno); #define CAUSE_SENDFAIL __cause_ex1 ("sendfail", filename, lineno) /* * function __send_buffer * * parameters: * buffer pointer to buffer descriptor * data pointer to data descriptor * prio priority for send action * timeout pointer to timeout value * filename source file name where function gets called * lineno linenumber in source file * * returns: * int 0 .. success * 1 .. timeout * * exceptions: * sendfail * * abstract: * implement the CHILL SEND buffer action. */ int __send_buffer (buffer, data, prio, timeout, filename, lineno) Buffer_Descr *buffer; Data_Descr *data; int prio; void *timeout; char *filename; int lineno; { Buffer_Queue *bq; Buffer_Send_Queue *bsq, *bsq_entry, *prev_bsq_entry; int cnt = 0; int retval = 0; /* if we don't have anything queued on that buffer, set up the structure */ memcpy (&bq, buffer->buf, sizeof (Buffer_Queue *)); if (bq == 0) { MALLOC (bq, sizeof (Buffer_Queue)); memset (bq, 0, sizeof (Buffer_Queue)); memcpy (buffer->buf, &bq, sizeof (Buffer_Queue *)); } /* look if there is a process delayed on that buffer */ if (bq->waitqueue != 0) { Buffer_Wait_Queue *listentry; /* there is already a processes waiting for that buffer, check datalength and copy the data in */ if (bq->waitqueue->datalen < data->length) CAUSE_SENDFAIL; memcpy (bq->waitqueue->dataptr, data->ptr, data->length); /* set up the entry */ bq->waitqueue->is_sent = 1; bq->waitqueue->who_sent = THIS; /* continue waiting process */ __continue_that (bq->waitqueue->this, prio, filename, lineno); /* now dequeue all entries of this list */ listentry = bq->waitqueue->startlist; while (listentry != 0) { Buffer_Wait_Queue *tmp, *prev_entry, *bwq; Buffer_Queue *bq; tmp = listentry->chain; memcpy (&bq, listentry->bufferaddr, sizeof (Buffer_Queue *)); prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue; bwq = bq->waitqueue; while (bwq != listentry) { prev_entry = bwq; bwq = bwq->forward; } /* dequeue it */ prev_entry->forward = bwq->forward; bq->waitqueuelength--; listentry = tmp; } /* all done */ return 0; } /* nothing in waitqueue, set up an entry for sendqueue. Note: we allocate here space for the data too, to reduce calls to malloc and let the dataptr point just behind the Buffer_Send_Queue structure. */ MALLOC (bsq_entry, sizeof (Buffer_Send_Queue) + data->length); memset (bsq_entry, 0, sizeof (Buffer_Send_Queue)); bsq_entry->priority = prio; bsq_entry->this = THIS; bsq_entry->datalen = data->length; bsq_entry->dataptr = bsq_entry + 1; memcpy (bsq_entry->dataptr, data->ptr, data->length); /* add entry to sendqueue */ prev_bsq_entry = (Buffer_Send_Queue *)&bq->sendqueue; bsq = bq->sendqueue; while (bsq != 0 && bsq->priority >= prio) { prev_bsq_entry = bsq; bsq = bsq->forward; } if (bsq == 0) { /* beginning or end of the list */ prev_bsq_entry->forward = bsq_entry; } else { /* somewhere in the middle */ bsq_entry->forward = prev_bsq_entry->forward; prev_bsq_entry->forward = bsq_entry; } if (buffer->maxqueuelength != (unsigned long)-1L && bq->sendqueuelength >= buffer->maxqueuelength) { /* we have to delay this process */ bsq_entry->is_delayed = 1; retval = __delay_this (wait_buffer_send, timeout, filename, lineno); if (retval) { prev_bsq_entry->forward = bsq_entry->forward; FREE (bsq_entry); } } else /* just say that there is one more entry in the queue */ bq->sendqueuelength++; return retval; } /* force function __print_buffer to be linked */ extern void __print_buffer (); static EntryPoint pev = __print_buffer;