blob: 188b6e0a9a24d799e9410457a507f55900606710 [file] [log] [blame]
/* do not edit automatically generated by mc from RTint. */
/* RTint.mod provides users of the COROUTINES library with the.
Copyright (C) 2009-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 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 3, or (at your option)
any later version.
GNU Modula-2 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.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include <stdbool.h>
# if !defined (PROC_D)
# define PROC_D
typedef void (*PROC_t) (void);
typedef struct { PROC_t proc; } PROC;
# endif
# if !defined (TRUE)
# define TRUE (1==1)
# endif
# if !defined (FALSE)
# define FALSE (1==0)
# endif
# include "GStorage.h"
# include "Gmcrts.h"
#if defined(__cplusplus)
# undef NULL
# define NULL 0
#endif
#define _RTint_C
#include "GRTint.h"
# include "GM2RTS.h"
# include "GStorage.h"
# include "GRTco.h"
# include "GCOROUTINES.h"
# include "Glibc.h"
# include "GAssertion.h"
# include "GSelective.h"
typedef struct RTint_DispatchVector_p RTint_DispatchVector;
# define Microseconds 1000000
# define DebugTime 0
# define Debugging false
typedef struct RTint__T1_r RTint__T1;
typedef RTint__T1 *RTint_Vector;
typedef struct RTint__T2_a RTint__T2;
typedef enum {RTint_input, RTint_output, RTint_time} RTint_VectorType;
struct RTint__T1_r {
RTint_VectorType type;
unsigned int priority;
void * arg;
RTint_Vector pending;
RTint_Vector exists;
unsigned int no;
int File;
Selective_Timeval rel;
Selective_Timeval abs_;
bool queued;
};
struct RTint__T2_a { RTint_Vector array[(7)-(COROUTINES_UnassignedPriority)+1]; };
static unsigned int VecNo;
static RTint_Vector Exists;
static RTint__T2 Pending;
static int lock;
static bool initialized;
/*
InitInputVector - returns an interrupt vector which is associated
with the file descriptor, fd.
*/
extern "C" unsigned int RTint_InitInputVector (int fd, unsigned int pri);
/*
InitOutputVector - returns an interrupt vector which is associated
with the file descriptor, fd.
*/
extern "C" unsigned int RTint_InitOutputVector (int fd, unsigned int pri);
/*
InitTimeVector - returns an interrupt vector associated with
the relative time.
*/
extern "C" unsigned int RTint_InitTimeVector (unsigned int micro, unsigned int secs, unsigned int pri);
/*
ReArmTimeVector - reprimes the vector, vec, to deliver an interrupt
at the new relative time.
*/
extern "C" void RTint_ReArmTimeVector (unsigned int vec, unsigned int micro, unsigned int secs);
/*
GetTimeVector - assigns, micro, and, secs, with the remaining
time before this interrupt will expire.
This value is only updated when a Listen
occurs.
*/
extern "C" void RTint_GetTimeVector (unsigned int vec, unsigned int *micro, unsigned int *secs);
/*
AttachVector - adds the pointer ptr to be associated with the interrupt
vector. It returns the previous value attached to this
vector.
*/
extern "C" void * RTint_AttachVector (unsigned int vec, void * ptr);
/*
IncludeVector - includes, vec, into the dispatcher list of
possible interrupt causes.
*/
extern "C" void RTint_IncludeVector (unsigned int vec);
/*
ExcludeVector - excludes, vec, from the dispatcher list of
possible interrupt causes.
*/
extern "C" void RTint_ExcludeVector (unsigned int vec);
/*
Listen - will either block indefinitely (until an interrupt)
or alteratively will test to see whether any interrupts
are pending.
If a pending interrupt was found then, call, is called
and then this procedure returns.
It only listens for interrupts > pri.
*/
extern "C" void RTint_Listen (bool untilInterrupt, RTint_DispatchVector call, unsigned int pri);
/*
Init -
*/
extern "C" void RTint_Init (void);
/*
Max - returns the maximum: i or j.
*/
static int Max (int i, int j);
static int Min (int i, int j);
/*
FindVector - searches the exists list for a vector of type
which is associated with file descriptor, fd.
*/
static RTint_Vector FindVector (int fd, RTint_VectorType type);
/*
FindVectorNo - searches the Exists list for vector vec.
*/
static RTint_Vector FindVectorNo (unsigned int vec);
/*
FindPendingVector - searches the pending list for vector, vec.
*/
static RTint_Vector FindPendingVector (unsigned int vec);
/*
AddFd - adds the file descriptor fd to set updating max.
*/
static void AddFd (Selective_SetOfFd *set, int *max, int fd);
/*
DumpPendingQueue - displays the pending queue.
*/
static void DumpPendingQueue (void);
/*
AddTime - t1 := t1 + t2
*/
static void AddTime (Selective_Timeval t1, Selective_Timeval t2);
/*
IsGreaterEqual - returns TRUE if, a>=b
*/
static bool IsGreaterEqual (Selective_Timeval a, Selective_Timeval b);
/*
SubTime - assigns, s and m, to a - b.
*/
static void SubTime (unsigned int *s, unsigned int *m, Selective_Timeval a, Selective_Timeval b);
/*
activatePending - activates the first interrupt pending and clears it.
*/
static bool activatePending (bool untilInterrupt, RTint_DispatchVector call, unsigned int pri, int maxFd, Selective_SetOfFd *inSet, Selective_SetOfFd *outSet, Selective_Timeval *timeval, Selective_Timeval b4, Selective_Timeval after);
/*
init -
*/
static void init (void);
/*
Max - returns the maximum: i or j.
*/
static int Max (int i, int j)
{
if (i > j)
{
return i;
}
else
{
return j;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
static int Min (int i, int j)
{
/*
Max - returns the minimum: i or j.
*/
if (i < j)
{
return i;
}
else
{
return j;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
FindVector - searches the exists list for a vector of type
which is associated with file descriptor, fd.
*/
static RTint_Vector FindVector (int fd, RTint_VectorType type)
{
RTint_Vector vec;
vec = Exists;
while (vec != NULL)
{
if ((vec->type == type) && (vec->File == fd))
{
return vec;
}
vec = vec->exists;
}
return NULL;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
FindVectorNo - searches the Exists list for vector vec.
*/
static RTint_Vector FindVectorNo (unsigned int vec)
{
RTint_Vector vptr;
vptr = Exists;
while ((vptr != NULL) && (vptr->no != vec))
{
vptr = vptr->exists;
}
return vptr;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
FindPendingVector - searches the pending list for vector, vec.
*/
static RTint_Vector FindPendingVector (unsigned int vec)
{
unsigned int pri;
RTint_Vector vptr;
for (pri=COROUTINES_UnassignedPriority; pri<=7; pri++)
{
vptr = Pending.array[pri-(COROUTINES_UnassignedPriority)];
while ((vptr != NULL) && (vptr->no != vec))
{
vptr = vptr->pending;
}
if ((vptr != NULL) && (vptr->no == vec))
{
return vptr;
}
}
return NULL;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
AddFd - adds the file descriptor fd to set updating max.
*/
static void AddFd (Selective_SetOfFd *set, int *max, int fd)
{
if (fd < 0)
{
return;
}
(*max) = Max (fd, (*max));
if ((*set) == NULL)
{
(*set) = Selective_InitSet ();
Selective_FdZero ((*set));
}
/* printf('%d, ', fd) */
Selective_FdSet (fd, (*set));
}
/*
DumpPendingQueue - displays the pending queue.
*/
static void DumpPendingQueue (void)
{
COROUTINES_PROTECTION pri;
RTint_Vector vptr;
unsigned int sec;
unsigned int micro;
libc_printf ((const char *) "Pending queue\\n", 15);
for (pri=COROUTINES_UnassignedPriority; pri<=7; pri++)
{
libc_printf ((const char *) "[%d] ", 6, pri);
vptr = Pending.array[pri-(COROUTINES_UnassignedPriority)];
while (vptr != NULL)
{
if ((vptr->type == RTint_input) || (vptr->type == RTint_output))
{
libc_printf ((const char *) "(fd=%d) (vec=%d)", 16, vptr->File, vptr->no);
}
else if (vptr->type == RTint_time)
{
/* avoid dangling else. */
Selective_GetTime (vptr->rel, &sec, &micro);
Assertion_Assert (micro < Microseconds);
libc_printf ((const char *) "time (%u.%06u secs) (arg = %p)\\n", 32, sec, micro, vptr->arg);
}
vptr = vptr->pending;
}
libc_printf ((const char *) " \\n", 3);
}
}
/*
AddTime - t1 := t1 + t2
*/
static void AddTime (Selective_Timeval t1, Selective_Timeval t2)
{
unsigned int a;
unsigned int b;
unsigned int s;
unsigned int m;
Selective_GetTime (t1, &s, &m);
Assertion_Assert (m < Microseconds);
Selective_GetTime (t2, &a, &b);
Assertion_Assert (b < Microseconds);
a += s;
b += m;
if (b >= Microseconds)
{
b -= Microseconds;
a += 1;
}
Selective_SetTime (t1, a, b);
}
/*
IsGreaterEqual - returns TRUE if, a>=b
*/
static bool IsGreaterEqual (Selective_Timeval a, Selective_Timeval b)
{
unsigned int as;
unsigned int am;
unsigned int bs;
unsigned int bm;
Selective_GetTime (a, &as, &am);
Assertion_Assert (am < Microseconds);
Selective_GetTime (b, &bs, &bm);
Assertion_Assert (bm < Microseconds);
return (as > bs) || ((as == bs) && (am >= bm));
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
SubTime - assigns, s and m, to a - b.
*/
static void SubTime (unsigned int *s, unsigned int *m, Selective_Timeval a, Selective_Timeval b)
{
unsigned int as;
unsigned int am;
unsigned int bs;
unsigned int bm;
Selective_GetTime (a, &as, &am);
Assertion_Assert (am < Microseconds);
Selective_GetTime (b, &bs, &bm);
Assertion_Assert (bm < Microseconds);
if (IsGreaterEqual (a, b))
{
(*s) = as-bs;
if (am >= bm)
{
(*m) = am-bm;
Assertion_Assert ((*m) < Microseconds);
}
else
{
Assertion_Assert ((*s) > 0);
(*s) -= 1;
(*m) = (Microseconds+am)-bm;
Assertion_Assert ((*m) < Microseconds);
}
}
else
{
(*s) = 0;
(*m) = 0;
}
}
/*
activatePending - activates the first interrupt pending and clears it.
*/
static bool activatePending (bool untilInterrupt, RTint_DispatchVector call, unsigned int pri, int maxFd, Selective_SetOfFd *inSet, Selective_SetOfFd *outSet, Selective_Timeval *timeval, Selective_Timeval b4, Selective_Timeval after)
{
int result;
unsigned int p;
RTint_Vector vec;
unsigned int b4s;
unsigned int b4m;
unsigned int afs;
unsigned int afm;
unsigned int sec;
unsigned int micro;
RTco_wait (lock);
p = static_cast<unsigned int> (7);
while (p > pri)
{
vec = Pending.array[p-(COROUTINES_UnassignedPriority)];
while (vec != NULL)
{
switch (vec->type)
{
case RTint_input:
if (((vec->File < maxFd) && ((*inSet) != NULL)) && (Selective_FdIsSet (vec->File, (*inSet))))
{
if (Debugging)
{
libc_printf ((const char *) "read (fd=%d) is ready (vec=%d)\\n", 32, vec->File, vec->no);
DumpPendingQueue ();
}
Selective_FdClr (vec->File, (*inSet)); /* so we dont activate this again from our select. */
RTco_signal (lock); /* so we dont activate this again from our select. */
(*call.proc) (vec->no, vec->priority, vec->arg);
return true;
}
break;
case RTint_output:
if (((vec->File < maxFd) && ((*outSet) != NULL)) && (Selective_FdIsSet (vec->File, (*outSet))))
{
if (Debugging)
{
libc_printf ((const char *) "write (fd=%d) is ready (vec=%d)\\n", 33, vec->File, vec->no);
DumpPendingQueue ();
}
Selective_FdClr (vec->File, (*outSet)); /* so we dont activate this again from our select. */
RTco_signal (lock); /* so we dont activate this again from our select. */
(*call.proc) (vec->no, vec->priority, vec->arg);
return true;
}
break;
case RTint_time:
if (untilInterrupt && ((*timeval) != NULL))
{
result = Selective_GetTimeOfDay (after);
Assertion_Assert (result == 0);
if (Debugging)
{
Selective_GetTime ((*timeval), &sec, &micro);
Assertion_Assert (micro < Microseconds);
Selective_GetTime (after, &afs, &afm);
Assertion_Assert (afm < Microseconds);
Selective_GetTime (b4, &b4s, &b4m);
Assertion_Assert (b4m < Microseconds);
libc_printf ((const char *) "waited %u.%06u + %u.%06u now is %u.%06u\\n", 41, sec, micro, b4s, b4m, afs, afm);
}
if (IsGreaterEqual (after, vec->abs_))
{
if (Debugging)
{
DumpPendingQueue ();
libc_printf ((const char *) "time has expired calling dispatcher\\n", 37);
}
(*timeval) = Selective_KillTime ((*timeval)); /* so we dont activate this again from our select. */
RTco_signal (lock); /* so we dont activate this again from our select. */
if (Debugging)
{
libc_printf ((const char *) "call (%d, %d, 0x%x)\\n", 21, vec->no, vec->priority, vec->arg);
}
(*call.proc) (vec->no, vec->priority, vec->arg);
return true;
}
else if (Debugging)
{
/* avoid dangling else. */
libc_printf ((const char *) "must wait longer as time has not expired\\n", 42);
}
}
break;
default:
CaseException ("../../gcc/m2/gm2-libs/RTint.def", 25, 1);
__builtin_unreachable ();
}
vec = vec->pending;
}
p -= 1;
}
RTco_signal (lock);
return false;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
init -
*/
static void init (void)
{
COROUTINES_PROTECTION p;
lock = RTco_initSemaphore (1);
RTco_wait (lock);
Exists = NULL;
for (p=COROUTINES_UnassignedPriority; p<=7; p++)
{
Pending.array[p-(COROUTINES_UnassignedPriority)] = NULL;
}
initialized = true;
RTco_signal (lock);
}
/*
InitInputVector - returns an interrupt vector which is associated
with the file descriptor, fd.
*/
extern "C" unsigned int RTint_InitInputVector (int fd, unsigned int pri)
{
RTint_Vector vptr;
if (Debugging)
{
libc_printf ((const char *) "InitInputVector fd = %d priority = %d\\n", 39, fd, pri);
}
RTco_wait (lock);
vptr = FindVector (fd, RTint_input);
if (vptr == NULL)
{
Storage_ALLOCATE ((void **) &vptr, sizeof (RTint__T1));
VecNo += 1;
vptr->type = RTint_input;
vptr->priority = pri;
vptr->arg = NULL;
vptr->pending = NULL;
vptr->exists = Exists;
vptr->no = VecNo;
vptr->File = fd;
Exists = vptr;
RTco_signal (lock);
return VecNo;
}
else
{
RTco_signal (lock);
return vptr->no;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
InitOutputVector - returns an interrupt vector which is associated
with the file descriptor, fd.
*/
extern "C" unsigned int RTint_InitOutputVector (int fd, unsigned int pri)
{
RTint_Vector vptr;
RTco_wait (lock);
vptr = FindVector (fd, RTint_output);
if (vptr == NULL)
{
Storage_ALLOCATE ((void **) &vptr, sizeof (RTint__T1));
if (vptr == NULL)
{
M2RTS_HALT (-1);
__builtin_unreachable ();
}
else
{
VecNo += 1;
vptr->type = RTint_output;
vptr->priority = pri;
vptr->arg = NULL;
vptr->pending = NULL;
vptr->exists = Exists;
vptr->no = VecNo;
vptr->File = fd;
Exists = vptr;
RTco_signal (lock);
return VecNo;
}
}
else
{
RTco_signal (lock);
return vptr->no;
}
ReturnException ("../../gcc/m2/gm2-libs/RTint.def", 25, 1);
__builtin_unreachable ();
}
/*
InitTimeVector - returns an interrupt vector associated with
the relative time.
*/
extern "C" unsigned int RTint_InitTimeVector (unsigned int micro, unsigned int secs, unsigned int pri)
{
RTint_Vector vptr;
RTco_wait (lock);
Storage_ALLOCATE ((void **) &vptr, sizeof (RTint__T1));
if (vptr == NULL)
{
M2RTS_HALT (-1);
__builtin_unreachable ();
}
else
{
VecNo += 1;
Assertion_Assert (micro < Microseconds);
vptr->type = RTint_time;
vptr->priority = pri;
vptr->arg = NULL;
vptr->pending = NULL;
vptr->exists = Exists;
vptr->no = VecNo;
vptr->rel = Selective_InitTime (secs+DebugTime, micro);
vptr->abs_ = Selective_InitTime (0, 0);
vptr->queued = false;
Exists = vptr;
}
RTco_signal (lock);
return VecNo;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
ReArmTimeVector - reprimes the vector, vec, to deliver an interrupt
at the new relative time.
*/
extern "C" void RTint_ReArmTimeVector (unsigned int vec, unsigned int micro, unsigned int secs)
{
RTint_Vector vptr;
Assertion_Assert (micro < Microseconds);
RTco_wait (lock);
vptr = FindVectorNo (vec);
if (vptr == NULL)
{
M2RTS_Halt ((const char *) "cannot find vector supplied", 27, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "ReArmTimeVector", 15, 287);
}
else
{
Selective_SetTime (vptr->rel, secs+DebugTime, micro);
}
RTco_signal (lock);
}
/*
GetTimeVector - assigns, micro, and, secs, with the remaining
time before this interrupt will expire.
This value is only updated when a Listen
occurs.
*/
extern "C" void RTint_GetTimeVector (unsigned int vec, unsigned int *micro, unsigned int *secs)
{
RTint_Vector vptr;
RTco_wait (lock);
vptr = FindVectorNo (vec);
if (vptr == NULL)
{
M2RTS_Halt ((const char *) "cannot find vector supplied", 27, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "GetTimeVector", 13, 313);
}
else
{
Selective_GetTime (vptr->rel, secs, micro);
Assertion_Assert ((*micro) < Microseconds);
}
RTco_signal (lock);
}
/*
AttachVector - adds the pointer ptr to be associated with the interrupt
vector. It returns the previous value attached to this
vector.
*/
extern "C" void * RTint_AttachVector (unsigned int vec, void * ptr)
{
RTint_Vector vptr;
void * prevArg;
RTco_wait (lock);
vptr = FindVectorNo (vec);
if (vptr == NULL)
{
M2RTS_Halt ((const char *) "cannot find vector supplied", 27, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "AttachVector", 12, 340);
}
else
{
prevArg = vptr->arg;
vptr->arg = ptr;
if (Debugging)
{
libc_printf ((const char *) "AttachVector %d with %p\\n", 25, vec, ptr);
DumpPendingQueue ();
}
RTco_signal (lock);
return prevArg;
}
ReturnException ("../../gcc/m2/gm2-libs/RTint.def", 25, 1);
__builtin_unreachable ();
}
/*
IncludeVector - includes, vec, into the dispatcher list of
possible interrupt causes.
*/
extern "C" void RTint_IncludeVector (unsigned int vec)
{
RTint_Vector vptr;
unsigned int micro;
unsigned int sec;
int result;
RTco_wait (lock);
vptr = FindPendingVector (vec);
if (vptr == NULL)
{
/* avoid dangling else. */
vptr = FindVectorNo (vec);
if (vptr == NULL)
{
M2RTS_Halt ((const char *) "cannot find vector supplied", 27, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "IncludeVector", 13, 374);
}
else
{
/* printf('including vector %d (fd = %d)
', vec, v^.File) ; */
vptr->pending = Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)];
Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)] = vptr;
if ((vptr->type == RTint_time) && ! vptr->queued)
{
vptr->queued = true;
result = Selective_GetTimeOfDay (vptr->abs_);
Assertion_Assert (result == 0);
Selective_GetTime (vptr->abs_, &sec, &micro);
Assertion_Assert (micro < Microseconds);
AddTime (vptr->abs_, vptr->rel);
Selective_GetTime (vptr->abs_, &sec, &micro);
Assertion_Assert (micro < Microseconds);
}
}
}
else
{
if (Debugging)
{
libc_printf ((const char *) "odd vector (%d) type (%d) arg (%p) is already attached to the pending queue\\n", 77, vec, vptr->type, vptr->arg);
}
}
RTco_signal (lock);
}
/*
ExcludeVector - excludes, vec, from the dispatcher list of
possible interrupt causes.
*/
extern "C" void RTint_ExcludeVector (unsigned int vec)
{
RTint_Vector vptr;
RTint_Vector uptr;
RTco_wait (lock);
vptr = FindPendingVector (vec);
if (vptr == NULL)
{
M2RTS_Halt ((const char *) "cannot find pending vector supplied", 35, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "ExcludeVector", 13, 416);
}
else
{
/* printf('excluding vector %d
', vec) ; */
if (Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)] == vptr)
{
Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)] = Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)]->pending;
}
else
{
uptr = Pending.array[vptr->priority-(COROUTINES_UnassignedPriority)];
while (uptr->pending != vptr)
{
uptr = uptr->pending;
}
uptr->pending = vptr->pending;
}
if (vptr->type == RTint_time)
{
vptr->queued = false;
}
}
RTco_signal (lock);
}
/*
Listen - will either block indefinitely (until an interrupt)
or alteratively will test to see whether any interrupts
are pending.
If a pending interrupt was found then, call, is called
and then this procedure returns.
It only listens for interrupts > pri.
*/
extern "C" void RTint_Listen (bool untilInterrupt, RTint_DispatchVector call, unsigned int pri)
{
bool found;
int result;
Selective_Timeval zero;
Selective_Timeval after;
Selective_Timeval b4;
Selective_Timeval timeval;
RTint_Vector vec;
Selective_SetOfFd inSet;
Selective_SetOfFd outSet;
unsigned int sec;
unsigned int micro;
int maxFd;
unsigned int p;
RTco_wait (lock);
if (pri < (7))
{
if (Debugging)
{
DumpPendingQueue ();
}
maxFd = -1;
timeval = NULL;
inSet = NULL;
outSet = NULL;
timeval = Selective_InitTime (static_cast<unsigned int> (INT_MAX), 0);
p = static_cast<unsigned int> (7);
found = false;
while (p > pri)
{
vec = Pending.array[p-(COROUTINES_UnassignedPriority)];
while (vec != NULL)
{
switch (vec->type)
{
case RTint_input:
AddFd (&inSet, &maxFd, vec->File);
break;
case RTint_output:
AddFd (&outSet, &maxFd, vec->File);
break;
case RTint_time:
if (IsGreaterEqual (timeval, vec->abs_))
{
Selective_GetTime (vec->abs_, &sec, &micro);
Assertion_Assert (micro < Microseconds);
if (Debugging)
{
libc_printf ((const char *) "shortest delay is %u.%06u\\n", 27, sec, micro);
}
Selective_SetTime (timeval, sec, micro);
found = true;
}
break;
default:
CaseException ("../../gcc/m2/gm2-libs/RTint.def", 25, 1);
__builtin_unreachable ();
}
vec = vec->pending;
}
p -= 1;
}
if (! untilInterrupt)
{
Selective_SetTime (timeval, 0, 0);
}
if ((untilInterrupt && (((inSet == NULL) && (outSet == NULL)) || (maxFd == -1))) && ! found)
{
M2RTS_Halt ((const char *) "deadlock found, no more processes to run and no interrupts active", 65, (const char *) "../../gcc/m2/gm2-libs/RTint.mod", 31, (const char *) "Listen", 6, 733);
}
/* printf('}
') ; */
if (! found && (maxFd == -1))
{
/* no file descriptors to be selected upon. */
timeval = Selective_KillTime (timeval);
RTco_signal (lock);
return;
}
else
{
Selective_GetTime (timeval, &sec, &micro);
Assertion_Assert (micro < Microseconds);
zero = Selective_InitTime (0, 0);
b4 = Selective_InitTime (0, 0);
after = Selective_InitTime (0, 0);
result = Selective_GetTimeOfDay (b4);
Assertion_Assert (result == 0);
SubTime (&sec, &micro, timeval, b4);
Selective_SetTime (timeval, sec, micro);
if (Debugging)
{
libc_printf ((const char *) "select waiting for %u.%06u seconds\\n", 36, sec, micro);
}
RTco_signal (lock);
do {
if (Debugging)
{
libc_printf ((const char *) "select (.., .., .., %u.%06u)\\n", 30, sec, micro);
}
if (maxFd < 0)
{
result = RTco_select (0, NULL, NULL, NULL, timeval);
}
else
{
result = RTco_select (maxFd+1, inSet, outSet, NULL, timeval);
}
if (result == -1)
{
if (Debugging)
{
libc_perror ((const char *) "select failed : ", 16);
}
result = RTco_select (maxFd+1, inSet, outSet, NULL, zero);
if (result != -1)
{
Selective_GetTime (timeval, &sec, &micro);
if (Debugging)
{
libc_printf ((const char *) "(nfds : %d timeval: %u.%06u) : \\n", 33, maxFd, sec, micro);
}
libc_perror ((const char *) "select timeout argument was faulty : ", 37);
}
else
{
result = RTco_select (maxFd+1, inSet, NULL, NULL, timeval);
if (result != -1)
{
libc_perror ((const char *) "select output fd argument was faulty : ", 39);
}
else
{
result = RTco_select (maxFd+1, NULL, outSet, NULL, timeval);
if (result != -1)
{
libc_perror ((const char *) "select input fd argument was faulty : ", 38);
}
else
{
if (maxFd == -1)
{
/* avoid dangling else. */
result = RTco_select (0, NULL, NULL, NULL, timeval);
if (result == -1)
{
if (Debugging)
{
libc_perror ((const char *) "select does not accept nfds == 0 ", 33);
}
result = 0;
}
}
else
{
libc_perror ((const char *) "select maxFD+1 argument was faulty : ", 37);
}
}
}
}
}
} while (! (result != -1));
}
while (activatePending (untilInterrupt, call, pri, maxFd+1, &inSet, &outSet, &timeval, b4, after))
{} /* empty. */
if (timeval != NULL)
{
timeval = Selective_KillTime (timeval);
}
if (zero != NULL)
{
zero = Selective_KillTime (zero);
}
if (after != NULL)
{
after = Selective_KillTime (after);
}
if (b4 != NULL)
{
b4 = Selective_KillTime (b4);
}
if (inSet != NULL)
{
inSet = Selective_KillSet (inSet);
}
if (outSet != NULL)
{
outSet = Selective_KillSet (outSet);
}
}
RTco_signal (lock);
}
/*
Init -
*/
extern "C" void RTint_Init (void)
{
if (! initialized)
{
init ();
}
}
extern "C" void _M2_RTint_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
RTint_Init ();
}
extern "C" void _M2_RTint_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
}