text: #include "clock.h"
  #include "stdint.h"
  #include "trap.h"
  #include "platform.h"
  #include "riscv.h"
  #include "sbi.h"
  #include "config.h"
  #include "cpu.h"
  #include "scheduler.h"
  #include "stdio.h"
  
  DEFINE_PER_CPU(system_clock_t,System_S_Clocks);
  
  /**
   * @note cpu`s clock interrupt handler.
   * @param trap_frame
   */
  static void system_s_clock_handler(trap_frame_t * trap_frame){
      /*
       * TOP HALF with irq off
       * and kernel preempt can`t execute
       * because of irq is off.
       */
      thread_t * self = GET_RUNNING_THREAD();
      if(trap_frame!=NULL){
          if(GET_BIT(trap_frame->sstatus,SSTATUS_SPP)){
              // running in kernel mode
              atomic_inc(&self->tms.tms_stime);
              if(self->p_thread!=NULL){
                  atomic_inc(&self->p_thread->tms.tms_cstime);
              }
          }
          else{
              // running in user mode
              atomic_inc(&self->tms.tms_utime);
              if(self->p_thread!=NULL) {
                  atomic_inc(&self->p_thread->tms.tms_cutime);
              }
          }
      }
      system_clock_t * clock = get_cpu_var_no_preempt(System_S_Clocks);
      //the next clock will set in scheduler
      if(clock->status == SYSTEM_CLOCK_STATUS_AVAILABLE){
          clock->counter++;
      }
      else if(clock->status == SYSTEM_CLOCK_STATUS_STOP){
          //STOPPED
      }
      else{
          //DEAD
          system_s_clock_stop();
          trap_unregister(get_cpu_id(),PLATFORM_IRQ_S_TIMER,true);
      }
      if(clock->counter >= clock->scheduler_trigger_number){
          clock->counter = 0;
          // set the resched flag
          threads_set_resched();
      }
      clock->time = r_time();
      sbi_set_timer(clock->time + clock->interval);
  
      /*
       * BOTTOM HALF
       */
  
      // turn on irq...
      intr_on();
  };
  
  /**
   * @note stop cpu local clock
   */
  void inline system_s_clock_stop(){
      w_sie(r_sie() & (~SIE_STIE));
  }
  
  /**
   * @note restart cpu local clock
   */
  void inline system_s_clock_restart(){
      w_sie(r_sie() | SIE_STIE);
      system_s_clock_handler(NULL);
  }
  
  /**
   * @note set new clock ack interval.
   */
  void inline system_s_clock_reset(uint64_t new_interval){
      System_S_Clocks[get_cpu_id()].interval = new_interval ;
      put_cpu_id();
  }
  
  void inline system_s_clcok_set_next(){
      system_clock_t * timer = &System_S_Clocks[get_cpu_id()];
      put_cpu_id();
      timer->time = r_time();
      sbi_set_timer(timer->time + timer->interval);
  }
  
  system_clock_t * system_s_clock_get(){
      return &System_S_Clocks[get_cpu_id()];
  }
  
  void system_s_clock_cpu_init(){
      int cpu = get_cpu_id();
      system_clock_t * clock = &System_S_Clocks[cpu];
      trap_register(cpu, PLATFORM_IRQ_S_TIMER, TRAP_TYPE_IRQ, system_s_clock_handler);
      clock->interval = CONFIG_SYS_S_TIMER_INTERVAL;
      clock->status = SYSTEM_CLOCK_STATUS_AVAILABLE;
      clock->counter = 0;
      clock->time = 0;
      clock->scheduler_trigger_number = CONFIG_TRIGGER_NUMBER;
      w_sie(r_sie() | SIE_STIE);
      clock->time = r_time();
      sbi_set_timer(clock->time + clock->interval);
      put_cpu_id();
  }
  
  
  