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