void sleep(int ticks) { if (getCurrentThread() == NULL) { // not ready to wait! uint64_t then = getUptime() + (uint64_t)ticks; while (getUptime() < then); } else { uint64_t then = getUptime() + (uint64_t)ticks; uint64_t nanoThen = then * (uint64_t)1000000; cli(); lockSched(); TimedEvent ev; timedPost(&ev, nanoThen); while (getNanotime() <= nanoThen) { waitThread(getCurrentThread()); unlockSched(); kyield(); cli(); lockSched(); }; timedCancel(&ev); unlockSched(); sti(); }; };
void onTick() { lockSched(); int doResched = 0; while (1) { if (timedEvents == NULL) break; if (getNanotime() <= timedEvents->nanotime) break; TimedEvent *ev = timedEvents; Thread *thread = ev->thread; timedEvents = ev->next; if (timedEvents != NULL) timedEvents->prev = NULL; ev->prev = ev->next = NULL; doResched = doResched || signalThread(thread); }; unlockSched(); if (doResched) kyield(); };
int pollThread(Regs *regs, int pid, int *stat_loc, int flags) { if (kernelStatus != KERNEL_RUNNING) { currentThread->therrno = EPERM; return -1; }; int sigcnt = getCurrentThread()->sigcnt; lockSched(); ASM("cli"); Thread *threadToKill = NULL; Thread *thread = currentThread->next; while (thread != currentThread) { if (thread->pidParent == currentThread->pid) { if ((thread->pid == pid) || (pid == -1)) { if (thread->flags & THREAD_TERMINATED) { threadToKill = thread; *stat_loc = thread->status; // unlink from the runqueue thread->prev->next = thread->next; thread->next->prev = thread->prev; break; }; }; }; thread = thread->next; }; // when WNOHANG is clear while ((threadToKill == NULL) && ((flags & WNOHANG) == 0)) { //currentThread->flags |= THREAD_WAITING; //currentThread->therrno = ECHILD; //*((int*)®s->rax) = -1; //switchTask(regs); getCurrentThread()->flags |= THREAD_WAITING; unlockSched(); kyield(); if (getCurrentThread()->sigcnt > sigcnt) { ERRNO = EINTR; return -1; }; lockSched(); }; unlockSched(); ASM("sti"); // when WNOHANG is set if (threadToKill == NULL) { currentThread->therrno = ECHILD; return -1; }; // there is a process ready to be deleted, it's already removed from the runqueue. kfree(thread->stack); DownrefProcessMemory(thread->pm); ftabDownref(thread->ftab); if (thread->fpexec != NULL) { if (thread->fpexec->close != NULL) thread->fpexec->close(thread->fpexec); kfree(thread->fpexec); }; if (thread->execPars != NULL) kfree(thread->execPars); int ret = thread->pid; kfree(thread); return ret; };
static void ipreasmThread(void *ignore) { // notice that we start in the waiting state, so as soon as we wake up, // scan the lists while (1) { spinlockAcquire(&reasmLock); //kprintf("REASSEMBLER TRIGGERED\n"); if (firstFragList == NULL) { ASM("cli"); reasmHandle->wakeTime = 0; reasmHandle->flags |= THREAD_WAITING; kyield(); }; IPFragmentList *list = firstFragList; int earliestDeadline = firstFragList->deadlineTicks; reasmHandle->wakeTime = 0; while (list != NULL) { if (getTicks() >= list->deadlineTicks) { // passed the deadline, just delete all fragments kprintf_debug("DEADLINE PASSED!\n"); IPFragment *frag = list->fragList; while (frag != NULL) { kprintf("FRAGMENT: offset=%d, size=%d, last=%d\n", (int) frag->fragOffset, (int) frag->fragSize, frag->lastFragment); IPFragment *next = frag->next; kfree(frag); frag = next; }; if (list == firstFragList) { firstFragList = list->next; }; if (list == lastFragList) { lastFragList = list->prev; }; if (list->prev != NULL) list->prev->next = list->next; if (list->next != NULL) list->next->prev = list->prev; IPFragmentList *nextList = list->next; kfree(list); list = nextList; } else { if (isFragmentListComplete(list)) { size_t packetSize = calculatePacketSize(list); char *buffer = (char*) kmalloc(packetSize); IPFragment *frag = list->fragList; while (frag != NULL) { memcpy(&buffer[frag->fragOffset], frag->data, frag->fragSize); IPFragment *next = frag->next; kfree(frag); frag = next; }; if (list->family == AF_INET) { struct sockaddr_in src; memset(&src, 0, sizeof(struct sockaddr_in)); src.sin_family = AF_INET; memcpy(&src.sin_addr, list->srcaddr, 4); struct sockaddr_in dest; memset(&dest, 0, sizeof(struct sockaddr_in)); dest.sin_family = AF_INET; memcpy(&dest.sin_addr, list->dstaddr, 4); onTransportPacket((struct sockaddr*)&src, (struct sockaddr*)&dest, sizeof(struct sockaddr_in), buffer, packetSize, list->proto); } else { struct sockaddr_in6 src; memset(&src, 0, sizeof(struct sockaddr_in6)); src.sin6_family = AF_INET6; memcpy(&src.sin6_addr, list->srcaddr, 16); struct sockaddr_in6 dest; memset(&dest, 0, sizeof(struct sockaddr_in6)); dest.sin6_family = AF_INET6; memcpy(&dest.sin6_addr, list->dstaddr, 16); onTransportPacket((struct sockaddr*) &src, (struct sockaddr*) &dest, sizeof(struct sockaddr_in6), buffer, packetSize, list->proto); }; if (list == firstFragList) { firstFragList = list->next; }; if (list == lastFragList) { lastFragList = list->prev; }; if (list->prev != NULL) list->prev->next = list->next; if (list->next != NULL) list->next->prev = list->prev; IPFragmentList *nextList = list->next; kfree(list); list = nextList; kprintf_debug("IPREASM: reassembled fragmented packet of size %d\n", (int) packetSize); kfree(buffer); } else { if (list->deadlineTicks < earliestDeadline) { earliestDeadline = list->deadlineTicks; }; list = list->next; }; }; }; ASM("cli"); reasmHandle->wakeTime = earliestDeadline; reasmHandle->flags |= THREAD_WAITING; spinlockRelease(&reasmLock); kyield(); }; };