Beispiel #1
0
/**
 * Locking routine.
 * @param type: as passed by user.
 * @param lock: as passed by user.
 * @param func: caller location.
 * @param file: caller location.
 * @param line: caller location.
 * @param tryfunc: the pthread_mutex_trylock or similar function.
 * @param timedfunc: the pthread_mutex_timedlock or similar function.
 *	Uses absolute timeout value.
 * @param arg: what to pass to tryfunc and timedlock.
 * @param exclusive: if lock must be exclusive (only one allowed).
 * @param getwr: if attempts to get writelock (or readlock) for rwlocks.
 */
static void 
checklock_lockit(enum check_lock_type type, struct checked_lock* lock,
        const char* func, const char* file, int line,
	int (*tryfunc)(void*), int (*timedfunc)(void*, struct timespec*),
	void* arg, int exclusive, int getwr)
{
	int err;
	int contend = 0;
	struct thr_check *thr = (struct thr_check*)pthread_getspecific(
		thr_debug_key);
	checktype(type, lock, func, file, line);
	if(!thr) lock_error(lock, func, file, line, "no thread info");
	
	acquire_locklock(lock, func, file, line);
	lock->wait_count ++;
	thr->waiting = lock;
	if(exclusive && lock->hold_count > 0 && lock->holder == thr) 
		lock_error(lock, func, file, line, "thread already owns lock");
	if(type==check_lock_rwlock && getwr && lock->writeholder == thr)
		lock_error(lock, func, file, line, "thread already has wrlock");
	LOCKRET(pthread_mutex_unlock(&lock->lock));

	/* first try; if busy increase contention counter */
	if((err=tryfunc(arg))) {
		struct timespec to;
		if(err != EBUSY) log_err("trylock: %s", strerror(err));
		to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT;
		to.tv_nsec = 0;
		if((err=timedfunc(arg, &to))) {
			if(err == ETIMEDOUT)
				lock_error(lock, func, file, line, 
					"timeout possible deadlock");
			log_err("timedlock: %s", strerror(err));
		}
		contend ++;
	}
	/* got the lock */

	acquire_locklock(lock, func, file, line);
	lock->contention_count += contend;
	lock->history_count++;
	if(exclusive && lock->hold_count > 0)
		lock_error(lock, func, file, line, "got nonexclusive lock");
	if(type==check_lock_rwlock && getwr && lock->writeholder)
		lock_error(lock, func, file, line, "got nonexclusive wrlock");
	if(type==check_lock_rwlock && getwr)
		lock->writeholder = thr;
	/* check the memory areas for unauthorized changes,
	 * between last unlock time and current lock time.
	 * we check while holding the lock (threadsafe).
	 */
	if(getwr || exclusive)
		prot_check(lock, func, file, line);
	finish_acquire_lock(thr, lock, func, file, line);
	LOCKRET(pthread_mutex_unlock(&lock->lock));
}
Beispiel #2
0
int
__try_tempname (char *tmpl, int suffixlen, void *args,
                int (*tryfunc) (char *, void *))
{
  int len;
  char *XXXXXX;
  static uint64_t value;
  uint64_t random_time_bits;
  unsigned int count;
  int fd = -1;
  int save_errno = errno;

  /* A lower bound on the number of temporary files to attempt to
     generate.  The maximum total number of temporary file names that
     can exist for a given template is 62**6.  It should never be
     necessary to try all of these combinations.  Instead if a reasonable
     number of names is tried (we define reasonable as 62**3) fail to
     give the system administrator the chance to remove the problems.  */
#define ATTEMPTS_MIN (62 * 62 * 62)

  /* The number of times to attempt to generate a temporary file.  To
     conform to POSIX, this must be no smaller than TMP_MAX.  */
#if ATTEMPTS_MIN < TMP_MAX
  unsigned int attempts = TMP_MAX;
#else
  unsigned int attempts = ATTEMPTS_MIN;
#endif

  len = strlen (tmpl);
  if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
    {
      __set_errno (EINVAL);
      return -1;
    }

  /* This is where the Xs start.  */
  XXXXXX = &tmpl[len - 6 - suffixlen];

  /* Get some more or less random data.  */
#ifdef RANDOM_BITS
  RANDOM_BITS (random_time_bits);
#else
  {
    struct timeval tv;
    __gettimeofday (&tv, NULL);
    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
  }
#endif
  value += random_time_bits ^ __getpid ();

  for (count = 0; count < attempts; value += 7777, ++count)
    {
      uint64_t v = value;

      /* Fill in the random bits.  */
      XXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXX[5] = letters[v % 62];

      fd = tryfunc (tmpl, args);
      if (fd >= 0)
        {
          __set_errno (save_errno);
          return fd;
        }
      else if (errno != EEXIST)
        return -1;
    }

  /* We got out of the loop because we ran out of combinations to try.  */
  __set_errno (EEXIST);
  return -1;
}