lwip-1.3.2.cの分析

12630 ワード

sys_arch:
sys.c:sys_などのosに関連する部分を呼び出すシステム抽象層arch_timeouts, sys_arch_mbox_fetchなど、lwipではsys_arch_名前の先頭にある、
「LwIPマイグレーションを容易にするために、オペレーティングシステムに属する関数呼び出しやデータ構造は、コードで直接使用されるのではなく、オペレーティングシステムシミュレーション層でこれらの関数の使用を代替する.オペレーティングシステムシミュレーション層は、タイマ、プロセス同期、メッセージングメカニズムなどのシステムサービスを提供するために統一されたインターフェースを使用する.原則として、LwIPをマイグレーションするには、目的に応じてスケールオペレーティングシステムはシミュレーションレイヤ実装を修正すればよい.TCPで使用されるタイマ機能は、オペレーティングシステムシミュレーション層によって提供される.このタイマは、少なくとも200 msの時間間隔を有する単一パルスタイマである(one-shot timer、単一パルスタイマとは、クロックが起動すると、メモリレジスタの値をカウンタに複素化し、結晶の各パルスがカウンタを1減少させることを指す.0に減少すると、割り込みが発生し、ソフトウェアが再起動するまで動作を停止し、時間オーバーフローが発生すると登録された関数が呼び出される.プロセス同期メカニズムは、信号量のみを提供します.信号量が最下位のオペレーティングシステムによってサポートされていなくても、条件変数やロックなどの他のベースの同期方式を使用してシミュレーションすることができる.メッセージングは、メールボックスと呼ばれる抽象的な方法を使用する簡単なメカニズムによって実現される.メールボックスには2つの操作があります.郵便(post)と抽出(fetch)では、郵便操作がプロセスをブロックしません.逆に、メールボックスに送信されたメッセージは、他のプロセスが取り出すまでシステムシミュレーション層としてキューに配置されます.最下位のオペレーティングシステム自体がメールボックスメカニズムをサポートしていない場合でも、信号量を採用することは容易です.」
sys_arch_timeouts
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/*   lwip       ,     */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
struct sys_timeouts *sys_arch_timeouts(void);

sys.c:
sys_timeout
/**
 * Create a one-shot timer (aka timeout). Timeouts are processed in the
 * following cases:
 * - while waiting for a message using sys_mbox_fetch()
 * - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout()
 * - while sleeping using the inbuilt sys_msleep()
 *
 * @param msecs time in milliseconds after that the timer should expire
 * @param h callback function to call when msecs have elapsed
 * @param arg argument to pass to the callback function
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/* lwip        , arp_timer igmp_timer    */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
  struct sys_timeouts *timeouts;
  struct sys_timeo *timeout, *t;

  timeout = memp_malloc(MEMP_SYS_TIMEOUT);
  if (timeout == NULL) {
    LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL);
    return;
  }
  timeout->next = NULL;
  timeout->h = h;
  timeout->arg = arg;
  timeout->time = msecs;

  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  /*   lwip        */
  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  timeouts = sys_arch_timeouts();

  LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p
", (void *)timeout, msecs, *(void**)&h, (void *)arg)); if (timeouts == NULL) { LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL); return; } if (timeouts->next == NULL) { timeouts->next = timeout; return; } /* BEGIN: Added by zhengxiang, 2013/10/2 PN:lwip_comment */ /* timeout lwip */ /* END: Added by zhengxiang, 2013/10/2 PN:lwip_comment */ if (timeouts->next->time > msecs) { timeouts->next->time -= msecs; timeout->next = timeouts->next; timeouts->next = timeout; } else { for(t = timeouts->next; t != NULL; t = t->next) { timeout->time -= t->time; if (t->next == NULL || t->next->time > timeout->time) { if (t->next != NULL) { t->next->time -= timeout->time; } timeout->next = t->next; t->next = timeout; break; } } } }

sys_untimeout
/**
 * Go through timeout list (for this task only) and remove the first matching
 * entry, even though the timeout has not triggered yet.
 *
 * @note This function only works as expected if there is only one timeout
 * calling 'h' in the list of timeouts.
 *
 * @param h callback function that would be called by the timeout
 * @param arg callback argument that would be passed to h
*/
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/*  h arg         */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
sys_untimeout(sys_timeout_handler h, void *arg)
{
  struct sys_timeouts *timeouts;
  struct sys_timeo *prev_t, *t;

  timeouts = sys_arch_timeouts();

  if (timeouts == NULL) {
    LWIP_ASSERT("sys_untimeout: timeouts != NULL", timeouts != NULL);
    return;
  }
  if (timeouts->next == NULL) {
    return;
  }

  for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
    if ((t->h == h) && (t->arg == arg)) {
      /* We have a match */
      /* Unlink from previous in list */
      if (prev_t == NULL) {
        timeouts->next = t->next;
      } else {
        prev_t->next = t->next;
      }
      /* If not the last one, add time of this one back to next */
      if (t->next != NULL) {
        t->next->time += t->time;
      }
      memp_free(MEMP_SYS_TIMEOUT, t);
      return;
    }
  }
  return;
}

