Example #1
0
cl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool)
{
	cl_list_item_t *p_list_item;

	CL_ASSERT(p_pool);
	CL_ASSERT(p_pool->state == CL_INITIALIZED);

	if (cl_is_qlist_empty(&p_pool->free_list)) {
		/*
		 * No object is available.
		 * Return NULL if the user does not want automatic growth.
		 */
		if (!p_pool->grow_size)
			return (NULL);

		/* We ran out of elements.  Get more */
		cl_qcpool_grow(p_pool, p_pool->grow_size);
		/*
		 * We may not have gotten everything we wanted but we might have
		 * gotten something.
		 */
		if (cl_is_qlist_empty(&p_pool->free_list))
			return (NULL);
	}

	p_list_item = cl_qlist_remove_tail(&p_pool->free_list);
	/* OK, at this point we have an object */
	CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list));
	return ((cl_pool_item_t *) p_list_item);
}
Example #2
0
void osm_vl15_destroy(IN osm_vl15_t * p_vl, IN struct osm_mad_pool *p_pool)
{
	osm_madw_t *p_madw;

	OSM_LOG_ENTER(p_vl->p_log);

	/*
	   Signal our threads that we're leaving.
	 */
	p_vl->thread_state = OSM_THREAD_STATE_EXIT;

	/*
	   Don't trigger unless event has been initialized.
	   Destroy the thread before we tear down the other objects.
	 */
	if (p_vl->state != OSM_VL15_STATE_INIT)
		cl_event_signal(&p_vl->signal);

	cl_thread_destroy(&p_vl->poller);

	/*
	   Return the outstanding messages to the pool
	 */

	cl_spinlock_acquire(&p_vl->lock);

	while (!cl_is_qlist_empty(&p_vl->rfifo)) {
		p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
		osm_mad_pool_put(p_pool, p_madw);
	}
	while (!cl_is_qlist_empty(&p_vl->ufifo)) {
		p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
		osm_mad_pool_put(p_pool, p_madw);
	}

	cl_spinlock_release(&p_vl->lock);

	cl_event_destroy(&p_vl->signal);
	p_vl->state = OSM_VL15_STATE_INIT;
	cl_spinlock_destroy(&p_vl->lock);

	OSM_LOG_EXIT(p_vl->p_log);
}
Example #3
0
void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool)
{
	/* CL_ASSERT that a non-NULL pointer was provided. */
	CL_ASSERT(p_pool);
	/* CL_ASSERT that we are in a valid state (not uninitialized memory). */
	CL_ASSERT(cl_is_state_valid(p_pool->state));

	if (p_pool->state == CL_INITIALIZED) {
		/*
		 * Assert if the user hasn't put everything back in the pool
		 * before destroying it
		 * if they haven't, then most likely they are still using memory
		 * that will be freed, and the destructor will not be called!
		 */
#ifdef _DEBUG_
		/* but we do not want "free" version to assert on this one */
		CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects);
#endif
		/* call the user's destructor for each object in the pool */
		if (p_pool->pfn_dtor) {
			while (!cl_is_qlist_empty(&p_pool->free_list)) {
				p_pool->pfn_dtor((cl_pool_item_t *)
						 cl_qlist_remove_head(&p_pool->
								      free_list),
						 (void *)p_pool->context);
			}
		} else {
			cl_qlist_remove_all(&p_pool->free_list);
		}

		/* Free all allocated memory blocks. */
		while (!cl_is_qlist_empty(&p_pool->alloc_list))
			free(cl_qlist_remove_head(&p_pool->alloc_list));

		if (p_pool->component_sizes) {
			free(p_pool->component_sizes);
			p_pool->component_sizes = NULL;
		}
	}

	p_pool->state = CL_UNINITIALIZED;
}
Example #4
0
cl_status_t
cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms)
{
	struct timeval curtime;
	cl_list_item_t *p_list_item;
	uint32_t delta_time = time_ms;

	CL_ASSERT(p_timer);
	CL_ASSERT(p_timer->state == CL_INITIALIZED);

	pthread_mutex_lock(&gp_timer_prov->mutex);
	/* Signal the timer provider thread to wake up. */
	pthread_cond_signal(&gp_timer_prov->cond);

	/* Remove the timer from the queue if currently queued. */
	if (p_timer->timer_state == CL_TIMER_QUEUED)
		cl_qlist_remove_item(&gp_timer_prov->queue,
				     &p_timer->list_item);

	/* Get the current time */
#ifndef timerclear
#define	timerclear(tvp)		(tvp)->tv_sec = (time_t)0, (tvp)->tv_usec = 0L
#endif
	timerclear(&curtime);
	gettimeofday(&curtime, NULL);

	/* do not do 0 wait ! */
	/* if (delta_time < 1000.0) {delta_time = 1000;} */

	/* Calculate the timeout. */
	p_timer->timeout.tv_sec = curtime.tv_sec + (delta_time / 1000);
	p_timer->timeout.tv_nsec =
	    (curtime.tv_usec + ((delta_time % 1000) * 1000)) * 1000;

	/* Add the timer to the queue. */
	if (cl_is_qlist_empty(&gp_timer_prov->queue)) {
		/* The timer list is empty.  Add to the head. */
		cl_qlist_insert_head(&gp_timer_prov->queue,
				     &p_timer->list_item);
	} else {
		/* Find the correct insertion place in the list for the timer. */
		p_list_item = cl_qlist_find_from_tail(&gp_timer_prov->queue,
						      __cl_timer_find, p_timer);

		/* Insert the timer. */
		cl_qlist_insert_next(&gp_timer_prov->queue, p_list_item,
				     &p_timer->list_item);
	}
	/* Set the state. */
	p_timer->timer_state = CL_TIMER_QUEUED;
	pthread_mutex_unlock(&gp_timer_prov->mutex);

	return (CL_SUCCESS);
}
Example #5
0
void cl_disp_shutdown(IN cl_dispatcher_t * const p_disp)
{
	CL_ASSERT(p_disp);

	/* Stop the thread pool. */
	cl_thread_pool_destroy(&p_disp->worker_threads);

	/* Process all outstanding callbacks. */
	__cl_disp_worker(p_disp);

	/* Free all registration info. */
	while (!cl_is_qlist_empty(&p_disp->reg_list))
		free(cl_qlist_remove_head(&p_disp->reg_list));
}
Example #6
0
/*
 * This is the internal work function executed by the timer's thread.
 */
