Esempio n. 1
0
/**
 * 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
}
Esempio n. 2
0
/* 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;
}