void * shmalloc (int size) { Header *p, *prevp; unsigned nbytes = (size + sizeof(Header) - 1)/sizeof(Header) + 1; if((prevp = freep) == NULL) { base->s.next = freep = prevp = base; base->s.size = 0; } for(p=prevp->s.next;; prevp = p, p = p->s.next) { if(p->s.size >= nbytes) { if (p->s.size == nbytes) { prevp->s.next = p->s.next; } else { p-> s.size -= nbytes; p += p->s.size; p->s.size = nbytes; } freep = prevp; return (void *) (p+1); // return beginning of user's data } if (p == freep) { // we wrapped around pr("[ERROR] Shared malloc is out of Memory!", 0x0, PR_CPU_ID | PR_STRING | PR_NEWL); force_shutdown(); } } }
/////////////////////////////////////////////////////////////////////////////// // BARRIER - Implements a barrier synchronization void STD_BARRIER(int ID, int n_proc) { if (ID >= 5){ pr("Error! BARRIER called with ID >= 5!", 0x0, PR_STRING | PR_NEWL); force_shutdown(); } volatile int *BARRIER = (volatile int*)(Barrier_Base + ID * Barrier_Size); #ifdef ULTRADEBUG pr("BARRIER(ID, n_proc) invoked by ID", ID, PR_CPU_ID | PR_STRING | PR_DEC | PR_TSTAMP | PR_NEWL); pr("BARRIER(ID, n_proc) invoked with n_proc", n_proc, PR_CPU_ID | PR_STRING | PR_DEC | PR_TSTAMP | PR_NEWL); #endif // A previous barrier is already up while (dummy(BARRIER[1]) != 0) { } WAIT(1); BARRIER[0] ++; SIGNAL(1); #ifdef ULTRADEBUG pr("BARRIER(): step 1 done", 0x0, PR_CPU_ID | PR_STRING | PR_TSTAMP | PR_NEWL); #endif while (dummy(BARRIER[0]) != n_proc) { #ifdef WITH_POWER_IDLE __asm("swi " SWI_CORE_GO_IDLEstr); //go sleep.... #endif } #ifdef ULTRADEBUG pr("BARRIER(): all processes arrived", 0x0, PR_CPU_ID | PR_STRING | PR_TSTAMP | PR_NEWL); #endif WAIT(1); BARRIER[1] ++; if (BARRIER[1] == n_proc) { BARRIER[0] = 0; BARRIER[1] = 0; } SIGNAL(1); #ifdef ULTRADEBUG pr("BARRIER() done!", 0x0, PR_CPU_ID | PR_STRING | PR_TSTAMP | PR_NEWL); #endif }
/////////////////////////////////////////////////////////////////////////////// // BARINIT - Initializes the barrier system // Don't call with id >= 5. void STD_BARINIT(int ID) { if (ID >= 5){ pr("Error! BARINIT called with ID >= 5!", 0x0, PR_STRING | PR_NEWL); force_shutdown(); } volatile int *BARRIER = (volatile int*)(Barrier_Base + ID * Barrier_Size); #ifdef ULTRADEBUG pr("BARINIT(ID) done! by ID", ID, PR_CPU_ID | PR_STRING | PR_DEC | PR_TSTAMP | PR_NEWL); #endif BARRIER[0] = 0; BARRIER[1] = 0; }
/*----------------------------------------------------------------------------- main -----------------------------------------------------------------------------*/ int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Syntax: %s <tracee> [<tracee args>]\n", argv[0]); return -1; } main_child = fork(); if (main_child == 0) { int argv_len = 0; for (int i = 1; i < argc; ++i) if (argv[i]) argv_len += strlen(argv[i]) + 1; char* new_argv = new char[argv_len + 1]; for (int i = 1; i < argc; ++i) { if (i > 1) strcat(new_argv, " "); strcat(new_argv, argv[i]); } char* execve_args[] = {(char*)"sh", (char*)"-c", new_argv, NULL}; ptrace(PTRACE_TRACEME, 0, 0, 0); execv("/bin/sh", execve_args); } else { unsigned char first_fork = 1; int status; pid_t pid; std::map<pid_t, struct minimal_childstate*>::iterator it; struct minimal_childstate* child = init_child(main_child); childs.insert(std::pair<pid_t, struct minimal_childstate*>(main_child, child)); // wait for the main child first to set the ptrace options if ((waitpid(-1, &status, 0) == main_child) && WIFSTOPPED(status)) { child_set_options(child); ptrace(PTRACE_SYSCALL, main_child, NULL, 0); } else { fprintf(stderr, "ERROR: Main child initialization failed\n"); force_shutdown(); } while ((pid = waitpid(-1, &status, __WALL | WUNTRACED)) != -1) { it = childs.find(pid); if (it == childs.end()) { if (childs.find(pid) == childs.end()) childs.insert(std::pair<pid_t, struct minimal_childstate*>(pid, init_child(pid))); } else { child = it->second; } if (WIFEXITED(status)) { child->child_exited = 1; check_shutdown(); ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WIFSTOPPED(status)) { if (WSTOPSIG(status) == (SIGTRAP|0x80)) { if (!child->child_in_syscall) { long syscall_no = ptrace(PTRACE_PEEKUSER, pid, 8 * ORIG_RAX, NULL); if (is_whitelisted_syscall(syscall_no)) child->child_syscalls_whitelisted++; child->child_syscalls++; } child->child_in_syscall = !child->child_in_syscall; ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WSTOPSIG(status) == SIGTRAP) { int event = ((status & 0x000F0000) >> 16); if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK || event == PTRACE_EVENT_CLONE) { long newpid; ptrace(PTRACE_GETEVENTMSG, pid, 0, &newpid); if (childs.find(newpid) == childs.end()) childs.insert(std::pair<pid_t, struct minimal_childstate*>(newpid, init_child(newpid))); //printf("fork event from child: %d [== FORK ==>] %d\n", pid, (pid_t)newpid); if (first_fork) { first_fork = 0; gettimeofday(&start_time, NULL); } } else { //fprintf(stderr, "ERROR: Unexpected SIGTRAP from child %d - event: %d\n", pid, event); //force_shutdown(); } ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else if (WSTOPSIG(status) == SIGSTOP) { if (!child->child_resumed) child->child_resumed = 1; else child->child_signals++; ptrace(PTRACE_SYSCALL, pid, NULL, 0); } else { child->child_signals++; ptrace(PTRACE_SYSCALL, pid, NULL, (void*)WSTOPSIG(status)); } } else {