[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[hurd] 33/64: Add atomicity support to fshelp_acquire_lock
From: |
Samuel Thibault |
Subject: |
[hurd] 33/64: Add atomicity support to fshelp_acquire_lock |
Date: |
Wed, 10 Dec 2014 15:17:06 +0000 |
This is an automated email from the git hooks/post-receive script.
sthibault pushed a commit to branch upstream
in repository hurd.
commit 7ca4c02513d7c6998d9c92dafb3c0fcbe8d6dd6d
Author: Samuel Thibault <address@hidden>
Date: Thu Nov 27 19:05:57 2014 +0100
Add atomicity support to fshelp_acquire_lock
This adds support for the __LOCK_ATOMIC flag which requests atomicity of
SH->EX
upgrades and EX->SH downgrades.
* libfshelp/lock-acquire.c (__LOCK_ATOMIC): New macro
(fshelp_acquire_lock): When __LOCK_ATOMIC is set, do not release the
lock early, change the lock hold atomically instead. On upgrade to LOCK_EX,
prevent new shared locks from being acquired to avoid starvation.
---
libfshelp/lock-acquire.c | 95 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 77 insertions(+), 18 deletions(-)
diff --git a/libfshelp/lock-acquire.c b/libfshelp/lock-acquire.c
index 574bc5c..06c93d8 100644
--- a/libfshelp/lock-acquire.c
+++ b/libfshelp/lock-acquire.c
@@ -23,17 +23,30 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA
02139, USA. */
#define EWOULDBLOCK EAGAIN /* XXX */
+/* Remove this when glibc has it. */
+#ifndef __LOCK_ATOMIC
+#define __LOCK_ATOMIC 16
+#endif
+
error_t
fshelp_acquire_lock (struct lock_box *box, int *user, pthread_mutex_t *mut,
int flags)
{
+ int atomic = 0;
+
if (!(flags & (LOCK_UN | LOCK_EX | LOCK_SH)))
return 0;
if ((flags & LOCK_UN)
&& (flags & (LOCK_SH | LOCK_EX)))
return EINVAL;
-
+
+ if (flags & __LOCK_ATOMIC)
+ {
+ atomic = 1;
+ flags &= ~__LOCK_ATOMIC;
+ }
+
if (flags & LOCK_EX)
flags &= ~LOCK_SH;
@@ -44,8 +57,10 @@ fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut,
if (*user & LOCK_UN)
return 0;
- assert (*user == box->type);
- assert (*user == LOCK_SH || *user == LOCK_EX);
+ assert (*user == box->type ||
+ (*user == LOCK_SH && box->type == (LOCK_SH | LOCK_EX)));
+ assert (*user == LOCK_SH || *user == LOCK_EX ||
+ *user == (LOCK_SH | LOCK_EX));
if (*user == LOCK_SH)
{
@@ -60,12 +75,39 @@ fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut,
box->waiting = 0;
pthread_cond_broadcast (&box->wait);
}
+ if (box->type == (LOCK_SH | LOCK_EX) && box->shcount == 1 &&
box->waiting)
+ {
+ box->waiting = 0;
+ pthread_cond_broadcast (&box->wait);
+ }
*user = LOCK_UN;
}
else
{
+ if (atomic && *user == (flags & (LOCK_SH | LOCK_EX)))
+ /* Already have it the right way. */
+ return 0;
+
+ if (atomic && *user == LOCK_EX && flags & LOCK_SH)
+ {
+ /* Easy atomic change. */
+ *user = LOCK_SH;
+ box->type = LOCK_SH;
+ box->shcount = 1;
+ if (box->waiting)
+ {
+ box->waiting = 0;
+ pthread_cond_broadcast (&box->wait);
+ }
+ return 0;
+ }
+
+ /* We can not have two people upgrading their lock, this is a deadlock!
*/
+ if (*user == LOCK_SH && atomic && box->type == (LOCK_SH | LOCK_EX))
+ return EDEADLK;
+
/* If we have an exclusive lock, release it. */
- if (*user == LOCK_EX)
+ if (*user == LOCK_EX && !atomic)
{
*user = LOCK_UN;
box->type = LOCK_UN;
@@ -75,19 +117,9 @@ fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut,
pthread_cond_broadcast (&box->wait);
}
}
-
- /* If there is an exclusive lock, wait for it to end. */
- while (box->type == LOCK_EX)
- {
- if (flags & LOCK_NB)
- return EWOULDBLOCK;
- box->waiting = 1;
- if (pthread_hurd_cond_wait_np (&box->wait, mut))
- return EINTR;
- }
/* If we have a shared lock, release it. */
- if (*user == LOCK_SH)
+ if (*user == LOCK_SH && !atomic)
{
*user = LOCK_UN;
if (!--box->shcount)
@@ -99,12 +131,29 @@ fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut,
pthread_cond_broadcast (&box->wait);
}
}
+ if (box->type == (LOCK_SH | LOCK_EX) && box->shcount == 1 &&
+ box->waiting)
+ {
+ box->waiting = 0;
+ pthread_cond_broadcast (&box->wait);
+ }
}
-
+
+ /* If there is another exclusive lock or a pending upgrade, wait for it
to
+ end. */
+ while (box->type & LOCK_EX)
+ {
+ if (flags & LOCK_NB)
+ return EWOULDBLOCK;
+ box->waiting = 1;
+ if (pthread_hurd_cond_wait_np (&box->wait, mut))
+ return EINTR;
+ }
+
assert ((flags & LOCK_SH) || (flags & LOCK_EX));
if (flags & LOCK_SH)
{
- assert (box->type != LOCK_EX);
+ assert (!(box->type & LOCK_EX));
*user = LOCK_SH;
box->type = LOCK_SH;
box->shcount++;
@@ -112,17 +161,27 @@ fshelp_acquire_lock (struct lock_box *box, int *user,
pthread_mutex_t *mut,
else if (flags & LOCK_EX)
{
/* Wait for any shared (and exclusive) locks to finish. */
- while (box->type != LOCK_UN)
+ while ((*user == LOCK_SH && box->shcount > 1) ||
+ (*user == LOCK_UN && box->type != LOCK_UN))
{
if (flags & LOCK_NB)
return EWOULDBLOCK;
else
{
+ /* Tell others that we are upgrading. */
+ if (*user == LOCK_SH && atomic)
+ box->type = LOCK_SH | LOCK_EX;
+
box->waiting = 1;
if (pthread_hurd_cond_wait_np (&box->wait, mut))
return EINTR;
}
}
+ if (*user == LOCK_SH)
+ {
+ assert (box->shcount == 1);
+ box->shcount = 0;
+ }
box->type = LOCK_EX;
*user = LOCK_EX;
}
--
Alioth's /usr/local/bin/git-commit-notice on
/srv/git.debian.org/git/pkg-hurd/hurd.git
- [hurd] 58/64: trans/symlink: disable default payload to port mapping, (continued)
- [hurd] 58/64: trans/symlink: disable default payload to port mapping, Samuel Thibault, 2014/12/10
- [hurd] 34/64: Revert "random: fix a receiver lookup", Samuel Thibault, 2014/12/10
- [hurd] 61/64: Fix mode of nodes created with mkfile, Samuel Thibault, 2014/12/10
- [hurd] 62/64: include: don't install nonexistent refcount.h, Samuel Thibault, 2014/12/10
- [hurd] 37/64: libports: add `ports_lookup_payload' and `ports_payload_get_name', Samuel Thibault, 2014/12/10
- [hurd] 44/64: auth: add a payload-aware intrans function, Samuel Thibault, 2014/12/10
- [hurd] 45/64: console: add a payload-aware intrans function, Samuel Thibault, 2014/12/10
- [hurd] 30/64: libpager: make the request queue more memory-efficient, Samuel Thibault, 2014/12/10
- [hurd] 63/64: fakeroot: Fix initializing default faked field of nodes, Samuel Thibault, 2014/12/10
- [hurd] 60/64: hurd: add intranpayload functions to all hurd types, Samuel Thibault, 2014/12/10
- [hurd] 33/64: Add atomicity support to fshelp_acquire_lock,
Samuel Thibault <=
- [hurd] 59/64: utils/rpctrace: make `trace_and_forward' payload-aware, Samuel Thibault, 2014/12/10
- [hurd] 53/64: term: add a payload-aware intrans function, Samuel Thibault, 2014/12/10
- [hurd] 57/64: trans/streamio: make the translator payload-aware, Samuel Thibault, 2014/12/10
- [hurd] 64/64: Merge remote-tracking branch 'upstream/master' into upstream, Samuel Thibault, 2014/12/10
- [hurd] 04/64: Fix mach-defpager's kalloc values, Samuel Thibault, 2014/12/10
- [hurd] 06/64: utils/rpctrace: fix crash while printing messages, Samuel Thibault, 2014/12/10
- [hurd] 03/64: Avoid hitting VM_MAX_ADDRESS, Samuel Thibault, 2014/12/10
- [hurd] 05/64: Make procfs appear in /proc/mounts, Samuel Thibault, 2014/12/10
- [hurd] 08/64: Fix recording complete path of passive relative translators, Samuel Thibault, 2014/12/10
- [hurd] 07/64: Let pty readers always read end of writer output, Samuel Thibault, 2014/12/10