diff options
-rw-r--r-- | libdiskfs/file-lock.c | 38 | ||||
-rw-r--r-- | libfshelp/lock-acquire.c | 128 | ||||
-rw-r--r-- | libfshelp/lock-init.c | 30 |
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; +} |