Exemple #1
0
int exec_thread( unsigned int cpu_id, struct thread *t, 
				 unsigned int milliseconds )
{
	assert( t != NULL );
	
	set_fpu_trap();
	
	set_map( t->process->map );

	cpu[ cpu_id ].sched.running = 1;			// Marked as running before
	cpu[ cpu_id ].sched.current_thread = t;		// Mark the thread.
	
	release_spinlock( &(cpu[ cpu_id ].sched.lock_scheduler) ); 
			// Other CPU's can register their need to mess with this CPU's tables.
	

					
		do
		{
		  	sysenter_set_esp( t->stack_kernel );
	
			cpu[ cpu_id ].system_tss->esp0 = t->stack_kernel;
			cpu[ cpu_id ].system_tss->esp  = t->stack;
			cpu[ cpu_id ].system_tss->cr3  = (uint32_t)t->process->map;

			set_apic_distance( cpu_id, milliseconds );
	
			stats_time( cpu_id, &(cpu[ cpu_id ].st_schedulerTime) ); // Scheduler time.

			t->stack = __switch_thread( t->stack );

			stats_time_start( &(cpu[ cpu_id ].st_schedulerTime) ); // Scheduler
		   
		} while ( cpu[cpu_id].sched.locked == 1 ); // in case...

	// If math was used....
	if ( t->math_state > 0 ) save_fpu( t );
	
	cpu[ cpu_id ].sched.current_thread = NULL;
	cpu[ cpu_id ].sched.running = 0;
			// WARNING: Don't use the *t pointer anymore after this.

			// Synchronization point occurs here. Table messing. 

	acquire_spinlock( &(cpu[cpu_id].sched.lock_scheduler) );

	
	return 0;
}
Exemple #2
0
void scheduler()
{
	unsigned int cpu_id = CPUID; 
	struct scheduler_info *si = &(cpu[ cpu_id ].sched);
	struct thread *tr;
	int idle;
	int flip = 0;
	uint64_t requested_time = TIMESLICE;

	// We will never go back.
	set_cpu_flags(  cpu_flags() & ~EFLAG_NESTED_TASK );

	// Now we're working.
	acquire_spinlock( &(si->lock_scheduler) );

	// Start timing the scheduler
	stats_time_start( &(cpu[ cpu_id ].st_schedulerTime) );

	assert( (cpu_flags() & EFLAG_INTERRUPT) == 0 );

	ack_apic();

	while (1==1)
	{
		// Just show the world that we're still alive.
		((char*)0xB8000)[158 - cpu_id * 2] ++ ;		/// \todo remove one day


		// If the garbage collector has work to do, let it run.
		if ( gc_has_work( cpu_id ) == 0 )
		{
			tr = smk_gc[ cpu_id ];
			exec_thread( cpu_id, tr, TIMESLICE, 0 );
			stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); 
		}

		
		// Find out when the next timed event is.
		requested_time = remove_timers( si, cpu[ cpu_id ].st_systemTime.usage );
		idle = 0;
			
		// Fast queue support
		if ( flip == 0 )
		{
			tr = get_fast( si );
			if ( tr != NULL )
			{
				exec_thread( cpu_id, tr, TIMESLICE, 0 );
				stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); 
														// Maintain CPU time.

				if ( si->sched_count != 0 ) flip = 1;	// Ensure others run
				continue;
			}
		}


		flip = 0;
		// Reset of fast queue
		
		// If there's nothing to do, do idle.
		if ( si->sched_count == 0 ) 
		{
			if ( gc_has_work( cpu_id ) == 0 ) continue;	// Al-e-oop!
				
			tr = smk_idle[ cpu_id ];
			idle = 1;		// Safe to wake up when required.
		}
		else
		{
			tr = si->sched_queue[ si->position ].tr;
			si->position = (si->position + 1) % si->sched_count;

			requested_time = TIMESLICE;
			idle = 0;		// Don't interrupt until timeslice is over
		}


		// And run the selected thread.
		exec_thread( cpu_id, tr, requested_time, idle );
		stats_time( cpu_id, &(cpu[ cpu_id ].st_systemTime) ); 
														// Maintain CPU time.
														//
		// If the previous thread requested a state change, honour it.
		remove_last( si );

	}

}
void request_stats_final(REQUEST *request)
{
	if (request->master_state == REQUEST_COUNTED) return;

	if (!request->listener) return;
	if (!request->client) return;

	if ((request->listener->type != RAD_LISTEN_NONE) &&
#ifdef WITH_ACCOUNTING
	    (request->listener->type != RAD_LISTEN_ACCT) &&
#endif
#ifdef WITH_COA
	    (request->listener->type != RAD_LISTEN_COA) &&
#endif
	    (request->listener->type != RAD_LISTEN_AUTH)) return;

	/* don't count statistic requests */
	if (request->packet->code == PW_CODE_STATUS_SERVER)
		return;

#undef INC_AUTH
#define INC_AUTH(_x) radius_auth_stats._x++;request->listener->stats._x++;request->client->auth._x++;


#undef INC_ACCT
#ifdef WITH_ACCOUNTING
#define INC_ACCT(_x) radius_acct_stats._x++;request->listener->stats._x++;request->client->acct._x++
#else
#define INC_ACCT(_x)
#endif

#undef INC_COA
#ifdef WITH_COA
#define INC_COA(_x) radius_coa_stats._x++;request->listener->stats._x++;request->client->coa._x++
#else
#define INC_COA(_x)
#endif

#undef INC_DSC
#ifdef WITH_DSC
#define INC_DSC(_x) radius_dsc_stats._x++;request->listener->stats._x++;request->client->dsc._x++
#else
#define INC_DSC(_x)
#endif

	/*
	 *	Update the statistics.
	 *
	 *	Note that we do NOT do this in a child thread.
	 *	Instead, we update the stats when a request is
	 *	deleted, because only the main server thread calls
	 *	this function, which makes it thread-safe.
	 */
	if (request->reply && (request->packet->code != PW_CODE_STATUS_SERVER)) switch (request->reply->code) {
	case PW_CODE_ACCESS_ACCEPT:
		INC_AUTH(total_access_accepts);

		auth_stats:
		INC_AUTH(total_responses);

		/*
		 *	FIXME: Do the time calculations once...
		 */
		stats_time(&radius_auth_stats,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		stats_time(&request->client->auth,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		stats_time(&request->listener->stats,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		break;

	case PW_CODE_ACCESS_REJECT:
		INC_AUTH(total_access_rejects);
		goto auth_stats;

	case PW_CODE_ACCESS_CHALLENGE:
		INC_AUTH(total_access_challenges);
		goto auth_stats;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_RESPONSE:
		INC_ACCT(total_responses);
		stats_time(&radius_acct_stats,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		stats_time(&request->client->acct,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		break;
#endif

#ifdef WITH_COA
	case PW_CODE_COA_ACK:
		INC_COA(total_access_accepts);
	  coa_stats:
		INC_COA(total_responses);
		stats_time(&request->client->coa,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		break;

	case PW_CODE_COA_NAK:
		INC_COA(total_access_rejects);
		goto coa_stats;

	case PW_CODE_DISCONNECT_ACK:
		INC_DSC(total_access_accepts);
	  dsc_stats:
		INC_DSC(total_responses);
		stats_time(&request->client->dsc,
			   &request->packet->timestamp,
			   &request->reply->timestamp);
		break;

	case PW_CODE_DISCONNECT_NAK:
		INC_DSC(total_access_rejects);
		goto dsc_stats;
#endif

		/*
		 *	No response, it must have been a bad
		 *	authenticator.
		 */
	case 0:
		if (request->packet->code == PW_CODE_ACCESS_REQUEST) {
			if (request->reply->offset == -2) {
				INC_AUTH(total_bad_authenticators);
			} else {
				INC_AUTH(total_packets_dropped);
			}
		} else if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) {
			if (request->reply->offset == -2) {
				INC_ACCT(total_bad_authenticators);
			} else {
				INC_ACCT(total_packets_dropped);
			}
		}
		break;

	default:
		break;
	}

#ifdef WITH_PROXY
	if (!request->proxy || !request->home_server) goto done;	/* simplifies formatting */

	switch (request->proxy->code) {
	case PW_CODE_ACCESS_REQUEST:
		proxy_auth_stats.total_requests += request->num_proxied_requests;
		request->home_server->stats.total_requests += request->num_proxied_requests;
		break;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_REQUEST:
		proxy_acct_stats.total_requests++;
		request->home_server->stats.total_requests += request->num_proxied_requests;
		break;
#endif

#ifdef WITH_COA
	case PW_CODE_COA_REQUEST:
		proxy_coa_stats.total_requests++;
		request->home_server->stats.total_requests += request->num_proxied_requests;
		break;

	case PW_CODE_DISCONNECT_REQUEST:
		proxy_dsc_stats.total_requests++;
		request->home_server->stats.total_requests += request->num_proxied_requests;
		break;
#endif

	default:
		break;
	}

	if (!request->proxy_reply) goto done;	/* simplifies formatting */

#undef INC
#define INC(_x) proxy_auth_stats._x += request->num_proxied_responses; request->home_server->stats._x += request->num_proxied_responses;

	switch (request->proxy_reply->code) {
	case PW_CODE_ACCESS_ACCEPT:
		INC(total_access_accepts);
	proxy_stats:
		INC(total_responses);
		stats_time(&proxy_auth_stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		stats_time(&request->home_server->stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		break;

	case PW_CODE_ACCESS_REJECT:
		INC(total_access_rejects);
		goto proxy_stats;

	case PW_CODE_ACCESS_CHALLENGE:
		INC(total_access_challenges);
		goto proxy_stats;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_RESPONSE:
		proxy_acct_stats.total_responses++;
		request->home_server->stats.total_responses++;
		stats_time(&proxy_acct_stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		stats_time(&request->home_server->stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		break;
#endif

#ifdef WITH_COA
	case PW_CODE_COA_ACK:
	case PW_CODE_COA_NAK:
		proxy_coa_stats.total_responses++;
		request->home_server->stats.total_responses++;
		stats_time(&proxy_acct_stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		stats_time(&request->home_server->stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		break;

	case PW_CODE_DISCONNECT_ACK:
	case PW_CODE_DISCONNECT_NAK:
		proxy_coa_stats.total_responses++;
		request->home_server->stats.total_responses++;
		stats_time(&proxy_acct_stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		stats_time(&request->home_server->stats,
			   &request->proxy->timestamp,
			   &request->proxy_reply->timestamp);
		break;
#endif

	default:
		proxy_auth_stats.total_unknown_types++;
		request->home_server->stats.total_unknown_types++;
		break;
	}

 done:
#endif /* WITH_PROXY */

	request->master_state = REQUEST_COUNTED;
}