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; }
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; }