/* attach a process to a debugger thread and suspend it */ static int debugger_attach( struct process *process, struct thread *debugger ) { if (process->debugger) goto error; /* already being debugged */ if (debugger->process == process) goto error; if (!is_process_init_done( process )) goto error; /* still starting up */ if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */ /* don't let a debugger debug its console... won't work */ if (debugger->process->console) { struct thread *renderer = console_get_renderer(debugger->process->console); if (renderer && renderer->process == process) goto error; } suspend_process( process ); if (!set_process_debugger( process, debugger )) { resume_process( process ); return 0; } if (!set_process_debug_flag( process, 1 )) { process->debugger = NULL; resume_process( process ); return 0; } return 1; error: set_error( STATUS_ACCESS_DENIED ); return 0; }
/* attach a process to a debugger thread and suspend it */ static int debugger_attach( struct process *process, struct thread *debugger ) { struct thread *thread; if (process->debugger) goto error; /* already being debugged */ if (!is_process_init_done( process )) goto error; /* still starting up */ if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */ /* make sure we don't create a debugging loop */ for (thread = debugger; thread; thread = thread->process->debugger) if (thread->process == process) goto error; /* don't let a debugger debug its console... won't work */ if (debugger->process->console && debugger->process->console->renderer->process == process) goto error; suspend_process( process ); if (!set_process_debugger( process, debugger )) { resume_process( process ); return 0; } if (!set_process_debug_flag( process, 1 )) { process->debugger = NULL; resume_process( process ); return 0; } return 1; error: set_error( STATUS_ACCESS_DENIED ); return 0; }
/* continue a debug event */ static int continue_debug_event( struct process *process, struct thread *thread, int status ) { struct debug_ctx *debug_ctx = current->debug_ctx; if (debug_ctx && process->debugger == current && thread->process == process) { struct debug_event *event; /* find the event in the queue */ LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { if (event->state != EVENT_SENT) continue; if (event->sender == thread) { assert( event->sender->debug_event == event ); event->status = status; event->state = EVENT_CONTINUED; wake_up( &event->obj, 0 ); unlink_event( debug_ctx, event ); resume_process( process ); return 1; } } } /* not debugging this process, or no such event */ set_error( STATUS_ACCESS_DENIED ); /* FIXME */ return 0; }
/* * wake_up_reader * * Wakes up a suspended process that was blocked on a read call that referenced * this pipe. This is called whenever some data is written to the pipe, or the pipe * is closed for writing. Once the process is resumed, the read system call will be * executed again, and either return some data to the calling process or indicate * end-of-file. */ static void wake_up_reader(pipe_buffer * p) { if (0 <= p->readpid) { resume_process(&processes[p->readpid]); p->readpid = -1; } }
int main (int argc, char* argv[]) { DWORD pid; if (argc <= 1) { process_list (); } else if (argc == 2) { pid = atoi (argv[1]); if (pid == 0) { printf ("invalid: %s\n", pid); return 1; } else { printf ("process: %u\n", pid); resume_process (pid); } } else { printf ("Usage:\n" "resume : show processlist\n" "resume PID: resuming thread\n"); } return 0; }
/* * Terminate the process. * Try to do this by sending the CTRL_C event. * If that fails, just terminate it. */ static int kill_process(Process *processp) { /* * Set the killed flag. * For threads, this will generate an exception * then next time it calls check_thread. */ processp->killed = 1; if(processp->is_thread) return 0; /* Get the process id */ if(processp->wid == 0) return -1; #if 0 /* Resume it so it can handle the exception */ GenerateConsoleCtrlEvent(CTRL_C_EVENT, processp->wid); resume_process(processp); #endif /* A lot of processes ignore the CTRL_C_EVENT, so just temrinate it */ TerminateProcess(processp->handle, 1); return 0; }
/* detach a process from a debugger thread (and resume it ?) */ int debugger_detach( struct process *process, struct thread *debugger ) { struct debug_event *event; struct debug_ctx *debug_ctx; if (!process->debugger || process->debugger != debugger) goto error; /* not currently debugged, or debugged by another debugger */ if (!debugger->debug_ctx ) goto error; /* should be a debugger */ /* init should be done, otherwise wouldn't be attached */ assert(is_process_init_done(process)); suspend_process( process ); /* send continue indication for all events */ debug_ctx = debugger->debug_ctx; /* find the event in the queue * FIXME: could loop on process' threads and look the debug_event field */ LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { if (event->state != EVENT_QUEUED) continue; if (event->sender->process == process) { assert( event->sender->debug_event == event ); event->status = DBG_CONTINUE; event->state = EVENT_CONTINUED; wake_up( &event->obj, 0 ); unlink_event( debug_ctx, event ); /* from queued debug event */ resume_process( process ); break; } } /* remove relationships between process and its debugger */ process->debugger = NULL; if (!set_process_debug_flag( process, 0 )) clear_error(); /* ignore error */ /* from this function */ resume_process( process ); return 0; error: set_error( STATUS_ACCESS_DENIED ); return 0; }
void print_B(){ int i = 0; print_B_process = get_current_process_id(); for(;;){ kprint("B"); for(i=0; i < 10000000; i++){ } resume_process(print_A_process); } }
/* * Terminate all jobs and exit. */ static void terminate_processes(void) { Process *processp; int wait; /* Send all processes the termination signal */ wait = 0; processp = state->processes; while(processp) { if(processp->pid != INIT_PID) { processp->killed = 1; if((processp->wid) && (processp->pid != INIT_PID)) { #ifdef OSH_DEBUG fprintf(stderr, "terminate_processes: Generating CTRL-C for process pid %i, group, status %i, is_thread %i, wid %i, \n", processp->pid, processp->pgrp, processp->status, processp->is_thread, processp->wid); fflush(stderr); #endif GenerateConsoleCtrlEvent(CTRL_C_EVENT, processp->wid); wait++; } resume_process(processp); } processp = processp->next; } /* Wait for them to die */ if(wait) { Sleep(1000); processp = state->processes; while(processp) { if((processp->wid) && (processp->pid != INIT_PID)) { #ifdef OSH_DEBUG fprintf(stderr, "terminate_processes: terminating process pid %i, wid %i\n", processp->pid, processp->wid); fflush(stderr); #endif TerminateProcess(processp->handle, 1); } processp = processp->next; } } }
void svc( SYSTEM_CALL_DATA *SystemCallData ) { short call_type; static short do_print = 10; short i; int Time; int ID; int k=0,m=0,n=0; int PR; int sid,tid,mlen; int actual_length; long tmp; INT32 diskstatus; long tmpid; void *next_context; char *tmpmsg; PCB *head; PCB *head1; PCB *pcb = (PCB *)malloc(sizeof(PCB)); call_type = (short)SystemCallData->SystemCallNumber; if ( do_print > 0 ) { printf( "SVC handler: %s\n", call_names[call_type]); for (i = 0; i < SystemCallData->NumberOfArguments - 1; i++ ) { //Value = (long)*SystemCallData->Argument[i]; printf( "Arg %d: Contents = (Decimal) %8ld, (Hex) %8lX\n", i, (unsigned long )SystemCallData->Argument[i], (unsigned long )SystemCallData->Argument[i]); } } switch(call_type) { case SYSNUM_GET_TIME_OF_DAY: MEM_READ(Z502ClockStatus, &Time); //Z502_REG1=Time; *SystemCallData->Argument[0]=Time; break; case SYSNUM_TERMINATE_PROCESS: tmpid = (long)SystemCallData->Argument[0]; if(tmpid>=0) { os_delete_process_ready(tmpid); Z502_REG9 = ERR_SUCCESS; } else if(tmpid == -1) { head =Running; Running = NULL; while(readyfront==NULL&&timerfront==NULL) { Z502Halt(); } //free(head); dispatcher(); Z502SwitchContext( SWITCH_CONTEXT_SAVE_MODE, &(Running->context) ); } else Z502Halt(); break; //the execution of sleep(); case SYSNUM_SLEEP: start_timer( (int)SystemCallData->Argument[0] ); break; case SYSNUM_GET_PROCESS_ID: *SystemCallData->Argument[1] = os_get_process_id((char *)SystemCallData->Argument[0]); break; case SYSNUM_CREATE_PROCESS: strcpy(pcb->Processname , (char *)SystemCallData->Argument[0]); pcb->Priority = (long)SystemCallData->Argument[2]; head = readyfront; head1 = readyfront; if(Pid < 20) { if(pcb->Priority >0) { if(readyfront == NULL&&readyrear == NULL) { readyfront = pcb; readyrear = pcb; //*SystemCallData->Argument[4] = ERR_SUCCESS; Z502_REG9 = ERR_SUCCESS; pcb->pid = Pid; pcb->next=NULL; Toppriority = pcb->Priority; *SystemCallData->Argument[3] = Pid; //pcb->context = (void *)SystemCallData->Argument[1]; Z502MakeContext( &next_context, (void *)SystemCallData->Argument[1], USER_MODE ); pcb->context = next_context; Pid++; } else if(readyfront!=NULL&&readyrear!=NULL) { if(checkPCBname(pcb) == 1) { if(pcb->Priority < Toppriority) { Z502_REG9 = ERR_SUCCESS; pcb->next = readyfront; readyfront = pcb; pcb->pid = Pid; pcb->next=NULL; Z502MakeContext( &next_context, (void *)SystemCallData->Argument[1], USER_MODE ); pcb->context = next_context; *SystemCallData->Argument[3] = Pid; Pid++; } else { while(head->next!=NULL) { if(pcb->Priority < head->Priority) break; else head = head->next; } if(head->next!=NULL) { while(head1->next!=head) { head1=head1->next; } Z502_REG9 = ERR_SUCCESS; head1->next = pcb; pcb->next=head; pcb->pid = Pid; Z502MakeContext( &next_context, (void *)SystemCallData->Argument[1], USER_MODE ); pcb->context = next_context; *SystemCallData->Argument[3] = Pid; Pid++; } else { if(pcb->Priority < head->Priority) { while(head1->next!=head) { head1=head1->next; } Z502_REG9 = ERR_SUCCESS; head1->next=pcb; pcb->next=head; pcb->pid = Pid; Z502MakeContext( &next_context, (void *)SystemCallData->Argument[1], USER_MODE ); pcb->context = next_context; *SystemCallData->Argument[3] = Pid; Pid++; } else { Z502_REG9 = ERR_SUCCESS; head->next = pcb; readyrear = pcb; pcb->next=NULL; pcb->pid = Pid; Z502MakeContext( &next_context, (void *)SystemCallData->Argument[1], USER_MODE ); pcb->context = next_context; *SystemCallData->Argument[3] = Pid; Pid++; } } } } else free(pcb); } } else free(pcb); } else { Z502_REG9++; free(pcb); } break; case SYSNUM_SUSPEND_PROCESS: ID = (int)SystemCallData->Argument[0]; head = suspendfront; while(head!=NULL) { if(head->pid == ID) { n = 1; break; } else head = head->next; } if(n!=1) { head = readyfront; while(head!=NULL) { if(head->pid == ID) { Z502_REG9 = ERR_SUCCESS; suspend_process_ready(head); k = 1; break; } else head = head->next; } if(k == 0) { head = timerfront; while(head!=NULL) { if(head->pid == ID) { Z502_REG9 = ERR_SUCCESS; suspend_process_timer(head); m = 1; break; } else head=head->next; } if(m == 0&&k == 0) { printf("illegal PID\n"); } } } if(n == 1) { printf("can not suspend suspended process\n"); } break; case SYSNUM_RESUME_PROCESS: ID = (int)SystemCallData->Argument[0]; head = suspendfront; while(head!=NULL) { if(head->pid == ID) { k=1; break; } else head=head->next; } if(k==1) resume_process(head); else printf("error\n"); break; case SYSNUM_CHANGE_PRIORITY: ID = (int)SystemCallData->Argument[0]; PR = (int)SystemCallData->Argument[1]; if(ID == -1) { Running->Priority = PR; Z502_REG9 = ERR_SUCCESS; } else { if(PR < 100) { if(checkReady(ID) == 1) { head = readyfront; while(head->pid != ID) head=head->next; change_priority_ready(head,PR); Z502_REG9 = ERR_SUCCESS; } else if(checkTimer(ID) == 1) { head = timerfront; while(head->pid != ID) head=head->next; change_priority_timer(head,PR); Z502_REG9 = ERR_SUCCESS; } else if(checkSuspend(ID) == 1) { head = suspendfront; while(head->pid != ID) head = head->next; change_priority_suspend(head,PR); Z502_REG9 = ERR_SUCCESS; } else { printf("ID ERROR!\n"); } } else { printf("illegal Priority"); } } break; case SYSNUM_SEND_MESSAGE: sid = Running->pid; tid = (int)SystemCallData->Argument[0]; tmpmsg =(char *)SystemCallData->Argument[1]; mlen = (int)SystemCallData->Argument[2]; if(maxbuffer < 8) { if(tid < 100) { if(mlen < 100) { if(tid>0) { send_message(sid,tid,mlen,tmpmsg); maxbuffer++; } else if(tid == -1) { send_message_to_all(sid,mlen,tmpmsg); maxbuffer++; } } else { printf("illegal length!\n"); } } else printf("illegal id!\n"); } else { printf("no space!\n"); Z502_REG9++; } break; case SYSNUM_RECEIVE_MESSAGE: sid = (int)SystemCallData->Argument[0]; mlen = (int)SystemCallData->Argument[2]; if(sid < 100) { if(mlen < 100) { if(sid == -1) { receive_message_fromall(); if(msgnum>0) { actual_length = strlen(checkmsg->msg_buffer); if(mlen >actual_length) { msg_out_queue(checkmsg); *SystemCallData->Argument[3] = actual_length; *SystemCallData->Argument[4] = checkmsg->source_pid; strcpy((char *)SystemCallData->Argument[1] ,checkmsg->msg_buffer); Z502_REG9 = ERR_SUCCESS; } else { printf("small buffer!\n"); } } } else { receive_message_fromone(sid); if(msgnum>0) { actual_length = strlen(checkmsg->msg_buffer); if(mlen >actual_length) { msg_out_queue(checkmsg); *SystemCallData->Argument[3] = actual_length; *SystemCallData->Argument[4] = checkmsg->source_pid; strcpy((char *)SystemCallData->Argument[1], checkmsg->msg_buffer); Z502_REG9 = ERR_SUCCESS; } else { printf("small buffer!\n"); } } } } else printf("illegal length!\n"); } else printf("illegal id!\n"); break; case SYSNUM_DISK_READ: disk_read(SystemCallData->Argument[0],SystemCallData->Argument[1],SystemCallData->Argument[2]); break; case SYSNUM_DISK_WRITE: disk_write(SystemCallData->Argument[0],SystemCallData->Argument[1],SystemCallData->Argument[2]); break; default: printf("call_type %d cannot be recognized\n",call_type); break; } do_print--; }