1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3321936Shselasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5321936Shselasky * 6321936Shselasky * This software is available to you under a choice of one of two 7321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 8321936Shselasky * General Public License (GPL) Version 2, available from the file 9321936Shselasky * COPYING in the main directory of this source tree, or the 10321936Shselasky * OpenIB.org BSD license below: 11321936Shselasky * 12321936Shselasky * Redistribution and use in source and binary forms, with or 13321936Shselasky * without modification, are permitted provided that the following 14321936Shselasky * conditions are met: 15321936Shselasky * 16321936Shselasky * - Redistributions of source code must retain the above 17321936Shselasky * copyright notice, this list of conditions and the following 18321936Shselasky * disclaimer. 19321936Shselasky * 20321936Shselasky * - Redistributions in binary form must reproduce the above 21321936Shselasky * copyright notice, this list of conditions and the following 22321936Shselasky * disclaimer in the documentation and/or other materials 23321936Shselasky * provided with the distribution. 24321936Shselasky * 25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32321936Shselasky * SOFTWARE. 33321936Shselasky * 34321936Shselasky */ 35321936Shselasky 36321936Shselasky#if HAVE_CONFIG_H 37321936Shselasky# include <config.h> 38321936Shselasky#endif /* HAVE_CONFIG_H */ 39321936Shselasky 40321936Shselasky#include <complib/cl_event.h> 41321936Shselasky#include <complib/cl_debug.h> 42321936Shselasky#include <sys/time.h> 43321936Shselasky#include <sys/errno.h> 44321936Shselasky 45321936Shselaskyvoid cl_event_construct(IN cl_event_t * p_event) 46321936Shselasky{ 47321936Shselasky CL_ASSERT(p_event); 48321936Shselasky 49321936Shselasky p_event->state = CL_UNINITIALIZED; 50321936Shselasky} 51321936Shselasky 52321936Shselaskycl_status_t cl_event_init(IN cl_event_t * const p_event, 53321936Shselasky IN const boolean_t manual_reset) 54321936Shselasky{ 55321936Shselasky CL_ASSERT(p_event); 56321936Shselasky 57321936Shselasky cl_event_construct(p_event); 58321936Shselasky 59321936Shselasky pthread_cond_init(&p_event->condvar, NULL); 60321936Shselasky pthread_mutex_init(&p_event->mutex, NULL); 61321936Shselasky p_event->signaled = FALSE; 62321936Shselasky p_event->manual_reset = manual_reset; 63321936Shselasky p_event->state = CL_INITIALIZED; 64321936Shselasky 65321936Shselasky return CL_SUCCESS; 66321936Shselasky} 67321936Shselasky 68321936Shselaskyvoid cl_event_destroy(IN cl_event_t * const p_event) 69321936Shselasky{ 70321936Shselasky CL_ASSERT(cl_is_state_valid(p_event->state)); 71321936Shselasky 72321936Shselasky /* Destroy only if the event was constructed */ 73321936Shselasky if (p_event->state == CL_INITIALIZED) { 74321936Shselasky pthread_cond_broadcast(&p_event->condvar); 75321936Shselasky pthread_cond_destroy(&p_event->condvar); 76321936Shselasky pthread_mutex_destroy(&p_event->mutex); 77321936Shselasky } 78321936Shselasky 79321936Shselasky p_event->state = CL_UNINITIALIZED; 80321936Shselasky} 81321936Shselasky 82321936Shselaskycl_status_t cl_event_signal(IN cl_event_t * const p_event) 83321936Shselasky{ 84321936Shselasky /* Make sure that the event was started */ 85321936Shselasky CL_ASSERT(p_event->state == CL_INITIALIZED); 86321936Shselasky 87321936Shselasky pthread_mutex_lock(&p_event->mutex); 88321936Shselasky p_event->signaled = TRUE; 89321936Shselasky /* Wake up one or all depending on whether the event is auto-resetting. */ 90321936Shselasky if (p_event->manual_reset) 91321936Shselasky pthread_cond_broadcast(&p_event->condvar); 92321936Shselasky else 93321936Shselasky pthread_cond_signal(&p_event->condvar); 94321936Shselasky 95321936Shselasky pthread_mutex_unlock(&p_event->mutex); 96321936Shselasky 97321936Shselasky return CL_SUCCESS; 98321936Shselasky} 99321936Shselasky 100321936Shselaskycl_status_t cl_event_reset(IN cl_event_t * const p_event) 101321936Shselasky{ 102321936Shselasky /* Make sure that the event was started */ 103321936Shselasky CL_ASSERT(p_event->state == CL_INITIALIZED); 104321936Shselasky 105321936Shselasky pthread_mutex_lock(&p_event->mutex); 106321936Shselasky p_event->signaled = FALSE; 107321936Shselasky pthread_mutex_unlock(&p_event->mutex); 108321936Shselasky 109321936Shselasky return CL_SUCCESS; 110321936Shselasky} 111321936Shselasky 112321936Shselaskycl_status_t cl_event_wait_on(IN cl_event_t * const p_event, 113321936Shselasky IN const uint32_t wait_us, 114321936Shselasky IN const boolean_t interruptible) 115321936Shselasky{ 116321936Shselasky cl_status_t status; 117321936Shselasky int wait_ret; 118321936Shselasky struct timespec timeout; 119321936Shselasky struct timeval curtime; 120321936Shselasky 121321936Shselasky /* Make sure that the event was Started */ 122321936Shselasky CL_ASSERT(p_event->state == CL_INITIALIZED); 123321936Shselasky 124321936Shselasky pthread_mutex_lock(&p_event->mutex); 125321936Shselasky 126321936Shselasky /* Return immediately if the event is signalled. */ 127321936Shselasky if (p_event->signaled) { 128321936Shselasky if (!p_event->manual_reset) 129321936Shselasky p_event->signaled = FALSE; 130321936Shselasky 131321936Shselasky pthread_mutex_unlock(&p_event->mutex); 132321936Shselasky return CL_SUCCESS; 133321936Shselasky } 134321936Shselasky 135321936Shselasky /* If just testing the state, return CL_TIMEOUT. */ 136321936Shselasky if (wait_us == 0) { 137321936Shselasky pthread_mutex_unlock(&p_event->mutex); 138321936Shselasky return CL_TIMEOUT; 139321936Shselasky } 140321936Shselasky 141321936Shselasky if (wait_us == EVENT_NO_TIMEOUT) { 142321936Shselasky /* Wait for condition variable to be signaled or broadcast. */ 143321936Shselasky if (pthread_cond_wait(&p_event->condvar, &p_event->mutex)) 144321936Shselasky status = CL_NOT_DONE; 145321936Shselasky else 146321936Shselasky status = CL_SUCCESS; 147321936Shselasky } else { 148321936Shselasky /* Get the current time */ 149321936Shselasky if (gettimeofday(&curtime, NULL) == 0) { 150321936Shselasky unsigned long n_sec = 151321936Shselasky (curtime.tv_usec + (wait_us % 1000000)) * 1000; 152321936Shselasky timeout.tv_sec = curtime.tv_sec + (wait_us / 1000000) 153321936Shselasky + (n_sec / 1000000000); 154321936Shselasky timeout.tv_nsec = n_sec % 1000000000; 155321936Shselasky 156321936Shselasky wait_ret = pthread_cond_timedwait(&p_event->condvar, 157321936Shselasky &p_event->mutex, 158321936Shselasky &timeout); 159321936Shselasky if (wait_ret == 0) 160321936Shselasky status = 161321936Shselasky (p_event-> 162321936Shselasky signaled ? CL_SUCCESS : CL_NOT_DONE); 163321936Shselasky else if (wait_ret == ETIMEDOUT) 164321936Shselasky status = CL_TIMEOUT; 165321936Shselasky else 166321936Shselasky status = CL_NOT_DONE; 167321936Shselasky } else 168321936Shselasky status = CL_ERROR; 169321936Shselasky } 170321936Shselasky if (!p_event->manual_reset) 171321936Shselasky p_event->signaled = FALSE; 172321936Shselasky 173321936Shselasky pthread_mutex_unlock(&p_event->mutex); 174321936Shselasky return status; 175321936Shselasky} 176