static void sig(int signo) { switch (signo) { case SIGINT: if (fgChild) { kill(fgChild, SIGINT); } fgChild = 0; break; // handle ctrl-z signal case SIGTSTP: if (fgChild) { kill(-fgChild, SIGTSTP); bgjobL* newBgJob = (bgjobL*) malloc(sizeof(bgjobL)); newBgJob->pid = fgChild; newBgJob->cmd_first = fgCmd_first; newBgJob->status = STOPPED; newBgJob->jobId = getJobId() + 1; AddBgJob(newBgJob); printf("[%d] %s %s\n",newBgJob-> jobId, "Stopped", fgCmd_first); fgChild = 0; fgCmd_first = NULL; } break; case SIGCONT: break; } fflush(stdout); }
/* * Check to see if the thread is in a job already * * Params: * passedInThreadPointer - The thread to check * * Returns: * True if the thread is in a job, else false. */ bool isThreadInJobAlready(struct thrent *passedInThreadPointer) { return getJobId(passedInThreadPointer) >= 0; }
void DotDRTBuilder::addEdge(const EdgeArgs& args){ out << "\t\tjob" << getJobId(args.src) << " -> job" << getJobId(args.dst) << " [label=\"" << args.mtime << "\"];" << endl; }
/** * Create a thread to start running a procedure. * @param procaddr procedure address * @param ssize stack size in bytes * @param priority thread priority * @param name name of the thread * @param nargs number of args that follow * @return new thread ID */ tid_typ create(void *procaddr, uint ssize, int priority, char *name, int nargs, ...) { register struct thrent *thrptr; /* thread control block */ intptr_t *saddr; /* stack address */ intptr_t *savargs; /* pointer to arg saving region */ tid_typ tid; /* stores new thread id */ va_list ap; /* points to list of var args */ int pads; /* padding entries in record. */ uint32_t i; void INITRET(void); irqmask im; im = disable(); if (ssize < MINSTK) { ssize = MINSTK; } saddr = stkget(ssize); /* allocate new stack */ tid = thrnew(); /* allocate new thread ID */ if (((SYSERR) == (int)saddr) || (SYSERR == tid)) { restore(im); return SYSERR; } thrcount++; thrptr = &thrtab[tid]; /* setup thread control block for new thread */ thrptr->state = THRSUSP; thrptr->prio = priority; thrptr->stkbase = saddr; thrptr->stklen = ssize; thrptr->stkptr = saddr; strncpy(thrptr->name, name, TNMLEN); thrptr->parent = gettid(); thrptr->hasmsg = FALSE; thrptr->memlist.next = NULL; thrptr->memlist.length = 0; //TEB: this is hardcoded for ARM //This is to enable the timer interrupt thrptr->intmask = 0x10010; /* set up default file descriptors */ /** \todo When the CONSOLE stuff works on fluke-arm, we need to reenable stdio for threads. */ #if 0 thrptr->fdesc[0] = CONSOLE; /* stdin is console */ thrptr->fdesc[1] = CONSOLE; /* stdout is console */ thrptr->fdesc[2] = CONSOLE; /* stderr is console */ #endif /* 0 */ /* Initialize stack with accounting block. */ *saddr = STACKMAGIC; *--saddr = tid; *--saddr = thrptr->stklen; *--saddr = (intptr_t)thrptr->stkbase - thrptr->stklen + sizeof(intptr_t); /* max stack addr */ if (0 == nargs) { pads = 4; } else if (0 == (nargs % 4)) /* pad size to multiple of 4 */ { pads = 0; } else { pads = 4 - (nargs % 4); } for (i = 0; i < pads; i++) { *--saddr = 0; } /* reserve space for all args. */ for (i = nargs; i > 4; i--) { *--saddr = 0; } savargs = saddr; /* build the context record as expected by ctxsw */ for (i = CONTEXT_WORDS; i > 0; i--) { *--saddr = 0; } thrptr->stkptr = saddr; /* address of thread entry point */ saddr[CONTEXT_WORDS - 1] = (intptr_t)procaddr; /* * Store the process's (where to jump to if the procaddr function returns) * return address value */ saddr[CONTEXT_WORDS - 2] = (intptr_t)INITRET; /* * Pass arguments to new processes. * * The ARM Procedure Call Standard (APCS) specifies that the first 4 * arguments be passed via r0-r3 (aka v1-v4). Additional arguments are * located on the stack at ((argnum-4) * 4) * SP (i.e. argument 5 is at * [sp, #0], 6 is at [sp, #4] and so on...) from the perspective of the * callee. */ va_start(ap, nargs); /* Store the first four arguments in the first 4 registers */ for( i = 0; i < 4 && i < nargs; i++ ) { saddr[i] = va_arg(ap, intptr_t); } /* Store the remaining arguments on the stack */ for( i = 4; i < nargs; i++ ) { *savargs++ = va_arg(ap, intptr_t); } va_end(ap); /* check if the parent is in a job */ int jobID = getJobId(thrptr->parent); if(jobID >= 0) { /* If it is, add it. Testing for functionality for now, should be thrown in a seperate function in jobgroup.c */ Job* job; for( i = 0; i < numberOfJobs; i++ ) { job = listOfJobs[i]; if( job->ID == jobID ) { break; } } //Grab the headProcess to assign the groupID to this child process Process* parentProcess = job->headProcess; Process* process = (Process*)malloc(sizeof(Process)); process->groupID = jobID; //Initialize the other properties of the child process process->dataThreadID = i; process->isParentProcess = FALSE; process->dataThread = thrptr; process->nextProcess = NULL; //Grab the last process in the job and assign it's next thread to the newly created child process Process* lastProcessInJob = job->tailProcess; lastProcessInJob->nextProcess = process; //Make the new process the tail thread job->tailProcess = process; } restore(im); return tid; }