/** * try lock the mutex in given time * * @param s * The timeout value in seconds * @param ms * The timeout value in milliseconds * @return * true, if lock successed */ bool Mutex::timedlock(unsigned s, unsigned ms) { #if NUT_PLATFORM_OS_WINDOWS && !NUT_PLATFORM_CC_MINGW const DWORD dw_milliseconds = s * 1000 + ms; return WAIT_OBJECT_0 == ::WaitForSingleObject(_hmutex, dw_milliseconds); #elif NUT_PLATFORM_OS_MAC struct timeval abstime; ::gettimeofday(&abstime, NULL); abstime.tv_sec += s; abstime.tv_usec += ((long)ms) * 1000; return 0 == _pthread_mutex_timedlock(&_mutex, &abstime); #else struct timespec abstime; # if NUT_PLATFORM_OS_WINDOWS && NUT_PLATFORM_CC_MINGW clock_getrealtime(&abstime); # else ::clock_gettime(CLOCK_REALTIME, &abstime); # endif abstime.tv_sec += s; abstime.tv_nsec += ((long)ms) * 1000 * 1000; const int lock_result = ::pthread_mutex_timedlock(&_mutex, &abstime); /** returned values : * 0, lock ok * EAGAIN, The mutex couldn't be acquired because the maximum number of recursive locks for the mutex has been exceeded. * EDEADLK, The current thread already owns the mutex. * EINVAL, The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex' current priority ceiling; the process or thread would have blocked, and the abs_timeout parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million; or the value specified by mutex doesn't refer to an initialized mutex object. * ETIMEDOUT, The mutex couldn't be locked before the specified timeout expired */ return 0 == lock_result; #endif }
/* Check on the initialisation thread and set cert policy. The `misc` parameter is never used (on Linux platform). The pointer of initialised LDAP struct is passed to the `ld` parameter. Return 1 if the initialisation thread is finished, 0 if it is still in progress, and -1 for error. */ int _ldap_finish_init_thread(char async, XTHREAD thread, int *timeout, void *misc, LDAP **ld) { int rc = 0; ldapInitThreadData *val = (ldapInitThreadData *)misc; struct timespec ts; struct timeval now; struct timespec rest; int wait_msec = 100; long long nanosecs = 0; unsigned long long start_time, end_time; int retval = 0; /* Sanity check. */ if (val == NULL) return -1; DEBUG("_ldap_finish_init_thread (async:%d, thread:%lu, timeout:%d, misc:%p)", async, thread, *timeout, misc); if (async || *timeout == -1) { wait_msec = 100; } else { wait_msec = *timeout; } /* Create absolute time. */ rc = gettimeofday(&now, NULL); if (rc != 0) { PyErr_BadInternalCall(); retval = -1; goto end; } ts.tv_sec = now.tv_sec; nanosecs = (now.tv_usec + 1000UL * wait_msec) * 1000UL; while (nanosecs >= 1000000000) { /* Nanosecs are over 1 second. */ ts.tv_sec += 1; nanosecs -= 1000000000; } ts.tv_nsec = (long)nanosecs; /* Waiting on thread to release the lock. */ rc = _pthread_mutex_timedlock(val->mux, &ts); switch (rc) { case ETIMEDOUT: if (async == 0 && *timeout != -1) { pthread_cancel(thread); set_exception(NULL, LDAP_TIMEOUT); free(val->ld); retval = -1; goto end; } return 0; case 0: if (val->flag == 0) { /* Premature locking, thread function is not finished. */ pthread_mutex_unlock(val->mux); /* Set 5ms for sleeping time. */ rest.tv_sec = 0; rest.tv_nsec = 5000000; /* Take a nap, try to avoid constantly locking from the main thread. */ nanosleep(&rest, NULL); if (*timeout != -1) { *timeout -= 5; if (*timeout < 0) *timeout = 0; } return 0; } /* Block until thread is finished, but if it's async already waited enough on releasing the lock. */ rc = pthread_join(thread, NULL); /* Thread is finished. */ if (val->retval != LDAP_SUCCESS) { #ifdef HAVE_KRB5 if (val->info->errmsg != NULL) { PyObject *error = get_error_by_code(0x31); if (error == NULL) goto end; PyErr_SetString(error, val->info->errmsg); Py_DECREF(error); } else { set_exception(NULL, val->retval); } #else set_exception(NULL, val->retval); #endif free(val->ld); retval = -1; goto end; } if (*timeout != -1) { /* Calculate passed time in milliseconds. */ start_time = (unsigned long long)(now.tv_sec) * 1000 + (unsigned long long)(now.tv_usec) / 1000; gettimeofday(&now, NULL); end_time = (unsigned long long)(now.tv_sec) * 1000 + (unsigned long long)(now.tv_usec) / 1000; /* Deduct the passed time from the overall timeout. */ *timeout -= (end_time - start_time); if (*timeout < 0) *timeout = 0; } /* Set initialised LDAP struct pointer. */ *ld = val->ld; retval = 1; goto end; default: /* The thread is failed. */ PyErr_BadInternalCall(); retval = -1; goto end; } end: /* Clean-up. */ free(val->url); pthread_mutex_destroy(val->mux); free(val->mux); free(val); return retval; }