blob: 5a69b53d9bb95576b2261f996f53a406f63082d1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file thread_native_condvar.c
* @brief Hythread condvar related functions
*/
#include "thread_private.h"
#include <apr_atomic.h>
#include <open/hythread_ext.h>
/** @name Conditional variable
*/
//@{
/**
* Waits on a conditional, handling interruptions and thread state.
*/
IDATA condvar_wait_impl(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano, IDATA interruptable) {
int r;
int disable_count;
hythread_t self;
self = tm_self_tls;
// check interrupted flag
if (interruptable && self->interrupted) {
// clean interrupted flag
IDATA status = hythread_clear_interrupted_other(self);
assert(status == TM_ERROR_INTERRUPT);
return TM_ERROR_INTERRUPT;
}
// Store provided cond into current thread cond
self->current_condition = interruptable ? cond : NULL;
disable_count = hythread_reset_suspend_disable();
r = os_cond_timedwait(cond, mutex, ms, nano);
hythread_set_suspend_disable(disable_count);
self->current_condition = NULL;
// check interrupted flag
if (interruptable && self->interrupted) {
// clean interrupted flag
IDATA status = hythread_clear_interrupted_other(self);
assert(status == TM_ERROR_INTERRUPT);
return TM_ERROR_INTERRUPT;
}
return r;
}
/**
* Instructs the current thread to wait until it is signaled to wake up.
*
* @param[in] cond the condition variable on which to block
* @param[in] mutex the mutex that must be locked upon entering this function
* @sa apr_thread_cond_wait()
* @return
* TM_NO_ERROR on success
*/
IDATA VMCALL hycond_wait(hycond_t *cond, osmutex_t *mutex) {
return condvar_wait_impl(cond, mutex, 0, 0, WAIT_NONINTERRUPTABLE);
}
/**
* Instructs the current thread to wait until signaled to wake up or
* the specified timeout is elapsed.
*
* @param[in] cond the condition variable on which to block.
* @param[in] mutex the mutex that must be locked upon entering this function
* @param[in] ms amount of time in milliseconds to wait
* @param[in] nano amount of time in nanoseconds to wait
* @sa apr_thread_cond_timedwait()
* @return
* TM_NO_ERROR on success
*/
IDATA VMCALL hycond_wait_timed(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano) {
return condvar_wait_impl(cond, mutex, ms, nano, WAIT_NONINTERRUPTABLE);
}
/**
* Instructs the current thread to wait until signaled to wake up or timeout.
* Directly using OS interfaces.
* This function does not implement interruptability and thread state functionality.
*/
IDATA VMCALL hycond_wait_timed_raw(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano) {
return os_cond_timedwait(cond, mutex, ms, nano);
}
/**
* Instructs the current thread to wait until signaled to wake up or
* the specified timeout is elapsed.
*
* @param[in] cond the condition variable on which to block.
* @param[in] mutex the mutex that must be locked upon entering this function
* @param[in] ms amount of time in milliseconds to wait
* @param[in] nano amount of time in nanoseconds to wait
* @sa apr_thread_cond_timedwait()
* @return
* TM_NO_ERROR on success
* TM_THREAD_INTERRUPTED in case thread was interrupted during wait.
*/
IDATA VMCALL hycond_wait_interruptable(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano) {
return condvar_wait_impl(cond, mutex, ms, nano, WAIT_INTERRUPTABLE);
}
//@}