int32_t message_send(uint32_t dst, uint32_t src, uint32_t length, uint8_t *data) { process *p = get_process(dst); if(!p) return -1; message *msg = (message *)kcalloc(sizeof(message)); msg->dst = dst; msg->src = src; process *srcp = get_process(src); msg->srcnum = srcp->pnum; msg->length = length; msg->data = data; if(p->messages.first == 0) { p->messages.first = p->messages.last = msg; } else { p->messages.last->next = msg; p->messages.last = msg; } return 0; }
void list_sched(){ struct queue_t *temp; struct process_control_block *pcb; int i = 0; enum QUEUES temp_current_group; if (scheduler == GROUP){ temp_current_group = current_group; temp = get_process(current_group); while (i < 4){ if (temp->head == null) { if (i == 3){ printf("Nothing is scheduled to run (all groups empty)\n"); break; } switch_group(); temp = get_process(current_group); } else { printprocess(*temp->head); break; } i++; } current_group = temp_current_group; } else{ pcb = iterate(0); if (pcb == null) { printf("Nothing is scheduled to run (ready queue empty)\n"); } else { printprocess(*pcb); } } }
void syscall_proc() { syscall_init_done = 1; while(1) { MESSAGE * msg_p = recv(NORMAL_MSG); // msg_p = va2la(msg_p->sender_pid, msg_p); //地址已经转换好了 // printf("syscall"); struct MSG_BODY_S * body_p = &(msg_p->body); switch (msg_p->type) { case MSG_get_ticks: body_p->arg1 = _get_ticks(); break; case MSG_write: _write(body_p->arg1, body_p->arg2, get_process(msg_p->sender_pid)); break; case MSG_writek: _writek(body_p->arg1, body_p->arg2, get_process(msg_p->sender_pid)); break; default: break; } unblock_process(msg_p->sender_pid); } }
int k_set_process_priority(int pid, int prio){ PCB *p; int time; #ifdef TIMING start_timer(); #endif // TODO: add check if (pid == PID_NULL || pid == PID_TIMER_IPROC || pid == PID_UART_IPROC || prio < HIGH || prio > LOWEST) { return RTX_ERR; } p = get_process(pid, gp_pcbs); if (p == NULL) { return RTX_ERR; } #ifdef DEBUG_0 printf("setting process %d priority from %d to %d\n", p->m_pid, p->m_priority, prio); #endif /* ! DEBUG_0 */ p->m_priority = prio; pq_sort(ready_queue); check_priority(); #ifdef TIMING time = end_timer(); #endif return RTX_OK; }
int kill(int pid, int sig) { if(current->proc->flags & PROC_FLAG_DEBUG) { debug("[info]KILL(%d, %d)\n", pid, sig); } /* debug("KILL(%d, %d)", pid, sig); */ if(pid <= 0) { errno = ESRCH; return -1; } if(sig > NUM_SIGNALS) { errno = EINVAL; return -1; } if(!get_process(pid)) { errno = ESRCH; return -1; } signal_process(pid, sig); return 0; }
void process_destroy(pid_t pid) { bool manageLock = processtable_biglock_do_i_hold(); if(manageLock == false) { processtable_biglock_acquire(); } KASSERT(processtable_biglock_do_i_hold()); struct process *process = get_process(pid); release_pid(pid); kfree(process->p_name); // lock_destroy(process->p_waitlock); sem_destroy(process->p_waitsem); // sem_destroy(process->p_forksem); // cv_destroy(process->p_waitcv); //processlist_cleanup(&process->p_waiters); kfree(process); int num = (int) pid; processtable[num] = NULL; parentprocesslist[pid] = -1; if(manageLock == false) { processtable_biglock_release(); } // kprintf("Cleaning process%d\n",pid); }
int main(int argc, const char * argv[]) { int pid = get_process("csgo_osx"); printf("The pid is %i\n", pid); uint32_t * imgBase[2]; const char * a[2] = {"/client.dylib", "/engine.dylib"}; task_for_pid(current_task(), getpid(), ¤t); csgo = get_client_module_info(current_task(), current_task(), pid, imgBase, a, 2); task_for_pid(current_task(), getpid(), ¤t); clientBase = * imgBase; engineBase = * (imgBase + 1); // collect info int iTeamNum; uint32_t glowObjectLoopStartAddress; localbaseInformation(clientBase, &iTeamNum); glowInfo(clientBase, &glowObjectLoopStartAddress); printf("glow loop address is 0x%x", glowObjectLoopStartAddress); // Apply Glow while (1) { localbaseInformation(clientBase, &iTeamNum); readPlayerPointAndHealth(clientBase, glowObjectLoopStartAddress, iTeamNum); //break; usleep(20000); } return 0; }
/*! * The following logic is used to select the next process: * * 1. Increment the score of each runnable process. The greater a process's * priority, the greater the increment. * 2. Select the process with the highest score. If multiple processes have the * same score, select the first process after the "current" process, where * the "current" process is the process pointed to by the ringbuffer index. * 3. Make the selected process the "current" process, set it's score to zero * and run it. * * Note that only runnable processes are given points. If non-runnable processs * are given points, they will attain insane scores. This could be problematic * if numerous non-runnable processes all became runnable at the same time * * This function is inefficient: the score of *every* process is bumped whenever * the function is called. As MAX_THREADS grows, the problem will only get * worse. Better solutions should be considered. One possible solution is to * examine only a limited number of processes each time this interrupt occurs, * rather than examining all processes. */ word far *Schedule( word far *p ) { process * const current = get_current( ); process * candidate = get_current( ); // Candidate for next runnable process process * choice; // Choice for next runnable process processID idle; // Used to find the idle thread if( NULL == current ) { print_at( count++, col, "thread pointing to NULL", 0x04 ); print_at( count++, col, "(has add_process() been called?)", 0x04 ); return p; } // What does this do? It is necessary for test program 1 to function. current->stack = p; // Make a default choice... idle.pid = IDLE; choice = get_process( idle ); // ... then see if any other suitable candidates exist. do { candidate = get_next( candidate->pid ); if( true == candidate->runnable ) { // Bump score before considering a process. This ensures that // `candidate` will always out-score the idle thread. candidate->score += candidate->priority; if( candidate->score > choice->score ) { choice = candidate; } } } while( candidate->pid.pid != current->pid.pid ); choice->score = 0; set_current( choice->pid ); // update ringbuffer index return choice->stack; }
void release_file_descriptor(pid_t pid, int fd) { struct process* proc = get_process(pid); proc->p_fd_table[fd] = NULL; // If fd was 0, 1, 2, reset fd to point to STDIN, STDOUT, STDERR? }
// move a job into the foreground int cmd_fg(tok_t arg[]){ process* p; if( arg[0] != NULL ) p = get_process( atoi( arg[0] ) ); else if( first_process != NULL ) p = first_process->prev; if( p != NULL ){ put_in_foreground( p, true ); } return 1; }
void list_Q(enum QUEUES queue) { struct queue_t *structqueue = get_process(queue); struct process_control_block *temp = structqueue->head; printf("Start of %s.\n", enum_to_string(queue)); while (temp) { printprocess(*temp); temp = temp->prev; } printf("End of %s.\n\n", enum_to_string(queue)); }
/* wait() is a system call, so the name conflicts in the test runner */ int wait_(){ struct queue_t *temp = get_process(RUNNING); /*Differenciate between different schedulers to do below code*/ if (scheduler == PRIORITY){ if(temp->head != null){ if(temp->head->priority < MAX_PRIORITY){ temp->head->priority++; } } } return move(RUNNING, WAITING); }
/** * Called by the pager. Reads a given page back into memory. * * @param page the page we wan't to read back into memory * @return SWAPPING_PENDING */ int swap_in(page_queue_item* page) { assert(page != NULL); file_table_entry* swap_fd = get_process(root_thread_g)->filetable[SWAP_FD]; assert(swap_fd != NULL); page->to_swap = 0; // to keep track of how many bytes are read TAILQ_INSERT_TAIL(&swapping_pages_head, page, entries); nfs_read(&swap_fd->file->nfs_handle, page->swap_offset+page->to_swap, BATCH_SIZE, &swap_read_callback, (int)page); return SWAPPING_PENDING; }
/** * This function will select a page (based on second chance) * and swap it out to file system. However if the selected page * was not dirty then we just need to mark it swapped again and * can return immediatly. * We stop the initiator thread as long as we're swapping * data out to the file system. The thread is restarted in the * write callback function (above). * * @param initiator ID of the thread who caused the swapping to happen * @return SWAPPING_PENDING in case we need to write the page to the disk * SWAPPING_COMPLETE in case the page was not dirty * OUT_OF_SWAP_SPACE if our swap space is already full * NO_PAGE_AVAILABLE if second_chance_select did not find a page */ int swap_out(L4_ThreadId_t initiator) { page_queue_item* page = second_chance_select(&active_pages_head); if(page == NULL) { return NO_PAGE_AVAILABLE; } assert(!is_referenced(page)); // decide where in the swap file our page will be if(page->swap_offset < 0 && (page->swap_offset = allocate_swap_entry()) < 0) return OUT_OF_SWAP_SPACE; dprintf(1, "swap_out: Second chance selected page: thread:0x%X vaddr:0x%X swap_offset:0x%X\n", page->tid, page->virtual_address, page->swap_offset); if(is_dirty(page)) { dprintf(1, "Selected page is dirty, need to write to swap space\n"); page->to_swap = PAGESIZE; page->initiator = initiator; TAILQ_INSERT_TAIL(&swapping_pages_head, page, entries); file_table_entry* swap_fd = get_process(root_thread_g)->filetable[SWAP_FD]; assert(swap_fd != NULL); data_ptr physical_page = pager_physical_lookup(page->tid, page->virtual_address); assert(physical_page != NULL); // write page in swap file assert(PAGESIZE % BATCH_SIZE == 0); for(int write_offset=0; write_offset < page->to_swap; write_offset += BATCH_SIZE) { nfs_write( &swap_fd->file->nfs_handle, page->swap_offset + write_offset, BATCH_SIZE, physical_page + write_offset, &swap_write_callback, (int)page ); } return SWAPPING_PENDING; } else { assert(page->swap_offset >= 0); page_table_entry* pte = pager_table_lookup(page->tid, page->virtual_address); frame_free(CLEAR_LOWER_BITS(pte->address)); mark_swapped(pte, page->swap_offset); free(page); return SWAPPING_COMPLETE; } }
// Simply return the file handle pointer stored in the file descriptor table. struct file_handle * get_file_handle(pid_t pid, int fd) { struct process* proc = get_process(pid); // To do: made sure fd is valid and account for errors. if(proc->p_fd_table[fd] == NULL) { //kprintf("File descriptor %d is not valid.\n", fd); return NULL; } return proc->p_fd_table[fd]; }
// Timer interrupt function. word far *schedule( word far *p ) { process *current_process; process *next_process; priority_t priority_level; bool found; // When the scheduler is called for the first time a non-Phoenix thread will be running. // Thus there is no "current process." To work around this just run the idle process for one // timer tick. Some other thread will take over at the next interrupt. Using the idle // process here is a bit of a hack but it's the only process we know we have. // if( first_time ) { processID idle_process; idle_process.pid = IDLE_PID; current_process = get_process( idle_process ); set_current( current_process ); first_time = false; return current_process->stack; } // Normal operation... // Get the current Phoenix process and search for a new one to schedule. // current_process = get_current( ); current_process->stack = p; // Search for next runnable process. found = false; for( priority_level = HIGH_PRIORITY; priority_level >= 0; --priority_level ) { next_process = get_next( current_process ); while( !found ) { if( next_process->runnable && next_process->priority == priority_level ) { found = true; break; } if( next_process == current_process ) break; next_process = get_next( next_process ); } if( found ) break; } // We should find a runnable process because the idle process is always runnable and the // loop above will stumble into it eventually. Note that the idle process should be the // only process at the IDLE_PRIORITY level. set_current( next_process ); return next_process->stack; }
//Checks for the first free file descriptor and returns it int get_free_file_descriptor(pid_t pid) { struct process* proc = get_process(pid); // 0 thru 2 are assumed to be used, so start at 3. for(int i=3; i < FD_MAX; i++) { // If the pointer is NULL, the descriptor is free for use. if(proc->p_fd_table[i] == NULL) { return i; } } // No free file descriptors. return -1; }
// move a job into the background int cmd_bg(tok_t arg[]){ process* p; if( arg[0] != NULL ){ p = get_process( atoi( arg[0] ) ); } else if( first_process != NULL ){ p = first_process->prev; } printf( "%d\n", p->pid ); if( p != NULL ){ put_in_background( p, true ); } return 1; }
int set_group(int group){ struct queue_t *temp = get_process(NEW); /* for the Group Scheduler, associates the group arg to which * group to place the process in */ if (scheduler == GROUP){ if(group == 0){ temp->head->group = READY0; return move(NEW, READY0); } else if(group == 1){ temp->head->group = READY1; return move(NEW, READY1); } else if(group == 2){ temp->head->group = READY2; return move(NEW, READY2); } else if(group == 3){ temp->head->group = READY3; return move(NEW, READY3); } else { delete(NEW, get_process(NEW)->head); return ERROR_GROUP_NOT_EXIST; /* Invalid group number */ } /* For the Priority scheduler, just moves the process to the default group * READY0 */ } else if (scheduler == PRIORITY) { return move(NEW, READY0); } return ERROR_SUCCESS; }
// Sends a message to the process int k_send_message (uint32_t pid, void *message) { MessageEnvelope *menv = (MessageEnvelope *)k_request_memory_block(); if (message == 0) return; menv->sender_id = (current_process())->m_pid; // Field 1: Sender menv->receiver_id = pid; // Field 2: Receiver menv->message_type = 0; // Field 3: Message Type menv->message = message; // Field 4: Message enqueue_envelope(pid, menv); if ((get_process(pid))->m_state == MSG_BLOCKED) move_to_ready(pid); }
int k_get_process_priority(int pid){ int time; PCB *p = get_process(pid, gp_pcbs); #ifdef TIMING start_timer(); #endif #ifdef DEBUG_0 printf("getting priority for process %d\n", p->m_pid); #endif /* ! DEBUG_0 */ if (p == NULL) { return -1; } #ifdef TIMING time = end_timer(); #endif return p->m_priority; }
int empty_term(){ struct queue_t *terminated = get_process(TERMINATED); int i = 0; /*If terminated queue is empty, return -1*/ if (terminated->head == null){ return ERROR_QUEUE_EMPTY; } terminated->head = null; terminated->tail = null; for (i = 0; i < terminated->size; i++) { if(terminated->top[i].empty == 0){ process_counter--; } clear(&terminated->top[i]); } return ERROR_SUCCESS; }
/** * Read Callback for the NFS library if we're reading a page back into memory. * Again we split the NFS calls up and always read BATCH_SIZE bytes per call. * Note that once the page is competely swapped in it is inserted back into * the page queue which holds all the active pages at any given time. * * @param token pointer to the page item * @param bytes_read should always be BATCH_SIZE * @param data pointer to the data */ static void swap_read_callback(uintptr_t token, int status, fattr_t *attr, int bytes_read, char *data) { page_queue_item* page = (page_queue_item*) token; page_table_entry* pte = pager_table_lookup(page->tid, page->virtual_address); file_table_entry* swap_fd = get_process(root_thread_g)->filetable[SWAP_FD]; if(page->process_deleted) { TAILQ_REMOVE(&swapping_pages_head, page, entries); free(page); return; } switch (status) { case NFS_OK: { assert(bytes_read == BATCH_SIZE); memcpy( ((char*)pte->address_ptr)+page->to_swap, data, bytes_read); page->to_swap += bytes_read; // swapping in complete if(page->to_swap == PAGESIZE) { // restart the thread because the page is in memory again TAILQ_REMOVE(&swapping_pages_head, page, entries); TAILQ_INSERT_TAIL(&active_pages_head, page, entries); send_ipc_reply(page->tid, L4_PAGEFAULT, 0); } else { // read next batch nfs_read(&swap_fd->file->nfs_handle, page->swap_offset+page->to_swap, BATCH_SIZE, &swap_read_callback, (int)page); } } break; default: dprintf(0, "%s: Bad NFS status (%d) from callback.\n", __FUNCTION__, status); assert(FALSE); // We could probably try to restart swapping here but since it failed before // we don't see much point in this. break; } }
int waitpid(int pid) { if(current->proc->flags & PROC_FLAG_DEBUG) { debug("[info]WAITPID(%d)\n", pid); } process_t *proc = get_process(pid); while(proc->state != PROC_STATE_FINISHED) { scheduler_sleep(current, &proc->waiting); schedule(); } int ret = proc->exit_code; free_process(proc); errno = 0; return ret; }
/* Called by exit() */ void process_exit(pid_t pid, int exitcode) { // kprintf("==Exit%d",pid); processtable_biglock_acquire(); /*If I have children, abandon them*/ abandon_children(pid); /*Store the exit code*/ exitcodelist[pid] = exitcode; /*Get the process that is exiting*/ struct process *process = get_process(pid); /*Wake up anyone listening (could be INIT_PROCESS)*/ V(process->p_waitsem); /*Notify any future waitpid() calls to return immediately*/ freepidlist[pid] = P_ZOMBIE; processtable_biglock_release(); /* Clean up when parent exits */ thread_exit(); }
/* Called by waitpid() */ int process_wait(pid_t pidToWait, pid_t pidToWaitFor) { (void)pidToWait; int exitCode; processtable_biglock_acquire(); struct process *notifier = get_process(pidToWaitFor); if(freepidlist[pidToWaitFor] == P_ZOMBIE) { //The process we're waiting for already exited. //Return to sys_waitpid to collect the exit code. exitCode = exitcodelist[pidToWaitFor]; processtable_biglock_release(); } else { processtable_biglock_release(); P(notifier->p_waitsem); exitCode = exitcodelist[pidToWaitFor]; } process_destroy(notifier->p_id); return exitCode; }
/** * A function that implements aging as well as finding the process with the highest priority to schedual next * NOTE: If there is nothing in the ready queue, highest_priority pointer will be null */ struct process_control_block *iterate(int do_aging){ struct queue_t *queue_temp = get_process(READY0); struct process_control_block *temp = queue_temp->tail; struct process_control_block *highest_priority = temp; while (temp != null){ if(do_aging == 1){ /*Aging*/ temp->quantum_count++; if(temp->quantum_count >= temp->priority){ temp->quantum_count = 0; if(temp->priority < MAX_PRIORITY){ temp->priority++; } } } /*Find highest priority*/ /*Since starting at head, if equal priority, don't want to replace highest_priority*/ if(temp->priority >= highest_priority->priority){ highest_priority = temp; } temp = temp->next; } return highest_priority; }
/** * Write callback for the NFS write function in case we swap out. * Note that because we cannot write 4096 bytes in one chunk * we split the writes up in 512 byte chunks. So this function * is called multiple times by the NFS library. * * @param token pointer to the page queue item we are swapping out */ static void swap_write_callback(uintptr_t token, int status, fattr_t *attr) { page_queue_item* page = (page_queue_item*) token; page_table_entry* pte = pager_table_lookup(page->tid, page->virtual_address); file_table_entry* swap_fd = get_process(root_thread_g)->filetable[SWAP_FD]; switch (status) { case NFS_OK: { // update file attributes swap_fd->file->status.st_size = attr->size; swap_fd->file->status.st_atime = attr->atime.useconds / 1000; page->to_swap -= BATCH_SIZE; // swapping complete, can we now finally free the frame? if(page->to_swap == 0) { if(!is_referenced(page)) { dprintf(1, "page is swapped out\n"); if(!page->process_deleted) { frame_free(CLEAR_LOWER_BITS(pte->address)); mark_swapped(pte, page->swap_offset); // restart the thread who ran out of memory if(!L4_IsNilThread(page->initiator)) send_ipc_reply(page->initiator, L4_PAGEFAULT, 0); } else {} // page was killed, nothing to do TAILQ_REMOVE(&swapping_pages_head, page, entries); free(page); } else { dprintf(1, "page is swapped out but referenced in the mean time\n"); // page has been referenced inbetween swapping out // we need to restart the whole swap procedure TAILQ_REMOVE(&swapping_pages_head, page, entries); if(!L4_IsNilThread(page->initiator)) { send_ipc_reply(page->initiator, L4_PAGEFAULT, 0); } if(!page->process_deleted) { page->initiator = L4_nilthread; TAILQ_INSERT_TAIL(&active_pages_head, page, entries); } else { free(page); } } } } break; case NFSERR_NOSPC: dprintf(0, "System ran out of memory _and_ swap space (this is bad).\n"); TAILQ_REMOVE(&swapping_pages_head, page, entries); free(page); assert(FALSE); break; default: dprintf(0, "%s: Bad NFS status (%d) from callback.\n", __FUNCTION__, status); TAILQ_REMOVE(&swapping_pages_head, page, entries); free(page); assert(FALSE); // We could probably try to restart swapping here but since it failed before // we don't see much point in this. break; } }
void localbaseInformation(mach_vm_address_t imgbase, int * i_teamNum){ // read localbaseStartaDDress uint32_t localBase; readUint32Mam(csgo, current, imgbase + 0x00EEFF04 + 0x10, &localBase); // read icrossHairID readUint32Mam(csgo, current, localBase + 0xe4, i_teamNum); } int main(int argc, const char * argv[]) { dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ startListen(); }); int pid = get_process("csgo_osx"); printf("The pid is %i\n", pid); uint32_t * imgBase[2]; const char * a[2] = {"/client.dylib", "/engine.dylib"}; task_for_pid(current_task(), getpid(), ¤t); csgo = get_client_module_info(current_task(), current_task(), pid, imgBase, a, 2); if (csgo == -1) { printf("No root permission\nPlease run it with root\n"); exit(0); } task_for_pid(current_task(), getpid(), ¤t); clientBase = * imgBase; engineBase = * (imgBase + 1); // collect info int iTeamNum;
void set_current_process (int pid) { cur_process = get_process ( pid ); }