static void *__cl_timer_prov_cb(IN void *const context)
{
	int ret;
	cl_timer_t *p_timer;

	pthread_mutex_lock(&gp_timer_prov->mutex);
	while (!gp_timer_prov->exit) {
		if (cl_is_qlist_empty(&gp_timer_prov->queue)) {
			/* Wait until we exit or a timer is queued. */
			/* cond wait does:
			 * pthread_cond_wait atomically unlocks the mutex (as per
			 * pthread_unlock_mutex) and waits for the condition variable
			 * cond to be signaled. The thread execution is suspended and
			 * does not consume any CPU time until the condition variable is
			 * signaled. The mutex must be locked by the calling thread on
			 * entrance to pthread_cond_wait. Before RETURNING TO THE
			 * CALLING THREAD, PTHREAD_COND_WAIT RE-ACQUIRES MUTEX (as per
			 * pthread_lock_mutex).
			 */
			ret = pthread_cond_wait(&gp_timer_prov->cond,
						&gp_timer_prov->mutex);
		} else {
			/*
			 * The timer elements are on the queue in expiration order.
			 * Get the first in the list to determine how long to wait.
			 */

			p_timer =
			    (cl_timer_t *) cl_qlist_head(&gp_timer_prov->queue);
			ret =
			    pthread_cond_timedwait(&gp_timer_prov->cond,
						   &gp_timer_prov->mutex,
						   &p_timer->timeout);

			/*
			   Sleep again on every event other than timeout and invalid
			   Note: EINVAL means that we got behind. This can occur when
			   we are very busy...
			 */
			if (ret != ETIMEDOUT && ret != EINVAL)
				continue;

			/*
			 * The timer expired.  Check the state in case it was cancelled
			 * after it expired but before we got a chance to invoke the
			 * callback.
			 */
			if (p_timer->timer_state != CL_TIMER_QUEUED)
				continue;

			/*
			 * Mark the timer as running to synchronize with its
			 * cancelation since we can't hold the mutex during the
			 * callback.
			 */
			p_timer->timer_state = CL_TIMER_RUNNING;

			/* Remove the item from the timer queue. */
			cl_qlist_remove_item(&gp_timer_prov->queue,
					     &p_timer->list_item);
			pthread_mutex_unlock(&gp_timer_prov->mutex);
			/* Invoke the callback. */
			p_timer->pfn_callback((void *)p_timer->context);

			/* Acquire the mutex again. */
			pthread_mutex_lock(&gp_timer_prov->mutex);
			/*
			 * Only set the state to idle if the timer has not been accessed
			 * from the callback
			 */
			if (p_timer->timer_state == CL_TIMER_RUNNING)
				p_timer->timer_state = CL_TIMER_IDLE;

			/*
			 * Signal any thread trying to manipulate the timer
			 * that expired.
			 */
			pthread_cond_signal(&p_timer->cond);
		}
	}
	gp_timer_prov->thread = 0;
	pthread_mutex_unlock(&gp_timer_prov->mutex);
	pthread_exit(NULL);
}
Example #7
0
ib_api_status_t
osm_transaction_mgr_insert_madw(IN osm_bind_handle_t * const p_bind,
				IN osm_madw_t * p_madw)
{
#ifdef OSM_VENDOR_INTF_MTL
	osm_vendor_t *const p_vend = ((osm_mtl_bind_info_t *) p_bind)->p_vend;
#else
	osm_vendor_t *const p_vend = ((osm_ts_bind_info_t *) p_bind)->p_vend;
#endif
	osm_transaction_mgr_t *trans_mgr_p;
	osm_madw_req_t *osm_madw_req_p;
	uint64_t timeout;
	uint64_t waking_time;
	cl_status_t cl_status;
	uint64_t key;
	const ib_mad_t *mad_p = p_madw->p_mad;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(mad_p);

	trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr;

	timeout = (uint64_t) (p_vend->timeout) * 1000;	/* change the miliseconds value of timeout to microseconds. */
	waking_time = timeout + cl_get_time_stamp();

	osm_madw_req_p = (osm_madw_req_t *) malloc(sizeof(osm_madw_req_t));

	osm_madw_req_p->p_madw = p_madw;
	osm_madw_req_p->waking_time = waking_time;
	osm_madw_req_p->retry_cnt = OSM_DEFAULT_RETRY_COUNT;
	osm_madw_req_p->p_bind = p_bind;

	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
		"osm_transaction_mgr_insert_madw: "
		"Inserting MADW:%p with waking_time: <0x%" PRIx64 ">  TID:<0x%"
		PRIx64 ">.\n", p_madw, waking_time, p_madw->p_mad->trans_id);

	/* Get the lock on the manager */
	cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock));
	/* If the list is empty - need to start the timer with timer of timeout (in miliseconds) */
	if (cl_is_qlist_empty(trans_mgr_p->madw_reqs_list_p)) {
		/*  stop the timer if it is running */
		cl_timer_stop(&trans_mgr_p->madw_list_timer);

		/*  start the timer to the timeout (in miliseconds) */
		cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer,
					   p_vend->timeout);
		if (cl_status != CL_SUCCESS) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_transaction_mgr_insert_madw : ERROR 1000: "
				"Failed to start timer\n");
		}
	}

	/*  insert the object to the qlist and the qmap */
	cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p,
			     &(osm_madw_req_p->list_item));
	/*  get the key */
	key = (uint64_t) mad_p->trans_id;
	cl_qmap_insert(trans_mgr_p->madw_by_tid_map_p, key,
		       &(osm_madw_req_p->map_item));
	cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock);

	OSM_LOG_EXIT(p_vend->p_log);

	return (IB_SUCCESS);
}
Example #8
0
/*        rank is a SWITCH for BFS purpose */
static int updn_subn_rank(IN updn_t * p_updn)
{
	osm_switch_t *p_sw;
	osm_physp_t *p_physp, *p_remote_physp;
	cl_qlist_t list;
	cl_map_item_t *item;
	struct updn_node *u, *remote_u;
	uint8_t num_ports, port_num;
	osm_log_t *p_log = &p_updn->p_osm->log;
	unsigned max_rank = 0;

	OSM_LOG_ENTER(p_log);
	cl_qlist_init(&list);

	/* add all roots to the list */
	for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
	     item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
	     item = cl_qmap_next(item)) {
		p_sw = (osm_switch_t *)item;
		u = p_sw->priv;
		if (!u->rank)
			cl_qlist_insert_tail(&list, &u->list);
	}

	/* BFS the list till it's empty */
	while (!cl_is_qlist_empty(&list)) {
		u = (struct updn_node *)cl_qlist_remove_head(&list);
		/* Go over all remote nodes and rank them (if not already visited) */
		p_sw = u->sw;
		num_ports = p_sw->num_ports;
		OSM_LOG(p_log, OSM_LOG_DEBUG,
			"Handling switch GUID 0x%" PRIx64 "\n",
			cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
		for (port_num = 1; port_num < num_ports; port_num++) {
			ib_net64_t port_guid;

			/* Current port fetched in order to get remote side */
			p_physp =
			    osm_node_get_physp_ptr(p_sw->p_node, port_num);

			if (!p_physp)
				continue;

			p_remote_physp = p_physp->p_remote_physp;

			/*
			   make sure that all the following occur on p_remote_physp:
			   1. The port isn't NULL
			   2. It is a switch
			 */
			if (p_remote_physp && p_remote_physp->p_node->sw) {
				remote_u = p_remote_physp->p_node->sw->priv;
				port_guid = p_remote_physp->port_guid;

				if (remote_u->rank > u->rank + 1) {
					remote_u->rank = u->rank + 1;
					max_rank = remote_u->rank;
					cl_qlist_insert_tail(&list,
							     &remote_u->list);
					OSM_LOG(p_log, OSM_LOG_DEBUG,
						"Rank of port GUID 0x%" PRIx64
						" = %u\n", cl_ntoh64(port_guid),
						remote_u->rank);
				}
			}
		}
	}

	/* Print Summary of ranking */
	OSM_LOG(p_log, OSM_LOG_VERBOSE,
		"Subnet ranking completed. Max Node Rank = %d\n", max_rank);
	OSM_LOG_EXIT(p_log);
	return 0;
}
Example #9
0
/**********************************************************************
 * This function does the bfs of min hop table calculation by guid index
 * as a starting point.
 **********************************************************************/
