| 782 | } |
| 783 | |
| 784 | prof_tctx_t * |
| 785 | prof_lookup(tsd_t *tsd, prof_bt_t *bt) { |
| 786 | union { |
| 787 | prof_tctx_t *p; |
| 788 | void *v; |
| 789 | } ret; |
| 790 | prof_tdata_t *tdata; |
| 791 | bool not_found; |
| 792 | |
| 793 | cassert(config_prof); |
| 794 | |
| 795 | tdata = prof_tdata_get(tsd, false); |
| 796 | if (tdata == NULL) { |
| 797 | return NULL; |
| 798 | } |
| 799 | |
| 800 | malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock); |
| 801 | not_found = ckh_search(&tdata->bt2tctx, bt, NULL, &ret.v); |
| 802 | if (!not_found) { /* Note double negative! */ |
| 803 | ret.p->prepared = true; |
| 804 | } |
| 805 | malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); |
| 806 | if (not_found) { |
| 807 | void *btkey; |
| 808 | prof_gctx_t *gctx; |
| 809 | bool new_gctx, error; |
| 810 | |
| 811 | /* |
| 812 | * This thread's cache lacks bt. Look for it in the global |
| 813 | * cache. |
| 814 | */ |
| 815 | if (prof_lookup_global(tsd, bt, tdata, &btkey, &gctx, |
| 816 | &new_gctx)) { |
| 817 | return NULL; |
| 818 | } |
| 819 | |
| 820 | /* Link a prof_tctx_t into gctx for this thread. */ |
| 821 | ret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t), |
| 822 | sz_size2index(sizeof(prof_tctx_t)), false, NULL, true, |
| 823 | arena_ichoose(tsd, NULL), true); |
| 824 | if (ret.p == NULL) { |
| 825 | if (new_gctx) { |
| 826 | prof_gctx_try_destroy(tsd, tdata, gctx, tdata); |
| 827 | } |
| 828 | return NULL; |
| 829 | } |
| 830 | ret.p->tdata = tdata; |
| 831 | ret.p->thr_uid = tdata->thr_uid; |
| 832 | ret.p->thr_discrim = tdata->thr_discrim; |
| 833 | memset(&ret.p->cnts, 0, sizeof(prof_cnt_t)); |
| 834 | ret.p->gctx = gctx; |
| 835 | ret.p->tctx_uid = tdata->tctx_uid_next++; |
| 836 | ret.p->prepared = true; |
| 837 | ret.p->state = prof_tctx_state_initializing; |
| 838 | malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock); |
| 839 | error = ckh_insert(tsd, &tdata->bt2tctx, btkey, ret.v); |
| 840 | malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); |
| 841 | if (error) { |
no test coverage detected