Esempio n. 1
0
void SerialScheduleNewEvent(unsigned int rcv, simtime_t stamp, unsigned int event_type, void *event_content, unsigned int event_size) {
	msg_t *event;

	// Sanity checks
	if(stamp < current_lvt) {
		rootsim_error(true, "LP %d is trying to send events in the past. Current time: %f, scheduled time: %f\n", current_lp, current_lvt, stamp);
	}

	if(event_size > MAX_EVENT_SIZE) {
		rootsim_error(true, "Trying to schedule an event too large. Maximum size is %d, requested is %d. Recompile changing MAX_EVENT_SIZE\n", MAX_EVENT_SIZE, event_size);
	}

	// Populate the message data structure
	event = rsalloc(sizeof(msg_t));
	bzero(event, sizeof(msg_t));
	event->sender = current_lp;
	event->receiver = rcv;
	event->timestamp = stamp;
	event->send_time = current_lvt;
	event->type = event_type;
	event->size = event_size;
	memcpy(event->event_content, event_content, event_size);

	// Put the event in the Calenda Queue
	calqueue_put(stamp, event);
}
Esempio n. 2
0
static void setup_numa_nodes(void) {

	unsigned int i;

	numa_nodes = rsalloc(sizeof(int) * n_cores);

	for(i = 0; i < n_cores; i++) {
		numa_nodes[i] = query_numa_node(i);
	}

}
Esempio n. 3
0
void serial_init(int argc, char **argv, int app_arg) {
	register unsigned int t;

	// Initialize the calendar queue
	calqueue_init();

	// TODO: qua è necessario inizializzare il sottosistema delle statistiche, utilizzando il nuovo approccio (da pensare)

	// Initialize the per LP variables
	serial_states = rsalloc(sizeof(void *) * n_prc_tot);
	serial_completed_simulation = rsalloc(sizeof(bool) * n_prc_tot);
	bzero(serial_states, sizeof(void *) * n_prc_tot);
	bzero(serial_completed_simulation, sizeof(bool) * n_prc_tot);

	// Sanity check on the number of LPs
	if(n_prc_tot == 0) {
		rootsim_error(true, "You must specify the total number of Logical Processes\n");
	}

	// We must pass the application-level args to the LP in the INIT event.
	// Skip all the NULL args (if any)
	while (argv[app_arg] != NULL && (argv[app_arg][0] == '\0' || argv[app_arg][0] == ' ')) {
		app_arg++;
	}

	// Generate the INIT events for all the LPs
	for (t = 0; t < n_prc_tot; t++) {

		// Copy the relevant string pointers to the INIT event payload
		if((argc - app_arg) > 0) {
			SerialScheduleNewEvent(t, 0.0, INIT, &argv[app_arg], (argc - app_arg) * sizeof(char *));
		} else {
			SerialScheduleNewEvent(t, 0.0, INIT, NULL, 0);
		}
	}

	// No LP is scheduled now
	current_lp = IDLE_PROCESS;
}
Esempio n. 4
0
void calqueue_put(double timestamp, void *payload) {

	int i;
	calqueue_node *new_node, *traverse;

	// Fill the node entry
	new_node = rsalloc(sizeof(calqueue_node));
	new_node->timestamp = timestamp;
	new_node->payload = payload;
	new_node->next = NULL;


	// Calculate the number of the bucket in which to place the new entry
	i = (int)(timestamp / (double)cwidth); // Virtual bucket
	i = i % nbuckets; // Actual bucket

	// Grab the head of events list in bucket i
	traverse = calendar[i];

	// Put at the head of the list, if appropriate
	if(traverse == NULL || traverse->timestamp > timestamp) {
		new_node->next = traverse;
		calendar[i] = new_node;
	} else {
		// Find the correct place in list
		while(traverse->next != NULL && traverse->next->timestamp <= timestamp)
			traverse = traverse->next;

		// Place the new event
		new_node->next = traverse->next;
		traverse->next = new_node;
	}

	// Update queue size
	qsize++;

	// Double the calendar size if needed
	if(qsize > top_threshold && nbuckets < MAXNBUCKETS) {
		resize(2 * nbuckets);
	}
}
Esempio n. 5
0
/**
* This function creates a full log of the current simulation states and returns a pointer to it.
* The algorithm behind this function is based on packing of the really allocated memory chunks into
* a contiguous memory area, exploiting some threshold-based approach to fasten it up even more.
* The contiguous copy is performed precomputing the size of the full log, and then scanning it
* using a pointer for storing the relevant information.
*
* For further information, please see the paper:
* 	R. Toccaceli, F. Quaglia
* 	DyMeLoR: Dynamic Memory Logger and Restorer Library for Optimistic Simulation Objects
* 	with Generic Memory Layout
*	Proceedings of the 22nd Workshop on Principles of Advanced and Distributed Simulation
*	2008
*
* To fully understand the changes in this function to support the incremental logging as well,
* please point to the paper:
* 	A. Pellegrini, R. Vitali, F. Quaglia
* 	Di-DyMeLoR: Logging only Dirty Chunks for Efficient Management of Dynamic Memory Based
* 	Optimistic Simulation Objects
*	Proceedings of the 23rd Workshop on Principles of Advanced and Distributed Simulation
*	2009
*
* @author Roberto Toccaceli
* @author Francesco Quaglia
* @author Alessandro Pellegrini
* @author Roberto Vitali
*
* @param lid The logical process' local identifier
* @return A pointer to a malloc()'d memory area which contains the full log of the current simulation state,
*         along with the relative meta-data which can be used to perform a restore operation.
*
* @todo must be declared static. This will entail changing the logic in gvt.c to save a state before rebuilding.
*/
void *log_full(int lid) {

	void *ptr, *ckpt;
	int i, j, k, idx, bitmap_blocks;
	size_t size, chunk_size;
	malloc_area * m_area;

	// Timers for self-tuning of the simulation platform
	timer checkpoint_timer;
	timer_start(checkpoint_timer);

	size = sizeof(malloc_state)  + sizeof(seed_type) + m_state[lid]->busy_areas * sizeof(malloc_area) + m_state[lid]->bitmap_size + m_state[lid]->total_log_size;

	// This code is in a malloc-wrapper package, so here we call the real malloc
	ckpt = rsalloc(size);

	if(ckpt == NULL)
		rootsim_error(true, "(%d) Unable to acquire memory for ckptging the current state (memory exhausted?)");


	ptr = ckpt;

	// Copy malloc_state in the ckpt
	memcpy(ptr, m_state[lid], sizeof(malloc_state));
	ptr = (void *)((char *)ptr + sizeof(malloc_state));
	((malloc_state*)ckpt)->timestamp = current_lvt;
	((malloc_state*)ckpt)->is_incremental = 0;


	// Copy the per-LP Seed State (to make the numerical library rollbackable and PWD)
	memcpy(ptr, &LPS[lid]->seed, sizeof(seed_type));
	ptr = (void *)((char *)ptr + sizeof(seed_type));


	for(i = 0; i < m_state[lid]->num_areas; i++){

		m_area = &m_state[lid]->areas[i];

		// Copy the bitmap
		bitmap_blocks = m_area->num_chunks / NUM_CHUNKS_PER_BLOCK;
		if (bitmap_blocks < 1)
			bitmap_blocks = 1;

		// Check if there is at least one chunk used in the area
		if(m_area->alloc_chunks == 0){

			m_area->dirty_chunks = 0;
			m_area->state_changed = 0;

			if (m_area->use_bitmap != NULL) {
				for(j = 0; j < bitmap_blocks; j++)
					m_area->dirty_bitmap[j] = 0;
			}

			continue;
		}

		// Copy malloc_area into the ckpt
		memcpy(ptr, m_area, sizeof(malloc_area));
		ptr = (void*)((char*)ptr + sizeof(malloc_area));

		memcpy(ptr, m_area->use_bitmap, bitmap_blocks * BLOCK_SIZE);
		ptr = (void*)((char*)ptr + bitmap_blocks * BLOCK_SIZE);

		chunk_size = m_area->chunk_size;
		RESET_BIT_AT(chunk_size, 0);	// ckpt Mode bit
		RESET_BIT_AT(chunk_size, 1);	// Lock bit

		// Check whether the area should be completely copied (not on a per-chunk basis)
		// using a threshold-based heuristic
		if(CHECK_LOG_MODE_BIT(m_area)){

			// If the malloc_area is almost (over a threshold) full, copy it entirely
			memcpy(ptr, m_area->area, m_area->num_chunks * chunk_size);
			ptr = (void*)((char*)ptr + m_area->num_chunks * chunk_size);

		} else {
			// Copy only the allocated chunks
			for(j = 0; j < bitmap_blocks; j++){

				// Check the allocation bitmap on a per-block basis, to enhance scan speed
				if(m_area->use_bitmap[j] == 0) {
					// Empty (no-chunks-allocated) block: skip to the next
					continue;

				} else {
					// At least one chunk is allocated: per-bit scan of the block is required
					for(k = 0; k < NUM_CHUNKS_PER_BLOCK; k++){

						if(CHECK_BIT_AT(m_area->use_bitmap[j], k)){

							idx = j * NUM_CHUNKS_PER_BLOCK + k;
							memcpy(ptr, (void*)((char*)m_area->area + (idx * chunk_size)), chunk_size);
							ptr = (void*)((char*)ptr + chunk_size);

						}
					}
				}
			}
		}

		// Reset Dirty Bitmap, as there is a full ckpt in the chain now
		m_area->dirty_chunks = 0;
		m_area->state_changed = 0;
		bzero((void *)m_area->dirty_bitmap, bitmap_blocks * BLOCK_SIZE);

	} // For each m_area in m_state

	// Sanity check
	if ((char *)ckpt + size != ptr){
		rootsim_error(false, "Actual (full) ckpt size different from the estimated one! ckpt = %p size = %x (%d), ptr = %p\n", ckpt, size, size, ptr);
	}

	m_state[lid]->dirty_areas = 0;
	m_state[lid]->dirty_bitmap_size = 0;
	m_state[lid]->total_inc_size = 0;

	int checkpoint_time = timer_value_micro(checkpoint_timer);
	statistics_post_lp_data(lid, STAT_CKPT_TIME, (double)checkpoint_time);
	statistics_post_lp_data(lid, STAT_CKPT_MEM, (double)size);

	return ckpt;
}