Example #1
0
void networkinterface_wantsSend(NetworkInterface* interface, Socket* socket) {
	MAGIC_ASSERT(interface);

	/* track the new socket for sending if not already tracking */
	switch(interface->qdisc) {
		case NIQ_RR: {
			if(!g_queue_find(interface->rrQueue, socket)) {
				descriptor_ref(socket);
				g_queue_push_tail(interface->rrQueue, socket);
			}
			break;
		}
		case NIQ_FIFO:
		default: {
			if(!priorityqueue_find(interface->fifoQueue, socket)) {
				descriptor_ref(socket);
				priorityqueue_push(interface->fifoQueue, socket);
			}
			break;
		}
	}

	/* trigger a send if we are currently idle */
	if(!(interface->flags & NIF_SENDING)) {
		_networkinterface_scheduleNextSend(interface);
	}
}
Example #2
0
gboolean asyncpriorityqueue_push(AsyncPriorityQueue *q, gpointer data) {
	g_assert(q);
	g_mutex_lock(&(q->lock));
	gboolean returnVal = priorityqueue_push(q->pq, data);
	g_mutex_unlock(&(q->lock));
	return returnVal;
}
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));
    }
}
Example #4
0
/* first-in-first-out queuing discipline ($ man tc)*/
static Packet* _networkinterface_selectFirstInFirstOut(NetworkInterface* interface, gint* socketHandle) {
	/* use packet priority field to select based on application ordering.
	 * this is really a simplification of prioritizing on timestamps. */
	Packet* packet = NULL;

	while(!packet && !priorityqueue_isEmpty(interface->fifoQueue)) {
		/* do fifo to get the next packet from the next socket */
		Socket* socket = priorityqueue_pop(interface->fifoQueue);
		packet = socket_pullOutPacket(socket);
		*socketHandle = *descriptor_getHandleReference((Descriptor*)socket);

		if(socket_peekNextPacket(socket)) {
			/* socket has more packets, and is still reffed from before */
			priorityqueue_push(interface->fifoQueue, socket);
		} else {
			/* socket has no more packets, unref it from the sendable queue */
			descriptor_unref((Descriptor*) socket);
		}
	}

	return packet;
}