inline void mcapi_sclchan_send( MCAPI_IN mcapi_sclchan_send_hndl_t send_handle, MCAPI_IN mcapi_uint64_t dataword, MCAPI_OUT mcapi_status_t* mcapi_status, size_t bytes) { //check for initialization if ( mcapi_trans_initialized() == MCAPI_FALSE ) { //no init means failure *mcapi_status = MCAPI_ERR_NODE_NOTINIT; return; } //critical section for endpoint begins here LOCK_CHANNEL( send_handle ); //handle must be valid send handle if ( !mcapi_trans_valid_sclchan_send_handle(send_handle) ) { *mcapi_status = MCAPI_ERR_CHAN_INVALID; } else { //POSIX will handle the rest, timeout of sending endpoint is used //priority is fixed to that expected of channel traffic *mcapi_status = pmq_send( send_handle.us->chan_msgq_id, (void*)&dataword, bytes, MCAPI_MAX_PRIORITY+1, send_handle.us->time_out ); } //critical section ends UNLOCK_CHANNEL( send_handle ); }
mcapi_uint_t mcapi_sclchan_available( MCAPI_IN mcapi_sclchan_recv_hndl_t receive_handle, MCAPI_OUT mcapi_status_t* mcapi_status ) { //return value mcapi_uint_t to_ret = MCAPI_NULL; //check for initialization if ( mcapi_trans_initialized() == MCAPI_FALSE ) { //no init means failure *mcapi_status = MCAPI_ERR_NODE_NOTINIT; return MCAPI_NULL; } LOCK_CHANNEL( receive_handle ); //handle must be valid if ( !mcapi_trans_valid_sclchan_recv_handle( receive_handle ) ) { *mcapi_status = MCAPI_ERR_CHAN_INVALID; } else { to_ret = pmq_avail( receive_handle.us->chan_msgq_id, mcapi_status ); } UNLOCK_CHANNEL( receive_handle ); return to_ret; }
inline mcapi_uint64_t mcapi_sclchan_recv( MCAPI_IN mcapi_sclchan_recv_hndl_t receive_handle, MCAPI_OUT mcapi_status_t* mcapi_status, size_t bytes) { //the priority obtained unsigned msg_prio; //the received value mcapi_uint64_t value = -1; //how long message we got in bytes size_t mslen; //check for initialization if ( !mcapi_trans_initialized() ) { //no init means failure *mcapi_status = MCAPI_ERR_NODE_NOTINIT; return -1; } LOCK_CHANNEL( receive_handle ); //handle must be valid if ( !mcapi_trans_valid_sclchan_recv_handle(receive_handle) ) { *mcapi_status = MCAPI_ERR_CHAN_INVALID; } else { //POSIX will handle the recv, timeout of receiving endpoint is used *mcapi_status = pmq_recv( receive_handle.us->chan_msgq_id, (void*)&value, bytes, &mslen, &msg_prio, receive_handle.us->time_out ); } UNLOCK_CHANNEL( receive_handle ); return value; }
/** * The runtime support for output actions. * * @param pt the PiThread structure of the thread trying to output * @param chan_ref the environment index of the output channel * @param chans the acquired channels (cf. compilation of output try) * @param nbchans the number of acquired channels * @param try_result an output variable for the result of the try (ENABLED if output can be performed, DISABLED if not, and COMMIT if a commiment must be recorded). * @return the matching input commitment, if any or NULL otherwise. */ PICC_Commit * PICC_try_output_action(PICC_PiThread *pt, int chan_ref, PICC_Channel* chans[], int nbchans, PICC_TryResult * try_result) { PICC_Channel* out_chan = PICC_channel_of_channel_value(&(pt->env[chan_ref])); // acquire the channel, if required if (chan_array_add(out_chan, chans, &nbchans)) { LOCK_CHANNEL(out_chan); } if(out_chan->global_rc == 1) { // if global reference count is one, then pt is the only // thread knowing the channel, hence the try is DISABLED. *try_result = PICC_TRY_DISABLED; return NULL; } PICC_Commit * commit = NULL; PICC_CommitStatus ok = PICC_CANNOT_ACQUIRE; do { // search for a valid input commitment commit = PICC_fetch_input_commitment(out_chan); if(commit == NULL) { // if no valid or invalid commitment left, need to // make an output commitment *try_result = PICC_TRY_COMMIT; return NULL; } // here, we have a candidate input commitment // try to awake the commiting thread do { ok = PICC_can_awake(commit->thread, commit); if(ok == PICC_CANNOT_ACQUIRE) { // to avoid contention on thread awaking PICC_low_level_yield(); } } while(ok == PICC_CANNOT_ACQUIRE); // here we have either a valid commitment // an an awoken thread, or an invalid commitment // that we just removed (lazy deletion). if (ok == PICC_VALID_COMMIT) { // ok, everything's fine a synchronization will occur *try_result = PICC_TRY_ENABLED; return commit; // we return the valid commitment } // otherwise it's invalid and deleted, and we will // try to find a further commitment } while (!(PICC_commit_list_is_empty(out_chan->incommits))); // TODO: raise a "dead code reached" error CRASH_NEW_ERROR(ERR_DEAD_CODE_REACHED); return NULL; }