void detalgo_1(long int sim_time, int service_rates[2], long int *num_arrivals[2], gboolean *overheard[2], long int total_arrivals[2], long int *max_ID_ack[2], long int *backlog[2], long int thres, gboolean *stable){

	long int i,j,k;
	int c[2];
	long int lastID[2] = {0,0};
	long int g[2],b[2],r[2];
	int FAST,SLOW;
	long int ID;
	int debug = 0;
	int mg,Mg;
	int counter;
	int flow;

	/* Initializations */
	r[0] = service_rates[0];  r[1] = service_rates[1];
	FAST = service_rates[FLOW_1] <= service_rates[FLOW_2]?FLOW_2:FLOW_1;
	SLOW = fmod(FAST+1,2);
	if (stable!=NULL) {*stable = TRUE; }

	/* Initialize TCPchecklist library. */
	TCPchecklist_init();

	/* Create TCP checklists */
	TCPchecklist[FLOW_1] = TCPchecklist_create(total_arrivals[FLOW_1]);
	TCPchecklist[FLOW_2] = TCPchecklist_create(total_arrivals[FLOW_2]);

	/* Begin simulation */
	for (i = 0; i<sim_time; i++){
		 
		/* Get new arrivals */
		for (k = 0; k<2; k++){ /* flow loop */
			for (j = 0; j<num_arrivals[k][i]; j++){ /* arrival loop */
				lastID[k]++;
				ID = lastID[k];
				if (overheard[k][ID-1]){
					g_queue_push_tail(queues[k][GOOD],GINT_TO_POINTER(ID));
				}
				else {
					g_queue_push_tail(queues[k][BAD],GINT_TO_POINTER(ID));
				}
			}
		}
		if(debug){
		printf("slot %ld\n",i);
		printf("after arrivals\n");
		print_queues();
		printf("************************************************\n");

		}

		/* Rename variables for easier reference. */
		g[0] = g_queue_get_length(queues[0][GOOD]); g[1] = g_queue_get_length(queues[1][GOOD]);
		b[0] = g_queue_get_length(queues[0][BAD]); b[1] = g_queue_get_length(queues[1][BAD]);


		/* Take controls */
		if (g[FAST] >= r[SLOW] && g[SLOW] >= r[SLOW]){
			evac( queues[FAST][GOOD],TCPchecklist[FAST],r[SLOW]);
			evac( queues[SLOW][GOOD],TCPchecklist[SLOW],r[SLOW]);
		}

		else if (b[FAST] >= r[FAST] && b[SLOW] >= r[SLOW]){
			k = (GPOINTER_TO_INT(g_queue_peek_head(queues[FAST][BAD])) < GPOINTER_TO_INT(g_queue_peek_head(queues[SLOW][BAD]))) ? FAST : SLOW;
			evac( queues[k][BAD],TCPchecklist[k],r[k]);		
		}

		else if (b[SLOW] >= r[SLOW]){
			evac( queues[SLOW][BAD],TCPchecklist[SLOW],r[SLOW]);		
		}

		else if (b[FAST] >= r[FAST]){
			evac( queues[FAST][BAD],TCPchecklist[FAST],r[FAST]);		
		}

		else if (b[SLOW] >= r[SLOW]){
			evac( queues[SLOW][BAD],TCPchecklist[SLOW],r[SLOW]);		
		}

		else if (g[SLOW] >= r[SLOW]){
			evac( queues[SLOW][GOOD],TCPchecklist[SLOW],r[SLOW]);		
		}
		else if (g[FAST] >= r[FAST]){
			evac( queues[FAST][GOOD],TCPchecklist[FAST],r[FAST]);		
		}

		/* anti-idleness controls */
		else{

			/* Determine what flow can send the most packets. */
			mg = MIN(g[SLOW],g[FAST]);
			Mg = MAX(g[SLOW],g[FAST]);

			counter=0;
			if ( MIN(r[SLOW],g[SLOW]+g[FAST] + b[SLOW] + b[FAST] ) >= MIN(r[FAST],g[FAST]+b[FAST]) ) {
				while(counter<r[SLOW]){
					g[0] = g_queue_get_length(queues[0][GOOD]); g[1] = g_queue_get_length(queues[1][GOOD]);
					b[0] = g_queue_get_length(queues[0][BAD]); b[1] = g_queue_get_length(queues[1][BAD]);

					/* Evacuate the g+g. */
					if (g[FLOW_1] && g[FLOW_2]){
						evac( queues[FAST][GOOD],TCPchecklist[FAST],1);
						evac( queues[SLOW][GOOD],TCPchecklist[SLOW],1);
						counter++;
						continue;
					}

					/* Evacuate any bad packets. */
					if (b[FAST] && b[SLOW] ){

						/* Choose the queue with the largest backlog. */
						flow = (MAX(b[FAST],b[SLOW]) == b[SLOW])?SLOW:FAST;

						evac( queues[flow][BAD],TCPchecklist[flow],1);	
						counter++;
						continue;
					}

					if (b[SLOW]){
						evac( queues[SLOW][BAD],TCPchecklist[SLOW],1);		
						counter++;
						continue;
					}

					if (b[FAST]){	
						evac( queues[FAST][BAD],TCPchecklist[FAST],1);
						counter++;
						continue;
					}

					/* g controls */
					if (g[SLOW]){
						evac( queues[SLOW][GOOD],TCPchecklist[SLOW],1);
						counter++;
						continue;	
					}
					if (g[FAST]){
						evac( queues[FAST][GOOD],TCPchecklist[FAST],1);		
						counter++;
						continue;
					}
					break;
				}
			}
			else {
				while(counter<r[FAST]){
					g[FAST] = g_queue_get_length(queues[FAST][GOOD]);
					b[FAST] = g_queue_get_length(queues[FAST][BAD]);
	
					/* First evacuate the fast bad packets. */
					if( b[FAST]){
						evac(queues[FAST][BAD],TCPchecklist[FAST],1);
						counter++;
						continue;
					}


					/* Then evacuate the fast good packets. */
					if(g[FAST]){
						evac(queues[FAST][GOOD],TCPchecklist[FAST],1);
						counter++;
						continue;
					}
					break;
				}
			}
		
		}
		if(debug){
		printf("after control\n");
		print_queues();
		printf("************************************************\n");}

		/* Get greatest ACKed ID for this slot. */
		max_ID_ack[FAST][i] = TCPchecklist_get_largest_consecutive_ACK_id(TCPchecklist[FAST]);
		max_ID_ack[SLOW][i] = TCPchecklist_get_largest_consecutive_ACK_id(TCPchecklist[SLOW]);

		/* Check if system is stable. Otherwise stop*/
		if (stable!=NULL && (lastID[FLOW_1]-max_ID_ack[FLOW_1][i] > thres || lastID[FLOW_2]-max_ID_ack[FLOW_2][i] > thres) ){
			*stable = FALSE;
			break;
		}

		/* Rename variables for easier reference. */
		g[0] = g_queue_get_length(queues[0][GOOD]); g[1] = g_queue_get_length(queues[1][GOOD]);
		b[0] = g_queue_get_length(queues[0][BAD]); b[1] = g_queue_get_length(queues[1][BAD]);

		/* Compute current backlog. */
		backlog[FLOW_1][i] = g[FLOW_1]+ b[FLOW_1];
		backlog[FLOW_2][i] = g[FLOW_2]+ b[FLOW_2];

		if(debug){
		printf("checklists largest ACK\n");
		printf("flow 1: %ld\nflow 2: %ld\n",max_ID_ack[FLOW_1][i],max_ID_ack[FLOW_2][i]);
		printf("************************************************\n");	
		printf("give values\n"); 
		scanf(" %ld ",&k);}
	}

	/* Finalize TCPchecklist. */ 
	TCPchecklist_finit(); 

	/* Evacuate the queue remnants. */
	g_queue_clear(queues[FLOW_1][GOOD]);
	g_queue_clear(queues[FLOW_1][BAD]);
	g_queue_clear(queues[FLOW_2][GOOD]);
	g_queue_clear(queues[FLOW_2][BAD]);
}
/*
 * This function is called by the assembly STUB function
 */
