int run_processes_parallel(int n, get_next_task_fn get_next_task, start_failure_fn start_failure, task_finished_fn task_finished, void *pp_cb) { int i, code; int output_timeout = 100; int spawn_cap = 4; struct parallel_processes pp; pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb); while (1) { for (i = 0; i < spawn_cap && !pp.shutdown && pp.nr_processes < pp.max_processes; i++) { code = pp_start_one(&pp); if (!code) continue; if (code < 0) { pp.shutdown = 1; kill_children(&pp, -code); } break; } if (!pp.nr_processes) break; pp_buffer_stderr(&pp, output_timeout); pp_output(&pp); code = pp_collect_finished(&pp); if (code) { pp.shutdown = 1; if (code < 0) kill_children(&pp, -code); } } pp_cleanup(&pp); return 0; }
//used to kill kernel threads DWORD kill_thread(PCB386 *ptr) { DWORD flags; dex32_stopints(&flags); kill_children(ptr->processid); //kill the children of this thread first!! //Tell the scheduler to remove this process from the process queue ps_dequeue(ptr); if (ptr->stackptr0!=0) free(ptr->stackptr0); free(ptr); dex32_restoreints(flags); return 1; ; };
static void handle_children_on_signal(int signo) { kill_children(pp_for_signal, signo); sigchain_pop(signo); raise(signo); }
/*called when another process wants to kill another. Also performs garbage collection (reclaims memory used by the application).*/ DWORD kill_process(DWORD processid) { PCB386 *ptr,*parentptr=0; sync_entercrit(&processmgr_busy); ptr = bridges_ps_findprocess(processid); if (ptr!=-1) { if (! (ptr->status&PS_ATTB_UNLOADABLE) ) { PCB386 *parent; kill_children(processid); //kill child processes first if (ptr->accesslevel == ACCESS_SYS) //a kernel thread? { dex32_killkthread(ptr); sync_leavecrit(&processmgr_busy); return 1; }; if ( ptr->status&PS_ATTB_THREAD ) //a thread process? If yes then redirect to another procedure { kill_thread(ptr); sync_leavecrit(&processmgr_busy); return 1; }; while (closeallfiles(ptr->processid)==1); parent=ps_findprocess(ptr->owner); if (parent!=-1) { parent->childwait=0; }; //locate the parent process and decrement its waiting //status...important for the dex32_wait() function if (ptr->accesslevel == ACCESS_SYS) free(ptr->stackptr); /*Perform memory garbage collection if necessary*/ if (ptr->meminfo!=0) freeprocessmemory(ptr->meminfo,(DWORD*)ptr->pagedirloc); if (!(ptr->status&PS_ATTB_THREAD) && (ptr->accesslevel != ACCESS_SYS) ) { //free the page tables used by the application dex32_freeuserpagetable((DWORD*)ptr->pagedirloc); #ifdef MEM_LEAK_CHECK printf("1 page freed (page directory).\n"); #endif mempush(ptr->pagedirloc); }; if (ptr->parameters!=0) free(ptr->parameters); if (ptr->stdout!=0) { free(ptr->stdout); }; //Tell the scheduler to remove this process from the queue ps_dequeue(ptr); free(ptr); sync_leavecrit(&processmgr_busy); return 1; }; }; sync_leavecrit(&processmgr_busy); return 0; };
int main(void) { int *child_pid, oldcount, newcount, shm_id, i, j; struct sched_param param; key_t key; nb_cpu = get_ncpu(); if (nb_cpu == -1) { printf("Can not get the number of CPUs of your machines.\n"); return PTS_UNRESOLVED; } child_pid = malloc(nb_cpu * sizeof(int)); key = ftok("conformance/interfaces/sched_setparam/9-1.c",1234); shm_id = shmget(key, sizeof(int), IPC_CREAT|0600); if (shm_id < 0) { perror("An error occurs when calling shmget()"); return PTS_UNRESOLVED; } shmptr = shmat(shm_id, 0, 0); if (shmptr == (void*)-1) { perror("An error occurs when calling shmat()"); return PTS_UNRESOLVED; } *shmptr = 0; param.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(getpid(), SCHED_FIFO, ¶m) != 0) { if (errno == EPERM) { printf("This process does not have the permission to set its own scheduling " "parameter.\nTry to launch this test as root\n"); } else { perror("An error occurs when calling sched_setscheduler()"); } return PTS_UNRESOLVED; } for (i = 0; i < (nb_cpu - 1); i++) { child_pid[i] = fork(); if (child_pid[i] == -1) { perror("An error occurs when calling fork()"); for (j = 0; j < i; j++) { kill(child_pid[j], SIGTERM); } return PTS_UNRESOLVED; } else if (child_pid[i] == 0) { child_process(); printf("This code should not be executed.\n"); return PTS_UNRESOLVED; } } child_pid[i] = fork(); if (child_pid[i] == -1) { perror("An error occurs when calling fork()"); for (j = 0; j < i; j++) { kill(child_pid[j], SIGTERM); } return PTS_UNRESOLVED; } else if (child_pid[i] == 0) { test_process(); printf("This code should not be executed.\n"); return PTS_UNRESOLVED; } sleep(1); param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2; oldcount = *shmptr; if (sched_setparam(child_pid[i], ¶m) != 0) { perror("An error occurs when calling sched_setparam()"); kill_children(child_pid); return PTS_UNRESOLVED; } newcount = *shmptr; if (newcount == oldcount) { printf("The target process does not preempt the calling process\n"); kill_children(child_pid); return PTS_FAIL; } printf("Test PASSED\n"); kill_children(child_pid); return PTS_PASS; }