static void _schedulerpolicyhoststeal_findMinTime(Host* host, HostStealSearchState* state) { g_rw_lock_reader_lock(&state->data->lock); HostStealQueueData* qdata = g_hash_table_lookup(state->data->hostToQueueDataMap, host); g_rw_lock_reader_unlock(&state->data->lock); utility_assert(qdata); g_mutex_lock(&(qdata->lock)); Event* event = priorityqueue_peek(qdata->pq); g_mutex_unlock(&(qdata->lock)); if(event != NULL) { state->nextEventTime = MIN(state->nextEventTime, event_getTime(event)); } }
static Event* _schedulerpolicyhoststeal_popFromThread(SchedulerPolicy* policy, HostStealThreadData* tdata, GQueue* assignedHosts, SimulationTime barrier) { /* if there is no tdata, that means this thread didn't get any hosts assigned to it */ if(!tdata) { return NULL; } HostStealPolicyData* data = policy->data; while(!g_queue_is_empty(assignedHosts) || tdata->runningHost) { /* if there's no running host, we completed the last assignment and need a new one */ if(!tdata->runningHost) { tdata->runningHost = g_queue_pop_head(assignedHosts); } Host* host = tdata->runningHost; g_rw_lock_reader_lock(&data->lock); HostStealQueueData* qdata = g_hash_table_lookup(data->hostToQueueDataMap, host); g_rw_lock_reader_unlock(&data->lock); utility_assert(qdata); g_mutex_lock(&(qdata->lock)); Event* nextEvent = priorityqueue_peek(qdata->pq); SimulationTime eventTime = (nextEvent != NULL) ? event_getTime(nextEvent) : SIMTIME_INVALID; if(nextEvent != NULL && eventTime < barrier) { utility_assert(eventTime >= qdata->lastEventTime); qdata->lastEventTime = eventTime; nextEvent = priorityqueue_pop(qdata->pq); qdata->nPopped++; /* migrate iff a migration is needed */ _schedulerpolicyhoststeal_migrateHost(policy, host, pthread_self()); } else { nextEvent = NULL; } if(nextEvent == NULL) { /* no more events on the runningHost, mark it as NULL so we get a new one */ g_queue_push_tail(tdata->processedHosts, host); tdata->runningHost = NULL; } g_mutex_unlock(&(qdata->lock)); if(nextEvent != NULL) { return nextEvent; } } /* if we make it here, all hosts for this thread have no more events before barrier */ return NULL; }
static void _schedulerpolicyhoststeal_push(SchedulerPolicy* policy, Event* event, Host* srcHost, Host* dstHost, SimulationTime barrier) { MAGIC_ASSERT(policy); HostStealPolicyData* data = policy->data; /* non-local events must be properly delayed so the event wont show up at another host * before the next scheduling interval. if the thread scheduler guaranteed to always run * the minimum time event accross all of its assigned hosts, then we would only need to * do the time adjustment if the srcThread and dstThread are not identical. however, * the logic of this policy allows a thread to run all events from a given host before * moving on to the next host, so we must adjust the time whenever the srcHost and * dstHost are not the same. */ SimulationTime eventTime = event_getTime(event); if(srcHost != dstHost && eventTime < barrier) { event_setTime(event, barrier); info("Inter-host event time %"G_GUINT64_FORMAT" changed to %"G_GUINT64_FORMAT" " "to ensure event causality", eventTime, barrier); } g_rw_lock_reader_lock(&data->lock); /* we want to track how long this thread spends idle waiting to push the event */ HostStealThreadData* tdata = g_hash_table_lookup(data->threadToThreadDataMap, GUINT_TO_POINTER(pthread_self())); /* get the queue for the destination */ HostStealQueueData* qdata = g_hash_table_lookup(data->hostToQueueDataMap, dstHost); g_rw_lock_reader_unlock(&data->lock); utility_assert(qdata); /* tracking idle time spent waiting for the destination queue lock */ if(tdata) { g_timer_continue(tdata->pushIdleTime); g_mutex_lock(&(tdata->lock)); } g_mutex_lock(&(qdata->lock)); if(tdata) { g_timer_stop(tdata->pushIdleTime); } /* 'deliver' the event to the destination queue */ priorityqueue_push(qdata->pq, event); qdata->nPushed++; /* release the destination queue lock */ g_mutex_unlock(&(qdata->lock)); if(tdata) { g_mutex_unlock(&(tdata->lock)); } }
void scheduler_push(Scheduler* scheduler, Event* event, GQuark senderHostID, GQuark receiverHostID) { MAGIC_ASSERT(scheduler); SimulationTime eventTime = event_getTime(event); if(eventTime > scheduler->endTime) { event_unref(event); return; } /* parties involved. sender may be NULL, receiver may not! * we MAY NOT OWN the receiver, so do not write to it! */ Host* sender = scheduler_getHost(scheduler, senderHostID); Host* receiver = scheduler_getHost(scheduler, receiverHostID); utility_assert(receiver); utility_assert(receiver == event_getHost(event)); /* push to a queue based on the policy */ scheduler->policy->push(scheduler->policy, event, sender, receiver, scheduler->currentRound.endTime); }