Advertisement
Guest User

libperfcount.c

a guest
Dec 31st, 2015
794
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.94 KB | None | 0 0
  1. /* Includes */
  2. #include "libperfcount.h"
  3. #include <ctype.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #define __USE_GNU
  11. #include <sched.h>
  12.  
  13.  
  14. /* Data Structures */
  15. struct UMASK;
  16. typedef struct UMASK UMASK;
  17. struct EVENT;
  18. typedef struct EVENT EVENT;
  19.  
  20. struct UMASK{
  21.     uint64_t      umaskVal;
  22.     const char*   name;
  23. };
  24. struct EVENT{
  25.     uint64_t      evtNum;
  26.     const UMASK*  umasks;
  27.     const char*   name;
  28. };
  29.  
  30.  
  31. /* Global data */
  32. static int cfgFd = -1;
  33. static int cntFd = -1;
  34.  
  35. static const struct UMASK UMASK_LIST[] = {
  36.     {0x02, "store_forward"},        /*   0 */ /* 0x03 */
  37.     {0x08, "no_sr"},
  38.     {0x00, NULL},
  39.     {0x01, "loads"},                /*   3 */ /* 0x05 */
  40.     {0x02, "stores"},
  41.     {0x00, NULL},
  42.     {0x01, "address_alias"},        /*   6 */ /* 0x07 */
  43.     {0x00, NULL},
  44.     {0x01, "miss_causes_a_walk"},   /*   8 */ /* 0x08 */
  45.     {0x02, "walk_completed_4k"},
  46.     {0x04, "walk_completed_2m_4m"},
  47.     {0x0e, "walk_completed"},
  48.     {0x10, "walk_duration"},
  49.     {0x20, "stlb_hit_4k"},
  50.     {0x40, "stlb_hit_2m"},
  51.     {0x60, "stlb_hit"},
  52.     {0x80, "pde_cache_miss"},
  53.     {0x00, NULL},
  54.     {0x03, "recovery_cycles"},      /*  18 */ /* 0x0D */
  55.     {0x00, NULL},
  56.     {0x01, "any"},                  /*  20 */ /* 0x0E */
  57.     {0x10, "flags_merge"},
  58.     {0x20, "slow_lea"},
  59.     {0x40, "single_mul"},
  60.     {0x00, NULL},
  61.     {0x21, "demand_data_rd_miss"},  /*  25 */ /* 0x24 */
  62.     {0x41, "demand_data_rd_hit"},
  63.     {0xE1, "all_demand_data_rd"},
  64.     {0x42, "rfo_hit"},
  65.     {0x22, "rfo_miss"},
  66.     {0xE2, "all_rfo"},
  67.     {0x44, "code_rd_hit"},
  68.     {0x24, "code_rd_miss"},
  69.     {0x27, "all_demand_miss"},
  70.     {0xE7, "all_demand_references"},
  71.     {0xE4, "all_code_rd"},
  72.     {0x50, "l2_pf_hit"},
  73.     {0x30, "l2_pf_miss"},
  74.     {0xF8, "all_pf"},
  75.     {0x3F, "miss"},
  76.     {0xFF, "references"},
  77.     {0x00, NULL},
  78.     {0x50, "wb_hit"},               /*  42 */ /* 0x27 */
  79.     {0x00, NULL},
  80.     {0x4F, "reference"},            /*  44 */ /* 0x2E */
  81.     {0x41, "miss"},
  82.     {0x00, NULL},
  83.     {0x00, "core_clk"},             /*  47 */ /* 0x3C */
  84.     {0x01, "ref_xclk"},
  85.     {0x00, NULL},
  86.     {0x01, "pending"},              /*  50 */ /* 0x48 */
  87.     {0x00, NULL},
  88.     {0x01, "miss_causes_a_walk"},   /*  52 */ /* 0x49 */
  89.     {0x02, "walk_completed_4k"},
  90.     {0x04, "walk_completed_2m_4m"},
  91.     {0x0E, "walk_completed"},
  92.     {0x10, "walk_duration"},
  93.     {0x20, "stlb_hit_4k"},
  94.     {0x40, "stlb_hit_2m"},
  95.     {0x60, "stlb_hit"},
  96.     {0x80, "pde_cache_miss"},
  97.     {0x00, NULL},
  98.     {0x01, "sw_pf"},                /*  62 */ /* 0x4C */
  99.     {0x02, "hw_pf"},
  100.     {0x00, NULL},
  101.     {0x01, "replacement"},          /*  65 */ /* 0x51 */
  102.     {0x00, NULL},
  103.     {0x01, "abort_conflict"},       /*  67 */ /* 0x54 */
  104.     {0x02, "abort_capacity_write"},
  105.     {0x04, "abort_hle_store_to_elided_lock"},
  106.     {0x08, "abort_hle_elision_buffer_not_empty"},
  107.     {0x10, "abort_hle_elision_buffer_mismatch"},
  108.     {0x20, "abort_hle_elision_buffer_unsupported_alignment"},
  109.     {0x40, "hle_elision_buffer_full"},
  110.     {0x00, NULL},
  111.     {0x04, "int_not_eliminated"},   /*  75 */ /* 0x58 */
  112.     {0x08, "simd_not_eliminated"},
  113.     {0x01, "int_not_eliminated"},
  114.     {0x02, "simd_eliminated"},
  115.     {0x00, NULL},
  116.     {0x01, "ring0"},                /*  80 */ /* 0x5C */
  117.     {0x02, "ring123"},
  118.     {0x00, NULL},
  119.     {0x01, "misc1"},                /*  83 */ /* 0x5D */
  120.     {0x02, "misc2"},
  121.     {0x04, "misc3"},
  122.     {0x08, "misc4"},
  123.     {0x10, "misc5"},
  124.     {0x00, NULL},
  125.     {0x01, "empty_cycles"},         /*  89 */ /* 0x5E */
  126.     {0x00, NULL},
  127.     {0x01, "demand_data_rd"},       /*  91 */ /* 0x60 */
  128.     {0x02, "demand_code_rd"},
  129.     {0x04, "demand_rfo"},
  130.     {0x08, "all_data_rd"},
  131.     {0x00, NULL},
  132.     {0x01, "split_lock_uc_lock_duration"}, /*  96 */ /* 0x63 */
  133.     {0x02, "cache_lock_duration"},
  134.     {0x00, NULL},
  135.     {0x02, "empty"},                /*  99 */ /* 0x79 */
  136.     {0x04, "mite_uops"},
  137.     {0x08, "dsb_uops"},
  138.     {0x10, "ms_dsb_uops"},
  139.     {0x20, "ms_mite_uops"},
  140.     {0x30, "ms_uops"},
  141.     {0x18, "all_dsb_cycles_any_uops"},
  142.     {0x18, "all_dsb_cycles_4_uops"},
  143.     {0x24, "all_mite_cycles_any_uops"},
  144.     {0x24, "all_mite_cycles_4_uops"},
  145.     {0x3C, "mite_all_uops"},
  146.     {0x00, NULL},
  147.     {0x02, "misses"},               /* 111 */ /* 0x80 */
  148.     {0x00, NULL},
  149.     {0x01, "miss_causes_a_walk"},   /* 113 */ /* 0x85 */
  150.     {0x02, "walk_completed_4k"},
  151.     {0x04, "walk_completed_2m_4m"},
  152.     {0x0E, "walk_completed"},
  153.     {0x10, "walk_duration"},
  154.     {0x20, "stlb_hit_4k"},
  155.     {0x40, "stlb_hit_2m"},
  156.     {0x60, "stlb_hit"},
  157.     {0x00, NULL},
  158.     {0x01, "lcp"},                  /* 122 */ /* 0x87 */
  159.     {0x04, "iq_full"},
  160.     {0x00, NULL},
  161.     {0x01, "cond"},                 /* 125 */ /* 0x88 */
  162.     {0x02, "direct_jmp"},
  163.     {0x04, "indirect_jmp_non_call_ret"},
  164.     {0x08, "return_near"},
  165.     {0x10, "direct_near_call"},
  166.     {0x20, "indirect_near_call"},
  167.     {0x40, "nontaken"},
  168.     {0x80, "taken"},
  169.     {0xFF, "all_branches"},
  170.     {0x00, NULL},
  171.     {0x01, "cond"},                 /* 135 */ /* 0x89 */
  172.     {0x04, "indirect_jmp_non_call_ret"},
  173.     {0x08, "return_near"},
  174.     {0x10, "direct_near_call"},
  175.     {0x20, "indirect_near_call"},
  176.     {0x40, "nontaken"},
  177.     {0x80, "taken"},
  178.     {0xFF, "all_branches"},
  179.     {0x00, NULL},
  180.     {0x01, "core"},                 /* 144 */ /* 0x9C */
  181.     {0x00, NULL},
  182.     {0x01, "port_0"},               /* 146 */ /* 0xA1 */
  183.     {0x02, "port_1"},
  184.     {0x04, "port_2"},
  185.     {0x08, "port_3"},
  186.     {0x10, "port_4"},
  187.     {0x20, "port_5"},
  188.     {0x40, "port_6"},
  189.     {0x80, "port_7"},
  190.     {0x00, NULL},
  191.     {0x01, "any"},                  /* 155 */ /* 0xA2 */
  192.     {0x04, "rs"},
  193.     {0x08, "sb"},
  194.     {0x10, "rob"},
  195.     {0x00, NULL},
  196.     {0x01, "cycles_l2_pending"},    /* 160 */ /* 0xA3 */
  197.     {0x02, "cycles_ldm_pending"},
  198.     {0x05, "stalls_l2_pending"},
  199.     {0x08, "cycles_l1d_pending"},
  200.     {0x0C, "stalls_l1d_pending"},
  201.     {0x00, NULL},
  202.     {0x01, "uops"},                 /* 166 */ /* 0xA8 */
  203.     {0x00, NULL},
  204.     {0x01, "itlb_flush"},           /* 168 */ /* 0xAE */
  205.     {0x00, NULL},
  206.     {0x01, "demand_data_rd"},       /* 170 */ /* 0xB0 */
  207.     {0x02, "demand_core_rd"},
  208.     {0x04, "demand_rfo"},
  209.     {0x08, "all_data_rd"},
  210.     {0x00, NULL},
  211.     {0x02, "core"},                 /* 175 */ /* 0xB1 */
  212.     {0x00, NULL},
  213.     {0x11, "dtlb_l1"},              /* 177 */ /* 0xBC */
  214.     {0x21, "itlb_l1"},
  215.     {0x12, "dtlb_l2"},
  216.     {0x22, "itlb_l2"},
  217.     {0x14, "dtlb_l3"},
  218.     {0x24, "itlb_l3"},
  219.     {0x18, "dtlb_memory"},
  220.     {0x28, "itlb_memory"},
  221.     {0x00, NULL},
  222.     {0x01, "dtlb_thread"},          /* 186 */ /* 0xBD */
  223.     {0x20, "stlb_any"},
  224.     {0x00, NULL},
  225.     {0x00, "any_p"},                /* 189 */ /* 0xC0 */
  226.     {0x01, "prec_dist"},
  227.     {0x00, NULL},
  228.     {0x08, "avx_to_sse"},           /* 192 */ /* 0xC1 */
  229.     {0x10, "sse_to_avx"},
  230.     {0x40, "any_wb_assist"},
  231.     {0x00, NULL},
  232.     {0x01, "all"},                  /* 196 */ /* 0xC2 */
  233.     {0x02, "retire_slots"},
  234.     {0x00, NULL},
  235.     {0x02, "memory_ordering"},      /* 199 */ /* 0xC3 */
  236.     {0x04, "smc"},
  237.     {0x20, "maskmov"},
  238.     {0x00, NULL},
  239.     {0x00, "all_branches"},         /* 203 */ /* 0xC4 */
  240.     {0x01, "conditional"},
  241.     {0x02, "near_call"},
  242.     {0x04, "all_branches_pebs"},
  243.     {0x08, "near_return"},
  244.     {0x10, "not_taken"},
  245.     {0x20, "near_taken"},
  246.     {0x40, "far_branch"},
  247.     {0x00, NULL},
  248.     {0x00, "all_branches"},         /* 212 */ /* 0xC5 */
  249.     {0x01, "conditional"},
  250.     {0x04, "all_branches_pebs"},
  251.     {0x20, "near_taken"},
  252.     {0x00, NULL},
  253.     {0x01, "start"},                /* 217 */ /* 0xC8 */
  254.     {0x02, "commit"},
  255.     {0x04, "aborted"},
  256.     {0x08, "aborted_mem"},
  257.     {0x10, "aborted_timer"},
  258.     {0x20, "aborted_unfriendly"},
  259.     {0x40, "aborted_memtype"},
  260.     {0x80, "aborted_events"},
  261.     {0x00, NULL},
  262.     {0x01, "start"},                /* 226 */ /* 0xC9 */
  263.     {0x02, "commit"},
  264.     {0x04, "aborted"},
  265.     {0x08, "aborted_mem"},
  266.     {0x10, "aborted_timer"},
  267.     {0x20, "aborted_unfriendly"},
  268.     {0x40, "aborted_memtype"},
  269.     {0x80, "aborted_events"},
  270.     {0x00, NULL},
  271.     {0x02, "x87_output"},           /* 235 */ /* 0xCA */
  272.     {0x04, "x87_input"},
  273.     {0x08, "simd_output"},
  274.     {0x10, "simd_input"},
  275.     {0x1E, "any"},
  276.     {0x00, NULL},
  277.     {0x20, "lbr_inserts"},          /* 241 */ /* 0xCC */
  278.     {0x00, NULL},
  279.     {0x11, "stlb_miss_loads"},      /* 243 */ /* 0xD0 */
  280.     {0x12, "stlb_miss_stores"},
  281.     {0x21, "lock_loads"},
  282.     {0x41, "split_loads"},
  283.     {0x42, "split_stores"},
  284.     {0x81, "all_loads"},
  285.     {0x82, "all_stores"},
  286.     {0x00, NULL},
  287.     {0x01, "l1_hit"},               /* 251 */ /* 0xD1 */
  288.     {0x02, "l2_hit"},
  289.     {0x04, "l3_hit"},
  290.     {0x08, "l1_miss"},
  291.     {0x10, "l2_miss"},
  292.     {0x20, "l3_miss"},
  293.     {0x40, "hit_lfb"},
  294.     {0x00, NULL},
  295.     {0x01, "xsnp_miss"},            /* 259 */ /* 0xD2 */
  296.     {0x02, "xsnp_hit"},
  297.     {0x04, "xsnp_hitm"},
  298.     {0x08, "xsnp_none"},
  299.     {0x00, NULL},
  300.     {0x01, "local_dram"},           /* 264 */ /* 0xD3 */
  301.     {0x00, NULL},
  302.     {0x1F, "any"},                  /* 266 */ /* 0xE6 */
  303.     {0x00, NULL},
  304.     {0x01, "demand_data_rd"},       /* 268 */ /* 0xF0 */
  305.     {0x02, "rfo"},
  306.     {0x04, "code_rd"},
  307.     {0x08, "all_pf"},
  308.     {0x10, "l1d_wb"},
  309.     {0x20, "l2_fill"},
  310.     {0x40, "l2_wb"},
  311.     {0x80, "all_requests"},
  312.     {0x00, NULL},
  313.     {0x01, "i"},                    /* 277 */ /* 0xF1 */
  314.     {0x02, "s"},
  315.     {0x04, "e"},
  316.     {0x07, "all"},
  317.     {0x00, NULL},
  318.     {0x05, "demand_clean"},         /* 282 */ /* 0xF2 */
  319.     {0x06, "demand_dirty"},
  320.     {0x00, NULL}
  321. };
  322. static const struct EVENT EVENT_LIST[256] = {
  323.     {0x03, &UMASK_LIST[   0], "ld_blocks"},
  324.     {0x05, &UMASK_LIST[   3], "misalign_mem_ref"},
  325.     {0x07, &UMASK_LIST[   6], "ld_blocks_partial"},
  326.     {0x08, &UMASK_LIST[   8], "dtlb_load_misses"},
  327.     {0x0D, &UMASK_LIST[  18], "int_misc"},
  328.     {0x0E, &UMASK_LIST[  20], "uops_issued"},
  329.     {0x24, &UMASK_LIST[  25], "l2_rqsts"},
  330.     {0x27, &UMASK_LIST[  42], "l2_demand_rqsts"},
  331.     {0x2E, &UMASK_LIST[  44], "llc"},
  332.     {0x3C, &UMASK_LIST[  47], "cpu_clk_unhalted"},
  333.     {0x48, &UMASK_LIST[  50], "l1d_pend_miss"},
  334.     {0x49, &UMASK_LIST[  52], "dtlb_store_misses"},
  335.     {0x4C, &UMASK_LIST[  62], "load_hit_pre"},
  336.     {0x51, &UMASK_LIST[  65], "l1d"},
  337.     {0x54, &UMASK_LIST[  67], "tx_mem"},
  338.     {0x58, &UMASK_LIST[  75], "move_elimination"},
  339.     {0x5C, &UMASK_LIST[  80], "cpl_cycles"},
  340.     {0x5D, &UMASK_LIST[  83], "tx_exec"},
  341.     {0x5E, &UMASK_LIST[  89], "rs_events"},
  342.     {0x60, &UMASK_LIST[  91], "offcore_requests_outstanding"},
  343.     {0x63, &UMASK_LIST[  96], "lock_cycles"},
  344.     {0x79, &UMASK_LIST[  99], "idq"},
  345.     {0x80, &UMASK_LIST[ 111], "icache"},
  346.     {0x85, &UMASK_LIST[ 113], "itlb_misses"},
  347.     {0x87, &UMASK_LIST[ 122], "ild_stall"},
  348.     {0x88, &UMASK_LIST[ 125], "br_inst_exec"},
  349.     {0x89, &UMASK_LIST[ 135], "br_misp_exec"},
  350.     {0x9C, &UMASK_LIST[ 144], "idq_uops_not_delivered"},
  351.     {0xA1, &UMASK_LIST[ 146], "uops_executed_port"},
  352.     {0xA2, &UMASK_LIST[ 155], "resource_stalls"},
  353.     {0xA3, &UMASK_LIST[ 160], "cycle_activity"},
  354.     {0xA8, &UMASK_LIST[ 166], "lsd"},
  355.     {0xAE, &UMASK_LIST[ 168], "itlb"},
  356.     {0xB0, &UMASK_LIST[ 170], "offcore_requests"},
  357.     {0xB1, &UMASK_LIST[ 175], "uops_executed"},
  358.     /* Ghost [0xB7] and [0xBB] OFF_CORE_RESPONSE_[01] */
  359.     {0xBC, &UMASK_LIST[ 177], "page_walker_loads"},
  360.     {0xBD, &UMASK_LIST[ 186], "tlb_flush"},
  361.     {0xC0, &UMASK_LIST[ 189], "inst_retired"},
  362.     {0xC1, &UMASK_LIST[ 192], "other_assists"},
  363.     {0xC2, &UMASK_LIST[ 196], "uops_retired"},
  364.     {0xC3, &UMASK_LIST[ 199], "machine_clears"},
  365.     {0xC4, &UMASK_LIST[ 203], "br_inst_retired"},
  366.     {0xC5, &UMASK_LIST[ 212], "br_misp_retired"},
  367.     {0xC8, &UMASK_LIST[ 217], "hle_retired"},
  368.     {0xC9, &UMASK_LIST[ 226], "rtm_retired"},
  369.     {0xCA, &UMASK_LIST[ 235], "fp_assist"},
  370.     {0xCC, &UMASK_LIST[ 241], "rob_misc_events"},
  371.     /* Ghost [0xCD] MEM_TRANS_RETIRED */
  372.     {0xD0, &UMASK_LIST[ 243], "mem_uops_retired"},
  373.     {0xD1, &UMASK_LIST[ 251], "mem_load_uops_retired"},
  374.     {0xD2, &UMASK_LIST[ 259], "mem_load_uops_l3_hit_retired"},
  375.     {0xD3, &UMASK_LIST[ 264], "mem_load_uops_l3_miss_retired"},
  376.     {0xE6, &UMASK_LIST[ 266], "baclears"},
  377.     {0xF0, &UMASK_LIST[ 268], "l2_trans"},
  378.     {0xF1, &UMASK_LIST[ 277], "l2_lines_in"},
  379.     {0xF2, &UMASK_LIST[ 282], "l2_lines_out"},
  380.     {0x00, NULL             , NULL}
  381. };
  382.  
  383.  
  384.  
  385. /* Function Definitions */
  386.  
  387. /**
  388.  * Initialize library
  389.  */
  390.  
  391. int pfcInit(void){
  392.     /**
  393.      * Open the magic files perfcount gives us access to
  394.      */
  395.    
  396.     cfgFd = open("/sys/module/perfcount/config", O_RDWR | O_CLOEXEC);
  397.     cntFd = open("/sys/module/perfcount/counts", O_RDWR | O_CLOEXEC);
  398.    
  399.     /**
  400.      * If failure, abort
  401.      */
  402.    
  403.     if(cfgFd<0 || cntFd<0){
  404.         printf("Could not open perfcount handles; Is module loaded?\n");
  405.         pfcFini();
  406.         return 1;
  407.     }else{
  408.         return 0;
  409.     }
  410. }
  411.  
  412. /**
  413.  * Finalize library
  414.  */
  415.  
  416. void pfcFini(void){
  417.     close(cfgFd);
  418.     cfgFd = -1;
  419.     close(cntFd);
  420.     cntFd = -1;
  421. }
  422.  
  423. /**
  424.  * Pins calling thread to given core
  425.  */
  426.  
  427. void pfcPinThread(int core){
  428.     cpu_set_t cpuset;
  429.     CPU_ZERO(&cpuset);
  430.     CPU_SET(core, &cpuset);
  431.     sched_setaffinity(0, sizeof(cpuset), &cpuset);
  432. }
  433.  
  434. /**
  435.  * Configure the n counters starting at counter k.
  436.  *
  437.  * Stops and disables the selected counters.
  438.  */
  439.  
  440. int  pfcWrConfigCnts(int f, int n, const uint64_t* cfg){
  441.     return pwrite(cfgFd, cfg, sizeof(uint64_t)*n, f*sizeof(uint64_t));
  442. }
  443.  
  444. /**
  445.  * Read configuration of the n counters starting at counter k.
  446.  */
  447.  
  448. int  pfcRdConfigCnts(int f, int n, uint64_t* cfg){
  449.     return pread (cfgFd, cfg, sizeof(uint64_t)*n, f*sizeof(uint64_t));
  450. }
  451.  
  452. /**
  453.  * Sets the starting counts for the n counters starting at counter k.
  454.  *
  455.  * Stops and disables the selected counters.
  456.  */
  457.  
  458. int  pfcWrCountsCnts(int f, int n, const uint64_t* cnt){
  459.     return pwrite(cntFd, cnt, sizeof(uint64_t)*n, f*sizeof(uint64_t));
  460. }
  461.  
  462. /**
  463.  * Read counts of the n counters starting at counter k.
  464.  *
  465.  * Starts the selected counters.
  466.  */
  467.  
  468. int  pfcRdCountsCnts(int f, int n, uint64_t* cnt){
  469.     return pread (cntFd, cnt, sizeof(uint64_t)*n, f*sizeof(uint64_t));
  470. }
  471.  
  472. /**
  473.  * Translate argument to configuration.
  474.  */
  475.  
  476. uint64_t pfcParseConfig(const char* s){
  477.     /**
  478.      * Null configs result in disabled counter.
  479.      */
  480.    
  481.     if(!s){
  482.         return 0;
  483.     }
  484.    
  485.     /**
  486.      * Is it edge triggered?
  487.      */
  488.    
  489.     uint64_t edgeTriggered = 0;
  490.     if(s[0] == '*'){
  491.         edgeTriggered = 1;
  492.         s++;
  493.     }
  494.    
  495.     /**
  496.      * Find event number.
  497.      */
  498.    
  499.     uint64_t evtNum = 0;
  500.     const UMASK* umaskList = NULL;
  501.     int i=0;
  502.     while(EVENT_LIST[i].name){
  503.         int n = strlen(EVENT_LIST[i].name);
  504.         if(strncasecmp(s, EVENT_LIST[i].name, n) == 0 && s[n] == '.'){
  505.             /* Found it. */
  506.             evtNum      = EVENT_LIST[i].evtNum;
  507.             umaskList   = EVENT_LIST[i].umasks;
  508.             s          += n+1;
  509.             break;
  510.         }
  511.        
  512.         i++;
  513.     }
  514.     if(!EVENT_LIST[i].name){
  515.         /* We didn't find the event by name. Parse as integer. */
  516.         evtNum = strtoull(s, (char**)&s, 0);
  517.         if(s[0] != '.'){
  518.             return 0;
  519.         }
  520.         s++;
  521.        
  522.         i=0;
  523.         while(EVENT_LIST[i].name){
  524.             if(EVENT_LIST[i].evtNum == evtNum){
  525.                 /* Found it. */
  526.                 umaskList   = EVENT_LIST[i].umasks;
  527.                 break;
  528.             }
  529.            
  530.             i++;
  531.         }
  532.        
  533.         if(!umaskList){
  534.             /* Couldn't find event at all. */
  535.             return 0;
  536.         }
  537.     }
  538.     evtNum &= 0xFF;
  539.    
  540.     /**
  541.      * Find umask value.
  542.      */
  543.    
  544.     uint64_t umaskVal = 0;
  545.     i=0;
  546.     while(umaskList[i].name){
  547.         int n = strlen(umaskList[i].name);
  548.         if(strncasecmp(s, umaskList[i].name, n) == 0 &&
  549.            (s[n] == '\0' || s[n] == '<' || (s[n] == '>' && s[n+1] == '='))){
  550.             /* Found it. */
  551.             umaskVal  = umaskList[i].umaskVal;
  552.             s        += n;
  553.             break;
  554.         }
  555.        
  556.         i++;
  557.     }
  558.     if(!umaskList[i].name){
  559.         umaskVal = strtoull(s, (char**)&s, 0);
  560.         if(s[0] != '\0' && s[0] != '<' && !(s[0] == '>' && s[1] == '=')){
  561.             /* Parsing umask as an integer made no sense. */
  562.             return 0;
  563.         }
  564.     }
  565.     umaskVal &= 0xFF;
  566.    
  567.     /**
  568.      * Parse comparison sign and cmask if available.
  569.      */
  570.    
  571.     uint64_t inv = 0, cmask = 0;
  572.     if(s[0] != '\0'){
  573.         if(s[0] == '>' && s[1] == '=' && isdigit(s[2])){
  574.             inv   = 0;
  575.             cmask = strtoull(s+2, NULL, 0) & 0xFF;
  576.         }else if(s[0] == '<' && isdigit(s[1])){
  577.             inv   = 1;
  578.             cmask = strtoull(s+1, NULL, 0) & 0xFF;
  579.         }else{
  580.             /* The condition's specification is broken. */
  581.             return 0;
  582.         }
  583.     }
  584.    
  585.     /**
  586.      * At last, assemble the pieces.
  587.      */
  588.    
  589.     uint64_t cfg = (cmask         << 24) |
  590.                    (inv           << 23) |
  591.                    (1ULL          << 22) |
  592.                    (edgeTriggered << 18) |
  593.                    (1ULL          << 16) |
  594.                    (umaskVal      <<  8) |
  595.                    (evtNum        <<  0);
  596.     return cfg;
  597. }
  598.  
  599. /**
  600.  * Dump out available events
  601.  */
  602.  
  603. void pfcDumpEvents(void){
  604.     const EVENT* evt   = EVENT_LIST;
  605.     const UMASK* umask;
  606.    
  607.     printf("Available events:\n");
  608.     while(evt->evtNum){
  609.         printf("\t%s:\n", evt->name);
  610.        
  611.         umask = evt->umasks;
  612.         while(umask->name){
  613.             printf("\t\t%s:\n", umask->name);
  614.             umask++;
  615.         }
  616.        
  617.         evt++;
  618.     }
  619. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement