⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 synth_intr.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
// when it requires attention, i.e. when one or more of the devices
// want to raise an interrupt. Finding out exactly which interrupt(s)
// are currently pending in the auxiliary requires communication with
// the auxiliary.
//
// If interrupts are currently disabled then the signal cannot be
// handled immediately. In particular SIGIO cannot be handled because
// there may already be ongoing communication with the auxiliary.
// Instead some volatile flags are used to keep track of which signals
// were raised while interrupts were disabled. 
//
// It might be better to perform the interaction with the auxiliary
// as soon as possible, i.e. either in the SIGIO handler or when the
// current communication completes. That way the mask of pending
// interrupts would remain up to date even when interrupts are
// disabled, thus allowing applications to run in polled mode.

// A little utility called when the auxiliary has been asked to exit,
// implicitly affecting this application as well. The sole purpose
// of this function is to put a suitably-named function on the stack
// to make it more obvious from inside gdb what is happening.
static void
synth_io_handle_shutdown_request_from_auxiliary(void)
{
    cyg_hal_sys_exit(0);
}

static void
synth_io_sighandler(int sig)
{
    CYG_PRECONDITION((CYG_HAL_SYS_SIGIO == sig), "Only SIGIO should be handled here");
    
    if (!hal_interrupts_enabled) {
        synth_sigio_pending = true;
        return;
    }
    
    // Interrupts were enabled, but must be blocked before any further processing.
    hal_interrupts_enabled = false;

    // Update the interrupt status "register" to match pending interrupts
    // Contact the auxiliary to find out what interrupts are currently pending there.
    // If there is no auxiliary at present, e.g. because it has just terminated
    // and things are generally somewhat messy, ignore it.
    //
    // This code also deals with the case where the user has requested program
    // termination. It would be wrong for the auxiliary to just exit, since the
    // application could not distinguish that case from a crash. Instead the
    // auxiliary can optionally return an additional byte of data, and if that
    // byte actually gets sent then that indicates pending termination.
    if (synth_auxiliary_running) {
        int             result;
        int             actual_len;
        unsigned char   dummy[1];
        synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_GET_IRQPENDING, 0, 0,
                                (const unsigned char*) 0, 0,        // The auxiliary does not need any additional data
                                &result, dummy, &actual_len, 1);
        synth_pending_isrs |= result;
        if (actual_len) {
            // The auxiliary has been asked to terminate by the user. This
            // request has now been passed on to the eCos application.
            synth_io_handle_shutdown_request_from_auxiliary();
        }
    }

    // If any of the pending interrupts are not masked, invoke the VSR
    if (0 != (synth_pending_isrs & ~synth_masked_isrs)) {
        (*synth_VSR)();
    } else {
        hal_interrupts_enabled = true;
    }

    // The VSR will have invoked interrupt_end() with interrupts
    // enabled, and they should still be enabled.
    CYG_ASSERT( hal_interrupts_enabled, "Interrupts should still be enabled on return from the VSR");
}

// ----------------------------------------------------------------------------
// Here we define an action to do in the idle thread. For the
// synthetic target it makes no sense to spin eating processor time
// that other processes could make use of. Instead we call select. The
// itimer will still go off and kick the scheduler back into life,
// giving us an escape path from the select. There is one problem: in
// some configurations, e.g. when preemption is disabled, the idle
// thread must yield continuously rather than blocking.
void
hal_idle_thread_action(cyg_uint32 loop_count)
{
#ifndef CYGIMP_HAL_IDLE_THREAD_SPIN
    cyg_hal_sys__newselect(0,
                           (struct cyg_hal_sys_fd_set*) 0,
                           (struct cyg_hal_sys_fd_set*) 0,
                           (struct cyg_hal_sys_fd_set*) 0,
                           (struct cyg_hal_sys_timeval*) 0);
#endif
    CYG_UNUSED_PARAM(cyg_uint32, loop_count);
}

// ----------------------------------------------------------------------------
// The I/O auxiliary.
//
// I/O happens via an auxiliary process. During startup this code attempts
// to locate and execute a program ecosynth which should be installed in
// ../libexec/ecosynth relative to some directory on the search path.
// Subsequent I/O operations involve interacting with this auxiliary.

#define MAKESTRING1(a) #a
#define MAKESTRING2(a) MAKESTRING1(a)
#define AUXILIARY       "../libexec/ecos/hal/synth/arch/" MAKESTRING2(CYGPKG_HAL_SYNTH) "/ecosynth"

// Is the auxiliary up and running?
cyg_bool    synth_auxiliary_running   = false;

// The pipes to and from the auxiliary.
static int  to_aux      = -1;
static int  from_aux    = -1;

