00001
00014 #include "op_hw_config.h"
00015 #include "op_events.h"
00016 #include "op_string.h"
00017 #include "op_hw_specific.h"
00018 #include "op_libiberty.h"
00019 #include "opd_printf.h"
00020 #include "opd_trans.h"
00021 #include "opd_events.h"
00022 #include "opd_kernel.h"
00023 #include "opd_anon.h"
00024 #include "opd_sfile.h"
00025 #include "opd_interface.h"
00026 #include "opd_mangling.h"
00027 #include "opd_extended.h"
00028 #include "opd_ibs.h"
00029 #include "opd_ibs_trans.h"
00030 #include "opd_ibs_macro.h"
00031
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <string.h>
00036 #include <limits.h>
00037
00038 extern op_cpu cpu_type;
00039 extern int no_event_ok;
00040 extern int sfile_equal(struct sfile const * sf, struct sfile const * sf2);
00041 extern void sfile_dup(struct sfile * to, struct sfile * from);
00042 extern char * session_dir;
00043
00044
00045 static unsigned int ibs_selected_size;
00046
00047
00048 static unsigned int ibs_fetch_selected_flag;
00049 static unsigned int ibs_op_selected_flag;
00050 static unsigned int ibs_op_ls_selected_flag;
00051 static unsigned int ibs_op_nb_selected_flag;
00052
00053
00054 static unsigned long ibs_fetch_sample_stats;
00055 static unsigned long ibs_fetch_incomplete_stats;
00056 static unsigned long ibs_op_sample_stats;
00057 static unsigned long ibs_op_incomplete_stats;
00058 static unsigned long ibs_derived_event_stats;
00059
00060
00061
00062
00063 struct opd_event ibs_vc[OP_MAX_IBS_COUNTERS];
00064
00065
00066 unsigned int ibs_vci_map[OP_MAX_IBS_COUNTERS];
00067
00068
00069 unsigned int ibs_family;
00070 unsigned int ibs_model;
00071 unsigned int ibs_stepping;
00072
00073
00074 static unsigned long ibs_bta_enabled;
00075
00076
00077 FILE * memaccess_log;
00078 FILE * bta_log;
00079
00085 static void opd_log_ibs_fetch(struct transient * trans)
00086 {
00087 struct ibs_fetch_sample * trans_fetch = ((struct ibs_sample*)(trans->ext))->fetch;
00088 if (!trans_fetch)
00089 return;
00090
00091 trans_ibs_fetch(trans, ibs_fetch_selected_flag);
00092 }
00093
00094
00099 static void opd_log_ibs_op(struct transient * trans)
00100 {
00101 struct ibs_op_sample * trans_op = ((struct ibs_sample*)(trans->ext))->op;
00102 if (!trans_op)
00103 return;
00104
00105 trans_ibs_op_mask_reserved(ibs_family, trans);
00106
00107 if (trans_ibs_op_rip_invalid(trans) != 0)
00108 return;
00109
00110 trans_ibs_op(trans, ibs_op_selected_flag);
00111 trans_ibs_op_ls(trans, ibs_op_ls_selected_flag);
00112 trans_ibs_op_nb(trans, ibs_op_nb_selected_flag);
00113 trans_ibs_op_ls_memaccess(trans);
00114 trans_ibs_op_bta(trans);
00115 }
00116
00117
00118 static void opd_put_ibs_sample(struct transient * trans)
00119 {
00120 unsigned long long event = 0;
00121 struct kernel_image * k_image = NULL;
00122 struct ibs_fetch_sample * trans_fetch = ((struct ibs_sample*)(trans->ext))->fetch;
00123
00124 if (!enough_remaining(trans, 1)) {
00125 trans->remaining = 0;
00126 return;
00127 }
00128
00129
00130
00131
00132
00133 if (trans->cookie == INVALID_COOKIE
00134 && (k_image = find_kernel_image(trans)) != NULL
00135 && (k_image->start != 0 && k_image->end != 0)
00136 && trans->in_kernel == 0)
00137 trans->in_kernel = 1;
00138
00139 if (trans->tracing != TRACING_ON)
00140 trans->event = event;
00141
00142
00143 if (trans->in_kernel != 0)
00144 clear_trans_current(trans);
00145
00146 if (!trans->in_kernel && trans->cookie == NO_COOKIE)
00147 trans->anon = find_anon_mapping(trans);
00148
00149
00150 if (!trans->current)
00151 trans->current = sfile_find(trans);
00152
00153
00154
00155
00156
00157 if (!trans->current)
00158 goto out;
00159
00160 if (trans_fetch)
00161 opd_log_ibs_fetch(trans);
00162 else
00163 opd_log_ibs_op(trans);
00164 out:
00165
00166 if (trans->tracing == TRACING_START)
00167 trans->tracing = TRACING_ON;
00168
00169 update_trans_last(trans);
00170 }
00171
00172
00173 static void get_ibs_bta_status()
00174 {
00175 FILE * fp = NULL;
00176 char buf[PATH_MAX];
00177
00178
00179 ibs_bta_enabled = 0;
00180
00181 snprintf(buf, PATH_MAX, "/dev/oprofile/ibs_op/branch_target");
00182 fp = fopen(buf, "r");
00183 if (!fp)
00184 return;
00185
00186 while (fgets(buf, PATH_MAX, fp) != NULL)
00187 ibs_bta_enabled = strtoul(buf, NULL, 10);
00188
00189 fclose(fp);
00190 }
00191
00192
00193 void code_ibs_fetch_sample(struct transient * trans)
00194 {
00195 struct ibs_fetch_sample * trans_fetch = NULL;
00196
00197 if (!enough_remaining(trans, 7)) {
00198 verbprintf(vext, "not enough remaining\n");
00199 trans->remaining = 0;
00200 ibs_fetch_incomplete_stats++;
00201 return;
00202 }
00203
00204 ibs_fetch_sample_stats++;
00205
00206 trans->ext = xmalloc(sizeof(struct ibs_sample));
00207 ((struct ibs_sample*)(trans->ext))->fetch = xmalloc(sizeof(struct ibs_fetch_sample));
00208 trans_fetch = ((struct ibs_sample*)(trans->ext))->fetch;
00209
00210 trans_fetch->rip = pop_buffer_value(trans);
00211
00212 trans_fetch->ibs_fetch_lin_addr_low = pop_buffer_value(trans);
00213 trans_fetch->ibs_fetch_lin_addr_high = pop_buffer_value(trans);
00214
00215 trans_fetch->ibs_fetch_ctl_low = pop_buffer_value(trans);
00216 trans_fetch->ibs_fetch_ctl_high = pop_buffer_value(trans);
00217 trans_fetch->ibs_fetch_phys_addr_low = pop_buffer_value(trans);
00218 trans_fetch->ibs_fetch_phys_addr_high = pop_buffer_value(trans);
00219
00220 verbprintf(vsamples,
00221 "FETCH_X CPU:%ld PID:%ld RIP:%lx CTL_H:%x LAT:%d P_HI:%x P_LO:%x L_HI:%x L_LO:%x\n",
00222 trans->cpu,
00223 (long)trans->tgid,
00224 trans_fetch->rip,
00225 (trans_fetch->ibs_fetch_ctl_high >> 16) & 0x3ff,
00226 (trans_fetch->ibs_fetch_ctl_high) & 0xffff,
00227 trans_fetch->ibs_fetch_phys_addr_high,
00228 trans_fetch->ibs_fetch_phys_addr_low,
00229 trans_fetch->ibs_fetch_lin_addr_high,
00230 trans_fetch->ibs_fetch_lin_addr_low) ;
00231
00232
00233 trans->pc = trans_fetch->rip;
00234
00235 opd_put_ibs_sample(trans);
00236
00237 free(trans_fetch);
00238 free(trans->ext);
00239 trans->ext = NULL;
00240 }
00241
00242
00243 static void get_ibs_op_bta_sample(struct transient * trans,
00244 struct ibs_op_sample * trans_op)
00245 {
00246
00247 if (!enough_remaining(trans, 2)) {
00248 verbprintf(vext, "not enough remaining\n");
00249 trans->remaining = 0;
00250 ibs_op_incomplete_stats++;
00251 return;
00252 }
00253
00254 if (ibs_bta_enabled == 1) {
00255 trans_op->ibs_op_brtgt_addr = pop_buffer_value(trans);
00256
00257
00258 if ((trans_op->ibs_op_data1_high & (0x00000001 << 5)) == 0) {
00259 trans_op->ibs_op_brtgt_addr = 0;
00260 }
00261 } else {
00262 trans_op->ibs_op_brtgt_addr = 0;
00263 }
00264 }
00265
00266
00267 void code_ibs_op_sample(struct transient * trans)
00268 {
00269 struct ibs_op_sample * trans_op= NULL;
00270
00271 if (!enough_remaining(trans, 13)) {
00272 verbprintf(vext, "not enough remaining\n");
00273 trans->remaining = 0;
00274 ibs_op_incomplete_stats++;
00275 return;
00276 }
00277
00278 ibs_op_sample_stats++;
00279
00280 trans->ext = xmalloc(sizeof(struct ibs_sample));
00281 ((struct ibs_sample*)(trans->ext))->op = xmalloc(sizeof(struct ibs_op_sample));
00282 trans_op = ((struct ibs_sample*)(trans->ext))->op;
00283
00284 trans_op->rip = pop_buffer_value(trans);
00285
00286 trans_op->ibs_op_lin_addr_low = pop_buffer_value(trans);
00287 trans_op->ibs_op_lin_addr_high = pop_buffer_value(trans);
00288
00289 trans_op->ibs_op_data1_low = pop_buffer_value(trans);
00290 trans_op->ibs_op_data1_high = pop_buffer_value(trans);
00291 trans_op->ibs_op_data2_low = pop_buffer_value(trans);
00292 trans_op->ibs_op_data2_high = pop_buffer_value(trans);
00293 trans_op->ibs_op_data3_low = pop_buffer_value(trans);
00294 trans_op->ibs_op_data3_high = pop_buffer_value(trans);
00295 trans_op->ibs_op_ldst_linaddr_low = pop_buffer_value(trans);
00296 trans_op->ibs_op_ldst_linaddr_high = pop_buffer_value(trans);
00297 trans_op->ibs_op_phys_addr_low = pop_buffer_value(trans);
00298 trans_op->ibs_op_phys_addr_high = pop_buffer_value(trans);
00299
00300 get_ibs_op_bta_sample(trans, trans_op);
00301
00302 verbprintf(vsamples,
00303 "IBS_OP_X CPU:%ld PID:%d RIP:%lx D1HI:%x D1LO:%x D2LO:%x D3HI:%x D3LO:%x L_LO:%x P_LO:%x\n",
00304 trans->cpu,
00305 trans->tgid,
00306 trans_op->rip,
00307 trans_op->ibs_op_data1_high,
00308 trans_op->ibs_op_data1_low,
00309 trans_op->ibs_op_data2_low,
00310 trans_op->ibs_op_data3_high,
00311 trans_op->ibs_op_data3_low,
00312 trans_op->ibs_op_ldst_linaddr_low,
00313 trans_op->ibs_op_phys_addr_low);
00314
00315
00316 trans->pc = trans_op->rip;
00317
00318 opd_put_ibs_sample(trans);
00319
00320 free(trans_op);
00321 free(trans->ext);
00322 trans->ext = NULL;
00323 }
00324
00325
00327 static unsigned long ibs_event_to_counter(unsigned long x)
00328 {
00329 unsigned long ret = ~0UL;
00330
00331 if (IS_IBS_FETCH(x))
00332 ret = (x - IBS_FETCH_BASE);
00333 else if (IS_IBS_OP(x))
00334 ret = (x - IBS_OP_BASE + IBS_FETCH_MAX);
00335 else if (IS_IBS_OP_LS(x))
00336 ret = (x - IBS_OP_LS_BASE + IBS_OP_MAX + IBS_FETCH_MAX);
00337 else if (IS_IBS_OP_NB(x))
00338 ret = (x - IBS_OP_NB_BASE + IBS_OP_LS_MAX + IBS_OP_MAX + IBS_FETCH_MAX);
00339
00340 return (ret != ~0UL) ? ret + OP_MAX_COUNTERS : ret;
00341 }
00342
00343
00344 void opd_log_ibs_event(unsigned int event,
00345 struct transient * trans)
00346 {
00347 ibs_derived_event_stats++;
00348 trans->event = event;
00349 sfile_log_sample_count(trans, 1);
00350 }
00351
00352
00353 void opd_log_ibs_count(unsigned int event,
00354 struct transient * trans,
00355 unsigned int count)
00356 {
00357 ibs_derived_event_stats++;
00358 trans->event = event;
00359 sfile_log_sample_count(trans, count);
00360 }
00361
00362
00363 static unsigned long get_ibs_vci_key(unsigned int event)
00364 {
00365 unsigned long key = ibs_event_to_counter(event);
00366 if (key == ~0UL || key < OP_MAX_COUNTERS)
00367 return ~0UL;
00368
00369 key = key - OP_MAX_COUNTERS;
00370
00371 return key;
00372 }
00373
00374
00375 static int ibs_parse_and_set_events(char * str)
00376 {
00377 char * tmp, * ptr, * tok1, * tok2 = NULL;
00378 int is_done = 0;
00379 struct op_event * event = NULL;
00380 op_cpu cpu_type = CPU_NO_GOOD;
00381 unsigned long key;
00382
00383 if (!str)
00384 return -1;
00385
00386 cpu_type = op_get_cpu_type();
00387 op_events(cpu_type);
00388
00389 tmp = op_xstrndup(str, strlen(str));
00390 ptr = tmp;
00391
00392 while (is_done != 1
00393 && (tok1 = strtok_r(ptr, ",", &tok2)) != NULL) {
00394
00395 if ((ptr = strstr(tok1, ":")) != NULL) {
00396 *ptr = '\0';
00397 is_done = 1;
00398 }
00399
00400
00401 event = find_event_by_name(tok1, 0, 0);
00402 if (!event)
00403 return -1;
00404
00405
00406 if (IS_IBS_FETCH(event->val)) {
00407 ibs_fetch_selected_flag |= 1 << IBS_FETCH_OFFSET(event->val);
00408 } else if (IS_IBS_OP(event->val)) {
00409 ibs_op_selected_flag |= 1 << IBS_OP_OFFSET(event->val);
00410 } else if (IS_IBS_OP_LS(event->val)) {
00411 ibs_op_ls_selected_flag |= 1 << IBS_OP_LS_OFFSET(event->val);
00412 } else if (IS_IBS_OP_NB(event->val)) {
00413 ibs_op_nb_selected_flag |= 1 << IBS_OP_NB_OFFSET(event->val);
00414 } else {
00415 return -1;
00416 }
00417
00418 key = get_ibs_vci_key(event->val);
00419 if (key == ~0UL)
00420 return -1;
00421
00422 ibs_vci_map[key] = ibs_selected_size;
00423
00424
00425 ibs_vc[ibs_selected_size].name = tok1;
00426 ibs_vc[ibs_selected_size].value = event->val;
00427 ibs_vc[ibs_selected_size].counter = ibs_selected_size + OP_MAX_COUNTERS;
00428 ibs_vc[ibs_selected_size].kernel = 1;
00429 ibs_vc[ibs_selected_size].user = 1;
00430
00431 ibs_selected_size++;
00432
00433 ptr = NULL;
00434 }
00435
00436 return 0;
00437 }
00438
00439
00440 static int ibs_parse_counts(char * str, unsigned long int * count)
00441 {
00442 char * tmp, * tok1, * tok2 = NULL, *end = NULL;
00443 if (!str)
00444 return -1;
00445
00446 tmp = op_xstrndup(str, strlen(str));
00447 tok1 = strtok_r(tmp, ":", &tok2);
00448 *count = strtoul(tok1, &end, 10);
00449 if ((end && *end) || *count == 0
00450 || errno == EINVAL || errno == ERANGE) {
00451 fprintf(stderr,"Invalid count (%s)\n", str);
00452 return -1;
00453 }
00454
00455 return 0;
00456 }
00457
00458
00459 static int ibs_parse_and_set_um_fetch(char const * str)
00460 {
00461 if (!str)
00462 return -1;
00463 return 0;
00464 }
00465
00466
00467 static int ibs_parse_and_set_um_op(char const * str, unsigned long int * ibs_op_um)
00468 {
00469 char * end = NULL;
00470 if (!str)
00471 return -1;
00472
00473 *ibs_op_um = strtoul(str, &end, 16);
00474 if ((end && *end) || errno == EINVAL || errno == ERANGE) {
00475 fprintf(stderr,"Invalid unitmaks (%s)\n", str);
00476 return -1;
00477 }
00478 return 0;
00479 }
00480
00481
00482 static void check_cpuid_family_model_stepping()
00483 {
00484 #if defined(__i386__) || defined(__x86_64__)
00485 unsigned eax = cpuid_signature();
00486
00487 ibs_family = cpu_family(eax);
00488 ibs_model = cpu_model(eax);
00489 ibs_stepping = cpu_stepping(eax);
00490 #else
00491 ibs_family = 0;
00492 ibs_model = 0;
00493 ibs_stepping = 0;
00494 #endif
00495 }
00496
00497
00498 static int ibs_init(char const * argv)
00499 {
00500 char * tmp, * ptr, * tok1, * tok2 = NULL;
00501 unsigned int i = 0;
00502 unsigned long int ibs_fetch_count = 0;
00503 unsigned long int ibs_op_count = 0;
00504 unsigned long int ibs_op_um = 0;
00505
00506 if (!argv)
00507 return -1;
00508
00509 if (empty_line(argv) != 0)
00510 return -1;
00511
00512 tmp = op_xstrndup(argv, strlen(argv));
00513 ptr = (char *) skip_ws(tmp);
00514
00515
00516 tok1 = strtok_r(ptr, "|", &tok2);
00517
00518 while (tok1 != NULL) {
00519
00520 if (!strncmp("fetch:", tok1, strlen("fetch:"))) {
00521
00522 tok1 = tok1 + strlen("fetch:");
00523 if (ibs_parse_and_set_events(tok1) == -1)
00524 return -1;
00525
00526
00527 while (tok1) {
00528 if (*tok1 == '\0')
00529 return -1;
00530 if (*tok1 != ':') {
00531 tok1++;
00532 } else {
00533 tok1++;
00534 break;
00535 }
00536 }
00537
00538 if (ibs_parse_counts(tok1, &ibs_fetch_count) == -1)
00539 return -1;
00540
00541
00542 while (tok1) {
00543 if (*tok1 == '\0')
00544 return -1;
00545 if (*tok1 != ':') {
00546 tok1++;
00547 } else {
00548 tok1++;
00549 break;
00550 }
00551 }
00552
00553 if (ibs_parse_and_set_um_fetch(tok1) == -1)
00554 return -1;
00555
00556 } else if (!strncmp("op:", tok1, strlen("op:"))) {
00557
00558 tok1 = tok1 + strlen("op:");
00559 if (ibs_parse_and_set_events(tok1) == -1)
00560 return -1;
00561
00562
00563 while (tok1) {
00564 if (*tok1 == '\0')
00565 return -1;
00566 if (*tok1 != ':') {
00567 tok1++;
00568 } else {
00569 tok1++;
00570 break;
00571 }
00572 }
00573
00574 if (ibs_parse_counts(tok1, &ibs_op_count) == -1)
00575 return -1;
00576
00577
00578 while (tok1) {
00579 if (*tok1 == '\0')
00580 return -1;
00581 if (*tok1 != ':') {
00582 tok1++;
00583 } else {
00584 tok1++;
00585 break;
00586 }
00587 }
00588
00589 if (ibs_parse_and_set_um_op(tok1, &ibs_op_um))
00590 return -1;
00591
00592 } else
00593 return -1;
00594
00595 tok1 = strtok_r(NULL, "|", &tok2);
00596 }
00597
00598
00599 for (i = 0 ; i < ibs_selected_size ; i++)
00600 {
00601 if (IS_IBS_FETCH(ibs_vc[i].value)) {
00602 ibs_vc[i].count = ibs_fetch_count;
00603 ibs_vc[i].um = 0;
00604 } else {
00605 ibs_vc[i].count = ibs_op_count;
00606 ibs_vc[i].um = ibs_op_um;
00607 }
00608 }
00609
00610
00611 no_event_ok = 1;
00612
00613 check_cpuid_family_model_stepping();
00614
00615 get_ibs_bta_status();
00616
00617
00618 memaccess_log = NULL;
00619 if (ibs_op_um & 0x2) {
00620 char filename[PATH_MAX];
00621 char * log_file = "/samples/ibs_memaccess.log";
00622 size_t path_len = strlen(session_dir) + strlen(log_file);
00623 if (path_len < PATH_MAX) {
00624 strcpy(filename, session_dir);
00625 strcat(filename, log_file);
00626 memaccess_log = fopen(filename, "w");
00627 }
00628 if ( memaccess_log == NULL) {
00629 verbprintf(vext, "Warning: Cannot create ibs_memaccess.log\n");
00630
00631 } else {
00632 fprintf (memaccess_log, "# IBS Memory Access Log\n\n");
00633 fprintf (memaccess_log, "# Format: app_cookie,cookie,cpu,tgid,tid,pc,branch-target-address,\n");
00634 fprintf (memaccess_log, "# phy-hi:phy-low,lin-hi:lin-low,accese-type,latency\n\n");
00635 }
00636 }
00637
00638
00639 bta_log = NULL;
00640 if (ibs_bta_enabled) {
00641 char filename[PATH_MAX];
00642 char * log_file = "/samples/ibs_bta.log";
00643 size_t path_len = strlen(session_dir) + strlen(log_file);
00644 if (path_len < PATH_MAX) {
00645 strcpy(filename, session_dir);
00646 strcat(filename, log_file);
00647 bta_log = fopen(filename, "w");
00648 }
00649 if ( bta_log == NULL) {
00650 verbprintf(vext, "Warning: Cannot create ibs_bta.log\n");
00651 } else {
00652 fprintf (bta_log, "# IBS Memory Access Log\n\n");
00653 fprintf (bta_log, "# Format: app_cookie,cookie,cpu,tgid,tid,pc,branch-target-address\n\n");
00654 }
00655 }
00656
00657 return 0;
00658 }
00659
00660
00661 static int ibs_deinit()
00662 {
00663 if (memaccess_log) {
00664 fclose (memaccess_log);
00665 memaccess_log = NULL;
00666 }
00667
00668 if (bta_log) {
00669 fclose (bta_log);
00670 bta_log = NULL;
00671 }
00672 return 0;
00673 }
00674
00675
00676 static int ibs_print_stats()
00677 {
00678 printf("Nr. IBS Fetch samples : %lu (%lu entries)\n",
00679 ibs_fetch_sample_stats, (ibs_fetch_sample_stats * 7));
00680 printf("Nr. IBS Fetch incompletes : %lu\n", ibs_fetch_incomplete_stats);
00681 printf("Nr. IBS Op samples : %lu (%lu entries)\n",
00682 ibs_op_sample_stats, (ibs_op_sample_stats * 13));
00683 printf("Nr. IBS Op incompletes : %lu\n", ibs_op_incomplete_stats);
00684 printf("Nr. IBS derived events : %lu\n", ibs_derived_event_stats);
00685 return 0;
00686 }
00687
00688
00689 static int ibs_sfile_create(struct sfile * sf)
00690 {
00691 unsigned int i;
00692 sf->ext_files = xmalloc(ibs_selected_size * sizeof(odb_t));
00693 for (i = 0 ; i < ibs_selected_size ; ++i)
00694 odb_init(&sf->ext_files[i]);
00695
00696 return 0;
00697 }
00698
00699
00700 static int ibs_sfile_dup (struct sfile * to, struct sfile * from)
00701 {
00702 unsigned int i;
00703 if (from->ext_files != NULL) {
00704 to->ext_files = xmalloc(ibs_selected_size * sizeof(odb_t));
00705 for (i = 0 ; i < ibs_selected_size ; ++i)
00706 odb_init(&to->ext_files[i]);
00707 } else {
00708 to->ext_files = NULL;
00709 }
00710 return 0;
00711 }
00712
00713 static int ibs_sfile_close(struct sfile * sf)
00714 {
00715 unsigned int i;
00716 if (sf->ext_files != NULL) {
00717 for (i = 0; i < ibs_selected_size ; ++i)
00718 odb_close(&sf->ext_files[i]);
00719
00720 free(sf->ext_files);
00721 sf->ext_files= NULL;
00722 }
00723 return 0;
00724 }
00725
00726 static int ibs_sfile_sync(struct sfile * sf)
00727 {
00728 unsigned int i;
00729 if (sf->ext_files != NULL) {
00730 for (i = 0; i < ibs_selected_size ; ++i)
00731 odb_sync(&sf->ext_files[i]);
00732 }
00733 return 0;
00734 }
00735
00736 static odb_t * ibs_sfile_get(struct transient const * trans, int is_cg)
00737 {
00738 struct sfile * sf = trans->current;
00739 struct sfile * last = trans->last;
00740 struct cg_entry * cg;
00741 struct list_head * pos;
00742 unsigned long hash;
00743 odb_t * file;
00744 unsigned long counter, ibs_vci, key;
00745
00746
00747
00748
00749
00750 key = get_ibs_vci_key(trans->event);
00751 if (key == ~0UL) {
00752 fprintf(stderr, "%s: Invalid IBS event %lu\n", __func__, trans->event);
00753 abort();
00754 }
00755 ibs_vci = ibs_vci_map[key];
00756 counter = ibs_vci + OP_MAX_COUNTERS;
00757
00758
00759 if (sf->ext_files == NULL)
00760 ibs_sfile_create(sf);
00761
00762 file = &(sf->ext_files[ibs_vci]);
00763 if (!is_cg)
00764 goto open;
00765
00766 hash = last->hashval & (CG_HASH_SIZE - 1);
00767
00768
00769
00770
00771 list_for_each(pos, &sf->cg_hash[hash]) {
00772 cg = list_entry(pos, struct cg_entry, hash);
00773 if (sfile_equal(last, &cg->to)) {
00774 file = &(cg->to.ext_files[ibs_vci]);
00775 goto open;
00776 }
00777 }
00778
00779 cg = xmalloc(sizeof(struct cg_entry));
00780 sfile_dup(&cg->to, last);
00781 list_add(&cg->hash, &sf->cg_hash[hash]);
00782 file = &(cg->to.ext_files[ibs_vci]);
00783
00784 open:
00785 if (!odb_open_count(file))
00786 opd_open_sample_file(file, last, sf, counter, is_cg);
00787
00788
00789 if (!odb_open_count(file))
00790 return NULL;
00791
00792 return file;
00793 }
00794
00795
00799 static struct opd_event * ibs_sfile_find_counter_event(unsigned long counter)
00800 {
00801 unsigned long ibs_vci;
00802
00803 if (counter >= OP_MAX_COUNTERS + OP_MAX_IBS_COUNTERS
00804 || counter < OP_MAX_COUNTERS) {
00805 fprintf(stderr,"Error: find_ibs_counter_event : "
00806 "invalid counter value %lu.\n", counter);
00807 abort();
00808 }
00809
00810 ibs_vci = counter - OP_MAX_COUNTERS;
00811 return &ibs_vc[ibs_vci];
00812 }
00813
00814
00815 struct opd_ext_sfile_handlers ibs_sfile_handlers =
00816 {
00817 .create = &ibs_sfile_create,
00818 .dup = &ibs_sfile_dup,
00819 .close = &ibs_sfile_close,
00820 .sync = &ibs_sfile_sync,
00821 .get = &ibs_sfile_get,
00822 .find_counter_event = &ibs_sfile_find_counter_event
00823 };
00824
00825
00826 struct opd_ext_handlers ibs_handlers =
00827 {
00828 .ext_init = &ibs_init,
00829 .ext_deinit = &ibs_deinit,
00830 .ext_print_stats = &ibs_print_stats,
00831 .ext_sfile = &ibs_sfile_handlers
00832 };