aboutsummaryrefslogtreecommitdiff
path: root/libatomic/config/mingw/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'libatomic/config/mingw/lock.c')
-rw-r--r--libatomic/config/mingw/lock.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/libatomic/config/mingw/lock.c b/libatomic/config/mingw/lock.c
index 17faa66..8b0b4dd 100644
--- a/libatomic/config/mingw/lock.c
+++ b/libatomic/config/mingw/lock.c
@@ -87,21 +87,30 @@ libat_lock_n (void *ptr, size_t n)
{
uintptr_t h = addr_hash (ptr);
size_t i = 0;
+ size_t nlocks
+ = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
/* Don't lock more than all the locks we have. */
- if (n > PAGE_SIZE)
- n = PAGE_SIZE;
+ if (nlocks > NLOCKS)
+ nlocks = NLOCKS;
- do
+ if (__builtin_expect (h + nlocks > NLOCKS, 0))
+ {
+ size_t j = h + nlocks - NLOCKS;
+ for (; i < j; ++i)
+ {
+ if (!locks[i].mutex)
+ locks[i].mutex = CreateMutex (NULL, FALSE, NULL);
+ WaitForSingleObject (locks[i].mutex, INFINITE);
+ }
+ }
+
+ for (; i < nlocks; ++i)
{
if (!locks[h].mutex)
- locks[h].mutex = CreateMutex (NULL, FALSE, NULL);
- WaitForSingleObject (locks[h].mutex, INFINITE);
- if (++h == NLOCKS)
- h = 0;
- i += WATCH_SIZE;
+ locks[h].mutex = CreateMutex (NULL, FALSE, NULL);
+ WaitForSingleObject (locks[h++].mutex, INFINITE);
}
- while (i < n);
}
void
@@ -109,17 +118,22 @@ libat_unlock_n (void *ptr, size_t n)
{
uintptr_t h = addr_hash (ptr);
size_t i = 0;
+ size_t nlocks
+ = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
- if (n > PAGE_SIZE)
- n = PAGE_SIZE;
+ /* Don't lock more than all the locks we have. */
+ if (nlocks > NLOCKS)
+ nlocks = NLOCKS;
- do
+ if (__builtin_expect (h + nlocks > NLOCKS, 0))
{
- if (locks[h].mutex)
- ReleaseMutex (locks[h].mutex);
- if (++h == NLOCKS)
- h = 0;
- i += WATCH_SIZE;
+ size_t j = h + nlocks - NLOCKS;
+ for (; i < j; ++i)
+ if (locks[i].mutex)
+ ReleaseMutex (locks[i].mutex);
}
- while (i < n);
+
+ for (; i < nlocks; ++i, ++h)
+ if (locks[h].mutex)
+ ReleaseMutex (locks[h].mutex);
}