Date: Thu, 26 Feb 1998 03:58:27 +0000 (GMT) From: Terry Lambert <tlambert@primenet.com> To: perlsta@cs.sunyit.edu (Alfred Perlstein) Cc: tlambert@primenet.com, nate@mt.sri.com, hackers@FreeBSD.ORG Subject: Re: so how goes java? Message-ID: <199802260358.UAA22328@usr07.primenet.com> In-Reply-To: <02f901bd424a$33dd5bc0$0600a8c0@win95.local.sunyit.edu> from "Alfred Perlstein" at Feb 25, 98 07:05:04 pm
next in thread | previous in thread | raw e-mail | index | archive | help
> ummm I think you just caused my brain to hemorrhage... :) > but let me try to rephrase that just to make sure i understand. > > if we have 2 threads busy looping, for instance just printing "i'm thread A" > and "i'm thread B", whichever thread starts first will not allow the other > thread to execute, correct? > > however if one thread tries to do a disk access or something that could > possibly block like a socket operation, the other thread will be allowed to > start executing? Yes. And in the first case, if the I/O can't be accomplished immediately, both threads will run. > ok, so what do I need to do to get a situation where the threads would > alternate printing "i'm thread A" and "i'm thread B" when they are just busy > looping? You will have to modify the threads scheduler, since it won't "round-robin" things. Then when it goes to check if it can do the write, it will decide to context switch between them. > i think i understand that what you are refering to as kernel threads would > work, however you also say they have a heavy overhead? Yes. They do a full process context switch when you make a blocking call. You are not guaranted that the remainder of your quantum will be given to another thread in your process ("why" is a discussion on "starvation and deadlock"; suffice it to say, you can starve other processes, starve yourself, or, if there are N user threads and M kernel threads, where N > M, like some Solaris/SVR4 implementation models, you get to CPU-starve M-N threads that are runnable). Effectively, this makes each of your threads a process like any other process on the system, with the caveat that, IF you *happen* to pick "thread B" after involuntarily context switching "thread A", instead of one of the other 70 processes on your system, THEN you won't take a full context switch overhead. They have a minor advantage that they compete as M processes instead of as 1 process, as in user space threading. > are there any alternatives? Depends on your processing model. Frequently, you could use "shared context, multiple process", where your model was "work to do". This roughly means that you put everything in shared memory and share the fd table. Basically this is exactly kernel threading with RFORK, except that everything not in the shared memory segment/mapped region is thread local storage, and you don't have to worry about preallocating your stack (it gets to grow dynamically instead). This beats kernel threading in a couple of cases; mostly when your I/O can be "stacked", that is, you get to express a preference for a thread. Typically you would do this with a kernel mux or arbitration process and IPC to dole work-to-do out in FILO order. The point of doing this is that the last thread to be waiting to do more work is more likely to have all of its necessary pages in core (I invented this for the NetWare for UNIX server; it's called "Hot Engine Scheduling"; the NetWare for UNIX server scorned ). This way you don't have to "bend over" as much for the scheduler as you would for the kernel threading case (the SVR4/Solaris answer to this is that you should write a new scheduling class, like that's trivial, and you should always know ahead of time how much stack you will use, etc.). The absolute best model (as far as a process is concerned) is a user and kernel space cooperative scheduler. This has the context switch advantage of a user space scheduler, the full quantum consumption advantage of a user space scheduler, and the SMP scalability and quantum competition advantages of a kernel scheduler. Unfortunately, no commercial OS has one of these yet, nor is likely to in the near future, as far as I can tell (I tried to get one started at USL, but you can't modify the tree there if you cross platform independent parts, unless you get a note from God; I was barely able to get descriptor table sharing in as a modification to fork and the procfs, and I had a clear case in favor of that from a lot of database vendors). The main reason you probably won't see this is the way the Streams scheduler is jammed into the system call trap; full quantum utilization would play hell with SVR4/Solaris streams performance. A close approximation of "the absolute best model" would be to have all blocking system calls create a contex, all potentially blocking system calls create a context if they block, else run to completion, and all non-blocking system calls run to completion. This needs an "async call gate" for system calls, which includes context creation and completion mechanisms for use by a scheduler (wait/cancel). It's actually better than "the absolute best model", until you get another CPU -- then it serializes operations unnecessarily. Anyway, that's way more detail than I started out to give, and you can go look at the -current archives if you want more depth. Terry Lambert terry@lambert.org --- Any opinions in this posting are my own and not those of my present or previous employers. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802260358.UAA22328>