Ejemplo n.º 1
0
static lagopus_result_t
s_test_thread_main(const lagopus_thread_t *tptr, void *arg) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  lagopus_chrono_t *dates = NULL;

  (void)arg;

  if (tptr != NULL) {
    test_thread_t tt = (test_thread_t)*tptr;


    if (tt != NULL) {
      ssize_t i;
      lagopus_chrono_t now;
      dates = (lagopus_chrono_t *)
              malloc(sizeof(lagopus_chrono_t) * (size_t)tt->m_n_puts);
      if (dates == NULL) {
        goto done;
      }

      /*
       * Ready, steady,
       */
      (void)lagopus_mutex_lock(&(tt->m_start_lock));
      /*
       * go.
       */
      (void)lagopus_mutex_unlock(&(tt->m_start_lock));

      for (i = 0; i < tt->m_n_puts; i++) {
        WHAT_TIME_IS_IT_NOW_IN_NSEC(dates[i]);
      }
      if (lagopus_bbq_put_n(&(tt->m_q), (void **)dates,
                            (size_t)tt->m_n_puts,
                            lagopus_chrono_t, -1LL, NULL) !=
          (lagopus_result_t)tt->m_n_puts) {
        goto done;
      }

      now = -1LL;
      if (lagopus_bbq_put(&(tt->m_q), &now, lagopus_chrono_t, -1LL) !=
          LAGOPUS_RESULT_OK) {
        goto done;
      }
      ret = tt->m_n_puts;

      lagopus_msg_debug(1, "Done, ret = " PFSZS(020, d)
                        ", req = " PFSZS(020, u) ".\n",
                        (size_t)ret, (size_t)tt->m_n_puts);
    }
  }

