· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Asterisk Source/Select Poll

AsteriskSource/SelectPoll

* select
  • select(0,NULL,NULL,NULL,NULL)
If the readfs , writefs , and errorfds arguments are all null pointers and the timeout  argument is a null pointer, select()  blocks until interrupted by a signal.
The call returns the number of `ready' FDs found, and the three fdsets are
modified in-place, with only the ready FDs left in the sets. Use the
`FD_ISSET' macro to test the returned sets.

* poll
  • <sys/poll.h>
  • int poll(struct poolfd *ufds, unsigned int nfds, int timeout);
  
    #define POLLIN      0x0001  // 읽을 데이타가 있다.
    #define POLLPRI     0x0002  // 긴급한 읽을 데이타가 있다.
    #define POLLOUT     0x0004  // 쓰기가 봉쇄(block)가 아니다. 
    #define POLLERR     0x0008  // 에러발생
    #define POLLHUP     0x0010  // 연결이 끊겼음
    #define POLLNVAL    0x0020  // 파일지시자가 열리지 않은것같은
                                // Invalid request (잘못된 요청)
  • 마지막 아규먼트인 timeout 는 select 의 time 와 같은 역할을 한다.
If none of the defined events have occurred on any selected file descriptor, poll() shall wait at least timeout milliseconds for an event to occur on any of the selected file descriptors. If the value of timeout is 0, poll() shall return immediately. If the value of timeout is -1, poll() shall block until a requested event occurs or until the call is interrupted.
RETURN value
   Upon successful completion, poll() shall return a non-negative value. A positive value indicates the total number of file descriptors that have been selected (that is, file descriptors for which the revents member is non-zero). A value of 0 indicates that the call timed out and no file descriptors have been selected. Upon failure, poll() shall return -1 and set errno to indicate the error.

schedule.c

* chan_sip.c
  • static void *do_monitor(void *data)
    • sched = sched_context_create();
    • res = ast_sched_wait(sched);
    • res = ast_io_wait(io, res);
    • if (res >= 0) ast_io_wait 에서 오류가 발생하지 않으면
      • ast_sched_runq(sched);
* struct sched_context *sched_context_create(void)
struct sched_context *sched_context_create(void)
{
        struct sched_context *tmp;
        tmp = malloc(sizeof(struct sched_context));
        if (tmp) {
                tmp->eventcnt = 1; no. of events processed
                tmp->schedcnt = 0; no. of outstanding schedule events
                tmp->schedq = NULL; schedule entry and main queue
#ifdef SCHED_MAX_CACHE
                tmp->schedc = NULL;
                tmp->schedccnt = 0;
#endif
        }
        return tmp;
}
  • eventcnt
    • sched_context_create 에서 1 로 설정
    • ast_sched_add 시 1 씩 증가
    • id 로 사용함 (queue 에 들어온 순서임)
    • ast_sched_del 에서 id 를 사용하여 제거함.
  • schedcnt
    • queue 에 있는 event 의 갯수임.
    • sched_context_create 에서 0 로 설정
    • schedule 시 1 씩 증가
    • ast_sched_del 에서 1 감소
    • ast_sched_runq 에서 수행시킨 만큼 감소
* int ast_sched_wait(struct sched_context *con)
int ast_sched_wait(struct sched_context *con)
{
        /*
         * Return the number of milliseconds
         * until the next scheduled event
         */
        struct timeval tv;
        int ms;
        DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));
        if (!con->schedq) 
                return -1;
        if (gettimeofday(&tv, NULL) < 0) {
                /* This should never happen */
                return 0;
        };
        ms = (con->schedq->when.tv_sec - tv.tv_sec) * 1000;
        ms += (con->schedq->when.tv_usec - tv.tv_usec) / 1000;
        if (ms < 0)
                ms = 0;
        return ms;
}
    • schedule queue 에 아무것도 없으면 return -1
    • 현재의 시간을 tv 에 assign
    • schedule queue 의 첫번째 event 의 when 이 이미 지난 시간이면 return 0
    • 아니면 남은 시간을 return
* int ast_sched_runq(struct sched_context *con)
  • x=0;
  • for
    • schedule queue 에 event 가 없으면 break
    • tv 에 현재 시간 assign
    • 현재 시간 이전으로 when 이 설정된 event 가 있으면
      • current = con->schedq;
      • con->schedq = con->schedq->next;
      • con->schedcnt--;
      • current->callback(current->data)
        • sched_release(con, current);
        • or schedule(con, current);
      • x++;
    • 없으면 break
  • return x;
* chan_sip.c
  • ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL);
  • res = ast_io_wait(io, res);
  • static int sipsock_read(int *id, int fd, short events, void *ignore)
  • handle_request(p, &req, &sin);
  • register_verify(p, sin, req)
  • parse_contact(p, peer, req)
  • p->expire = ast_sched_add(sched, expirey * 1000, expire_register, p);
* int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, void *data)
  • tmp->id = con->eventcnt++;
  • tmp->callback = callback;
  • tmp->data = data;
  • tmp->resched = when;
  • sched_settime(&tmp->when, when)
    • 현재 시간에 when 을 더하여 tmp->when 에 설정
  • schedule(con, tmp);
    • schedq 는 시간 순의 events list 임.
    • 새로 추가하는 event 의 시간과 현재 있는 events 들의 시간을 비교하여 맞는 자리에 추가함.
  • return tmp->id;
* static struct sched *sched_alloc(struct sched_context *con)
static struct sched *sched_alloc(struct sched_context *con)
{
        /*
         * We keep a small cache of schedule entries
         * to minimize the number of necessary malloc()'s
         */
        struct sched *tmp;
#ifdef SCHED_MAX_CACHE
        if (con->schedc) {
                tmp = con->schedc;
                con->schedc = con->schedc->next;
                con->schedccnt--;
        } else
#endif
                tmp = malloc(sizeof(struct sched));
        return tmp;
}
* static inline int sched_settime(struct timeval *tv, int when)
static inline int sched_settime(struct timeval *tv, int when)
{
        if (gettimeofday(tv, NULL) < 0) {
                        /* This shouldn't ever happen, but let's be sure */
                        ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
                        return -1;
        }
        tv->tv_sec += when/1000;
        tv->tv_usec += (when % 1000) * 1000;
        if (tv->tv_usec > 1000000) {
                tv->tv_sec++;
                tv->tv_usec-= 1000000;
        }
        return 0;
}
* static void schedule(struct sched_context *con, struct sched *s)
static void schedule(struct sched_context *con, struct sched *s)
{
        /*
         * Take a sched structure and put it in the
         * queue, such that the soonest event is
         * first in the list.
         */

        struct sched *last=NULL;
        struct sched *current=con->schedq;
        while(current) {
                if (SOONER(s->when, current->when))
                        break;
                last = current;
                current = current->next;
        }
        /* Insert this event into the schedule */
        s->next = current;
        if (last)
                last->next = s;
        else
                con->schedq = s;
        con->schedcnt++;
}
* static void sched_release(struct sched_context *con, struct sched *tmp)
static void sched_release(struct sched_context *con, struct sched *tmp)
{
        /*
         * Add to the cache, or just free() if we
         * already have too many cache entries
         */

#ifdef SCHED_MAX_CACHE
        if (con->schedccnt < SCHED_MAX_CACHE) {
                tmp->next = con->schedc;
                con->schedc = tmp;
                con->schedccnt++;
        } else
#endif
                free(tmp);
}



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2008-08-27 17:52:19
Processing time 0.0106 sec