IRC channel logs
2023-08-13.log
back to list of logs
<almuhs>../configure --host=i686-gnu CC='gcc -m32' LD='ld -melf_i386' --enable-apic --enable-kdb --enable-ncpus=8--disable-linux-groups <almuhs>smp now it's a bit faster, in fact. But doesn't boot yet, like Damien told <almuhs>do you know where can i find documentation about gnumach's scheduler design? I want to know the algorithm criteria and details <youpi>that'd be cmu research papers, probably <almuhs>reading the code, i don't have clear what criteria are using to set priorities, by example <youpi>again, priorities won't matter for boot speed <almuhs>but... the gnumach scheduler is literally the same than cmu mach scheduler? <youpi>but it's probably mostly coming from it <almuhs>i want to find gaps in the algorithm <almuhs>usecases that the scheduler don't takes account <almuhs>understand scheduler simply reading the code is very hard. I tried many times and i don't understand how it works in detail. By this reason i want to find docs <youpi>you can probably for a start read scheduling chapters of OS books <almuhs>i have some knowledge about it from my degree <almuhs>i have a subject with a long topic about scheduling algorithms and strategies. By this reason, i detected that gnumach's scheduler has multiple queues and priorities <almuhs>and the queues have some feedback: some process change from a queue to another. <almuhs>but i don't understand the gnumach's scheduler source code in deep <almuhs>i don't know if algorithm is round robin with priorities, or a SRT, SJF... or a fully custom <almuhs>even i don't know if all queues has the same algorithm or each queue has the self. It's very common that in multiqueue scheduling each queue has a different algorithm <almuhs>but, the most important thing is ... how the scheduler distribute the work between the multiple processors? How the scheduler selects what processor execute each process <youpi>it has two policies: time sharing and fixed priority; I guess the first is like unix's SCHED_OTHER, and the second is like Unix's SCHED_RR <youpi>the distribution of work is probably not very advanced <youpi>that's not really an immediate problem anyway <almuhs>fixed priorily seems like round robin <almuhs>"Processor sets may restrict the allowed policies, so this call will fail if the processor set to which thread is currently assigned does not permit policy. " <almuhs>the criteria in other mode is that "(for timesharing, this means adding an increment derived from cpu usage)." <almuhs>so, when the process starts, it have the lowest priority <almuhs>but, this could produce that some new process never get the cpu, because there are many older and long process which are using it all the time <youpi>I don't think process that start have lowest priority <youpi>usually it's the converse that is done <almuhs>ok, in the docs adds this info "Newly created threads obtain their priority from their task and their max priority from the thread. " <almuhs>full paragraph: "Threads have three priorities associated with them by the system, a priority, a maximum priority, and a scheduled priority. The scheduled priority is used to make scheduling decisions about the thread. It is determined from the priority by the policy (for timesharing, this means adding an increment derived from cpu usage). The priority can be set under user control, but may never exceed the maximum priority. Changing t <almuhs>he maximum priority requires presentation of the control port for the thread's processor set; since the control port for the default processor set is privileged, users cannot raise their maximum priority to unfairly compete with other users on that set. Newly created threads obtain their priority from their task and their max priority from the thread. " <almuhs>what do it refers with "from their task"? <youpi>well, the task in which is was created? <damo22>i think with MACH_HOST set to 0, there is only one processor set <youpi>I don't think mach creates processor sets by itself anyway, it's rather an admin thing <almuhs>now the question is... how the task get its priority? <damo22>i think so for fixed priority threads <damo22>youpi says the priority is not causing slow boot speed <almuhs>check if currently are using fixed priority or timeshare as policy <youpi>and users can use "nice" to lower priorities <youpi>almuhs: it's usually timesharing by default <youpi>since that's what user expect usually <damo22>almuhs: i have another few patches only in my local, to bind every thread to master cpu <almuhs>i think that some could be some bad scenarios in which some threads keeps in a low priority and never gets the cpu by this reason <youpi>almuhs: that's not a problem <youpi>it's fine for a thread to leave cpu to another thread <almuhs>could be a problem if this thread is a essential component of the system <youpi>that'll still be useful for boot to proceed <youpi>there's nothing "essential" as in that it needs deadlines <youpi>again, threads don't consume cpus just for fancy <youpi>so it doesn't really matter which thread runs when <youpi>it's doing useful stuff anyway <almuhs>by example, what matters if some ext2fs thread never gets cpu? <damo22>context switching is set to maximum 33Hz <youpi>if everything else in the system is waiting for that thread, then that thread *will* get the cpu <youpi>and again, all of this is the *same* on uni-processor gnumach <almuhs>the problem is not only slow. is that, once started INIT, this never gets to start the filesystem <youpi>the only difference on smp is possibly waking the other cpu to run thread sin parallel <youpi>almuhs: which can very probably be explained by merely something hanging for whatever reason <damo22>almuhs: the theory of that one is that there are races in userspace servers that lock up the system <almuhs>but i think that some races could be produced by lacks in scheduler <damo22>because they are not used to running threads exactly at the same time <youpi>damn, I have a hard time finishing that python3.11 build on hurd-amd64 <youpi>almuhs: there *could* be some races in the scheduler that make it miss some threads, yes <youpi>but by binding everything on cpu0 we should be avoiding that <youpi>which means, well, everything that a microkernel does :) <almuhs>if all threads goes to the same cpu, the problem can make worse. Because the competition is bigger <damo22>uhh, no cpu0 can only run one thread at a time <youpi>threads do produce useful stuff during boot <youpi>whatever their order really *does*. *not*. matter <damo22>it cant matter, because they cant rely on ordering of operations <youpi>put another way: competition for *what*? <almuhs>i worried about, if the cpu only can execute one thread every time, and there are so so many threads, even many which requires many cpu. If the priority increase with cpu usage, the longer process can keep all cpu for itself <youpi>if it has stuff to do, then that's good <youpi>booting will need that done anyway <youpi>it doesn't matter if it's doing before or after the others <almuhs>if there are so new process which casually has a low priority, maybe it never gets the cpu, and this task keeps freezed because of that <youpi>the "other threads" are not spending cpu time for nothing <youpi>during boot, *ALL* threads are contributing to booting <damo22>also on an smp system, every thread has to accept being interrupted at any time to be rescheduled at a later time because there arent enough cpus to run every thread simultanously <damo22>so maybe this slowness is something to do with IPI/interrupts <youpi>if there are thousands of IPIs per second, that's a problem for sure <almuhs>yes, but imagine that ext2fs gets priority=10. And, in the same time, other server has priority=100 and increasing because it are are entering one and once time in the cpu. And each time that procfs out of cpu, auth gets the cpu because priority=50 and increasing. ext2fs never gets the cpu <youpi>it's not a problem for other processes to eat cpu <almuhs>the problem is that ext2fs never gets to make its work <youpi>if the other processes at some point really want something from ext2fs, they'll block <youpi>and thus leave the cpu to ext2fs <youpi>at worse when *EVERYBODY ELSE* has nothing to do <damo22>i think what youpi means is that the other threads are busy doing things that progress the boot, when they finish their timeslices and block, they will eventually force cpu onto ext2fs <youpi>and that *DOESN'T* matter for the whole boot time duration <youpi>the global time spent will be the *SAME* <youpi>cpu being busy doing stuff from whatever thread all the time <almuhs>yes, but if every time some thread out of cpu, enter other thread different than ext2fs? <almuhs>because every thread has high priority than ext2fs? <youpi>there cannot be an infinite amount of threads that have stuff to do <youpi>at some ponit they'll just all be waiting for ext2fs <damo22>eventually there will be a time when ext2fs is the only thread that hasnt progressed <youpi>and *then* ext2fs will obviously get the cpyu <damo22>unless there is a bug and the run queue for NCPUS > 1 is buggy <youpi>there can be waking mistake yes <youpi>the scheduler missing that some thread is ready for running <youpi>though, again, it's all the same on UP <youpi>so again, I wouldn't prioritize looking there <damo22>when i compile for smp and use -smp 1 its still slow <almuhs>but i think that, once getting INIT, the problem is not only that the boot is slow. Is that some server gets locked <damo22>almuhs: that problem is solved by binding to cpu0 <youpi>that's a very probable thing yes <damo22>probably on some pthreading issue <youpi>almuhs: I would doubt about that <youpi>from their ponit of view, there is no difference betwen UP and SMP <almuhs>the boot always keeps freeze in the step in which filesystem are starting <damo22>there could be a pthread race in ext2fs <almuhs>i remember that, some years ago, youpi and me was searching the cause that ext2fs freeze in booting. We bound it, and this doesn't solve the problem <almuhs>and we found that there was a ext2fs thread which never was assigned <damo22>when i bind everything on cpu0 nothing deadlocks its just slow <almuhs>maybe the scheduler is buggy, as you told before, and it's not assigning the threads <damo22>i will check how often we get ipi <damo22>- if (myprocessor->state != PROCESSOR_IDLE) { <damo22>- * Something happened, try again. <damo22>- simple_unlock(&pset->idle_lock); <almuhs>maybe the scheduler is different when NCPUS > 1, and it has a bug that, even when all is bound to cpu0, it keeps without assign cpu to the threads. Or, exactly, doesn't assign cpu to ext2fs threads <damo22>why not just dispatch the cpu again <almuhs>damo22: what are there in retry label? <youpi>damo22: it just goes back to looking at the value again <youpi>since it changed between the test without the lock, and the test with the lock <damo22>why do we care about the test with the lock <youpi>because otherwise you're not synchronized with whatever processor that changed the state <youpi>you want atomicity between the state change and the other variables concerning that state <almuhs>check the codeblocks that are only of NCPUS > 1. Because the scheduler seems work fine in NCPUS = 1 <damo22>so if it stayed true to the state, why do we set it to running instead of dispatching? <almuhs>so could be a bug that only appears in NCPUS > 1 <damo22>if processor was not dispatched, why not set it to dispatching and goto retry? <almuhs>sched_prim.c. line 1255. There are a very long code specific to NCPUS > 1 <damo22>what is the point of setting it running and block on idle thread? <almuhs>line 1269 is related to idle processor <damo22> * Processor was not dispatched (Rare). <damo22>it seems to be setting an idle processor to running state when we already have a nice thread to dispatch directly on the idle processor <almuhs> * But first check the last processor it ran on. <almuhs> processor = th->last_processor; <almuhs>what if the thread never ran before? <damo22>that code path only works on HW_FOOTPRINT = 1 <almuhs>then we have to check after line 1293 <almuhs>because the previous HW_FOOTPRINT modify it <damo22>default_pset.idle_count is the number of idle processors <almuhs>but, who increase or decrease it? <almuhs>1293: if (pset->idle_count > 0) { <almuhs>1295: if (pset->idle_count > 0) { <almuhs>1367: if (default_pset.idle_count > 0) { <almuhs>1371: default_pset.idle_count--; <almuhs>ok, it's not only in HW_FOOTPRINT <almuhs>then... idle_count only decrease, never increase <almuhs>me fail: 1611 is out usecase too <almuhs>then we could discard this as problem, as a first view <almuhs>if (processor != current_processor()) <damo22>it causes an IPI so it interrupts machine_idle before the next clock interrupt <damo22>because machine_idle halts the cpu until next interrupt <almuhs>1388: if (may_preempt && (current_thread()->sched_pri > th->sched_pri)) { <almuhs>if may_preempt is not assigned, it could casually value false by default, and then the processor never preempt <almuhs>then we have to find which calls to this <almuhs>343: thread_setrun(thread, TRUE); <almuhs>428: thread_setrun(thread, TRUE); <almuhs>714: thread_setrun(old_thread, FALSE); <almuhs>966: thread_setrun(thread, FALSE); <almuhs>1179: * run_queue_enqueue macro for thread_setrun(). <almuhs>1768: thread_setrun(new_thread, FALSE); <almuhs>1990: thread_setrun(thread, TRUE); <almuhs>then could be a queue bug or a unlock broken <damo22>with bound threads on cpu0 there are no IPIs being sent <almuhs> processor = (processor_t) queue_first(&pset->idle_queue); <almuhs> queue_remove(&(pset->idle_queue), processor, processor_t, <almuhs> processor->state = PROCESSOR_DISPATCHING; <almuhs> simple_unlock(&pset->idle_lock); <almuhs> if (processor != current_processor()) <almuhs> simple_unlock(&pset->idle_lock); <almuhs> (pset == current_processor()->processor_set) && <almuhs> (current_thread()->sched_pri > th->sched_pri)) { <almuhs> * Turn off first_quantum to allow csw. <almuhs> current_processor()->first_quantum = FALSE; <almuhs> ast_on(cpu_number(), AST_BLOCK); <almuhs>ok, then could be a common bug between bound and no-bound <almuhs>the only common code between bound and no-bound is that <almuhs>if (th->sched_stamp != sched_tick) { <almuhs> assert(th->runq == RUN_QUEUE_NULL); <damo22>i guess it makes sense there is nothing to signal when bound on cpu0 <almuhs>and this is the only function, in this file, which has significant differences between NCPUS = 1 and NCPUS > 1 <almuhs> new_thread->last_processor = current_processor(); <almuhs>then only rest the previous little code <almuhs>if (th->sched_stamp != sched_tick) { <almuhs> assert(th->runq == RUN_QUEUE_NULL); <almuhs>variables seems correctly assigned, then the rest are update_priority() or the assert(). Probably the assert <damo22> * Bound, can only run on bound processor. Have to lock <damo22> * processor here because it may not be the current one. <damo22>processor_lock(processor) could be expensive <almuhs>but then, why the slow is in bound and no-bound? <almuhs>freeze i refers that boot doesn't progress after INIT <damo22>can we rewrite the dispatch code for bound processors to not lock the processor? <almuhs>processor.h:225:#define processor_lock(pr) simple_lock(&(pr)->lock) <almuhs>maybe, instead lock the processor, it could be assigned by a flag that, each time a thread search a processor where execute, discard the processors which have the bound flag <damo22>processor is the bound processor in this codepath <damo22>but it might not be current_processor <almuhs>yes, i'm searching possible bugs in that <almuhs>if (processor != current_processor()) <almuhs>assume that could be more than one bound processor? because if not, i don't understand how the bound processor could not be the current <damo22>bound processor is arbitrary per thread <almuhs>oh, bound refers that the thread cannot change of cpu? <almuhs>but could be more than a cpu works at same time <damo22>it can only be bound to a single processor <almuhs>each thread is assigned to a unique cpu. Each time that thread enter to cpu, always be the same <damo22>if bound_processor == PROCESSOR_NULL, then it is unbound <almuhs>bound doesn't implies no-SMP, only implies that threads cannot change of cpu <damo22>yea, it basically means it always must be scheduled on the same cpu <almuhs>but i think than we could force to execute in bound processor only with logic, without locks <damo22>i think the lock is needed because the bound processor could be running a different thread currently while this other cpu is choosing to dispatch it <damo22>but it might not matter if its idle <almuhs>in no-bound code, there are other simple_lock <damo22>we have that lock as well in bound case <almuhs>yes, because processor_lock is a simple_lock <damo22>i think we dont have to lock processor because thats only to read the processor_set <almuhs>in no-bound even there are two simple_lock!! <almuhs>in no-bound there are 3 simple_lock like this simple_lock(&pset->idle_lock); <damo22>you cant update the idle_queue of idle processors without that lock <almuhs>fix: there are a simple_lock and two simple_unlock. It has more sense <almuhs>i'm a bit tired and i have errors <almuhs>could be anyway to set this locks with other mechanism than a while loop? <damo22>its not expensive if the lock is not already taken <damo22>otherwise it just waits until free <almuhs>then we only can remove the locks in the cases than it's not necessary <almuhs>and continue checking the code to find possible bugs <almuhs>you can continue checking void thread_setrun() <almuhs>this is the key of the scheduler <ioio>Hello folks, I've been trying my hands around hurd, but I'm having a hard time with the SSH connection. <ioio>I'm not able to connect despite not having set the password, and I think it has something to do with how the new SSH is configured. <damo22>i think the scheduler thread itself is consuming much of the cpu time <youpi>damo22: ? there is no scheduler thread <youpi>at best only the idle thread that doesn't much beyond calling the scheduler <damo22>is (hz / 33) : 33 times / second? <damo22>thread_setrun in the bound_processor path gets called heaps <damo22>like it pages off a few screens before rumpdisk has a chance to print anything <damo22>can we reduce the frequency of the scheduler <youpi>you can reduce MIN_QUANTUM, yes <youpi>I mean, reduce 33, so the MIN_QUANTUM gets bigger <damo22>makes no difference to boot speed