Skip to content

Software architecture design

CYRIL INGENIERIE edited this page Sep 10, 2015 · 23 revisions

Architecture

Producer / Consumer

  • One Producer instance per CPU
  • One Consumer instance per CPU

Client / Server

  • One server daemon process
  • Many client processes

Instructions

  • Producer
    One kernel thread bound to a CPU id.
    Cycle_<ArchName>() functions defined in intelfreq.c

  • Consumer
    One user-space thread bound to the same CPU id.
    Core_Cycle() function defined in intelfreq.c

  • Time division
    A single timer which periodically notifies the kernel threads to start execution.
    Cycle_Timer() function defined in intelfreq.c

  • Priority
    1- kernel thread executes first,
    2- user-space thread executes next.

Data

  • Producer
    One private data allocated memory per kernel thread.
    KPRIVATE{} structure defined in intelfreq.h

    One public data allocated memory per kernel thread, shared between the kernel thread and the server thread.
    KPUBLIC{} structure defined in intelfreq.h

    A global data allocated memory shared between the kernel process and the server process.
    PROC{} structure defined in intelapi.h

  • Consumer
    One public data allocated memory per server thread shared with the client processes.
    CPU_STRUCT{} structure defined in corefreq.h

    A global data allocated memory shared between the server and the client processes.
    PROC_STRUCT{} structure defined in corefreq.h

  • Server & Clients
    A data memory space of shared pointers between the server and the client processes.
    SHM_STRUCT{} structure defined in corefreq.h

Algorithm:

1- Kernel thread waits for a completion synchronization in Cycle_<ArchName>() functions.

Cycle_<ArchName>() {    
    wait_for_completion_timeout(&KPrivate->Join[cpu]->Elapsed)
}

2- Timer wakes all kernel threads up through their private completion variable

hrtimer_restart() {
    /* for all CPU */
    complete(&KPrivate->Join[cpu]->Elapsed)
    /* then rearm the timer for a future interruption */
    hrtimer_forward()
}

3- Each kernel thread:

  • reads some Core data, such as:
    counters state. Counters_<ArchName>()
    temperature Core_Thermal()
  • updates the public kernel data structure.
    CORE{} structure defined in intelapi.h
  • synchronizes with the user-space thread.
    BITSET(Core->Sync.V, 0)
  1. Each server thread:
  • waits to start execution in Core_Cycle()
  • sleeps and periodically watches for a kernel synchronization change.
    while(!BITWISEAND(Core->Sync.V, 0x1)) usleep(Proc->msleep * 100)
  • resets the kernel synchronization variable.
    BITCLR(Core->Sync.V, 0)
  • checks if its associated room bit is raised
    ---> if true then selects an alternated flip-flop data memory.
    Cpu->Toggle =! Cpu->Toggle
    and clear the room bit.
    BITCLR(Proc->Room, cpu)
    ---> if false, keeps the current flip-flop data memory.
  • computes some CPU ratios from the public kernel thread data structure.
    CORE{}
  • fills the selected flip-flop data structure with the computed ratios.
    FLIP_FLOP{} sub-structure of CPU_STRUCT{} defined in corefreq.h
  • loops back to the waiting point.
  1. Aggregation Server thread:
  • waits to start execution in Proc_Cycle()
  • sleeps until all room bits are cleared. while(BITWISEAND(Shm->Proc.Room,roomSeed)) usleep(Shm->Proc.msleep * 100);
  • sums the ratios from each CPU alternate flip-flop data structure.
  • sets all room bits to one.
  • computes the average ratios.
  • synchronizes with the client processes.
    BITSET(Shm->Proc.Sync, 0)
  • loops back to the waiting point.
  1. Client process:
  • waits to start execution in corefreq-cli.c
  • sleeps and periodically watches for a server synchronization change.
    while(!BITWISEAND(Shm->Proc.Sync, 0x1) && !Shutdown) usleep(Shm->Proc.msleep * 100); BITCLR(Shm->Proc.Sync, 0);
  • displays CPU ratios and Processor average ratios
  • loops back to the waiting point.
Clone this wiki locally