| /* 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, µ); |
| 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, µ); |
| 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, µ); |
| Assertion_Assert (micro < Microseconds); |
| AddTime (vptr->abs_, vptr->rel); |
| Selective_GetTime (vptr->abs_, &sec, µ); |
| 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, µ); |
| 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, µ); |
| 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, µ, 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, µ); |
| 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[]) |
| { |
| } |