예제 #1
0
파일: devlock.c 프로젝트: imtx/bareos
/*
 * Unlock write lock
 *  Start any waiting writers in preference to waiting readers
 */
int devlock::writeunlock()
{
    devlock *rwl = this;
    int status, status2;

    if (rwl->valid != DEVLOCK_VALID) {
        return EINVAL;
    }
    if ((status = pthread_mutex_lock(&rwl->mutex)) != 0) {
        return status;
    }
    if (rwl->w_active <= 0) {
        pthread_mutex_unlock(&rwl->mutex);
        Jmsg0(NULL, M_ABORT, 0, _("writeunlock called too many times.\n"));
    }
    rwl->w_active--;
    if (!pthread_equal(pthread_self(), rwl->writer_id)) {
        pthread_mutex_unlock(&rwl->mutex);
        Jmsg0(NULL, M_ABORT, 0, _("writeunlock by non-owner.\n"));
    }
    if (rwl->w_active > 0) {
        status = 0;                       /* writers still active */
    } else {
        lmgr_do_unlock(rwl);
        /* No more writers, awaken someone */
        if (rwl->r_wait > 0) {         /* if readers waiting */
            status = pthread_cond_broadcast(&rwl->read);
        } else if (rwl->w_wait > 0) {
            status = pthread_cond_broadcast(&rwl->write);
        }
    }
    status2 = pthread_mutex_unlock(&rwl->mutex);
    return (status == 0 ? status2 : status);
}
예제 #2
0
파일: devlock.c 프로젝트: imtx/bareos
/*
 * Lock for write access, wait until locked (or error).
 *   Multiple nested write locking is permitted.
 */
int devlock::writelock(int areason, bool acan_take)
{
    devlock *rwl = this;
    int status;

    if (rwl->valid != DEVLOCK_VALID) {
        return EINVAL;
    }
    if ((status = pthread_mutex_lock(&rwl->mutex)) != 0) {
        return status;
    }
    if (rwl->w_active && pthread_equal(rwl->writer_id, pthread_self())) {
        rwl->w_active++;
        pthread_mutex_unlock(&rwl->mutex);
        return 0;
    }
    lmgr_pre_lock(rwl, rwl->priority, __FILE__, __LINE__);
    if (rwl->w_active || rwl->r_active > 0) {
        rwl->w_wait++;                  /* indicate that we are waiting */
        pthread_cleanup_push(devlock_write_release, (void *)rwl);
        while (rwl->w_active || rwl->r_active > 0) {
            if ((status = pthread_cond_wait(&rwl->write, &rwl->mutex)) != 0) {
                lmgr_do_unlock(rwl);
                break;                    /* error, bail out */
            }
        }
        pthread_cleanup_pop(0);
        rwl->w_wait--;                  /* we are no longer waiting */
    }
    if (status == 0) {
        rwl->w_active++;                /* we are running */
        rwl->writer_id = pthread_self(); /* save writer thread's id */
        lmgr_post_lock();
    }
    rwl->reason = areason;
    rwl->can_take = acan_take;
    pthread_mutex_unlock(&rwl->mutex);
    return status;
}
예제 #3
0
파일: rwlock.c 프로젝트: anarexia/bacula
/*
 * Lock for write access, wait until locked (or error).
 *   Multiple nested write locking is permitted.
 */
int rwl_writelock_p(brwlock_t *rwl, const char *file, int line)
{
   int stat;

   if (rwl->valid != RWLOCK_VALID) {
      return EINVAL;
   }
   if ((stat = pthread_mutex_lock(&rwl->mutex)) != 0) {
      return stat;
   }
   if (rwl->w_active && pthread_equal(rwl->writer_id, pthread_self())) {
      rwl->w_active++;
      pthread_mutex_unlock(&rwl->mutex);
      return 0;
   }
   lmgr_pre_lock(rwl, rwl->priority, file, line);
   if (rwl->w_active || rwl->r_active > 0) {
      rwl->w_wait++;                  /* indicate that we are waiting */
      pthread_cleanup_push(rwl_write_release, (void *)rwl);
      while (rwl->w_active || rwl->r_active > 0) {
         if ((stat = pthread_cond_wait(&rwl->write, &rwl->mutex)) != 0) {
            lmgr_do_unlock(rwl);
            break;                    /* error, bail out */
         }
      }
      pthread_cleanup_pop(0);
      rwl->w_wait--;                  /* we are no longer waiting */
   }
   if (stat == 0) {
      rwl->w_active++;                /* we are running */
      rwl->writer_id = pthread_self(); /* save writer thread's id */
      lmgr_post_lock();
   } 
   pthread_mutex_unlock(&rwl->mutex);
   return stat;
}