DPDK学习(rte_eal_init)

时间:2021-05-16 22:26:37

lcore_config

struct lcore_config {
   unsigned detected;         /**< true if lcore was detected */
   pthread_t thread_id;       /**< pthread identifier */
   int pipe_master2slave[2];  /**< communication pipe with master */
   int pipe_slave2master[2];  /**< communication pipe with master */
   lcore_function_t * volatile f;         /**< function to call */
   void * volatile arg;       /**< argument of function */
   volatile int ret;          /**< return value of function */
   volatile enum rte_lcore_state_t state; /**< lcore state */
   unsigned socket_id;        /**< physical socket id for this lcore */
   unsigned core_id;          /**< core number on socket for this lcore */
   int core_index;            /**< relative index, starting from 0 */
   rte_cpuset_t cpuset;       /**< cpu set which the lcore affinity to */
   uint8_t core_role;         /**< role of core eg: OFF, RTE, SERVICE */
};

extern struct lcore_config lcore_config[RTE_MAX_LCORE];

rte_eal_init()

rte_eal_init() {
    ...
    // 读取/sys/devices/system/cpu/cpuX和/sys/devices/system/node/nodeX中的信息,填充到lcore_config
    rte_eal_cpu_init()
    ...
    /* 解析-c、--master_lcore、--lcores等参数
       确认可用的logical CPU
       调用eal_adjust_config()设置cfg->master_lcore = 0 (设置第一个lcore为MASTER lcore) */
    eal_parse_args() {
        ...
        eal_parse_common_option() {
            ...
            eal_parse_coremask()
            ...
            eal_parse_master_lcore()
            ...
            eal_parse_lcores()
            ...
        }
        ...
        eal_adjust_config()
        ...
    }
    ...
    // 设置当前线程为MASTER lcore,调用eal_thread_set_affinity()绑定MASTER lcore到logical CPU
    eal_thread_init_master() {
        ...
        eal_thread_set_affinity()
        ...
    }
    ...
    /* 为每个SLAVE lcore创建线程,调用eal_thread_loop()->eal_thread_set_affinity()
       绑定SLAVE lcore到logical CPU */
    RTE_LCORE_FOREACH_SLAVE(i) {

        /*
         * create communication pipes between master thread
         * and children
         */
        // MASTER lcore创建pipes用于MASTER和SLAVE lcore间通信(父子线程间通信)
        if (pipe(lcore_config[i].pipe_master2slave) < 0)
            rte_panic("Cannot create pipe\n");
        if (pipe(lcore_config[i].pipe_slave2master) < 0)
            rte_panic("Cannot create pipe\n");

        lcore_config[i].state = WAIT;

        /* create a thread for each lcore */
        ret = pthread_create(&lcore_config[i].thread_id, NULL, eal_thread_loop, NULL);
        ...
    }

    /*
     * Launch a dummy function on all slave lcores, so that master lcore
     * knows they are all ready when this function returns.
     */
    rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
    rte_eal_mp_wait_lcore();
    ...
}

rte_eal_remote_launch()

调用rte_eal_remote_launch()将回调函数和参数注册到lcore_config[].f和lcore_config[].arg中,并通知SLAVE lcore执行该回调函数

/* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the * remote lcore switch in FINISHED state. */
int
rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id)
{
   int n;
   char c = 0;
   int m2s = lcore_config[slave_id].pipe_master2slave[1];
   int s2m = lcore_config[slave_id].pipe_slave2master[0];

   if (lcore_config[slave_id].state != WAIT)
      return -EBUSY;

   // 注册回调函数和参数
   lcore_config[slave_id].f = f;
   lcore_config[slave_id].arg = arg;

   /* send message */
   // 发送信号给SLAVE lcore
   n = 0;
   while (n == 0 || (n < 0 && errno == EINTR))
      n = write(m2s, &c, 1);
   if (n < 0)
      rte_panic("cannot write on configuration pipe\n");

   /* wait ack */
   do {
      n = read(s2m, &c, 1);
   } while (n < 0 && errno == EINTR);

   if (n <= 0)
      rte_panic("cannot read on configuration pipe\n");

   return 0;
}

rte_eal_mp_remote_launch()

/*
 * Check that every SLAVE lcores are in WAIT state, then call
 * rte_eal_remote_launch() for all of them. If call_master is true
 * (set to CALL_MASTER), also call the function on the master lcore.
 */
int
rte_eal_mp_remote_launch(int (*f)(void *), void *arg,
          enum rte_rmt_call_master_t call_master)
{
   int lcore_id;
   int master = rte_get_master_lcore();

   /* check state of lcores */
   // 检查每个SLAVE lcore的状态是否为WAIT
   RTE_LCORE_FOREACH_SLAVE(lcore_id) {
      if (lcore_config[lcore_id].state != WAIT)
         return -EBUSY;
   }

   /* send messages to cores */
   RTE_LCORE_FOREACH_SLAVE(lcore_id) {
      rte_eal_remote_launch(f, arg, lcore_id);
   }

   // 在MASTER lcore上调用该回调函数
   if (call_master == CALL_MASTER) {
      lcore_config[master].ret = f(arg);
      lcore_config[master].state = FINISHED;
   }

   return 0;
}

rte_eal_wait_lcore()

/*
 * Wait until a lcore finished its job.
 */
int
rte_eal_wait_lcore(unsigned slave_id)
{
   if (lcore_config[slave_id].state == WAIT)
      return 0;

   // 等待各个SLAVE lcore执行完毕 
   while (lcore_config[slave_id].state != WAIT &&
          lcore_config[slave_id].state != FINISHED)
      rte_pause();

   rte_rmb();

   /* we are in finished state, go to wait state */
   // 修改SLAVE lcore的状态为WAIT
   lcore_config[slave_id].state = WAIT;
   return lcore_config[slave_id].ret;
}

rte_eal_mp_wait_lcore()

/*
 * Do a rte_eal_wait_lcore() for every lcore. The return values are
 * ignored.
 */
void
rte_eal_mp_wait_lcore(void)
{
   unsigned lcore_id;

   RTE_LCORE_FOREACH_SLAVE(lcore_id) {
      rte_eal_wait_lcore(lcore_id);
   }
}

DPDK学习(rte_eal_init)