예제 #1
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;
}
예제 #2
0
static void
s_once_proc(void) {
  char *dbg_lvl_str = getenv("MCCP_LOG_DEBUGLEVEL");
  char *logfile = getenv("MCCP_LOG_FILE");
  uint64_t d = 0;
  mccp_log_destination_t log_dst = MCCP_LOG_EMIT_TO_UNKNOWN;

  if (IS_VALID_STRING(dbg_lvl_str) == true) {
    uint64_t tmp = 0;
    if (mccp_str_parse_uint64(dbg_lvl_str, &tmp) == MCCP_RESULT_OK) {
      d = tmp;
    }
  }
  if ((logfile = s_validate_path(logfile, s_is_valid_path)) != NULL) {
    log_dst = MCCP_LOG_EMIT_TO_FILE;
  }

  if (mccp_log_initialize(log_dst, logfile, false, true, d, 0LL) !=
      MCCP_RESULT_OK) {
    mccp_exit_error(1, "logger initialization error.\n");
  }

  if (d > 0) {
    mccp_msg_debug(d, "Logger debug level is set to: " PF64(u) ".\n", d);
  }
}
예제 #3
0
void
test_idle_force(void) {
  lagopus_result_t r = LAGOPUS_RESULT_ANY_FAILURES;
  lagopus_callout_task_t t = NULL;
  size_t n_exec;
  size_t i;
  callout_arg_t arg = NULL;
  lagopus_callout_task_state_t st;

  arg = s_alloc_arg(10, 0LL);
  TEST_ASSERT_NOT_EQUAL(arg, NULL);

  r = lagopus_callout_create_task(&t, 0, __func__,
                                  callout_task, (void *)arg,
                                  s_freeup_arg);
  TEST_ASSERT_EQUAL(r, LAGOPUS_RESULT_OK);

  r = lagopus_callout_submit_task(&t,
                                  -1LL,
                                  500LL * 1000LL * 1000LL);
  TEST_ASSERT_EQUAL(r, LAGOPUS_RESULT_OK);

  (void)lagopus_chrono_nanosleep(1000LL * 1000LL * 1000LL, NULL);

  for (i = 0; i < 5; i++) {
    lagopus_msg_debug(1, "iter. " PF64(u) "\n", i);

    r = lagopus_callout_task_state(&t, &st);
    TEST_ASSERT_EQUAL(r, LAGOPUS_RESULT_OK);

    if (st == TASK_STATE_ENQUEUED) {
      r = lagopus_callout_exec_task_forcibly(&t);
      if (r == LAGOPUS_RESULT_INVALID_STATE) {
        continue;
      }
      TEST_ASSERT_EQUAL(r, LAGOPUS_RESULT_OK);
    } else if (st == TASK_STATE_UNKNOWN ||
               st == TASK_STATE_CANCELLED) {
      break;
    }

    (void)lagopus_chrono_nanosleep(100LL * 1000LL * 1000LL, NULL);
  }

  n_exec = s_wait_freeup_arg(arg);
  TEST_ASSERT_EQUAL(n_exec, 10);

  s_destroy_arg(arg);
}
예제 #4
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;
}
예제 #5
0
int
main(int argc, const char *const argv[]) {
  lagopus_result_t st = LAGOPUS_RESULT_ANY_FAILURES;
  lagopus_pipeline_stage_t s = NULL;

  size_t nthd = 1;

  (void)argc;

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

  fprintf(stdout, "Creating... ");
  st = lagopus_pipeline_stage_create(&s, 0, "a_test",
                                     nthd,
                                     sizeof(void *), 1024,
                                     s_pre_pause,
                                     s_sched,
                                     s_setup,
                                     s_fetch,
                                     s_main,
                                     s_throw,
                                     s_shutdown,
                                     s_finalize,
                                     s_freeup);
  if (st == LAGOPUS_RESULT_OK) {
    fprintf(stdout, "Created.\n");
    fprintf(stdout, "Setting up... ");
    st = lagopus_pipeline_stage_setup(&s);
    if (st == LAGOPUS_RESULT_OK) {
      fprintf(stdout, "Set up.\n");
      fprintf(stdout, "Starting... ");
      st = lagopus_pipeline_stage_start(&s);
      if (st == LAGOPUS_RESULT_OK) {
        fprintf(stdout, "Started.\n");
        fprintf(stdout, "Opening the front door... ");
        st = global_state_set(GLOBAL_STATE_STARTED);
        if (st == LAGOPUS_RESULT_OK) {
          char buf[1024];
          char *cmd = NULL;
          fprintf(stdout, "The front door is open.\n");

          fprintf(stdout, "> ");
          while (fgets(buf, sizeof(buf), stdin) != NULL &&
                 st == LAGOPUS_RESULT_OK) {
            (void)lagopus_str_trim_right(buf, "\r\n\t ", &cmd);

            if (strcasecmp(cmd, "pause") == 0 ||
                strcasecmp(cmd, "spause") == 0) {
              fprintf(stdout, "Pausing... ");
              if ((st = lagopus_pipeline_stage_pause(&s, -1LL)) ==
                  LAGOPUS_RESULT_OK) {
                if (strcasecmp(cmd, "spause") == 0) {
                  s_set(0LL);
                }
                fprintf(stdout, "Paused " PF64(u) "\n", s_get());
              } else {
                fprintf(stdout, "Failure.\n");
              }
            } else if (strcasecmp(cmd, "resume") == 0) {
              fprintf(stdout, "Resuming... ");
              if ((st = lagopus_pipeline_stage_resume(&s)) ==
                  LAGOPUS_RESULT_OK) {
                fprintf(stdout, "Resumed.\n");
              } else {
                fprintf(stdout, "Failure.\n");
              }
            } else if (strcasecmp(cmd, "get") == 0) {
              fprintf(stdout, PF64(u) "\n", s_get());
            }

            free((void *)cmd);
            cmd = NULL;
            fprintf(stdout, "> ");
          }
          fprintf(stdout, "\nDone.\n");

          fprintf(stdout, "Shutting down... ");
          st = lagopus_pipeline_stage_shutdown(&s, SHUTDOWN_GRACEFULLY);
          if (st == LAGOPUS_RESULT_OK) {
            fprintf(stdout, "Shutdown accepted... ");
            sleep(1);
            s_do_stop = true;
            fprintf(stdout, "Waiting shutdown... ");
            st = lagopus_pipeline_stage_wait(&s, -1LL);
            if (st == LAGOPUS_RESULT_OK) {
              fprintf(stdout, "OK, Shutdown.\n");
            }
          }
        }
      }
    }
  }
  fflush(stdout);

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

  fprintf(stdout, "Destroying... ");
  lagopus_pipeline_stage_destroy(&s);
  fprintf(stdout, "Destroyed.\n");

  return (st == LAGOPUS_RESULT_OK) ? 0 : 1;
}
예제 #6
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;
}
예제 #7
0
static inline lagopus_result_t
s_wait_io_ready(lagopus_cbuffer_t cb,
                lagopus_cond_t *cptr,
                lagopus_chrono_t nsec) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  size_t n_waiters;

  if (cb != NULL && cptr != NULL) {
    if (nsec != 0LL) {

      lagopus_msg_debug(5, "wait " PF64(d) " nsec.\n",
                        nsec);

      (void)__sync_fetch_and_add(&(cb->m_n_waiters), 1);
      ret = lagopus_cond_wait(cptr, &(cb->m_lock), nsec);
      n_waiters = __sync_sub_and_fetch(&(cb->m_n_waiters), 1);

      if (cb->m_is_awakened == true) {
        lagopus_msg_debug(5, "awakened while sleeping " PF64(d) " nsec.\n",
                          nsec);
      } else {
        lagopus_msg_debug(5, "wait " PF64(d) " nsec done.\n",
                          nsec);
      }

      if (ret == LAGOPUS_RESULT_OK &&
          cb->m_is_awakened == true) {
        /*
         * A waker wakes all the waiting threads up. Note that the
         * waker is waiting for a notification that the all the
         * waiters are awakened and leave this function.
         */
        if (cb->m_is_operational == true) {
          if (n_waiters == 0) {

            /*
             * All the waiters are gone. Wake the waker up.
             */

            lagopus_msg_debug(5, "sync wakeup who woke me up.\n");

            cb->m_is_awakened = false;
            (void)lagopus_cond_notify(&(cb->m_cond_awakened), true);
          }
          ret = LAGOPUS_RESULT_WAKEUP_REQUESTED;
        } else {
          cb->m_is_awakened = false;
          (void)lagopus_cond_notify(&(cb->m_cond_awakened), true);
          ret = LAGOPUS_RESULT_NOT_OPERATIONAL;
        }
      }

    } else {
      ret = LAGOPUS_RESULT_OK;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}