static int updn_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn,
			    IN osm_switch_t * p_sw)
{
	uint8_t pn, pn_rem;
	cl_qlist_t list;
	uint16_t lid;
	struct updn_node *u;
	updn_switch_dir_t next_dir, current_dir;

	OSM_LOG_ENTER(p_log);

	lid = osm_node_get_base_lid(p_sw->p_node, 0);
	lid = cl_ntoh16(lid);
	osm_switch_set_hops(p_sw, lid, 0, 0);

	OSM_LOG(p_log, OSM_LOG_DEBUG,
		"Starting from switch - port GUID 0x%" PRIx64 " lid %u\n",
		cl_ntoh64(p_sw->p_node->node_info.port_guid), lid);

	u = p_sw->priv;
	u->dir = UP;

	/* Update list with the new element */
	cl_qlist_init(&list);
	cl_qlist_insert_tail(&list, &u->list);

	/* BFS the list till no next element */
	while (!cl_is_qlist_empty(&list)) {
		u = (struct updn_node *)cl_qlist_remove_head(&list);
		u->visited = 0;	/* cleanup */
		current_dir = u->dir;
		/* Go over all ports of the switch and find unvisited remote nodes */
		for (pn = 1; pn < u->sw->num_ports; pn++) {
			osm_node_t *p_remote_node;
			struct updn_node *rem_u;
			uint8_t current_min_hop, remote_min_hop,
			    set_hop_return_value;
			osm_switch_t *p_remote_sw;

			p_remote_node =
			    osm_node_get_remote_node(u->sw->p_node, pn,
						     &pn_rem);
			/* If no remote node OR remote node is not a SWITCH
			   continue to next pn */
			if (!p_remote_node || !p_remote_node->sw)
				continue;
			/* Fetch remote guid only after validation of remote node */
			p_remote_sw = p_remote_node->sw;
			rem_u = p_remote_sw->priv;
			/* Decide which direction to mark it (UP/DOWN) */
			next_dir = updn_get_dir(u->rank, rem_u->rank,
						u->id, rem_u->id);

			/* Check if this is a legal step : the only illegal step is going
			   from DOWN to UP */
			if ((current_dir == DOWN) && (next_dir == UP)) {
				OSM_LOG(p_log, OSM_LOG_DEBUG,
					"Avoiding move from 0x%016" PRIx64
					" to 0x%016" PRIx64 "\n",
					cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)),
					cl_ntoh64(osm_node_get_node_guid(p_remote_node)));
				/* Illegal step */
				continue;
			}
			/* Set MinHop value for the current lid */
			current_min_hop = osm_switch_get_least_hops(u->sw, lid);
			/* Check hop count if better insert into list && update
			   the remote node Min Hop Table */
			remote_min_hop =
			    osm_switch_get_hop_count(p_remote_sw, lid, pn_rem);
			if (current_min_hop + 1 < remote_min_hop) {
				set_hop_return_value =
				    osm_switch_set_hops(p_remote_sw, lid,
							pn_rem,
							current_min_hop + 1);
				if (set_hop_return_value) {
					OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AA01: "
						"Invalid value returned from set min hop is: %d\n",
						set_hop_return_value);
				}
				/* Check if remote port has already been visited */
				if (!rem_u->visited) {
					/* Insert updn_switch item into the list */
					rem_u->dir = next_dir;
					rem_u->visited = 1;
					cl_qlist_insert_tail(&list,
							     &rem_u->list);
				}
			}
		}
	}

	OSM_LOG_EXIT(p_log);
	return 0;
}
cl_status_t cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel,
			       IN const uint64_t key,
			       IN const uint64_t aging_time_usec,
			       IN cl_pfn_event_aged_cb_t pfn_callback,
			       IN void *const context)
{
	cl_event_wheel_reg_info_t *p_event;
	uint64_t timeout;
	uint32_t to;
	cl_status_t cl_status = CL_SUCCESS;
	cl_list_item_t *prev_event_list_item;
	cl_map_item_t *p_map_item;

	/* Get the lock on the manager */
	cl_spinlock_acquire(&(p_event_wheel->lock));

	cl_event_wheel_dump(p_event_wheel);

	/* Make sure such a key does not exists */
	p_map_item = cl_qmap_get(&p_event_wheel->events_map, key);
	if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) {
		CL_DBG("cl_event_wheel_reg: Already exists key:0x%"
		       PRIx64 "\n", key);

		/* already there - remove it from the list as it is getting a new time */
		p_event =
		    PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t,
				  map_item);

		/* remove the item from the qlist */
		cl_qlist_remove_item(&p_event_wheel->events_wheel,
				     &p_event->list_item);
		/* and the qmap */
		cl_qmap_remove_item(&p_event_wheel->events_map,
				    &p_event->map_item);
	} else {
		/* make a new one */
		p_event = (cl_event_wheel_reg_info_t *)
		    malloc(sizeof(cl_event_wheel_reg_info_t));
		p_event->num_regs = 0;
	}

	p_event->key = key;
	p_event->aging_time = aging_time_usec;
	p_event->pfn_aged_callback = pfn_callback;
	p_event->context = context;
	p_event->num_regs++;

	CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64
	       " aging in %u [msec]\n", p_event->key,
	       (uint32_t) ((p_event->aging_time - cl_get_time_stamp()) / 1000));

	/* If the list is empty - need to start the timer */
	if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) {
		/* Edward Bortnikov 03/29/2003
		 * ++TBD Consider moving the timer manipulation behind the list manipulation.
		 */

		/* calculate the new timeout */
		timeout =
		    (p_event->aging_time - cl_get_time_stamp() + 500) / 1000;

		/* stop the timer if it is running */

		/* Edward Bortnikov 03/29/2003
		 * Don't call cl_timer_stop() because it spins forever.
		 * cl_timer_start() will invoke cl_timer_stop() by itself.
		 *
		 * The problematic scenario is when __cl_event_wheel_callback()
		 * is in race condition with this code. It sets timer.in_timer_cb
		 * to TRUE and then blocks on p_event_wheel->lock. Following this,
		 * the call to cl_timer_stop() hangs. Following this, the whole system
		 * enters into a deadlock.
		 *
		 * cl_timer_stop(&p_event_wheel->timer);
		 */

		/* The timeout for the cl_timer_start should be given as uint32_t.
		   if there is an overflow - warn about it. */
		to = (uint32_t) timeout;
		if (timeout > (uint32_t) timeout) {
			to = 0xffffffff;	/* max 32 bit timer */
			CL_DBG("cl_event_wheel_reg: timeout requested is "
			       "too large. Using timeout: %u\n", to);
		}

		/* start the timer to the timeout [msec] */
		cl_status = cl_timer_start(&p_event_wheel->timer, to);
		if (cl_status != CL_SUCCESS) {
			CL_DBG("cl_event_wheel_reg : ERR 6203: "
			       "Failed to start timer\n");
			goto Exit;
		}
	}

	/* insert the object to the qlist and the qmap */

	/* BUT WE MUST INSERT IT IN A SORTED MANNER */
	prev_event_list_item =
	    cl_qlist_find_from_tail(&p_event_wheel->events_wheel,
				    __event_will_age_before,
				    &p_event->aging_time);

	cl_qlist_insert_next(&p_event_wheel->events_wheel,
			     prev_event_list_item, &p_event->list_item);

	cl_qmap_insert(&p_event_wheel->events_map, key, &(p_event->map_item));

Exit:
	cl_spinlock_release(&p_event_wheel->lock);

	return cl_status;
}