/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* This file implements the transaction processing logic common to send
* and receive transactions in IBMF.
*/
extern int ibmf_trace_level;
/*
* ibmf_i_terminate_transaction():
* Do transaction termination processing.
*/
void
{
"ibmf_i_terminate_transaction(): clientp = 0x%p, msgp = 0x%p, "
/*
* Cancel the transaction timer. timer is probably only active if status
* was not success and this is a recv operation, but unset_timer() will
* check.
*/
/*
* For unsolicited messages, do not notify the client
* if an error was encontered in the transfer.
* For solicited messages, call the transaction callback
* provided by the client in the message context.
*/
} else {
"ibmf_i_terminate_transaction(): %s, "
"trans_state_flags = 0x%x, msg_flags = 0x%x\n",
/* mark as recv_compl happened */
/*
* Check if last send is done before marking as done.
* We should get here for sequenced transactions and
* non-sequenced send RMPP transaction.
*/
if (msgimplp->im_trans_state_flags &
}
}
"ibmf_i_terminate_transaction() exit\n");
}
/*
* ibmf_i_notify_client():
* If the transaction is done, call the appropriate callback
*/
void
{
void *async_cb_arg;
/*
* message is removed so no more threads will find message;
* wait for any current clients to finish
*/
/*
* If the message reference count is not zero, then some duplicate
* MAD has arrived for this message. The thread processing the MAD
* found the message on the client's list before this thread was able
* to remove the message from the list. Since, we should not notify
* the client of the transaction completion until all the threads
* working on this message have completed (we don't want the client
* to free the message while a thread is working on it), we let one
* of the other threads notify the client of the completion once
* the message reference count is zero.
*/
if (msgimplp->im_ref_count != 0) {
"", "ibmf_i_notify_client(): %s\n",
"ibmf_i_notify_client() exit\n");
return;
}
/*
* Free up the UD dest resource so it is not tied down by
* the message in case the message is not freed immediately.
* Clean up the UD dest list as well so that excess UD dest
* resources are returned to the CI.
*/
}
/*
* Do nothing if error status
*/
} else {
}
"ibmf_i_notify_client(): %s, status = %d\n",
"ibmf_i_notify_client() exit\n");
return;
}
/*
* Check to see if
* a callback has been registered with the client
* for this unsolicited message.
* If one has been registered, up the recvs active
* count to get the teardown routine to wait until
* this callback is complete.
*/
"", "ibmf_i_notify_client(): %s\n",
"ibmf_tear_down_recv_cb already occurred");
IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
} else {
"", "ibmf_i_notify_client(): %s\n",
"ibmf_tear_down_recv_cb already occurred");
IBMF_TNF_TRACE, "",
"ibmf_i_notify_client() exit\n");
return;
}
}
} else {
/* Solicited transaction processing */
/* Processing for a blocking transaction */
if (msgimplp->im_trans_state_flags &
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
} else {
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
}
} else {
/* Processing for a non-blocking transaction */
"ibmf_i_notify_client(): %s, msg = 0x%p\n",
(ibmf_msg_t *)msgimplp,
}
}
}
}
/*
* ibmf_i_notify_sequence()
* Checks for the need to create a termination context before
* notifying the client.
*/
void
int msg_flags)
{
int status;
"ibmf_i_notify_sequence() enter, clientp = %p, msgimplp = %p\n",
if (msg_flags & IBMF_MSG_FLAGS_TERMINATION) {
"IBMF_MSG_FLAGS_TERMINATION already set",
return;
}
if (msg_flags & IBMF_MSG_FLAGS_SET_TERMINATION) {
/*
* In some cases, we need to check if the termination context
* needs to be set up for early termination of non-double-sided
* RMPP receiver transactions. In these cases we set up the
* termination context, and then notify the client.
* If the set up of the termination context fails, attempt to
* reverse state to the regular context, and set the response
* timer for the termination timeout and exit without notifying
* the client in this failure case. If the setting of the
* response timer fails, simply notify the client without
* going through the process of timing out in the response
* timer.
*/
if (status != IBMF_SUCCESS) {
"", "ibmf_i_notify_sequence(): %s, "
"ibmf_setup_term_ctx() failed,"
"reversing to regular termination",
/*
* Set the flags cleared in
* ibmf_i_terminate_transaction()
*/
/* Re-add the message to the list */
} else {
/*
* The termination context has been
* set up. Notify the client that the
* regular message is done.
*/
}
} else {
}
"ibmf_i_notify_sequence() exit, msgimplp = %p\n",
}