From: Piotr Dałek Date: Sat, 23 Apr 2016 12:06:42 +0000 (+0200) Subject: lockdep: Convert free_ids from list to bitmap X-Git-Tag: v11.0.0~304^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a81e2bb48c05d80b2ddb7d2f7fd97d489d12c50a;p=ceph.git lockdep: Convert free_ids from list to bitmap Convert "free_ids" list to bitmap, reducing its memory usage from 16 + MAX_LOCKS * 20 (~20KB) to MAX_LOCKS/8 (512b) and save some time (re)populating the free id array. Signed-off-by: Piotr Dałek --- diff --git a/src/common/lockdep.cc b/src/common/lockdep.cc index 0b2046b6bc92..12165b92c8f8 100644 --- a/src/common/lockdep.cc +++ b/src/common/lockdep.cc @@ -52,11 +52,12 @@ static lockdep_stopper_t lockdep_stopper; static ceph::unordered_map lock_ids; static map lock_names; static map lock_refs; -static list free_ids; +static char free_ids[MAX_LOCKS/8]; // bit set = free static ceph::unordered_map > held; static char follows[MAX_LOCKS][MAX_LOCKS/8]; // follows[a][b] means b taken after a static BackTrace *follows_bt[MAX_LOCKS][MAX_LOCKS]; unsigned current_maxid; +int last_freed_id; static bool lockdep_force_backtrace() { @@ -67,6 +68,8 @@ static bool lockdep_force_backtrace() /******* Functions **********/ void lockdep_register_ceph_context(CephContext *cct) { + static_assert((MAX_LOCKS > 0) && (MAX_LOCKS % 8 == 0), + "lockdep's MAX_LOCKS needs to be divisible by 8 to operate correctly."); pthread_mutex_lock(&lockdep_mutex); if (g_lockdep_ceph_ctx == NULL) { ANNOTATE_BENIGN_RACE_SIZED(&g_lockdep_ceph_ctx, sizeof(g_lockdep_ceph_ctx), @@ -77,10 +80,9 @@ void lockdep_register_ceph_context(CephContext *cct) g_lockdep_ceph_ctx = cct; lockdep_dout(0) << "lockdep start" << dendl; current_maxid = 0; + last_freed_id = -1; - for (int i=0; i= 0) && + (free_ids[last_freed_id/8] & (1 << (last_freed_id % 8)))) { + int tmp = last_freed_id; + last_freed_id = -1; + free_ids[tmp/8] &= 255 - (1 << (tmp % 8)); + lockdep_dout(1) << "reusing last freed id " << tmp << dendl; + return tmp; + } + + // walk through entire array and locate nonzero char, then find + // actual bit. + for (int i = 0; i < MAX_LOCKS / 8; ++i) { + if (free_ids[i] != 0) { + for (int j = 0; j < 8; ++j) { + if (free_ids[i] & (1 << j)) { + free_ids[i] &= 255 - (1 << j); + lockdep_dout(1) << "using id " << i * 8 + j << dendl; + return i * 8 + j; + } + } + } + } + + // not found + lockdep_dout(0) << "failing miserably..." << dendl; + return -1; +} + int lockdep_register(const char *name) { int id; @@ -142,16 +176,15 @@ int lockdep_register(const char *name) pthread_mutex_lock(&lockdep_mutex); ceph::unordered_map::iterator p = lock_ids.find(name); if (p == lock_ids.end()) { - if (free_ids.empty()) { - lockdep_dout(0) << "ERROR OUT OF IDS .. have " << free_ids.size() + id = lockdep_get_free_id(); + if (id < 0) { + lockdep_dout(0) << "ERROR OUT OF IDS .. have 0" << " max " << MAX_LOCKS << dendl; for (auto& p : lock_names) { lockdep_dout(0) << " lock " << p.first << " " << p.second << dendl; } - assert(!free_ids.empty()); + assert(false); } - id = free_ids.front(); - free_ids.pop_front(); if (current_maxid <= (unsigned)id) { current_maxid = (unsigned)id + 1; } @@ -198,7 +231,8 @@ void lockdep_unregister(int id) lock_ids.erase(p->second); lock_names.erase(id); lock_refs.erase(id); - free_ids.push_front(id); + free_ids[id/8] |= (1 << (id % 8)); + last_freed_id = id; } else { lockdep_dout(20) << "have " << refs << " of '" << p->second << "' " << "from " << id << dendl;