safelock.c
/* Attempt to lock an open Safelock
 *
 * safelock_lock will fail if it is unable to lock the file within
 * "timeout" microseconds. "timeout == 0" will wait for success.
 *
 * Return 0 on success, otherwise returns errno:
 * - ETIMEDOUT: Lock attempt timed out
 * - EDEADLK: Caller owners the lock
 * - EINVAL: Safelock removed, need to close and re-open the lock file
 * - ..
 */
Attempt to lock an open Safelock
safelock_lock will fail if it is unable to lock the file within
"timeout" microseconds. "timeout == 0" will wait for success.

Return 0 on success, otherwise returns errno:
- ETIMEDOUT: Lock attempt timed out
- EDEADLK: Caller owners the lock
- EINVAL: Safelock removed, need to close and re-open the lock file
Attempt to lock an open Safelock safelock_lock will fail if it is unable to lock the file within " timeout " microseconds . " timeout == 0 " will wait for success . Return 0 on success otherwise returns errno : - ETIMEDOUT : Lock attempt timed out - EDEADLK : Caller owners the lock - EINVAL : Safelock removed need to close and re - open the lock file
int safelock_lock(safelock_t lock, uint64_t timeout, int data)
{
    lock_data_t *shared;
    uint64_t deadline;
    int err;
    assert(lock);
    deadline = timeout;
    if (deadline > SAFELOCK_LOCK_TRY)
        deadline += gettimeofday_us();
    shared = lock->shared;
    err = mutex_lock(&shared->open_mutex, deadline, NULL);
    if (err == ETIMEDOUT) {
        safelock_status_t status;
        err = safelock_fetch_status(lock, &status);
        if (err == ENOTRECOVERABLE || err == EINVAL)
            return err;
        return ETIMEDOUT;
    }
    if (err)
        return err;
    err = data_mutex_lock(lock, NULL);
    if (err) {
        NOFAIL(pthread_mutex_unlock(&shared->open_mutex));
        return err;
    }
    err = mutex_lock(&shared->owner_mutex, SAFELOCK_LOCK_TRY, NULL);
    if (err) {
        NOFAIL(pthread_mutex_unlock(&shared->open_mutex));
        return ENOTRECOVERABLE;
    }
    shared->pid = getpid();
    shared->taken = gettimeofday_us();
    shared->data = data;
    shared->data_valid = 1;
    NOFAIL(pthread_mutex_unlock(&shared->data_mutex));
    lock->locked = 1;
    return 0;
}
int safelock_lock ( safelock_t lock , uint64_t timeout , int data ) { lock_data_t * shared ; uint64_t deadline ; int err ; assert ( lock ) ; deadline = timeout ; if ( deadline > SAFELOCK_LOCK_TRY ) deadline += gettimeofday_us ( ) ; shared = lock -> shared ; err = mutex_lock ( & shared -> open_mutex , deadline , NULL ) ; if ( err == ETIMEDOUT ) { safelock_status_t status ; err = safelock_fetch_status ( lock , & status ) ; if ( err == ENOTRECOVERABLE || err == EINVAL ) return err ; return ETIMEDOUT ; } if ( err ) return err ; err = data_mutex_lock ( lock , NULL ) ; if ( err ) { NOFAIL ( pthread_mutex_unlock ( & shared -> open_mutex ) ) ; return err ; } err = mutex_lock ( & shared -> owner_mutex , SAFELOCK_LOCK_TRY , NULL ) ; if ( err ) { NOFAIL ( pthread_mutex_unlock ( & shared -> open_mutex ) ) ; return ENOTRECOVERABLE ; } shared -> pid = getpid ( ) ; shared -> taken = gettimeofday_us ( ) ; shared -> data = data ; shared -> data_valid = 1 ; NOFAIL ( pthread_mutex_unlock ( & shared -> data_mutex ) ) ; lock -> locked = 1 ; return 0 ; }
Attempt to lock an open Safelock
 safelock_lock will fail if it is unable to lock the file within
 "timeout" microseconds.
Attempt to lock an open Safelock safelock_lock will fail if it is unable to lock the file within " timeout " microseconds .
/* Wait for owner mutex to be freed here */ /* After a timeout, check whether the safelock is broken */ /* Check the lock status after a timeout.
         * ENOTRECOVERABLE: Caller must remove lock
         * EINVAL: Caller must re-open lock */ /* By definition, owner_mutex must be free since we have
     * acquired the open_mutex. owner_mutex is always released before
     * open_mutex. */ /* Failure to obtain the owner_mutex indicates the safelock
         * is unusable or a bug:
         * - corrupted owner_mutex
         * - another process has incorrectly locked owner_mutex */