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

📄 event.c

📁 Vista 核心Rally技术之-LLTD 实现源代码
💻 C
字号:
/*
 * LICENSE NOTICE.
 *
 * Use of the Microsoft Windows Rally Development Kit is covered under
 * the Microsoft Windows Rally Development Kit License Agreement,
 * which is provided within the Microsoft Windows Rally Development
 * Kit or at http://www.microsoft.com/whdc/rally/rallykit.mspx. If you
 * want a license from Microsoft to use the software in the Microsoft
 * Windows Rally Development Kit, you must (1) complete the designated
 * "licensee" information in the Windows Rally Development Kit License
 * Agreement, and (2) sign and return the Agreement AS IS to Microsoft
 * at the address provided in the Agreement.
 */

/*
 * Copyright (c) Microsoft Corporation 2005.  All rights reserved.
 * This software is provided with NO WARRANTY.
 */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include "globals.h"

/* Static list of event_t's, sorted by their firing times */
static event_t *Events;


typedef struct {
    int           eio_fd;
    event_io_fn_t eio_function;
    void         *eio_state;
} event_io_t;

/* Limited to just a handful of IO handler for ease: */
#define NIOS 2
static event_io_t Ios[NIOS];


void
event_init(void)
{
    int i;

    /* mark all IO slots as available */
    for (i=0; i<NIOS; i++)
    {
        Ios[i].eio_fd = -1;
        Ios[i].eio_function = NULL;
        Ios[i].eio_state = NULL;
    }
}


/* Add a new event to the list, calling "function(state)" at "firetime". */
event_t *
event_add(struct timeval *firetime, event_fn_t function, void *state)
{
    event_t *prev = NULL;
    event_t *here = Events;

    event_t *ne = xmalloc(sizeof(event_t));
    ne->ev_firetime = *firetime;
    ne->ev_function = function;
    ne->ev_state    = state;
    ne->ev_next     = NULL;

    while (here != NULL && timerle(&here->ev_firetime, &ne->ev_firetime))
    {
	prev = here;
	here = here->ev_next;
    }

    ne->ev_next = here;
    if (!prev)
	Events = ne;
    else
	prev->ev_next = ne;

    return ne;
}


/* Cancel a previously requested event; return TRUE if successful, FALSE if the
 * event wasn't found. */
bool_t
event_cancel(event_t *event)
{
    event_t *prev = NULL;
    event_t *here = Events;

    while (here != NULL)
    {
	if (here == event)
	{
	    if (prev)
		prev->ev_next = here->ev_next;
	    else
		Events = here->ev_next;
	    xfree(here);
	    return TRUE;
	}

	prev = here;
	here = here->ev_next;
    }

    return FALSE;
}

/* You can register a handler function to deal with IO on a file descriptor: */
void
event_add_io(int fd, event_io_fn_t function, void *state)
{
    int i = 0;

    /* find next free io slot */
    while (i < NIOS && Ios[i].eio_fd != -1)
	i++;
    if (i == NIOS)
	die("event_add_io: no free IO slots (all %d used)\n", NIOS);

    Ios[i].eio_fd = fd;
    Ios[i].eio_function = function;
    Ios[i].eio_state = state;
}

void
event_remove_io(int fd)
{
    int i = 0;

    while (i < NIOS && Ios[i].eio_fd != fd)
	i++;
    if (i == NIOS)
    {
	warn("event_remove_io: fd %d is unknown; ignoring", fd);
	return;
    }

    Ios[i].eio_fd = -1;
    Ios[i].eio_function = NULL;
    Ios[i].eio_state = NULL;
}


/* Capture the current thread, and run event and IO handlers forever.
 * Does not return. */


void
event_mainloop(void)
{
    struct timeval tv, now, *timeout;
    fd_set readfds;
    int ret;
    int i;
    int maxfd;

#ifdef ADJUSTING_FOR_EARLY_WAKEUP
    /* If your OS can wake you before the full timeout has elapsed, we
     * end up looping through and not running any event functions,
     * then setting a really short timeout (~10us!) to get back on
     * track.  We avoid this by adding wake_lead_time to the timeout
     * which we calculate dynamically based on how often we get
     * spurious wakeups.  We reduce the lead time if its been correct
     * for a while. */
    int wake_lead_time = 0;
    int wake_time_correct = 0;
#endif
    while (1)
    {
        /* IO activity to monitor */
        FD_ZERO(&readfds);
        maxfd = -1;
        for (i=0; i<NIOS; i++)
        {
            if (Ios[i].eio_fd != -1)
            {
                FD_SET(Ios[i].eio_fd, &readfds);
                maxfd = TOPOMAX(maxfd, Ios[i].eio_fd);
            }
        }

        /* work out a suitable timeout */
        if (Events == NULL)
        {
            /* no events so block forever */
            timeout = NULL;
        }
        else
        {
            gettimeofday(&now, NULL);
            timeout = &tv;
            /* is event in the past? */
            if (timerle(&Events->ev_firetime, &now))
            {
                /* don't block, just poll at the select statement below */
                timeout->tv_sec = 0;
                timeout->tv_usec = 0;
            }
            else
            {
                /* how far in the future is it? */
                bsd_timersub(&Events->ev_firetime, &now, timeout);
#ifdef ADJUSTING_FOR_EARLY_WAKEUP
                timeval_add_ms(timeout, wake_lead_time);
#endif
            }
        }

        ret = select(maxfd + 1, &readfds, NULL, NULL, timeout);
        if (ret < 0)
        {
            if (errno == EINTR)
                continue;
            die("event_mainloop: select: %s\n", strerror(errno));
        }
        if (ret == 0) /* timeout */
        {
            bool_t did_some_work = FALSE;

            /* run event functions */
            gettimeofday(&now, NULL);
            while (Events != NULL && timerle(&Events->ev_firetime, &now))
            {
                event_t *e = Events;
                Events = Events->ev_next;
                e->ev_function(e->ev_state);
                xfree(e);
                did_some_work = TRUE;
                gettimeofday(&now, NULL);
            }

#ifdef ADJUSTING_FOR_EARLY_WAKEUP
            if (!did_some_work)
            {
                /* we woke too early; increase the lead time */
                wake_lead_time++;
                if (wake_lead_time > 50)
                {
                    warn("event_mainloop: wake_lead_time clamped at %dms; "
                         "is your select() implementation really waking that early?!\n",
                         wake_lead_time);
                           wake_lead_time = 50;
                }
//*/		dbgprintf("increased wake_lead_time to %d\n", wake_lead_time);
            }
            else
            {
                /* If the wake time was right, it might also be too high.
                 * So trim the lead time down a little. */
                wake_time_correct++;
                if (wake_time_correct > 100)
                {
                    wake_time_correct = 0;
                    if (wake_lead_time > 0)
                    {
                        wake_lead_time--;
//*/			dbgprintf("reducing wake_lead_time to %d\n", wake_lead_time);
                    }
                }
            }
#endif
        }
        else
        {
#ifdef SIOCGSTAMP_NOT_AVAILABLE
            /* Capture pkt-IO timestamp as early as possible */
            uint64_t	   temp;

            gettimeofday(&now, NULL);
            temp = now.tv_sec * (uint64_t)1000000UL;
            g_pktio_timestamp = temp + now.tv_usec;
#endif
            /* run IO function(s) */
            for (i=0; i<NIOS; i++)
                if (Ios[i].eio_fd != -1 && FD_ISSET(Ios[i].eio_fd, &readfds))
                    Ios[i].eio_function(Ios[i].eio_fd, Ios[i].eio_state);
        }
    }
}

⌨️ 快捷键说明

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