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(); }; };
int OSGLContext::getMaxOpenGLHeight() { static int maxCPUHeight = 0; static int maxGPUHeight = 0; if (_imp->useGPUContext) { if (maxGPUHeight == 0) { boost::shared_ptr<OSGLContextAttacher> attacher; if (getCurrentThread() != QThread::currentThread()) { attacher = OSGLContextAttacher::create(shared_from_this()); attacher->attach(); } GL_GPU::GetIntegerv(GL_MAX_TEXTURE_SIZE, &maxGPUHeight); } return maxGPUHeight; } else { #ifdef HAVE_OSMESA if (maxCPUHeight == 0) { boost::shared_ptr<OSGLContextAttacher> attacher; if (getCurrentThread() != QThread::currentThread()) { attacher = OSGLContextAttacher::create(shared_from_this()); attacher->attach(); } GL_CPU::GetIntegerv(GL_MAX_TEXTURE_SIZE, &maxCPUHeight); int osmesaMaxHeight = OSGLContext_osmesa::getMaxHeight(); maxCPUHeight = std::min(maxCPUHeight, osmesaMaxHeight); } #endif return maxCPUHeight; } }
SysThread::SysThread(Thread *userThread, size_t stackSize, int priority, bool privileged) { LOG(SYS, INFO, "Thread %p created\n", this); assert(priority <= Thread::maxPriority); this->userThread = userThread; group = NULL; if (getCurrentThread() != NULL) group = getCurrentThread()->group; nextInGroup = NULL; prevInGroupRef = NULL; prev = NULL; next = NULL; operation = NULL; firstLocked = NULL; this->stackSize = stackSize; if (stackSize == 0) this->stack = NULL; else this->stack = gcnew(char[stackSize]); this->flags = (privileged ? FLAG_PRIVILEGED : 0) | FLAG_SUSPENDED | priority; lastGCStackItem = NULL; lastGCConstrItem = NULL; tmpStackObjRef = NULL; memset(&context, 0, sizeof(context)); }
static ssize_t pipe_read(File *fp, void *buffer, size_t size) { if (size == 0) return 0; Pipe *pipe = (Pipe*) fp->fsdata; semWait(&pipe->sem); if (pipe->size == 0) { if (pipe->writecount == 0) { semSignal(&pipe->sem); return 0; } else if (fp->oflag & O_NONBLOCK) { semSignal(&pipe->sem); getCurrentThread()->therrno = EAGAIN; return -1; } else { semSignal(&pipe->sem); while (1) { if (getCurrentThread()->sigcnt > 0) { getCurrentThread()->therrno = EINTR; return -1; }; semWait(&pipe->sem); if (pipe->size > 0) break; semSignal(&pipe->sem); }; }; }; if (size > pipe->size) size = pipe->size; ssize_t outSize = 0; uint8_t *out = (uint8_t*) buffer; while (size--) { *out++ = pipe->buffer[pipe->offRead]; pipe->offRead = (pipe->offRead + 1) % 1024; outSize++; pipe->size--; }; semSignal(&pipe->sem); return outSize; };
static ssize_t pipe_write(File *fp, const void *buffer, size_t size) { if (size == 0) return 0; Pipe *pipe = (Pipe*) fp->fsdata; semWait(&pipe->sem); if (pipe->readcount == 0) { semSignal(&pipe->sem); return 0; }; if ((pipe->size+size) > 1024) { if (fp->oflag & O_NONBLOCK) { semSignal(&pipe->sem); getCurrentThread()->therrno = EAGAIN; return -1; } else { semSignal(&pipe->sem); while (1) { if (getCurrentThread()->sigcnt > 0) { getCurrentThread()->therrno = EINTR; return -1; }; semWait(&pipe->sem); if ((pipe->size+size) <= 1024) break; semSignal(&pipe->sem); }; }; }; ssize_t inSize = 0; const uint8_t *in = (const uint8_t*) buffer; while (size--) { pipe->buffer[pipe->offWrite] = *in++;; pipe->offWrite = (pipe->offWrite + 1) % 1024; inSize++; pipe->size++; }; semSignal(&pipe->sem); return inSize; };
void kyield() { while (getCurrentThread()->flags & THREAD_WAITING) { ASM("sti; hlt"); }; #if 0 cli(); uint64_t counter = switchTaskCounter; apic->timerInitCount = 0; sti(); // at this point, we have 2 possiblities: // 1) the APIC timer fired before we turned it off above. in this case, "switchTaskCounter" changed, // and we have already rescheduled, so just return. // 2) we turned the APIC timer off before it fired, so "switchTaskCounter" did not change. in this case // we must reprogram it to 1, and we can be sure that we reschedule before this function returns. if (switchTaskCounter == counter) { apic->timerInitCount = 2; nop(); // make sure it fires before we return by using at least 1 CPU cycle }; #endif };
void Thread::setPriority(Priority pr) { if(pr.validate()==false) errorHandler(INVALID_PARAMETERS); PauseKernelLock lock; Thread *current=getCurrentThread(); //If thread is locking at least one mutex if(current->mutexLocked!=0) { //savedPriority always changes, since when all mutexes are unlocked //setPriority() must become effective if(current->savedPriority==pr) return; current->savedPriority=pr; //Calculate new priority of thread, which is //max(savedPriority, inheritedPriority) Mutex *walk=current->mutexLocked; while(walk!=0) { if(walk->waiting.empty()==false) pr=std::max(pr,walk->waiting.front()->getPriority()); walk=walk->next; } } //If old priority == desired priority, nothing to do. if(pr==current->getPriority()) return; Scheduler::PKsetPriority(current,pr); #ifdef SCHED_TYPE_EDF if(isKernelRunning()) yield(); //Another thread might have a closer deadline #endif //SCHED_TYPE_EDF }
int sys_pipe(int *pipefd) { int rfd=-1, wfd=-1; FileTable *ftab = getCurrentThread()->ftab; spinlockAcquire(&ftab->spinlock); int i; for (i=0; i<MAX_OPEN_FILES; i++) { if (ftab->entries[i] == NULL) { if (rfd == -1) { rfd = i; } else if (wfd == -1) { wfd = i; break; }; }; }; if ((rfd == -1) || (wfd == -1)) { getCurrentThread()->therrno = EMFILE; return -1; }; Pipe *pipe = (Pipe*) kmalloc(sizeof(Pipe)); semInit(&pipe->sem); pipe->readcount = 0; pipe->writecount = 0; pipe->offRead = 0; pipe->offWrite = 0; pipe->size = 0; ftab->entries[rfd] = openPipe(pipe, O_RDONLY); ftab->entries[wfd] = openPipe(pipe, O_WRONLY); pipefd[0] = rfd; pipefd[1] = wfd; spinlockRelease(&ftab->spinlock); return 0; };
static ssize_t termWrite(Inode *inode, File *file, const void *buffer, size_t size, off_t pos) { if (getCurrentThread()->creds->pgid != termGroup) { cli(); lockSched(); siginfo_t si; si.si_signo = SIGTTOU; sendSignal(getCurrentThread(), &si); unlockSched(); sti(); ERRNO = ENOTTY; return -1; }; kputbuf((const char*) buffer, size); return size; };
// calculates \sum_K v_i'*A*v_i double dosum(Matrix A, Matrix v) { double alpha=0.0; Matrix temp; int i, t; t = getMaxThreads(); temp = createMatrix(A->rows, t); #pragma omp parallel for schedule(static) reduction(+:alpha) for(i=0;i<v->cols;++i) { MxV(temp->col[getCurrentThread()],A,v->col[i], 1.0, 0.0, 'N'); alpha += dotproduct(temp->col[getCurrentThread()],v->col[i]); } freeMatrix(temp); return alpha; }
void ghsInitExceptions() { if (p__cpp_exception_init_ptr->getAddress()) { auto thread = getCurrentThread(); // Invoke the exception initializer (*p__cpp_exception_init_ptr)(&thread->_ghs__eh_globals); } }
void timedPost(TimedEvent *ev, uint64_t nanotime) { ev->nanotime = nanotime; ev->thread = getCurrentThread(); if (nanotime == 0) { ev->prev = ev->next = NULL; return; }; if (timedEvents == NULL) { ev->prev = ev->next = NULL; timedEvents = ev; } else { if (nanotime <= timedEvents->nanotime) { //ev->prev = timedEvents; //ev->next = timedEvents->next; //timedEvents = ev; timedEvents->prev = ev; ev->prev = NULL; ev->next = timedEvents; timedEvents = ev; return; }; TimedEvent *scan = timedEvents; while (1) { if (scan->next == NULL) { ev->prev = scan; ev->next = NULL; scan->next = ev; return; } else { if ((scan->nanotime <= nanotime) && (scan->next->nanotime >= nanotime)) { ev->next = scan->next; ev->prev = scan; scan->next->prev = ev; scan->next = ev; return; }; scan = scan->next; }; }; }; };
int MprThreadService::getCurrentThreadId() { MprThread *tp; tp = getCurrentThread(); if (tp) { return tp->getId(); } return -1; }
/** * 実行中スレッドの処理待ち * @param target int:時間待ち(ms), string:トリガ待ち, obj:オブジェクト待ち * @param timeout タイムアウト(省略時は無限に待つ) * @return 待ちがキャンセルされたら true */ SQRESULT Thread::global_wait(HSQUIRRELVM v) { Thread *th = getCurrentThread(v); if (!th) { return ERROR_NOTHREAD(v); } th->_wait(v); return sq_suspendvm(v); }
pid_t sysWaitPid(pid_t filter, void *waitStatus, int options) { //check if any of the current children that match the filter are status=PROCSTATE_FINISHED //if so return pid_t ret = 0; bool exist = false; thread_t curThread = getCurrentThread(); struct Process *proc = curThread->process; acquireSpinlock(&curThread->lock); //lock curThread early to prevent child exit during execution of this function acquireSpinlock(&proc->lock); struct Process *child = proc->children; while (child) { acquireSpinlock(&child->lock); if (checkFilter(filter, child)) { exist = true; if (child->state == PROCSTATE_FINISHED) { releaseSpinlock(&child->lock); ret = child->pid; break; } } struct Process *next = child->nextChild; releaseSpinlock(&child->lock); child = next; } releaseSpinlock(&proc->lock); if (ret > 0) { if (waitStatus) { //*waitStatus = child->exitValue; //TODO expand this when signals get added memcpy(waitStatus, &proc->exitInfo, sizeof(proc->exitInfo)); } removeProcess(child); releaseSpinlock(&curThread->lock); return ret; } if (!exist) { releaseSpinlock(&curThread->lock); return -ECHILD; //child does not exist } //save filter //Wait for children to exit curThread->state = THREADSTATE_PIDWAIT; curThread->waitPid = filter; kthreadStop(); if (waitStatus) { //*waitStatus = curThread->waitProc->exitValue; memcpy(waitStatus, &proc->exitInfo, sizeof(proc->exitInfo)); } removeProcess(curThread->waitProc); return curThread->waitPid; }
void ghsCleanupExceptions() { if (p__cpp_exception_cleanup_ptr->getAddress()) { auto thread = getCurrentThread(); if (thread->_ghs__eh_globals.getAddress()) { (*p__cpp_exception_cleanup_ptr)(&thread->_ghs__eh_globals); thread->_ghs__eh_globals = nullptr; } } }
static ssize_t termRead(Inode *inode, File *fp, void *buffer, size_t size, off_t pos) { if (getCurrentThread()->creds->pgid != termGroup) { cli(); lockSched(); siginfo_t si; si.si_signo = SIGTTIN; sendSignal(getCurrentThread(), &si); unlockSched(); sti(); ERRNO = ENOTTY; return -1; }; int count = semWaitGen(&semCount, (int) size, SEM_W_INTR, 0); if (count < 0) { ERRNO = -count; return -1; }; semWait(&semInput); if (size > (size_t) count) size = (size_t) count; ssize_t out = 0; while (size > 0) { if (inputRead == INPUT_BUFFER_SIZE) inputRead = 0; size_t max = INPUT_BUFFER_SIZE - inputRead; if (max > size) max = size; memcpy(buffer, &inputBuffer[inputRead], max); size -= max; out += max; inputRead += max; buffer = (void*)((uint64_t)buffer + max); }; semSignal(&semInput); return out; };
/** * スクリプトを切り替える * @param func スレッドで実行するファンクション */ SQRESULT Thread::global_exec(HSQUIRRELVM v) { Thread *th = getCurrentThread(v); if (!th) { return ERROR_NOTHREAD(v); } if (sq_gettop(v) <= 1) { return ERROR_INVALIDPARAM(v); } th->_exec(v); return sq_suspendvm(v); }
/* suspend the thread */ bool Thread::suspendCallerUntil(const TTime reactivationTime, void* signaler) { Thread* caller = getCurrentThread(); PRIORITY_CEILING { caller->waitingFor = signaler; caller->suspendedUntil = reactivationTime; } yield(); caller->waitingFor = 0; /** after yield: It was resumed (suspendedUntil set to 0) or time was reached ?*/ if(caller->suspendedUntil == 0) return true; // it was resumed! return false; // time was reached }
/** * コマンド実行 * @param func スレッドで実行するファンクション * @return 終了コード */ SQRESULT Thread::global_system(HSQUIRRELVM v) { Thread *th = getCurrentThread(v); if (!th) { return ERROR_NOTHREAD(v); } if (!_fork(v)) { return ERROR_FORK(v); } th->_system(v); sq_pop(v,1); return sq_suspendvm(v); }
static void spawnProc(void *stack) { kprintf("%$\x02" "Done%#\n"); initInterp(); kprintf("Allocating memory for bootstrap... "); FrameList *fl = palloc(2); AddSegment(getCurrentThread()->pm, 1, fl, PROT_READ | PROT_WRITE | PROT_EXEC); pdownref(fl); SetProcessMemory(getCurrentThread()->pm); kprintf("%$\x02" "Done%#\n"); kprintf("Setting up the terminal... "); setupTerminal(getCurrentThread()->ftab); kprintf("%$\x02" "Done%#\n"); kprintf("Loading /initrd/usbs... "); int err; File *file = vfsOpen("/initrd/usbs", VFS_CHECK_ACCESS, &err); if (file == NULL) { kprintf("%$\x04" "Failed%#\n"); panic("failed to open /initrd/usbs"); }; ssize_t count = vfsRead(file, (void*) 0x1000, 0x1000); if (count < 1) { kprintf("%$\x04" "Failed%#\n"); panic("read() /initrd/usbs: %d\n", count); }; vfsClose(file); kprintf("%$\x02" "%d bytes%#\n", count); kprintf("Control will be transferred to usbs now.\n"); _jmp_usbs(stack); };
//exit info already set in process void signalExit(void) { thread_t curThread = getCurrentThread(); if (curThread->process->pid == 1) { panic("\n[PANIC] Attempted to kill init!"); } //kill all other threads //set current thread as mainThread threadQueueRemove(curThread); exitProcess(curThread->process); //exit thread curThread->detached = true; kthreadExit(NULL); }
/** pause execution of this thread and call scheduler */ void Thread::yield() { if(!isSchedulingEnabled) return; // I really do not like This! but required /** Optimisation: Avoid unnecesary context swtichs: see Scheduler::schedule() ***/ long long timeNow = NOW(); Thread* preselection = findNextToRun(timeNow); if(preselection == getCurrentThread()) return; // schedule is required, The scheduler shall not repeate my computations: Scheduler::preSelectedNextToRun = preselection; Scheduler::preSelectedTime = timeNow; /* reschedule next timer interrupt to avoid interruptions of while switching */ Timer::stop(); __asmSaveContextAndCallScheduler(); }
static jvmtiError GetLocal_checkArgs(jvmtiEnv* env, jthread *thread, jint depth, jint UNREF slot, void* value_ptr) { jint state; jvmtiError err; // TODO: check error condition: JVMTI_ERROR_MUST_POSSESS_CAPABILITY if (*thread == 0) { *thread = getCurrentThread(); } // check error condition: JVMTI_ERROR_INVALID_THREAD err = jvmtiGetThreadState(env, *thread, &state); if (err != JVMTI_ERROR_NONE) { return err; } // check error condition: JVMTI_ERROR_THREAD_NOT_ALIVE if ((state & JVMTI_THREAD_STATE_ALIVE) == 0) { return JVMTI_ERROR_THREAD_NOT_ALIVE; } // check error condition: JVMTI_ERROR_ILLEGAL_ARGUMENT if (depth < 0) { return JVMTI_ERROR_ILLEGAL_ARGUMENT; } // check error condition: JVMTI_ERROR_NULL_POINTER if (value_ptr == 0) { return JVMTI_ERROR_NULL_POINTER; } return JVMTI_ERROR_NONE; }
static UINT32 onPowerButton(void *ignore) { (void)ignore; Thread *thread = getCurrentThread(); while (thread->pid != 1) { thread = thread->next; }; siginfo_t info; info.si_signo = SIGHUP; info.si_code = 0; info.si_errno = 0; info.si_pid = 0; info.si_uid = 0; info.si_addr = NULL; info.si_status = 0; info.si_band = 0; info.si_value.sival_int = 0; sendSignal(thread, &info); return 0; };
int sysArchPrctl(int which, void *addr) { int error = 0; uintptr_t uaddr = (uintptr_t)addr; if (uaddr & (0xFFFF8000UL << 32)) { return -EINVAL; } thread_t thread = getCurrentThread(); switch (which) { case PRCTL_FS: thread->fsBase = addr; wrmsr(0xC0000100, uaddr); break; case PRCTL_GS: thread->gsBase = addr; wrmsr(0xC0000102, uaddr); break; default: error = -EINVAL; break; } return error; }
int elfExec(Regs *regs, const char *path, const char *pars, size_t parsz) { //getCurrentThread()->therrno = ENOEXEC; vfsLockCreation(); struct stat st; int error = vfsStat(path, &st); if (error != 0) { vfsUnlockCreation(); return sysOpenErrno(error); }; if (!vfsCanCurrentThread(&st, 1)) { vfsUnlockCreation(); getCurrentThread()->therrno = EPERM; return -1; }; File *fp = vfsOpen(path, VFS_CHECK_ACCESS, &error); if (fp == NULL) { vfsUnlockCreation(); return sysOpenErrno(error); }; vfsUnlockCreation(); if (fp->seek == NULL) { vfsClose(fp); getCurrentThread()->therrno = EIO; return -1; }; if (fp->dup == NULL) { vfsClose(fp); getCurrentThread()->therrno = EIO; return -1; }; Elf64_Ehdr elfHeader; if (vfsRead(fp, &elfHeader, sizeof(Elf64_Ehdr)) < sizeof(Elf64_Ehdr)) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (memcmp(elfHeader.e_ident, "\x7f" "ELF", 4) != 0) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (elfHeader.e_ident[EI_CLASS] != ELFCLASS64) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (elfHeader.e_ident[EI_DATA] != ELFDATA2LSB) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (elfHeader.e_ident[EI_VERSION] != 1) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (elfHeader.e_type != ET_EXEC) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (elfHeader.e_phentsize < sizeof(Elf64_Phdr)) { vfsClose(fp); getCurrentThread()->therrno = ENOEXEC; return -1; }; ProgramSegment *segments = (ProgramSegment*) kmalloc(sizeof(ProgramSegment)*(elfHeader.e_phnum)); memset(segments, 0, sizeof(ProgramSegment) * elfHeader.e_phnum); int interpNeeded = 0; Elf64_Dyn *dynamic; unsigned int i; for (i=0; i<elfHeader.e_phnum; i++) { fp->seek(fp, elfHeader.e_phoff + i * elfHeader.e_phentsize, SEEK_SET); Elf64_Phdr proghead; if (vfsRead(fp, &proghead, sizeof(Elf64_Phdr)) < sizeof(Elf64_Phdr)) { kfree(segments); getCurrentThread()->therrno = ENOEXEC; return -1; }; if (proghead.p_type == PT_PHDR) { continue; } else if (proghead.p_type == PT_NULL) { continue; } else if (proghead.p_type == PT_LOAD) { if (proghead.p_vaddr < 0x1000) { vfsClose(fp); kfree(segments); getCurrentThread()->therrno = ENOEXEC; return -1; }; if ((proghead.p_vaddr+proghead.p_memsz) > 0x8000000000) { vfsClose(fp); kfree(segments); return -1; }; uint64_t start = proghead.p_vaddr; segments[i].index = (start)/0x1000; uint64_t end = proghead.p_vaddr + proghead.p_memsz; uint64_t size = end - start; uint64_t numPages = ((start + size) / 0x1000) - segments[i].index + 1; //if (size % 0x1000) numPages++; segments[i].count = (int) numPages; segments[i].fileOffset = proghead.p_offset; segments[i].memorySize = proghead.p_memsz; segments[i].fileSize = proghead.p_filesz; segments[i].loadAddr = proghead.p_vaddr; segments[i].flags = 0; if (proghead.p_flags & PF_R) { segments[i].flags |= PROT_READ; }; if (proghead.p_flags & PF_W) { segments[i].flags |= PROT_WRITE; }; if (proghead.p_flags & PF_X) { segments[i].flags |= PROT_EXEC; }; } else if (proghead.p_type == PT_INTERP) { interpNeeded = 1; } else if (proghead.p_type == PT_DYNAMIC) { dynamic = (Elf64_Dyn*) proghead.p_vaddr; } else { kfree(segments); getCurrentThread()->therrno = ENOEXEC; return -1; }; }; // set the signal handler to default. getCurrentThread()->rootSigHandler = 0; // thread name strcpy(getCurrentThread()->name, path); // set the execPars Thread *thread = getCurrentThread(); if (thread->execPars != NULL) kfree(thread->execPars); thread->execPars = (char*) kmalloc(parsz); thread->szExecPars = parsz; memcpy(thread->execPars, pars, parsz); // create a new address space ProcMem *pm = CreateProcessMemory(); // switch the address space, so that AddSegment() can optimize mapping lockSched(); ProcMem *oldPM = thread->pm; thread->pm = pm; unlockSched(); SetProcessMemory(pm); DownrefProcessMemory(oldPM); // pass 1: allocate the frames and map them for (i=0; i<(elfHeader.e_phnum); i++) { if (segments[i].count > 0) { FrameList *fl = palloc_later(segments[i].count, segments[i].fileOffset, segments[i].fileSize); if (AddSegment(pm, segments[i].index, fl, segments[i].flags) != 0) { getCurrentThread()->therrno = ENOEXEC; pdownref(fl); DownrefProcessMemory(pm); break; }; pdownref(fl); }; }; // change the fpexec if (thread->fpexec != NULL) { if (thread->fpexec->close != NULL) thread->fpexec->close(thread->fpexec); kfree(thread->fpexec); }; thread->fpexec = fp; // make sure we jump to the entry upon return regs->rip = elfHeader.e_entry; // the errnoptr is now invalid thread->errnoptr = NULL; // close all files marked with O_CLOEXEC (on glidx a.k.a. FD_CLOEXEC) spinlockAcquire(&getCurrentThread()->ftab->spinlock); for (i=0; i<MAX_OPEN_FILES; i++) { File *fp = getCurrentThread()->ftab->entries[i]; if (fp != NULL) { if (fp->oflag & O_CLOEXEC) { getCurrentThread()->ftab->entries[i] = NULL; vfsClose(fp); }; }; }; spinlockRelease(&getCurrentThread()->ftab->spinlock); // suid/sgid stuff if (st.st_mode & VFS_MODE_SETUID) { thread->euid = st.st_uid; //thread->ruid = st.st_uid; //thread->suid = st.st_uid; thread->flags |= THREAD_REBEL; }; if (st.st_mode & VFS_MODE_SETGID) { thread->egid = st.st_gid; //thread->rgid = st.st_gid; //thread->sgid = st.st_gid; thread->flags |= THREAD_REBEL; }; if (interpNeeded) { linkInterp(regs, dynamic, pm); }; return 0; };
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; };
void joinThreadGroup(SysThreadGroup *group) { getCurrentThread()->joinGroup(group); }
int termIoctl(Inode *inode, File *fp, uint64_t cmd, void *argp) { Thread *target = NULL; Thread *scan; int pgid; struct termios *tc = (struct termios*) argp; TermWinSize *winsz = (TermWinSize*) argp; switch (cmd) { case IOCTL_TTY_GETATTR: memcpy(tc, &termState, sizeof(struct termios)); return 0; case IOCTL_TTY_SETATTR: termState.c_iflag = tc->c_iflag; termState.c_oflag = tc->c_oflag; termState.c_cflag = tc->c_cflag; termState.c_lflag = tc->c_lflag; return 0; case IOCTL_TTY_GETPGID: *((int*)argp) = termGroup; return 0; case IOCTL_TTY_SETPGID: if (getCurrentThread()->creds->sid != 1) { ERRNO = ENOTTY; return -1; }; pgid = *((int*)argp); cli(); lockSched(); scan = getCurrentThread(); do { if (scan->creds != NULL) { if (scan->creds->pgid == pgid) { target = scan; break; }; }; scan = scan->next; } while (scan != getCurrentThread()); if (target == NULL) { unlockSched(); sti(); ERRNO = EPERM; return -1; }; if (target->creds->sid != 1) { unlockSched(); sti(); ERRNO = EPERM; return -1; }; unlockSched(); sti(); termGroup = pgid; return 0; case IOCTL_TTY_ISATTY: return 0; case IOCTL_TTY_GETSIZE: getConsoleSize(&winsz->ws_col, &winsz->ws_row); winsz->ws_xpixel = 0; winsz->ws_ypixel = 0; return 0; default: ERRNO = ENODEV; return -1; }; };