| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- /*
- * Description (nslock.c)
- *
- * This modules provides an interprocess locking mechanism, based
- * on a named lock.
- */
- #include "netsite.h"
- #include "base/file.h"
- #define __PRIVATE_NSLOCK
- #include "nslock.h"
- #include <assert.h>
- char * NSLock_Program = "NSLOCK";
- #ifdef FILE_UNIX
- /*
- * The process-wide list of locks, NSLock_List, is protected by the
- * critical section, NSLock_Crit.
- */
- CRITICAL NSLock_Crit = 0;
- NSLock_t * NSLock_List = 0;
- #endif /* FILE_UNIX */
- /*
- * Description (nsLockOpen)
- *
- * This function is used to initialize a handle for a lock. The
- * caller specifies a unique name for the lock, and a handle is
- * returned. The returned handle should be used by only one
- * thread at a time, i.e. if multiple threads in a process are
- * using the same lock, they should either have their own handles
- * or protect a single handle with a critical section.
- *
- * Arguments:
- *
- * errp - error frame list pointer (may be null)
- * lockname - pointer to name of lock
- * plock - pointer to returned handle for lock
- *
- * Returns:
- *
- * If successful, a handle for the specified lock is returned via
- * 'plock', and the return value is zero. Otherwise the return
- * value is a negative error code (see nslock.h), and an error
- * frame is generated if an error frame list was provided.
- */
- NSAPI_PUBLIC int nsLockOpen(NSErr_t * errp, char * lockname, void **plock)
- {
- NSLock_t * nl = 0; /* pointer to lock structure */
- int len; /* length of lockname */
- int eid;
- int rv;
- #ifdef FILE_UNIX
- /* Have we created the critical section for NSLock_List yet? */
- if (NSLock_Crit == 0) {
- /* Narrow the window for simultaneous initialization */
- NSLock_Crit = (CRITICAL)(-1);
- /* Create it */
- NSLock_Crit = crit_init();
- }
- /* Lock the list of locks */
- crit_enter(NSLock_Crit);
- /* See if a lock with the specified name exists already */
- for (nl = NSLock_List; nl != 0; nl = nl->nl_next) {
- if (!strcmp(nl->nl_name, lockname)) break;
- }
- /* Create a new lock if we didn't find it */
- if (nl == 0) {
- len = strlen(lockname);
- nl = (NSLock_t *)PERM_MALLOC(sizeof(NSLock_t) + len + 5);
- if (nl == 0) goto err_nomem;
- nl->nl_name = (char *)(nl + 1);
- strcpy(nl->nl_name, lockname);
- strcpy(&nl->nl_name[len], ".lck");
- nl->nl_cnt = 0;
- nl->nl_fd = open(nl->nl_name, O_RDWR|O_CREAT|O_EXCL, 0644);
- if (nl->nl_fd < 0) {
- if (errno != EEXIST) {
- crit_exit(NSLock_Crit);
- goto err_create;
- }
- /* O_RDWR or O_WRONLY is required to use lockf on Solaris */
- nl->nl_fd = open(nl->nl_name, O_RDWR, 0);
- if (nl->nl_fd < 0) {
- crit_exit(NSLock_Crit);
- goto err_open;
- }
- }
- /* Remove ".lck" from the lock name */
- nl->nl_name[len] = 0;
- /* Create a critical section for this lock (gag!) */
- nl->nl_crit = crit_init();
- /* Add this lock to NSLock_List */
- nl->nl_next = NSLock_List;
- NSLock_List = nl;
- }
- crit_exit(NSLock_Crit);
- #else
- /* write me */
- nl = (void *)4;
- #endif /* FILE_UNIX */
- *plock = (void *)nl;
- return 0;
- err_nomem:
- eid = NSLERR1000;
- rv = NSLERRNOMEM;
- nserrGenerate(errp, rv, eid, NSLock_Program, 0);
- goto punt;
- err_create:
- eid = NSLERR1020;
- rv = NSLERRCREATE;
- goto err_file;
- err_open:
- eid = NSLERR1040;
- rv = NSLERROPEN;
- err_file:
- nserrGenerate(errp, rv, eid, NSLock_Program, 1, nl->nl_name);
- punt:
- if (nl) {
- FREE(nl);
- }
- *plock = 0;
- return rv;
- }
- /*
- * Description (nsLockAcquire)
- *
- * This function is used to acquire exclusive ownership of a lock
- * previously accessed via nsLockOpen(). The calling thread will
- * be blocked until the lock is acquired. Other threads in the
- * process should not be blocked.
- *
- * Arguments:
- *
- * errp - error frame list pointer (may be null)
- * lock - handle for lock from nsLockOpen()
- *
- * Returns:
- *
- * If successful, the return value is zero. Otherwise the return
- * value is a negative error code (see nslock.h), and an error
- * frame is generated if an error frame list was provided.
- */
- NSAPI_PUBLIC int nsLockAcquire(NSErr_t * errp, void * lock)
- {
- NSLock_t * nl = (NSLock_t *)lock;
- int eid;
- int rv;
- #ifdef FILE_UNIX
- /* Enter the critical section for the lock */
- crit_enter(nl->nl_crit);
- /* Acquire the file lock if we haven't already */
- if (nl->nl_cnt == 0) {
- rv = system_flock(nl->nl_fd);
- if (rv) {
- crit_exit(nl->nl_crit);
- goto err_lock;
- }
- }
- /* Bump the lock count */
- nl->nl_cnt++;
- crit_exit(nl->nl_crit);
- #else
- /* write me */
- #endif /* FILE_UNIX */
- /* Indicate success */
- return 0;
- err_lock:
- eid = NSLERR1100;
- rv = NSLERRLOCK;
- nserrGenerate(errp, rv, eid, NSLock_Program, 1, nl->nl_name);
- return rv;
- }
- /*
- * Description (nsLockRelease)
- *
- * This function is used to release exclusive ownership to a lock
- * that was previously obtained via nsLockAcquire().
- *
- * Arguments:
- *
- * lock - handle for lock from nsLockOpen()
- */
- NSAPI_PUBLIC void nsLockRelease(void * lock)
- {
- NSLock_t * nl = (NSLock_t *)lock;
- #ifdef FILE_UNIX
- assert(nl->nl_cnt > 0);
- crit_enter(nl->nl_crit);
- if (--nl->nl_cnt <= 0) {
- system_ulock(nl->nl_fd);
- nl->nl_cnt = 0;
- }
- crit_exit(nl->nl_crit);
- #endif /* FILE_UNIX */
- }
- /*
- * Description (nsLockClose)
- *
- * This function is used to close a lock handle that was previously
- * acquired via nsLockOpen(). The lock should not be owned.
- *
- * Arguments:
- *
- * lock - handle for lock from nsLockOpen()
- */
- NSAPI_PUBLIC void nsLockClose(void * lock)
- {
- NSLock_t * nl = (NSLock_t *)lock;
- #ifdef FILE_UNIX
- /* Don't do anything with the lock, since it will get used again */
- #if 0
- crit_enter(nl->nl_crit);
- close(nl->nl_fd);
- crit_exit(nl->nl_crit);
- FREE(nl);
- #endif
- #else
- /* write me */
- #endif FILE_UNIX
- }
|