| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All Rights Reserved. |
| 3 * |
| 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions |
| 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. |
| 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 * |
| 25 */ |
| 26 |
| 27 #include "config.h" |
| 28 #include "core/dom/LockManager.h" |
| 29 |
| 30 #include "core/dom/ExecutionContext.h" |
| 31 |
| 32 namespace WebCore { |
| 33 |
| 34 static inline uint32_t murmurHash3Finalize(uint32_t h) |
| 35 { |
| 36 h ^= h >> 16; |
| 37 h *= 0x85ebca6b; |
| 38 h ^= h >> 13; |
| 39 h *= 0xc2b2ae35; |
| 40 h ^= h >> 16; |
| 41 return h; |
| 42 } |
| 43 |
| 44 static inline void getIndexes(uint32_t uid, uint32_t *shard, uint32_t *lock) |
| 45 { |
| 46 uint32_t hash = murmurHash3Finalize(uid); |
| 47 *shard = hash & SHARD_MASK; |
| 48 *lock = hash >> SHARD_BITS; |
| 49 } |
| 50 |
| 51 class LockInfo { |
| 52 public: |
| 53 LockInfo(); |
| 54 bool locked; |
| 55 ThreadCondition cond; |
| 56 uint32_t holdCount; |
| 57 }; |
| 58 |
| 59 LockInfo::LockInfo() |
| 60 : locked(false) |
| 61 , holdCount(0) |
| 62 { |
| 63 } |
| 64 |
| 65 LockShard::~LockShard() |
| 66 { |
| 67 // printf("destroying shard %p\n", this); |
| 68 LockHashMap::iterator iter; |
| 69 for (iter = locks.begin(); iter != locks.end(); ++iter) { |
| 70 delete iter->value; |
| 71 } |
| 72 locks.clear(); |
| 73 } |
| 74 |
| 75 LockInfo* LockShard::get(uint32_t uid) |
| 76 { |
| 77 LockHashMap::iterator iter = locks.find(uid); |
| 78 if (iter != locks.end()) { |
| 79 return iter->value; |
| 80 } |
| 81 LockInfo* info = new LockInfo(); |
| 82 locks.add(uid, info); |
| 83 return info; |
| 84 } |
| 85 |
| 86 void LockManagerImpl::lock(uint32_t uid) |
| 87 { |
| 88 uint32_t shardID; |
| 89 uint32_t lock; |
| 90 getIndexes(uid, &shardID, &lock); |
| 91 LockShard& shard = shards[shardID]; |
| 92 shard.mutex.lock(); |
| 93 LockInfo* info = shard.get(lock); |
| 94 // printf("enter %u %u %u\n", uid, shardID, lock); |
| 95 info->holdCount += 1; |
| 96 if (info->holdCount != 1) { |
| 97 info->cond.wait(shard.mutex); |
| 98 } |
| 99 // printf("lock %u %u %u\n", uid, shardID, lock); |
| 100 shard.mutex.unlock(); |
| 101 } |
| 102 |
| 103 void LockManagerImpl::unlock(uint32_t uid) |
| 104 { |
| 105 uint32_t shardID; |
| 106 uint32_t lock; |
| 107 getIndexes(uid, &shardID, &lock); |
| 108 LockShard& shard = shards[shardID]; |
| 109 shard.mutex.lock(); |
| 110 LockInfo* info = shard.get(lock); |
| 111 info->holdCount -= 1; |
| 112 if (info->holdCount) { |
| 113 info->cond.signal(); |
| 114 } |
| 115 // printf("unlock %u %u %u\n", uid, shardID, lock); |
| 116 shard.mutex.unlock(); |
| 117 } |
| 118 |
| 119 // Store the impl in a singleton to avoid the need to transfer the lock manager. |
| 120 // This is an awful hack to speed up prototyping. |
| 121 class LockManagerHack { |
| 122 public: |
| 123 ~LockManagerHack() |
| 124 { |
| 125 } |
| 126 PassRefPtr<LockManagerImpl> get() |
| 127 { |
| 128 MutexLocker lock(m); |
| 129 if (!impl) { |
| 130 impl = adoptRef(new LockManagerImpl()); |
| 131 } |
| 132 return impl; |
| 133 } |
| 134 private: |
| 135 Mutex m; |
| 136 RefPtr<LockManagerImpl> impl; |
| 137 }; |
| 138 |
| 139 #pragma clang diagnostic push |
| 140 #pragma clang diagnostic ignored "-Wglobal-constructors" |
| 141 #pragma clang diagnostic ignored "-Wexit-time-destructors" |
| 142 static LockManagerHack hack; |
| 143 #pragma clang diagnostic pop |
| 144 |
| 145 LockManager::LockManager(ExecutionContext*) |
| 146 : impl(hack.get()) |
| 147 { |
| 148 } |
| 149 |
| 150 void LockManager::lock(unsigned long uid) |
| 151 { |
| 152 impl->lock(uid); |
| 153 } |
| 154 |
| 155 void LockManager::unlock(unsigned long uid) |
| 156 { |
| 157 impl->unlock(uid); |
| 158 } |
| 159 |
| 160 void LockManager::nop() |
| 161 { |
| 162 } |
| 163 |
| 164 } // namespace WebCore |
| OLD | NEW |