sys_sem_wait
/**
 * Wait (forever) for a semaphore to become available.
 * While waiting, timeouts (for this thread) are processed.
 *
 * @param sem semaphore to wait for
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/* forever     semaphore,      ,lwip            */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
void
sys_sem_wait(sys_sem_t sem)
{
  u32_t time_needed;
  struct sys_timeouts *timeouts;
  struct sys_timeo *tmptimeout;
  sys_timeout_handler h;
  void *arg;

 again:

  timeouts = sys_arch_timeouts();

  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  /*   lwip       , sys_arch_sem_wait(sem, 0)     0,          */
  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  if (!timeouts || !timeouts->next) {
    sys_arch_sem_wait(sem, 0);
  } else {
    /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
    /*               ,       ,  sys_arch_sem_wait */
    /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
    if (timeouts->next->time > 0) {
	  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
	  /* time_needed:               */
	  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
      time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
    } else {
      time_needed = SYS_ARCH_TIMEOUT;
    }

	/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
	/* SYS_ARCH_TIMEOUT             ,          ,    (forever   ) */
	/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
    if (time_needed == SYS_ARCH_TIMEOUT) {
      /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
        could be fetched. We should now call the timeout handler and
        deallocate the memory allocated for the timeout. */
      tmptimeout = timeouts->next;
      timeouts->next = tmptimeout->next;
      h = tmptimeout->h;
      arg = tmptimeout->arg;
      memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
      if (h != NULL) {
        LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)
", *(void**)&h, (void *)arg)); h(arg); } /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ /* BEGIN: Added by zhengxiang, 2013/10/2 PN:lwip_comment */ /* , */ /* ?: , , ?contact me:[email protected] */ /* END: Added by zhengxiang, 2013/10/2 PN:lwip_comment */ if (time_needed < timeouts->next->time) { timeouts->next->time -= time_needed; } else { timeouts->next->time = 0; } } } }

sys_sem_wait_timeout
/**
 * Wait for a semaphore with timeout (specified in ms)
 *
 * @param sem semaphore to wait
 * @param timeout timeout in ms (0: wait forever)
 * @return 0 on timeout, 1 otherwise
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/*              */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
int
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
{
  struct sswt_cb sswt_cb;

  sswt_cb.psem = &sem;
  sswt_cb.timeflag = 0;

  /* If timeout is zero, then just wait forever */
  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  /*       ,  sys_timeout lwip          */
  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  if (timeout > 0) {
    /* Create a timer and pass it the address of our flag */
    sys_timeout(timeout, sswt_handler, &sswt_cb);
  }

  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  /*   sswt_handler   ,         ,    sys_sem_wait    forever    */
  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
  sys_sem_wait(sem);
  /* Was it a timeout? */
  if (sswt_cb.timeflag) {
    /* timeout */
    return 0;
  } else {
    /* Not a timeout. Remove timeout entry */
    sys_untimeout(sswt_handler, &sswt_cb);
    return 1;
  }
}

sswt_handler
/**
 * Timeout handler function for sys_sem_wait_timeout()
 *
 * @param arg struct sswt_cb* used to signal a semaphore and end waiting.
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/*              */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
static void
sswt_handler(void *arg)
{
  struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;

  /* Timeout. Set flag to TRUE and signal semaphore */
  sswt_cb->timeflag = 1;
  sys_sem_signal(*(sswt_cb->psem));
}

sys_msleep
/**
 * Sleep for some ms. Timeouts are processed while sleeping.
 *
 * @param ms number of milliseconds to sleep
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/*   some ms,            ,   sys_sem_wait_timeout      */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
void
sys_msleep(u32_t ms)
{
  sys_sem_t delaysem = sys_sem_new(0);

  sys_sem_wait_timeout(delaysem, ms);

  sys_sem_free(delaysem);
}

sys_mbox_fetch
/**
 * Wait (forever) for a message to arrive in an mbox.
 * While waiting, timeouts (for this thread) are processed.
 *
 * @param mbox the mbox to fetch the message from
 * @param msg the place to store the message
 */
/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
/* forever         message,      lwip           */
/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
  u32_t time_needed;
  struct sys_timeouts *timeouts;
  struct sys_timeo *tmptimeout;
  sys_timeout_handler h;
  void *arg;

 again:
  timeouts = sys_arch_timeouts();

  if (!timeouts || !timeouts->next) {
    UNLOCK_TCPIP_CORE();
	/* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
	/*    0,        message */
	/* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
    time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
    LOCK_TCPIP_CORE();
  } else {
    if (timeouts->next->time > 0) {
      UNLOCK_TCPIP_CORE();
	  /* BEGIN: Added by zhengxiang, 2013/10/2   PN:lwip_comment */
	  /*   lwip          (    )    ,       */
	  /* END:   Added by zhengxiang, 2013/10/2   PN:lwip_comment */
      time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
      LOCK_TCPIP_CORE();
    } else {
      time_needed = SYS_ARCH_TIMEOUT;
    }

    if (time_needed == SYS_ARCH_TIMEOUT) {
      /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
         could be fetched. We should now call the timeout handler and
         deallocate the memory allocated for the timeout. */
      tmptimeout = timeouts->next;
      timeouts->next = tmptimeout->next;
      h   = tmptimeout->h;
      arg = tmptimeout->arg;
      memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
      if (h != NULL) {
        LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)
", *(void**)&h, arg)); h(arg); } /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < timeouts->next->time) { timeouts->next->time -= time_needed; } else { timeouts->next->time = 0; } } } }