CVector* divideFam(CVector *wordVec, int wordLength, char ch, int *max_index) { int n = 1; for (int i = 0; i < wordLength; i++) { n += n; } CVector **fam = malloc(n * sizeof(CVector*)); for (int i = 0; i < n; i++) { fam[i] = NULL; } int *arr = calloc(n, sizeof(int)); int index = 0; for (void *cur = cvec_first(wordVec); cur != NULL; cur = cvec_next(wordVec, cur)) { char *word = (char*)cur; int check = 0; for (int i = wordLength -1; i >= 0; i--) { if (word[i] == ch) { if(check != 0) { // means the character appears more than once. // remove it from the current family cvec_remove(fam[check], cvec_count(fam[check]) - 1); arr[check]--; check = check | (1 << (wordLength -i - 1)); } check = check | (1 << (wordLength -i - 1)); appendElem(fam, check, wordLength, arr, word); } } if (check == 0) { appendElem(fam, check, wordLength, arr, word); } } *max_index = getMaxIndex(arr, n); free(arr); return fam[*max_index]; }
int doSchedule(int *spsr, volatile unsigned int *sp[], q_elem **next, int timedSchedule) { #if DEBUG_SCHEDULE kprintf("do Schedule timed=%d forcere=%d forceup=%d\r\n", timedSchedule, force_reschedule, force_updateRegs); #endif int returnValue = 0; if(!timedSchedule && !force_reschedule) { (*next) = thread.current; return returnValue; } if(current_wants_to_be_destroyed) { q_elem *tmp = thread.current; thread.thread_count--; thread.threads_ready--; threadsPerPidCount[tmp->tcb.pid]--; // free stack unsigned int stackMap = getMapping(tmp->tcb.pid, 0xB+tmp->id)-0xA; free_0_63&=(~(1<<stackMap)); minvalidate(tmp->tcb.pid, 0xB+tmp->id); // free data if all threads of a process died if(threadsPerPidCount[tmp->tcb.pid]<=0) { unsigned int dataMap = getMapping(tmp->tcb.pid, 0xA)-0xA; free_0_63&=(~(1<<dataMap)); minvalidate(tmp->tcb.pid, 0xA); } thread.current = nextThread(); queueOut(tmp, &thread.head); appendElem(tmp, &thread.free_elems); force_updateRegs = 1; current_wants_to_be_destroyed = 0; } if(!force_updateRegs) { saveCurrentThread(*sp, *spsr); (*next) = nextThread(); } else { (*next) = thread.current; } #if DEBUG kprintf("waiting: "); printListPrev(thread.waiting); kprintf("\r\n"); kprintf("queue: "); printListPrev(thread.head); kprintf("\r\n"); kprintf("next %d\r\n", (*next)->id); #endif if(force_reschedule) force_reschedule=0; updateTimer(next, timedSchedule); #if DEBUG kprintf("TIMER NEXT\r\n"); kprintf("waiting: "); printListPrev(thread.waiting); kprintf("\r\n"); kprintf("queue: "); printListPrev(thread.head); kprintf("\r\n"); kprintf("next %d\r\n", (*next)->id); #endif #if DEBUG_THREAD_REGS kprintf("next PC %x before THREAD REGS\r\n",(*next)->tcb.regs[15]); #endif switch(updateThreadRegs((*next),sp)) { // didn't do the context switch, so update LR case 1: returnValue = 1; break; case -1: kprintf("ERROR no next Thread, something went wrong\r\n"); while(1); break; } return returnValue; }
// init new thread and append at the beginning of the queue int createThread(void (*startFun)(void* args, int len), void *args, int len, int prio, int newProcess) { if(thread.free_elems) { q_elem *newfree = thread.free_elems; thread.free_elems = thread.free_elems->next; thread.free_elems->prev = 0; newfree->next = thread.head; // if we're not adding the idle thread and prio is // less than zero throw error if(thread.thread_count>0 && prio<=0) { return -2; } else { newfree->priority = prio; } appendElem(newfree, &thread.head); // we're going to copy args to begining of thread stack int argbuffer[32]; // if it is a new thread we need to copy data into kernel // space so we can copy it to the new thread if(newProcess) { len = len>32?32:len; // no buffer overflow ;) int i; for(i=0;i<len;i++) { argbuffer[i] = ((int *) args)[i]; } args=argbuffer; unsigned int newpid; for(newpid=0;threadsPerPidCount[newpid] && newpid<MAX_PIDS;newpid++); if(newpid==MAX_PIDS) return -1; int newMemAdr = nextFreeBlock(); if(newMemAdr==-1) return -1; newMemAdr+=0xA; mmap(newpid, 0xA, newMemAdr, mmu_readwrite); // data segment - just one per process newfree->tcb.pid = newpid; set_ttbr0(get_mmu(newpid)); // load new table tlbiall(); // flush tlb } else { newfree->tcb.pid = thread.current->tcb.pid; } threadsPerPidCount[newfree->tcb.pid]++; int newMemAdr = nextFreeBlock(); if(newMemAdr==-1) return -1; newMemAdr+=0xA; mmap(newfree->tcb.pid, 0xB+newfree->id, newMemAdr, mmu_readwrite); // stack one for each thread newfree->tcb.regs[0] = 0xBffffc + (newfree->id<<20) - (len<<2); newfree->tcb.regs[1] = len; // SP = USR BASE + Thread Count Offset 64k - args (copied to stack) newfree->tcb.regs[13] = newfree->tcb.regs[0]; // sp newfree->tcb.regs[14] = (int) &exitThread; // lr //printf("set LR to: %x\r\n", thread.head->tcb.regs[14]); newfree->tcb.regs[15] = (int) startFun; // pc // init cpsr, user mode enable IRQs, no thumb no FIQ newfree->tcb.cpsr = 0b1010000; // copy args to stack int i; int curAddr = newfree->tcb.regs[13]; for(i=0;i<len;i++) { int arg = ((int *) args)[i]; write_u32(curAddr,arg); curAddr+=4; } thread.thread_count++; thread.threads_ready++; if(newProcess && thread.current) { set_ttbr0(get_mmu(thread.current->tcb.pid)); // load current table tlbiall(); // flush tlb } // if there was currently just the idle Thread read // and we got a new one -> force reschedule! if(thread.threads_ready==2) { // setTimer(0); #if DEBUG kprintf("create force \r\n"); #endif force_reschedule=1; } return 1; } else return -1; }
void threadIntoWait(int spsr, volatile unsigned int sp[], enum thread_status status) { #if DEBUG kprintf("thread into wait\r\n"); #endif // if we're able to put a char into the output Buffer // the thread doesn't need to wait if(status==thread_waiting_putChr) { #if DEBUG kprintf("try to put char %c\r\n", (char) sp[2]); #endif if(putChar(sp[2])) { #if DEBUG kprintf("putted char\r\n"); #endif return; } } if(status==thread_waiting_getChr) { #if DEBUG kprintf("try to put char %c\r\n", (char) sp[2]); #endif char chr = getChar(); if(chr) { sp[2] = getChar(); #if DEBUG kprintf("putted char\r\n"); #endif return; } } saveCurrentThread(sp, spsr); thread.current->tcb.status = status; if(status==thread_waiting_time) { thread.current->tcb.waitTime = thread.current->tcb.regs[0]; #if DEBUG kprintf("put thread %d into waiting for %dns\r\n",thread.current->id ,thread.current->tcb.waitTime); #endif } q_elem *tmp = thread.current; thread.threads_ready--; thread.current = nextThread(); #if DEBUG kprintf(" new current %d \r\n", thread.current->id); #endif queueOut(tmp, &thread.head); appendElem(tmp, &thread.waiting); force_reschedule = 1; force_updateRegs = 1; }