int _papi_hwi_initialize_thread( ThreadInfo_t ** dest, int tid ) { int retval; ThreadInfo_t *thread; int i; if ( ( thread = allocate_thread( tid ) ) == NULL ) { *dest = NULL; return PAPI_ENOMEM; } /* Call the substrate to fill in anything special. */ for ( i = 0; i < papi_num_components; i++ ) { retval = _papi_hwd[i]->init( thread->context[i] ); if ( retval ) { free_thread( &thread ); *dest = NULL; return retval; } } insert_thread( thread, tid ); *dest = thread; return PAPI_OK; }
void Timer::suicide() { if(m_impl) { TimerThread* thread = allocate_thread(); thread->active_timers.remove(m_impl); thread->spare_timers.append(m_impl); m_impl->init(); m = nullptr; } delete this; }
void Timer::cleanup() { auto thread = allocate_thread(); for(;;) { auto timer = thread->spare_timers.first(); if(!timer) break; thread->spare_timers.remove(timer); delete timer; } }
Timer::~Timer() { if(m_impl) { TimerThread* thread = allocate_thread(); if(thread) { thread->active_timers.remove(m_impl); } delete m_impl; } }
unsigned long Timer::runTimers(TimerThreadId* thread_id) { TimerThread* thread; if(thread_id) { thread = (TimerThread*) thread_id; } else { thread = allocate_thread(); } unsigned long long curr_time = current_nanoseconds(); unsigned long min_time = numeric_limits<unsigned long>::max(); auto timer = thread->active_timers.first(); while(timer) { //Make sure we fetch the next_timer before the callback //so that the timer could be removed from the active_timers list. auto next_timer = timer->next(); if(timer->is_running && timer->interval >= 0) { if(curr_time >= timer->wakeup_time) { timer->callback(timer->iface, timer->callback_data); timer->wakeup_time = curr_time + timer->interval; } if(timer->wakeup_time < min_time) { min_time = timer->wakeup_time; } } timer = next_timer; } if(min_time > curr_time) { return (min_time - curr_time); } return 0; }
Timer::Timer(unsigned long interval) { TimerThread* thread = allocate_thread(); if(!thread) return; if(thread->spare_timers.empty()) { m = new TimerImpl; } else { m = thread->spare_timers.last(); thread->spare_timers.remove(m_impl); } m_impl->iface = this; setInterval(interval); thread->active_timers.append(m_impl); }
TimerThreadId* Timer::reserveThreadId() { auto thread = allocate_thread(); thread->is_reserved = true; return (TimerThreadId*) thread; }
int system_call_implementation(void) { register int schedule=0; /*!< System calls may set this variable to 1. The variable is used as input to the scheduler to indicate if scheduling is necessary. */ switch(SYSCALL_ARGUMENTS.rax) { case SYSCALL_PRINTS: { kprints((char*) (SYSCALL_ARGUMENTS.rdi)); SYSCALL_ARGUMENTS.rax = ALL_OK; break; } case SYSCALL_PRINTHEX: { kprinthex(SYSCALL_ARGUMENTS.rdi); SYSCALL_ARGUMENTS.rax = ALL_OK; break; } case SYSCALL_DEBUGGER: { /* Enable the bochs iodevice and force a return to the debugger. */ outw(0x8a00, 0x8a00); outw(0x8a00, 0x8ae0); SYSCALL_ARGUMENTS.rax = ALL_OK; break; } case SYSCALL_VERSION: { SYSCALL_ARGUMENTS.rax = KERNEL_VERSION; break; } case SYSCALL_CREATEPROCESS: { int process_number, thread_number; long int executable_number = SYSCALL_ARGUMENTS.rdi; struct prepare_process_return_value prepare_process_ret_val; for (process_number = 0; process_number < MAX_NUMBER_OF_PROCESSES && process_table[process_number].threads > 0; process_number++) { } prepare_process_ret_val = prepare_process( executable_table[executable_number].elf_image, process_number, executable_table[executable_number].memory_footprint_size); if(0 == prepare_process_ret_val.first_instruction_address) { kprints("Error starting image\n"); } process_table[process_number].parent = thread_table[cpu_private_data.thread_index].data.owner; thread_number = allocate_thread(); thread_table[thread_number].data.owner = process_number; thread_table[thread_number].data.registers.integer_registers.rflags = 0x200; thread_table[thread_number].data.registers.integer_registers.rip = prepare_process_ret_val.first_instruction_address; process_table[process_number].threads += 1; SYSCALL_ARGUMENTS.rax = ALL_OK; thread_queue_enqueue(&ready_queue,thread_number); /*cpu_private_data.thread_index = thread_number;*/ break; } case SYSCALL_TERMINATE: { int i; int owner_process = thread_table[cpu_private_data.thread_index].data.owner; int parent_process = process_table[owner_process].parent; thread_table[cpu_private_data.thread_index].data.owner = -1; /* Terminate Thread */ process_table[owner_process].threads -= 1; /* Decrement Thread count */ if(process_table[owner_process].threads < 1) { cleanup_process(owner_process); } for(i=0; i < MAX_NUMBER_OF_THREADS && thread_table[i].data.owner != parent_process; i++) { } /*cpu_private_data.thread_index = i;*/ /*thread_queue_dequeue(&ready_queue);*/ schedule = 1; break; } /* Do not touch any lines above or including this line. */ /* Add the implementation of more system calls here. */ /* Do not touch any lines below or including this line. */ default: { /* No system call defined. */ SYSCALL_ARGUMENTS.rax = ERROR_ILLEGAL_SYSCALL; } } return schedule; }