done:
  free((void *)dates);

  return ret;
}
Ejemplo n.º 2
0
int
main(int argc, const char *const argv[]) {
  size_t i;
  uint64_t zz = 0;
  struct timespec ts0;
  struct timespec ts1;
  struct timespec ts2;
  lagopus_chrono_t now;
  uint64_t start0, start1, start2, end0, end1, end2;

  WHAT_TIME_IS_IT_NOW_IN_NSEC(now);

  NSEC_TO_TS(now, ts0);
  NSEC_TO_TS_MOD(now, ts1);
  NSEC_TO_TS_ASM(now, ts2);

  fprintf(stderr, "ts0: " PF64(u) ", " PF64(u) "\n",
          ts0.tv_sec, ts0.tv_nsec);
  fprintf(stderr, "ts1: " PF64(u) ", " PF64(u) "\n",
          ts1.tv_sec, ts1.tv_nsec);
  fprintf(stderr, "ts2: " PF64(u) ", " PF64(u) "\n",
          ts2.tv_sec, ts2.tv_nsec);

  for (i = 0; i < 1000LL * 1000LL * 1000LL; i++) {
    zz += i;
  }
  fprintf(stderr, "zz = " PF64(u) "\n", zz);

  start0 = lagopus_rdtsc();
  for (i = 0; i < 1000LL * 1000LL * 1000LL; i++) {
    NSEC_TO_TS(i, ts0);
  }
  end0 = lagopus_rdtsc();

  start1 = lagopus_rdtsc();
  for (i = 0; i < 1000LL * 1000LL * 1000LL; i++) {
    NSEC_TO_TS_MOD(i, ts1);
  }
  end1 = lagopus_rdtsc();

  start2 = lagopus_rdtsc();
  for (i = 0; i < 1000LL * 1000LL * 1000LL; i++) {
    NSEC_TO_TS_ASM(i, ts0);
  }
  end2 = lagopus_rdtsc();

  fprintf(stderr, "cur: " PF64(u) "\n", end0 - start0);
  fprintf(stderr, "mod: " PF64(u) "\n", end1 - start1);
  fprintf(stderr, "asm: " PF64(u) "\n", end2 - start2);

  return 0;
}
Ejemplo n.º 3
0
static gallus_result_t
s_ingress_main(const gallus_pipeline_stage_t *sptr,
               size_t idx,
               void *evbuf,
               size_t n_evs) {
  gallus_result_t ret = GALLUS_RESULT_ANY_FAILURES;

  (void)evbuf;
  (void)n_evs;

  if (likely(sptr != NULL && *sptr != NULL)) {
    test_stage_t ts = (test_stage_t)(*sptr);
    base_stage_t bs = (base_stage_t)ts;

    if (likely(bs != NULL && bs->m_next_stg != NULL)) {
      if (likely(ts->m_states[idx] != test_stage_state_done)) {
        gallus_chrono_t start_time;
        uint64_t start_clock;
        uint64_t end_clock;
        uint64_t *addr = ts->m_data + ts->m_enq_infos[idx].m_offset;
        size_t len = ts->m_enq_infos[idx].m_length;

        WHAT_TIME_IS_IT_NOW_IN_NSEC(start_time);

        start_clock = gallus_rdtsc();
        ret = gallus_pipeline_stage_submit((gallus_pipeline_stage_t *)
                                            &(bs->m_next_stg),
                                            (void *)addr, len, (void *)idx);
        end_clock = gallus_rdtsc();

        gallus_atomic_update_min(uint64_t, &(ts->m_start_clock),
                                  0, start_clock);
        gallus_atomic_update_max(uint64_t, &(ts->m_end_clock),
                                  0, end_clock);

        gallus_atomic_update_min(gallus_chrono_t, &(ts->m_start_time),
                                  -1LL, start_time);
        
        ts->m_states[idx] = test_stage_state_done;
        mbar();
      } else {
        ret = s_test_stage_wait(ts);
      }
    } else {
      ret = GALLUS_RESULT_INVALID_ARGS;
    }
  } else {
    ret = GALLUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 4
0
lagopus_result_t
lagopus_cond_wait(lagopus_cond_t *cndptr,
                  lagopus_mutex_t *mtxptr,
                  lagopus_chrono_t nsec) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (mtxptr != NULL &&
      *mtxptr != NULL &&
      cndptr != NULL &&
      *cndptr != NULL) {
    int st;

    errno = 0;
    if (nsec < 0) {
      if ((st = pthread_cond_wait(&((*cndptr)->m_cond),
                                  &((*mtxptr)->m_mtx))) == 0) {
        ret = LAGOPUS_RESULT_OK;
      } else {
        errno = st;
        ret = LAGOPUS_RESULT_POSIX_API_ERROR;
      }
    } else {
      struct timespec ts;
      lagopus_chrono_t now;

      WHAT_TIME_IS_IT_NOW_IN_NSEC(now);
      now += nsec;
      NSEC_TO_TS(now, ts);
    retry:
      errno = 0;
      if ((st = pthread_cond_timedwait(&((*cndptr)->m_cond),
                                       &((*mtxptr)->m_mtx),
                                       &ts)) == 0) {
        ret = LAGOPUS_RESULT_OK;
      } else {
        if (st == EINTR) {
          goto retry;
        } else if (st == ETIMEDOUT) {
          ret = LAGOPUS_RESULT_TIMEDOUT;
        } else {
          errno = st;
          ret = LAGOPUS_RESULT_POSIX_API_ERROR;
        }
      }
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 5
0
static inline lagopus_result_t
s_wait_stage(lagopus_pipeline_stage_t ps, size_t n, lagopus_chrono_t nsec,
             bool is_in_destroy) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (ps != NULL) {
    size_t i;

    if (is_in_destroy == false && nsec > 0) {
      lagopus_chrono_t w_begin;
      lagopus_chrono_t w_end;
      lagopus_chrono_t w = nsec;

      for (ret = LAGOPUS_RESULT_OK, i = 0;
           i < n && ret == LAGOPUS_RESULT_OK && w > 0LL;
           i++) {
        WHAT_TIME_IS_IT_NOW_IN_NSEC(w_begin);
        ret = s_worker_wait(&(ps->m_workers[i]), w);
        WHAT_TIME_IS_IT_NOW_IN_NSEC(w_end);

        if (ret == LAGOPUS_RESULT_OK) {
          w = w_end - w_begin;
        }
      }
    } else {
      for (i = 0; i < n; i++) {
        (void)s_worker_wait(&(ps->m_workers[i]), -1LL);
      }
      ret = LAGOPUS_RESULT_OK;
    }

  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 6
0
lagopus_result_t
lagopus_rwlock_writer_timedlock(lagopus_rwlock_t *rwlptr,
                                lagopus_chrono_t nsec) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (rwlptr != NULL &&
      *rwlptr != NULL) {
    int st;

    if (nsec < 0) {
      if ((st = pthread_rwlock_wrlock(&((*rwlptr)->m_rwl))) == 0) {
        (*rwlptr)->m_prev_cancel_state = -INT_MAX;
        ret = LAGOPUS_RESULT_OK;
      } else {
        errno = st;
        ret = LAGOPUS_RESULT_POSIX_API_ERROR;
      }
    } else {
      struct timespec ts;
      lagopus_chrono_t now;

      WHAT_TIME_IS_IT_NOW_IN_NSEC(now);
      now += nsec;
      NSEC_TO_TS(now, ts);

      if ((st = pthread_rwlock_timedwrlock(&((*rwlptr)->m_rwl),
                                           &ts)) == 0) {
        (*rwlptr)->m_prev_cancel_state = -INT_MAX;
        ret = LAGOPUS_RESULT_OK;
      } else {
        errno = st;
        if (st == ETIMEDOUT) {
          ret = LAGOPUS_RESULT_TIMEDOUT;
        } else {
          ret = LAGOPUS_RESULT_POSIX_API_ERROR;
        }
      }
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 7
0
static lagopus_result_t
callout_task(void *arg) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  lagopus_chrono_t now;

  WHAT_TIME_IS_IT_NOW_IN_NSEC(now);

  lagopus_msg_debug(1, "enter.\n");

  if (likely(arg != NULL)) {
    callout_arg_t carg = (callout_arg_t)arg;
    size_t n_exec = __sync_add_and_fetch(&(carg->m_n_exec), 1);

    lagopus_msg_debug(1, "exec " PFSZ(u) ".\n", n_exec);

    if (carg->m_last_exec_abstime != 0) {
      lagopus_msg_debug(1, "interval: " PF64(d) " nsec.\n",
                        now - carg->m_last_exec_abstime);
    }
    carg->m_last_exec_abstime = now;

    if (carg->m_wait_nsec > 0) {
      lagopus_msg_debug(1, "sleep " PFSZ(u) " nsec.\n",
                        carg->m_wait_nsec);
      (void)lagopus_chrono_nanosleep(carg->m_wait_nsec, NULL);
    }

    if (n_exec < carg->m_n_stop) {
      ret = LAGOPUS_RESULT_OK;
    }
  }

  lagopus_msg_debug(1, "leave.\n");

  return ret;
}
Ejemplo n.º 8
0
gallus_result_t
gallus_module_wait_all(gallus_chrono_t nsec) {
  gallus_result_t ret = GALLUS_RESULT_ANY_FAILURES;

  s_lock();
  {

    s_gstate = MODULE_GLOBAL_STATE_WAITING;

    if (s_n_modules > 0) {
      gallus_result_t first_err = GALLUS_RESULT_OK;
      size_t i;
      a_module *mptr;

      /*
       * Reverse order.
       */

      if (nsec < 0LL) {

        for (i = 0; i < s_n_modules; i++) {
          mptr = &(s_modules[s_n_modules - i - 1]);
          ret = s_wait_module(mptr, -1LL);
          if (ret != GALLUS_RESULT_OK) {
            gallus_perror(ret);
            gallus_msg_error("can't wait module \"%s\".\n",
                              mptr->m_name);
            if (first_err == GALLUS_RESULT_OK) {
              first_err = ret;
            }
          }
          /*
           * Just carry on wait no matter what kind of errors
           * occur.
           */
        }

      } else {

        gallus_chrono_t w_begin;
        gallus_chrono_t w_end;
        gallus_chrono_t w = nsec;

        for (i = 0; i < s_n_modules; i++) {
          mptr = &(s_modules[s_n_modules - i - 1]);
          WHAT_TIME_IS_IT_NOW_IN_NSEC(w_begin);
          ret = s_wait_module(mptr, w);
          WHAT_TIME_IS_IT_NOW_IN_NSEC(w_end);
          if (ret != GALLUS_RESULT_OK) {
            gallus_perror(ret);
            gallus_msg_error("can't wait module \"%s\".\n",
                              mptr->m_name);
            if (first_err == GALLUS_RESULT_OK) {
              first_err = ret;
            }
          }
          /*
           * Just carry on wait no matter what kind of errors
           * occur.
           */
          w = nsec - (w_end - w_begin);
          if (w < 0LL) {
            w = 0LL;
          }
        }
      }

      ret = first_err;

    } else {
      ret = GALLUS_RESULT_OK;
    }

    if (ret == GALLUS_RESULT_OK) {
      s_gstate = MODULE_GLOBAL_STATE_SHUTDOWN;
    }

  }
  s_unlock();

  return ret;
}
Ejemplo n.º 9
0
static inline lagopus_result_t
s_start_callout_main_loop(void) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  global_state_t s;
  shutdown_grace_level_t l;

  ret = global_state_wait_for(GLOBAL_STATE_STARTED, &s, &l, -1LL);
  if (likely(ret == LAGOPUS_RESULT_OK)) {
    if (likely(s == GLOBAL_STATE_STARTED)) {
#ifdef CO_MSG_DEBUG
      lagopus_chrono_t timeout = s_idle_interval;
#else
      lagopus_chrono_t timeout;
#endif /* CO_MSG_DEBUG */

      lagopus_callout_task_t out_tasks[CALLOUT_TASK_MAX * 3];
      size_t n_out_tasks;

      lagopus_callout_task_t urgent_tasks[CALLOUT_TASK_MAX];
      lagopus_result_t sn_urgent_tasks;

      lagopus_callout_task_t idle_tasks[CALLOUT_TASK_MAX];
      lagopus_result_t sn_idle_tasks;

      lagopus_callout_task_t timed_tasks[CALLOUT_TASK_MAX];
      lagopus_result_t sn_timed_tasks;

      lagopus_result_t r;

      lagopus_chrono_t now;
      lagopus_chrono_t next_wakeup;
      lagopus_chrono_t prev_wakeup;

      int cstate = 0;

      WHAT_TIME_IS_IT_NOW_IN_NSEC(prev_wakeup);

      (void)lagopus_mutex_enter_critical(&s_sched_lck, &cstate);
      {
        s_is_stopped = false;
        mbar();

        while (s_do_loop == true) {

          n_out_tasks = 0;

          /*
           * Get the current time.
           */
          WHAT_TIME_IS_IT_NOW_IN_NSEC(now);

#ifdef CO_MSG_DEBUG
          lagopus_msg_debug(3, "now:  " PF64(d) "\n", now);
          lagopus_msg_debug(3, "prv:  " PF64(d) "\n", prev_wakeup);
          lagopus_msg_debug(3, "to:   " PF64(d) "\n", timeout);
#endif /* CO_MSG_DEBUG */

          s_lock_global();
          {

            /*
             * Acquire the global lock to make the task
             * submisson/fetch atomic.
             */

            sn_urgent_tasks = 
                lagopus_bbq_get_n(&s_urgent_tsk_q, (void **)urgent_tasks,
                                  CALLOUT_TASK_MAX, 1LL,
                                  lagopus_callout_task_t,
                                  0LL, NULL);
            sn_idle_tasks = 
                lagopus_bbq_get_n(&s_idle_tsk_q, (void **)idle_tasks,
                                  CALLOUT_TASK_MAX, 1LL,
                                  lagopus_callout_task_t,
                                  0LL, NULL);

          }
          s_unlock_global();

          /*
           * Pack the tasks into a buffer.
           */

          sn_timed_tasks = s_get_runnable_timed_task(now, timed_tasks,
                                                     CALLOUT_TASK_MAX,
                                                     &next_wakeup);
          if (sn_timed_tasks > 0) {
            /*
             * Pack the timed tasks.
             */
            (void)memcpy((void *)(out_tasks + n_out_tasks),
                         timed_tasks,
                         (size_t)(sn_timed_tasks) *
                         sizeof(lagopus_callout_task_t));
            n_out_tasks += (size_t)sn_timed_tasks;

#ifdef CO_MSG_DEBUG
            lagopus_msg_debug(3, "timed task " PF64(u) ".\n",
                              sn_timed_tasks);
            lagopus_msg_debug(3, "nw:   " PF64(d) ".\n",
                              next_wakeup);
#endif /* CO_MSG_DEBUG */

          } else if (sn_timed_tasks < 0) {
            /*
             * We can't be treat this as a fatal error. Carry on.
             */
            lagopus_perror(sn_timed_tasks);
            lagopus_msg_error("timed tasks fetch failed.\n");
          }

          if (sn_urgent_tasks > 0) {
            /*
             * Pack the urgent tasks.
             */
            (void)memcpy((void *)(out_tasks + n_out_tasks),
                         urgent_tasks,
                         (size_t)(sn_urgent_tasks) *
                         sizeof(lagopus_callout_task_t));
            n_out_tasks += (size_t)sn_urgent_tasks;
          } else if (sn_urgent_tasks < 0) {
            /*
             * We can't be treat this as a fatal error. Carry on.
             */
            lagopus_perror(sn_urgent_tasks);
            lagopus_msg_error("urgent tasks fetch failed.\n");
          }

          if (sn_idle_tasks > 0) {
            /*
             * Pack the idle tasks.
             */
            (void)memcpy((void *)(out_tasks + n_out_tasks),
                         idle_tasks,
                         (size_t)(sn_idle_tasks) *
                         sizeof(lagopus_callout_task_t));
            n_out_tasks += (size_t)sn_idle_tasks;
          } else if (sn_idle_tasks < 0) {
            /*
             * We can't be treat this as a fatal error. Carry on.
             */
            lagopus_perror(sn_idle_tasks);
            lagopus_msg_error("idle tasks fetch failed.\n");
          }

          if (n_out_tasks > 0) {
            /*
             * Run/Submit the tasks.
             */
            r = (s_final_task_sched_proc)(out_tasks, now, n_out_tasks);
            if (unlikely(r <= 0)) {
              /*
               * We can't be treat this as a fatal error. Carry on.
               */
              lagopus_perror(r);
              lagopus_msg_error("failed to submit " PFSZ(u) 
                                " urgent/timed tasks.\n", n_out_tasks);
            }
          }

          if (s_idle_proc != NULL &&
              s_next_idle_abstime < (now + CALLOUT_TASK_SCHED_JITTER)) {
            if (likely(s_idle_proc(s_idle_proc_arg) ==
                       LAGOPUS_RESULT_OK)) {
              s_next_idle_abstime = now + s_idle_interval;
            } else {
              /*
               * Stop the main loop and return (clean finish.)
               */
              s_do_loop = false;
              goto critical_end;
            }
          }

          /*
           * fetch the start time of the timed task in the queue head.
           */
          next_wakeup = s_peek_current_wakeup_time();
          if (next_wakeup <= 0LL) {
            /*
             * Nothing in the timed Q.
             */
            if (s_next_idle_abstime <= 0LL) {
              s_next_idle_abstime = now + s_idle_interval;
            }
            next_wakeup = s_next_idle_abstime;
          }

          /*
           * TODO
           *
           *	Re-optimize forcible waje up by timed task submission
           *	timing and times. See also
           *	callout_queue.c:s_do_sched().
           */

          /*
           * calculate the timeout and sleep.
           */
          timeout = next_wakeup - now;
          if (likely(timeout > 0LL)) {
            if (timeout > s_idle_interval) {
              timeout = s_idle_interval;
              next_wakeup = now + timeout;
            }

#ifdef CO_MSG_DEBUG
            lagopus_msg_debug(4,
                              "about to sleep, timeout " PF64(d) " nsec.\n",
                              timeout);
#endif /* CO_MSG_DEBUG */

            prev_wakeup = next_wakeup;

            r = lagopus_bbq_wait_gettable(&s_urgent_tsk_q, timeout);
            if (unlikely(r <= 0 &&
                         r != LAGOPUS_RESULT_TIMEDOUT &&
                         r != LAGOPUS_RESULT_WAKEUP_REQUESTED)) {
              lagopus_perror(r);
              lagopus_msg_error("Event wait failure.\n");
              ret = r;
              goto critical_end;
            } else {
              if (r == LAGOPUS_RESULT_WAKEUP_REQUESTED) {

#ifdef CO_MSG_DEBUG
                lagopus_msg_debug(4, "woke up.\n");
#endif /* CO_MSG_DEBUG */

              }
            }
          } else {
            WHAT_TIME_IS_IT_NOW_IN_NSEC(next_wakeup);

            prev_wakeup = next_wakeup;

#ifdef CO_MSG_DEBUG
            lagopus_msg_debug(4, "timeout zero. contiune.\n");
#endif /* CO_MSG_DEBUG */

          }

          /*
           * The end of the desired potion of the loop.
           */

        } /* while (s_do_loop == true) */

      }
   critical_end:
      s_is_stopped = true;
      s_wakeup_sched();
      (void)lagopus_mutex_leave_critical(&s_sched_lck, cstate);
  
      if (s_do_loop == false) {
        /*
         * The clean finish.
         */
        ret = LAGOPUS_RESULT_OK;
      }

    } else { /* s == GLOBAL_STATE_STARTED */
      s_is_stopped = true;
      ret = LAGOPUS_RESULT_INVALID_STATE_TRANSITION;
    }
  } else {
    s_is_stopped = true;
  }    

  return ret;
}
Ejemplo n.º 10
0
static inline lagopus_chrono_t
s_do_sched(lagopus_callout_task_t t) {
  lagopus_result_t ret = -1LL;
  lagopus_result_t r;
  lagopus_callout_task_t e;

  s_lock_task_q();
  {

    s_lock_task(t);
    {
      if (likely(t->m_is_in_timed_q == false)) {

        /*
         * Firstly (re-)compute the next exeution time of this
         * task.
         */
        if (t->m_is_first == false && t->m_do_repeat == true) {
          t->m_next_abstime = t->m_last_abstime + t->m_interval_time;
        } else {
          WHAT_TIME_IS_IT_NOW_IN_NSEC(t->m_last_abstime);
          t->m_next_abstime = t->m_last_abstime + t->m_initial_delay_time;
        }

        /*
         * Then insert the task into the Q.
         */
        e = TAILQ_FIRST(&s_chrono_tsk_q);
        if (e != NULL) {
          if (e->m_next_abstime > t->m_next_abstime) {
            TAILQ_INSERT_HEAD(&s_chrono_tsk_q, t, m_entry);
          } else {
            for (;
                 e != NULL && e->m_next_abstime <= t->m_next_abstime;
                 e = TAILQ_NEXT(e, m_entry)) {
              ;
            }
            if (e != NULL) {
              TAILQ_INSERT_BEFORE(e, t, m_entry);
            } else {
              TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry);
            }
          }
        } else {
          TAILQ_INSERT_TAIL(&s_chrono_tsk_q, t, m_entry);
        }

        (void)s_set_task_state_in_table(t, TASK_STATE_ENQUEUED);
        t->m_status = TASK_STATE_ENQUEUED;
        t->m_is_in_timed_q = true;

        ret = t->m_next_abstime;

        /*
         * Fianlly wake the master scheduler.
         */
        lagopus_msg_debug(4, "wake the master scheduler up.\n");

        /*
         * TODO
         *
         *	Re-optimize forcible wake up by timed task submission
         *	timing and times. See also
         *	callout.c:s_start_callout_main_loop()
         */

        r = lagopus_bbq_wakeup(&s_urgent_tsk_q, 0LL);
        if (unlikely(r != LAGOPUS_RESULT_OK)) {
          lagopus_perror(r);
          lagopus_msg_error("can't wake the callout task master "
                            "scheduler up.\n");
        }
      }
    }
    s_unlock_task(t);

  }
  s_unlock_task_q();

  return ret;
}
Ejemplo n.º 11
0
static inline lagopus_result_t
s_get_n(lagopus_cbuffer_t *cbptr,
        void *valptr,
        size_t n_vals_max,
        size_t n_at_least,
        size_t valsz,
        lagopus_chrono_t nsec,
        size_t *n_actual_get,
        bool do_incr) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  lagopus_cbuffer_t cb = NULL;

  if (cbptr != NULL && (cb = *cbptr) != NULL &&
      valptr != NULL &&
      valsz == cb->m_element_size) {

    if (n_vals_max > 0) {

      int64_t n_copyout = 0LL;

      if (nsec == 0LL) {

        s_lock(cb);
        {

          /*
           * Just get and return.
           */
          if (cb->m_is_operational == true) {
            n_copyout = ret = s_copyout(cb, valptr, n_vals_max, do_incr);
          } else {
            ret = LAGOPUS_RESULT_NOT_OPERATIONAL;
          }

        }
        s_unlock(cb);

      } else if (nsec < 0LL) {

        s_lock(cb);
        {

          /*
           * Repeat getting until all the required # of the data are got.
           */
        check_inf:
          mbar();
          if (cb->m_is_operational == true) {
            n_copyout += s_copyout(cb,
                                   (void *)((char *)valptr +
                                            ((size_t)n_copyout * valsz)),
                                   n_vals_max - (size_t)n_copyout,
                                   do_incr);
            if ((size_t)n_copyout < n_vals_max) {
              /*
               * Need to repeat.
               */
              if (cb->m_n_elements < 1LL) {
                /*
                 * No data. Need to wait for someone put data to the
                 * buffer.
                 */
                if ((ret = s_wait_gettable(cb, -1LL)) ==
                    LAGOPUS_RESULT_OK) {
                  goto check_inf;
                } else {
                  /*
                   * Any errors occur while waiting.
                   */
                  if (ret == LAGOPUS_RESULT_TIMEDOUT) {
                    /*
                     * Must not happen.
                     */
                    lagopus_msg_fatal("Timed out must not happen here.\n");
                  }
                }
              } else {
                /*
                 * The buffer still has data but it couldn't get all
                 * the data??  Must not happen??
                 */
                lagopus_msg_fatal("Couldn't get all the data even the data "
                                  "available. Must not happen.\n");
              }
            } else {
              /*
               * Succeeded.
               */
              ret = n_copyout;
            }
          } else {
            ret = LAGOPUS_RESULT_NOT_OPERATIONAL;
          }

        }
        s_unlock(cb);

      } else {

        s_lock(cb);
        {

          /*
           * Repeat getting until all the required # of the data are
           * got or the spcified time limit is expired.
           */
          lagopus_chrono_t copy_start;
          lagopus_chrono_t wait_end;
          lagopus_chrono_t to = nsec;

        check_to:
          mbar();
          if (cb->m_is_operational == true) {
            WHAT_TIME_IS_IT_NOW_IN_NSEC(copy_start);
            n_copyout += s_copyout(cb,
                                   (void *)((char *)valptr +
                                            ((size_t)n_copyout * valsz)),
                                   n_vals_max - (size_t)n_copyout,
                                   do_incr);
            if ((size_t)n_copyout < n_at_least) {
              /*
               * Need to repeat.
               */
              if (cb->m_n_elements < 1LL) {
                /*
                 * No data. Need to wait for someone put data to the
                 * buffer.
                 */
                if ((ret = s_wait_gettable(cb, to)) ==
                    LAGOPUS_RESULT_OK) {
                  WHAT_TIME_IS_IT_NOW_IN_NSEC(wait_end);
                  to -= (wait_end - copy_start);
                  if (to > 0LL) {
                    goto check_to;
                  }
                  ret = LAGOPUS_RESULT_TIMEDOUT;
                }
              } else {
                /*
                 * The buffer still has data but it couldn't get all
                 * the data??  Must not happen??
                 */
                lagopus_msg_fatal("Couldn't get all the data even the data "
                                  "available. Must not happen.\n");
              }
            } else {
              /*
               * Succeeded.
               */
              ret = n_copyout;
            }
          } else {
            ret = LAGOPUS_RESULT_NOT_OPERATIONAL;
          }

        }
        s_unlock(cb);

      }

      if (n_actual_get != NULL) {
        *n_actual_get = (size_t)n_copyout;
      }

    } else {
      if (n_actual_get != NULL) {
        *n_actual_get = 0LL;
      }
      ret = LAGOPUS_RESULT_OK;
    }

  } else {
    if (n_actual_get != NULL) {
      *n_actual_get = 0LL;
    }
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 12
0
lagopus_chrono_t
lagopus_chrono_now(void) {
  lagopus_chrono_t ret = 0;
  WHAT_TIME_IS_IT_NOW_IN_NSEC(ret);
  return ret;
}
Ejemplo n.º 13
0
static int
do_run(size_t nthds, ssize_t nputs) {
  int ret = 1;

  lagopus_result_t r;

  size_t i;
  size_t j;
  char thdname[16];

  lagopus_chrono_t *put_dates = NULL;

  size_t n_need_watch = 0;
  size_t n_valid_polls = 0;
  ssize_t qsz;

  test_thread_t tt;
  lagopus_bbq_t bbq;

  lagopus_chrono_t t_begin;
  lagopus_chrono_t t_end;

  lagopus_chrono_t p_begin;
  lagopus_chrono_t p_t;

  ssize_t n_gets = 0;
  lagopus_chrono_t p_min = LLONG_MAX;
  lagopus_chrono_t p_max = LLONG_MIN;
  double p_sum = 0.0;
  double p_sum2 = 0.0;

  double p_avg;
  double p_sd;

  lagopus_chrono_t t_total = 0;
  double t_avg;

  /*
   * This is only for choking clang/scan-build.
   */
  WHAT_TIME_IS_IT_NOW_IN_NSEC(t_begin);

  put_dates = (lagopus_chrono_t *)
              malloc(sizeof(lagopus_chrono_t) * (size_t)nputs);
  if (put_dates == NULL) {
    goto done;
  }

  if ((r = lagopus_mutex_create(&start_lock)) != LAGOPUS_RESULT_OK) {
    lagopus_perror(r);
    goto done;
  }
  if ((r = lagopus_mutex_create(&stop_lock)) != LAGOPUS_RESULT_OK) {
    lagopus_perror(r);
    goto done;
  }

  /*
   * Create the qmuxer.
   */
  if ((r = lagopus_qmuxer_create(&qmx)) != LAGOPUS_RESULT_OK) {
    lagopus_perror(r);
    goto done;
  }

  /*
   * Then create queues.
   */
  bbqs = (lagopus_bbq_t *)malloc(sizeof(lagopus_bbq_t) * nthds);
  if (bbqs == NULL) {
    goto done;
  }
  for (i = 0; i < nthds; i++) {
    if ((r = lagopus_bbq_create(&(bbqs[i]), lagopus_chrono_t,
                                1000LL * 1000LL,
                                NULL)) != LAGOPUS_RESULT_OK) {
      lagopus_perror(r);
      goto done;
    }
    n_created_bbqs++;
  }
  if (n_created_bbqs == 0) {
    goto done;
  }

  /*
   * Then create poll objects for the each queue.
   */
  polls = (lagopus_qmuxer_poll_t *)malloc(sizeof(lagopus_qmuxer_poll_t) *
                                          n_created_bbqs);
  if (polls == NULL) {
    goto done;
  }
  for (i = 0; i < n_created_bbqs; i++) {
    if ((r = lagopus_qmuxer_poll_create(&(polls[i]),
                                        bbqs[i],
                                        LAGOPUS_QMUXER_POLL_READABLE)) !=
        LAGOPUS_RESULT_OK) {
      lagopus_perror(r);
      goto done;
    }
    n_created_polls++;
  }
  if (n_created_polls == 0) {
    goto done;
  }

  /*
   * Then create threads for the each poll objects/queues.
   */
  tts = (test_thread_record *)malloc(sizeof(test_thread_record) *
                                     n_created_polls);
  if (tts == NULL) {
    goto done;
  }
  for (i = 0; i < n_created_polls; i++) {
    snprintf(thdname, sizeof(thdname), "putter " PFSZS(4, u), i);
    tt = &(tts[i]);
    if (test_thread_create(&tt, start_lock, bbqs[i], nputs,
                           (const char *)thdname) != true) {
      goto done;
    }
    n_created_thds++;
  }
  if (n_created_thds == 0) {
    goto done;
  }

  /*
   * Let the initiation begin.
   */

  /*
   * Ready, note that all the created threads do this lock.
   */
  (void)lagopus_mutex_lock(&start_lock);

  /*
   * Steady,
   */
  for (i = 0; i < n_created_thds; i++) {
    tt = &(tts[i]);
    if (lagopus_thread_start((lagopus_thread_t *)&tt, false) !=
        LAGOPUS_RESULT_OK) {
      (void)lagopus_mutex_unlock(&start_lock);
      goto done;
    }
  }

  fprintf(stdout, "Test for " PFSZ(u) " threads " PFSZ(u)
          " events/thdread start.\n", n_created_thds, (size_t)nputs);

  /*
   * Go.
   */
  (void)lagopus_mutex_unlock(&start_lock);

  WHAT_TIME_IS_IT_NOW_IN_NSEC(t_begin);

  while (true) {
    /*
     * Like the select(2)/poll(2), initialize poll objects before
     * checking events.
     */
    n_need_watch = 0;
    n_valid_polls = 0;
    for (i = 0; i < n_created_thds; i++) {
      /*
       * Check if the poll has a valid queue.
       */
      bbq = NULL;
      if ((r = lagopus_qmuxer_poll_get_queue(&(polls[i]), &bbq)) !=
          LAGOPUS_RESULT_OK) {
        lagopus_perror(r);
        break;
      }
      if (bbq != NULL) {
        n_valid_polls++;
      }

      /*
       * Reset the poll status.
       */
      if ((r = lagopus_qmuxer_poll_reset(&(polls[i]))) != LAGOPUS_RESULT_OK) {
        lagopus_perror(r);
        break;
      }
      n_need_watch++;
    }

    /*
     * If there are no valid queues, exit.
     */
    if (n_valid_polls == 0) {
      break;
    }

    /*
     * Wait for an event.
     *
     *  Note that we better set timeout, not waiting forever.
     */
    r = lagopus_qmuxer_poll(&qmx, (lagopus_qmuxer_poll_t *const)polls,
                            n_need_watch,
                            100LL * 1000LL * 1000LL);

    if (r > 0) {
      /*
       * Check which poll got an event. Actually, check all the queues
       * in this sample.
       */
      size_t n_actual_get = 0LL;

      for (i = 0; i < n_created_thds; i++) {

        if ((qsz = lagopus_bbq_size(&(bbqs[i]))) > 0) {

          lagopus_msg_debug(1, "Got " PFSZS(8, u) " events from the Q"
                            PFSZS(03, u) ".\n",
                            (size_t)qsz, (size_t)i);
          if ((r = lagopus_bbq_get_n(&(bbqs[i]), (void **)put_dates,
                                     (size_t)nputs, 1LL,
                                     lagopus_chrono_t,
                                     1000LL * 1000LL * 1000LL,
                                     &n_actual_get)) > 0) {
#if 1
            WHAT_TIME_IS_IT_NOW_IN_NSEC(p_begin);
#endif
            for (j = 0; j < n_actual_get; j++) {
              /*
               * In this sample, -1LL is kinda 'EOF'. Check if we got
               * the EOF.
               */
              if (put_dates[j] == -1LL) {
                /*
                 * The queue is kinda 'closed'. From now on we don't
                 * check this queue anymore. To specify this:
                 */
                lagopus_msg_debug(1, "Got an EOF from the Q" PFSZS(04, u)
                                  ".\n", i);
                goto nullify;
              }

#if 0
              WHAT_TIME_IS_IT_NOW_IN_NSEC(p_begin);
#endif

              p_t = p_begin - put_dates[j];

              if (p_t < p_min) {
                p_min = p_t;
              }
              if (p_t > p_max) {
                p_max = p_t;
              }
              p_sum += (double)p_t;
              p_sum2 += ((double)p_t * (double)p_t);
              n_gets++;
            }

          } else {
            /*
             * Something wrong for the queue. But we must not exit
             * here. Keep on checking other queues. In order to do
             * this, set NULL as the queue into the poll object for
             * the queue.
             */
            lagopus_perror(r);
          nullify:
            if ((r = lagopus_qmuxer_poll_set_queue(&(polls[i]), NULL)) ==
                LAGOPUS_RESULT_OK) {
              lagopus_msg_debug(1, "Q" PFSZS(04, u) " is not valid "
                                "anymore, ignore the queue.\n", i);
              break;
            } else {
              /*
               * There is nothing we can do now.
               */
              lagopus_perror(r);
              goto done;
            }
          }

        }

      }

    } else if (r == LAGOPUS_RESULT_TIMEDOUT) {
      lagopus_msg_debug(1, "Timedout. continue.\n");
      continue;
    } else {
      lagopus_perror(r);
      lagopus_msg_debug(1, "Break the loop due to error(s).\n");
      goto done;
    }
  }

  ret = 0;

done:

  WHAT_TIME_IS_IT_NOW_IN_NSEC(t_end);

  if (is_signaled == false) {
    fprintf(stdout, "Done.\n");
  } else {
    fprintf(stdout, "Stopped.\n");
  }

  fprintf(stdout, "Total # of the events:\t" PFSZS(22, u) "\n\n", n_gets);

  p_avg = p_sum / (double)n_gets;
  p_sd = (p_sum2 -
          2.0 * p_avg * p_sum +
          p_avg * p_avg * (double)n_gets) / (double)(n_gets - 1);
  p_sd = sqrt(p_sd);

  fprintf(stdout, "Queue stats:\n");
  fprintf(stdout, "wait time min =\t" PFSZS(22, d) " nsec.\n", p_min);
  fprintf(stdout, "wait time max =\t" PFSZS(22, d) " nsec.\n", p_max);
  fprintf(stdout, "wait time avg =\t%25.2f nsec.\n", p_avg);
  fprintf(stdout, "wait time sd =\t%25.2f.\n\n", p_sd);

  t_total = t_end - t_begin;
  t_avg = (double)t_total / (double)n_gets;

  fprintf(stdout, "Throughput:\n");
  fprintf(stdout, "total time:\t" PFSZS(22, d) " msec.\n",
          (size_t)(t_total / 1000LL / 1000LL));
  fprintf(stdout, "total avg:\t%25.2f nsec/event.\n", t_avg);

  s_destroy_all();

  free((void *)put_dates);

  return ret;
}
Ejemplo n.º 14
0
static gallus_result_t
s_intermediate_main(const gallus_pipeline_stage_t *sptr,
                    size_t idx,
                    void *evbuf,
                    size_t n_evs) {
  gallus_result_t ret = GALLUS_RESULT_ANY_FAILURES;

  if (likely(sptr != NULL && *sptr != NULL)) {
    test_stage_t ts = (test_stage_t)(*sptr);
    size_t n_cur_evs = __sync_add_and_fetch(&(ts->m_n_events), 0);

    if (likely(n_cur_evs < ts->m_n_data)) {
      uint64_t *data = (uint64_t *)evbuf;
      size_t i;
      size_t j;
      uint64_t sum = 0;

      if (unlikely(ts->m_states[idx] == test_stage_state_initialized)) {
        uint64_t cur_clock = gallus_rdtsc();
        gallus_atomic_update_min(uint64_t, &(ts->m_start_clock),
                                  0, cur_clock);
        ts->m_states[idx] = test_stage_state_running;
      }

      for (i = 0; i < ts->m_weight; i++) {
        sum = 0;
        for (j = 0; j < n_evs; j++) {
          sum += data[j];
        }
      }

      (void)__sync_add_and_fetch(&(ts->m_sum), sum);
      n_cur_evs = __sync_add_and_fetch(&(ts->m_n_events), n_evs);

      if (unlikely(ts->m_n_data == n_cur_evs)) {
        uint64_t cur_clock = gallus_rdtsc();
        gallus_chrono_t end_time;

        WHAT_TIME_IS_IT_NOW_IN_NSEC(end_time);

        gallus_msg_debug(1, "got " PFSZ(u) " / " PFSZ(u)"  events.\n",
                          n_cur_evs, ts->m_n_data);

        gallus_atomic_update_min(uint64_t, &(ts->m_end_clock),
                                  0, cur_clock);

        gallus_atomic_update_max(gallus_chrono_t, &(ts->m_end_time),
                                  -1, end_time);

        ts->m_states[idx] = test_stage_state_done;
        mbar();

        if (ts->m_type == test_stage_type_egress) {
          /*
           * Wake the master up.
           */
          (void)s_test_stage_wakeup(ts);
        }
      }

      ret = (gallus_result_t)n_evs;

    } else {
      ret = s_test_stage_wait(ts);
    }
  } else {
    ret = GALLUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
Ejemplo n.º 15
0
lagopus_result_t
lagopus_module_wait_all(lagopus_chrono_t nsec) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  s_lock();
  {
    if (s_n_modules > 0) {
      lagopus_result_t first_err = LAGOPUS_RESULT_OK;
      size_t i;
      a_module *mptr;

      /*
       * Reverse order.
       */

      if (nsec < 0LL) {

        for (i = 0; i < s_n_modules; i++) {
          mptr = &(s_modules[s_n_modules - i - 1]);
          ret = s_wait_module(mptr, -1LL);
          if (ret != LAGOPUS_RESULT_OK) {
            lagopus_perror(ret);
            lagopus_msg_error("can't wait module \"%s\".\n",
                              mptr->m_name);
            if (first_err == LAGOPUS_RESULT_OK) {
              first_err = ret;
            }
          }
          /*
           * Just carry on wait no matter what kind of errors
           * occur.
           */
        }

      } else {

        lagopus_chrono_t w_begin;
        lagopus_chrono_t w_end;
        lagopus_chrono_t w = nsec;

        for (i = 0; i < s_n_modules; i++) {
          mptr = &(s_modules[s_n_modules - i - 1]);
          WHAT_TIME_IS_IT_NOW_IN_NSEC(w_begin);
          ret = s_wait_module(mptr, w);
          WHAT_TIME_IS_IT_NOW_IN_NSEC(w_end);
          if (ret != LAGOPUS_RESULT_OK) {
            lagopus_perror(ret);
            lagopus_msg_error("can't wait module \"%s\".\n",
                              mptr->m_name);
            if (first_err == LAGOPUS_RESULT_OK) {
              first_err = ret;
            }
          }
          /*
           * Just carry on wait no matter what kind of errors
           * occur.
           */
          w = nsec - (w_end - w_begin);
          if (w < 0LL) {
            w = 0LL;
          }
        }
      }

      ret = first_err;

    } else {
      ret = LAGOPUS_RESULT_OK;
    }
  }
  s_unlock();

  return ret;
}
Ejemplo n.º 16
0
int
main(int argc, const char *const argv[]) {
  lagopus_result_t st = LAGOPUS_RESULT_ANY_FAILURES;
  test_stage_t t = NULL;
  size_t tmp;

  size_t nthd = 1;
  size_t c_max = 1000LL * 1000LL * 100LL;
  size_t mod = 0;

  lagopus_chrono_t t_begin;
  lagopus_chrono_t t_end;
  lagopus_chrono_t t_total;

  (void)argc;

  WHAT_TIME_IS_IT_NOW_IN_NSEC(t_begin);

  if (IS_VALID_STRING(argv[1]) == true) {
    if (lagopus_str_parse_uint64(argv[1], &tmp) == LAGOPUS_RESULT_OK &&
        tmp > 0LL) {
      nthd = tmp;
    }
    if (IS_VALID_STRING(argv[2]) == true) {
      if (lagopus_str_parse_uint64(argv[2], &tmp) == LAGOPUS_RESULT_OK &&
          tmp > 0LL) {
        c_max = tmp;
      }
      if (IS_VALID_STRING(argv[3]) == true) {
        if (lagopus_str_parse_uint64(argv[3], &tmp) == LAGOPUS_RESULT_OK) {
          mod = tmp;
        }
      }
    }
  }

  st = lagopus_pipeline_stage_create((lagopus_pipeline_stage_t *)&t,
                                     sizeof(*t), "a_test",
                                     nthd,
                                     sizeof(void *), 1024,
                                     s_pre_pause,
                                     s_sched,
                                     s_setup,
                                     /* s_fetch, */ NULL,
                                     s_main,
                                     /* s_throw, */ NULL,
                                     s_shutdown,
                                     s_finalize,
                                     s_freeup);
  if (st == LAGOPUS_RESULT_OK) {
    t->m_n_max_count = c_max;
    t->m_mod = mod;

    st = lagopus_pipeline_stage_setup((lagopus_pipeline_stage_t *)&t);
    if (st == LAGOPUS_RESULT_OK) {
      st = lagopus_pipeline_stage_start((lagopus_pipeline_stage_t *)&t);
      if (st == LAGOPUS_RESULT_OK) {
        WHAT_TIME_IS_IT_NOW_IN_NSEC(t_begin);
        st = global_state_set(GLOBAL_STATE_STARTED);
        if (st == LAGOPUS_RESULT_OK) {
          sleep(1);
          st = lagopus_pipeline_stage_shutdown((lagopus_pipeline_stage_t *)&t,
                                               SHUTDOWN_GRACEFULLY);
          if (st == LAGOPUS_RESULT_OK) {
            st = lagopus_pipeline_stage_wait((lagopus_pipeline_stage_t *)&t,
                                             -1LL);
          }
        }
      }
    }
  }

  WHAT_TIME_IS_IT_NOW_IN_NSEC(t_end);

  t_total = t_end - t_begin;

  if (st != LAGOPUS_RESULT_OK) {
    lagopus_perror(st);
  }

  fprintf(stdout,
          "total %f sec.\n\n"
          "single thd throughput: %f Mops/s\n"
          "total throuput:        %f Mops/s\n\n"

          "%f nsec/op\n",

          (double)t_total / 1000.0 / 1000.0 / 1000.0,
          (double)c_max / (double)t_total * 1000.0,
          (double)c_max * (double)nthd / (double)t_total * 1000.0,
          (double)t_total / (double)c_max);

  return (st == LAGOPUS_RESULT_OK) ? 0 : 1;
}