summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdiskfs/file-lock.c38
-rw-r--r--libfshelp/lock-acquire.c128
-rw-r--r--libfshelp/lock-init.c30
3 files changed, 196 insertions, 0 deletions
diff --git a/libdiskfs/file-lock.c b/libdiskfs/file-lock.c
new file mode 100644
index 00000000..3ffd86e2
--- /dev/null
+++ b/libdiskfs/file-lock.c
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1993, 1994 Free Software Foundation
+
+This file is part of the GNU Hurd.
+
+The GNU Hurd is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+The GNU Hurd is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+error_t
+diskfs_S_file_lock (struct protid *cred, int flags)
+{
+ error_t err;
+ if (!cred)
+ return EOPNOTSUPP;
+ mutex_lock (&cred->po->np->lock);
+ err = fshelp_acquire_lock (&cred->po->np->userlock, cred->po->lock_status,
+ &cred->po->np->lock, flags);
+ mutex_unlcok (&cred->po->np->lock);
+ return err;
+}
+
+
diff --git a/libfshelp/lock-acquire.c b/libfshelp/lock-acquire.c
new file mode 100644
index 00000000..0c1bb788
--- /dev/null
+++ b/libfshelp/lock-acquire.c
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 1993, 1994 Free Software Foundation
+
+This file is part of the GNU Hurd.
+
+The GNU Hurd is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+The GNU Hurd is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "fshelp.h"
+
+error_t
+fshelp_acquire_lock (struct lock_box *box, int *user, struct mutex *mut,
+ int flags)
+{
+ if (!(flags & (LOCK_UN | LOCK_EX | LOCK_SH)))
+ return 0;
+
+ if ((flags & LOCK_UN)
+ && (flags & (LOCK_SH | LOCK_EX)))
+ return EINVAL;
+
+ if (flags & LOCK_EX)
+ flags &= ~LOCK_SH;
+
+ /* flags now contains exactly one of LOCK_UN, LOCK_SH, or LOCK_EX. */
+
+ if (flags & LOCK_UN)
+ {
+ if (*user & LOCK_UN)
+ return EBADF;
+ assert (*user == box->type);
+ assert (*user == LOCK_SH || *user == LOCK_EX);
+ if (*user == LOCK_SH)
+ {
+ if (!--box->shcount)
+ box->lock_type == LOCK_UN;
+ }
+ else if (*user == LOCK_EX)
+ box->lock_type == LOCK_UN;
+
+ if (box->lock_type == LOCK_UN && box->waiting)
+ {
+ box->waiting = 0;
+ condition_broadcast (&box->wait);
+ }
+ *user = LOCK_UN;
+ }
+ else
+ {
+ /* If we have an exclusive lock, release it. */
+ if (*user == LOCK_EX)
+ {
+ *user = LOCK_UN;
+ box->type = LOCK_UN;
+ if (box->waiting)
+ {
+ box->waiting = 0;
+ condition_broadcast (&box->wait);
+ }
+ }
+
+ /* If there is an exclusive lock, wait for it to end. */
+ while (lock->type == LOCK_EX)
+ {
+ if (flags & LOCK_NB)
+ return EWOULDBLOCK;
+ box->waiting = 1;
+ condition_wait (&box->wait, mut);
+ }
+
+ /* If we have a shared lock, release it. */
+ if (*user == LOCK_SH)
+ {
+ *user = LOCK_UN;
+ if (!--box->shcount)
+ {
+ box->type = LOCK_UN;
+ if (box->waiting)
+ {
+ box->waiting = 0;
+ condition_broadcast (&box->wait);
+ }
+ }
+ }
+
+ assert ((flags & LOCK_SH) || (flags & LOCK_EX));
+ if (flags & LOCK_SH)
+ {
+ assert (box->type != LOCK_EX);
+ *user = LOCK_SH;
+ box->type = LOCK_SH;
+ box->shcount++;
+ }
+ else if (flags & LOCK_EX)
+ {
+ /* Wait for any shared locks to finish. */
+ while (box->type == LOCK_SH)
+ {
+ if (flags & LOCK_NB)
+ return EWOULDBLOCK;
+ else
+ {
+ box->waiting = 1;
+ condition_wait (&box->wait, mut);
+ }
+ }
+ box->type = LOCK_EX;
+ *user = LOCK_EX;
+ }
+ }
+ return 0;
+}
+
+
+
diff --git a/libfshelp/lock-init.c b/libfshelp/lock-init.c
new file mode 100644
index 00000000..f32dfae8
--- /dev/null
+++ b/libfshelp/lock-init.c
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1993, 1994 Free Software Foundation
+
+This file is part of the GNU Hurd.
+
+The GNU Hurd is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+The GNU Hurd is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+/* Initialize a lock box. */
+void
+fshelp_lock_init (struct lock_box *box)
+{
+ box->type = LOCK_UN;
+ condition_init (&box->wait);
+ box->waiting = 0;
+ box->shcount = 0;
+}