void uart_handler() {
	
	// Disable all interupts
	atomic_up();
	
	#ifdef _IO_DEBUG
		rtx_dbug_outs((CHAR *) "Enter: uart_handler\r\n");
		rtx_dbug_outs((CHAR *) "Reading data...\r\n");
	#endif

	// irene said this should be enough - would be
	// very rare if it wasn't ready to read
	while (!(SERIAL1_UCSR & 1)) { }
	
	char_in = SERIAL1_RD;

	#ifdef _IO_DEBUG
		rtx_dbug_outs((CHAR *) "Determining what to do with char...\r\n");
	#endif

	struct io_message * msg;

	switch(char_in) {
		#ifdef _HOTKEYS_DEBUG
			case '!':
				rtx_dbug_outs((CHAR *) "'!' hotkey detected...\r\n");
				print_queues();	// print processes on ready queue and priorities
				break;
			case '@':
				rtx_dbug_outs((CHAR *) "'@' hotkey detected...\r\n");
				print_mem_blocked();	// print processes on memory blocked queue and priorities
				break;
			case '#':
				rtx_dbug_outs((CHAR *) "'#' hotkey detected...\r\n");
				print_msg_blocked();	// print processes on message blocked queue and priorities
				break;
			case '$':
				rtx_dbug_outs((CHAR *) "'$' hotkey detected...\r\n");
				print_availible_mem_queue();	// print available memory queue
				break;
			case '^':
				rtx_dbug_outs((CHAR *) "'^' hotkey detected...\r\n");
				print_used_mem_queue();	// print used memory queue
				break;
			case '&':
				rtx_dbug_outs((CHAR *) "'&' hotkey detected...\r\n");		
				output_kcd_buffer();	// print kcd buffer
				break;
			case '*':
				rtx_dbug_outs((CHAR *) "'*' hotkey detected...\r\n");
				print_cmds();	// print valid commands
				break;
		#endif
		
		default:
			#ifdef _IO_DEBUG
				rtx_dbug_outs((CHAR *) "Sending message to KCD proc...\r\n");
			#endif
			
			if (!are_blocks_available()) {
				atomic_down();
				return;
			}

			msg = (io_message *)request_memory_block();
			
			// reset tx/rx and send it to kcd
			msg->tx = UART_PID;
			msg->rx = KCD_PID;
			msg->msg[0] = char_in;
			send_message(KCD_PID, msg);
			break;
	}
	
	// Enable all interupts
	atomic_down();
}