// Attempt to start up the auxiliary. Note that this happens early on
// during system initialization so it is "known" that the world is
// still simple, e.g. that no other files have been opened.
static void
synth_start_auxiliary(void)
{
#define BUFSIZE 256
    char        filename[BUFSIZE];
    const char* path = 0;
    int         i, j;
    cyg_bool    found   = false;
    int         to_aux_pipe[2];
    int         from_aux_pipe[2];
    int         child;
    int         aux_version;
#if 1
    // Check for a command line argument -io. Only run the auxiliary if this
    // argument is provided, i.e. default to traditional behaviour.
    for (i = 1; i < cyg_hal_sys_argc; i++) {
        const char* tmp = cyg_hal_sys_argv[i];
        if ('-' == *tmp) {
            // Arguments beyond -- are reserved for use by the application,
            // and should not be interpreted by the HAL itself or by ecosynth.
            if (('-' == tmp[1]) && ('\0' == tmp[2])) {
                break;
            }
            tmp++;
            if ('-' == *tmp) {
                // Do not distinguish between -io and --io
                tmp++;
            }
            if (('i' == tmp[0]) && ('o' == tmp[1]) && ('\0' == tmp[2])) {
                found = 1;
                break;
            }
        }
    }
    if (!found) {
        return;
    }
#else
    // Check for a command line argument -ni or -nio. Always run the
    // auxiliary unless this argument is given, i.e. default to full
    // I/O support.
    for (i = 1; i < cyg_hal_sys_argc; i++) {
        const char* tmp = cyg_hal_sys_argv[i];
        if ('-' == *tmp) {
            if (('-' == tmp[1]) && ('\0' == tmp[2])) {
                break;
            }
            tmp++;
            if ('-' == *tmp) {
                tmp++;
            }
            if ('n' == *tmp) {
                tmp++;
                if ('i' == *tmp) {
                    tmp++;
                    if ('\0' == *tmp) {
                        found = 1;  // -ni or --ni
                        break;
                    }
                    if (('o' == *tmp) && ('\0' == tmp[1])) {
                        found = 1;  // -nio or --nio
                        break;
                    }
                }
            }
        }
    }
    if (found) {
        return;
    }
#endif
    
    // The auxiliary must be found relative to the current search path,
    // so look for a PATH= environment variable.
    for (i = 0; (0 == path) && (0 != cyg_hal_sys_environ[i]); i++) {
        const char *var = cyg_hal_sys_environ[i];
        if (('P' == var[0]) && ('A' == var[1]) && ('T' == var[2]) && ('H' == var[3]) && ('=' == var[4])) {
            path = var + 5;
        }
    }
    if (0 == path) {
        // Very unlikely, but just in case.
        path = ".:/bin:/usr/bin";
    }

    found = 0;
    while (!found && ('\0' != *path)) {         // for every entry in the path
        char *tmp = AUXILIARY;
        
        j = 0;

        // As a special case, an empty string in the path corresponds to the
        // current directory.
        if (':' == *path) {
            filename[j++] = '.';
            path++;
        } else {
            while ((j < BUFSIZE) && ('\0' != *path) && (':' != *path)) {
                filename[j++] = *path++;
            }
            // If not at the end of the search path, move on to the next entry.
            if ('\0' != *path) {
                while ((':' != *path) && ('\0' != *path)) {
                    path++;
                }
                if (':' == *path) {
                    path++;
                }
            }
        }
        // Now append a directory separator, and then the name of the executable.
        if (j < BUFSIZE) {
            filename[j++] = '/';
        }
        while ((j < BUFSIZE) && ('\0' != *tmp)) {
            filename[j++] = *tmp++;
        }
        // If there has been a buffer overflow, skip this entry.
        if (j == BUFSIZE) {
            filename[BUFSIZE-1] = '\0';
            diag_printf("Warning: buffer limit reached while searching PATH for the I/O auxiliary.\n");
            diag_printf("       : skipping current entry.\n");
        } else {
            // filename now contains a possible match for the auxiliary.
            filename[j++]    = '\0';
            if (0 == cyg_hal_sys_access(filename, CYG_HAL_SYS_X_OK)) {
                found = true;
            }
        }
    }
#undef BUFSIZE

    if (!found) {
        diag_printf("Error: unable to find the I/O auxiliary program on the current search PATH\n");
        diag_printf("     : please install the appropriate host-side tools.\n");
        cyg_hal_sys_exit(1);
    }

    // An apparently valid executable exists (or at the very least it existed...),
    // so create the pipes that will be used for communication.
    if ((0 != cyg_hal_sys_pipe(to_aux_pipe)) ||
        (0 != cyg_hal_sys_pipe(from_aux_pipe))) {
        diag_printf("Error: unable to set up pipes for communicating with the I/O auxiliary.\n");
        cyg_hal_sys_exit(1);
    }
    
    // Time to fork().
    child = cyg_hal_sys_fork();
    if (child < 0) {
        diag_printf("Error: failed to fork() process for the I/O auxiliary.\n");
        cyg_hal_sys_exit(1);
    } else if (child == 0) {
        cyg_bool    found_dotdot;
        // There should not be any problems rearranging the file descriptors as desired...
        cyg_bool    unexpected_error = 0;
        
        // In the child process. Close unwanted file descriptors, then some dup2'ing,
        // and execve() the I/O auxiliary. The auxiliary will inherit stdin,
        // stdout and stderr from the eCos application, so that functions like
        // printf() work as expected. In addition fd 3 will be the pipe from
        // the eCos application and fd 4 the pipe to the application. It is possible

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -