---
title: WWDC2001 Session 140
framework: wwdc
role: article
path: wwdc/wwdc2001-140
---

# WWDC2001 Session 140

## Transcript

Kind: captions Language: en surprised more people than I thought would survive till this time on Friday thanks to the marquee decide we're here to talk about the colonel at 3:30 on Friday no exciting demos to give it's just me you and hopefully we can cover some topics that you guys are really concerned about so let's get this thing going here where is it up there it is okay it's over here so what are you going to learn today well the main thing you're going to learn is what the basic colonel services are that are available to you as programmers you're also going to learn some of the layering that goes on above those services inside of our system one of the things that you know we've been able to talk about for the last few years here at WWDC is you know this really cool kernel technology we have this year part of the message is yeah we have really cool technology don't use it right so how are you gonna use it well you're going to use the layers that are built above it you're gonna mostly be writing Carbon applications or cocoa applications your some of you are going to be writing BSD applications and wrapping them as you just saw right to give them the user experience of a higher-level application right and we want to show you how some of those services are are layered above ours what you're going to learn is you know when it's safe to directly call some of our services right and when it's not safe to call some of our service what those higher-level services are that are available to you through the hire frameworks right to use those instead all right and the one of the key things that that this session is going to teach you is all right although you're not going to be directly programming to very many of our services in the kernel all right when it comes time to do debugging right you're going to have to know what's happening at those lower levels of the system because the debuggers tend to jump you in at some of the lowest levels and you have to work your way back up right and so if you don't know how a thread is tied to some of the higher level services then you're going to be in trouble alright again the same thing when you're trying to tune your application right you have to understand how everything is put together how the low level services are used by the frameworks that you're writing to in order to get the correct performance characteristics that you're looking for what you're not going to learn here right we're not going to talk about how to build file system cats right there was another session right a lot of people come to the kernel session saying great I'm gonna learn about all about how to program in the kernel well you're gonna learn about the services we provide and some of those are available to catch traders as well but then they're rapid in a whole different set of services some obscuring some of ours promoting some of their own we're not here just specifically to talk about how to write one of those right nor are we here to talk about how to write a networked kernel extension the networking sessions covered most of that and in general we're not here to talk about how to write in the program in the kernel alright that while a lot of this applies the same services are available in the kernel again you're going to tend to be in one of those specialized environments either an i/o kit extension or a filesystem extension or potentially and network text and when you're in each of those environments the view on these services is different you can do some of these things you can't do some of these things that we're going to talk about and some of the in kernel programming environments access to these services are spelled a little bit differently or take a few different parameters we're not going to get into those right so who's who would this book before then this session right and it's for all those people who are out there writing applications today right that they need to understand how to get the most out of your program and the kernel services that it's using will tell you how to get the best performance and how to understand all of that is what we're here for same thing text developers you may learn a little bit but you're not going to learn the details of how to do your work and power users I mean when you run some of the performance tools hopefully some of you made it to the performance section performance tool section you're going to see a lot of things going on in the system right it helps to understand how they're put together with the lower-level services where Darwin is the lowest level of Mac os10 everything that happens in Mac OS 10 to some extent or another is mitigated managed controlled by the Darwin layer and in the Darwin layer right the kernel part is the most critical part okay so some of the general truths about being in a Mac OS 10 application the first is that every application that's a native application in Mac OS 10 is a bsd process alright it's not that some of them are some of them aren't if you can see them if they're an application you can see them and manage them and control them as BSD processes and because of the way we implemented our kernel most beasts of all processes are actually mock tasks as well so inside of the darwin kernel there's a layering of mock and BSD and so every process is a mock task it owns and controls a mock task right and one of the things you're also going to notice and be very tempted by is the fact that the API is for all of these different layers tend to be available everywhere right you know if you happen to be writing carbon CFM application will then maybe not everywhere but other than that you look at the headers and you look at the frameworks and there's a lot of api's available to you right and one of the things you have to do is is try to stick to the highest level service that you can for what programming environment you're in use the services available there they tend to map on to the lower level services right and if you stick to those you're going to be much better off alright so what you've seen probably a few times already today is this picture of the Darwin kernel right where it talks about file systems and networking and and the i/o kit drivers that are available and that you can write well we're not really here to talk about those bubbles that are there here to talk about the background everything else right the services that the kernel provides that lets those things and all the applications do what they have to do right and again you've traditionally seen this division of the mach kernel versus the bsd part of the kernel right we tend to think of those as while there is a distinction and we try to keep the formal layering there right what we're concerned about is the services that the kernel provides to you as developers and how to make those services the best the best matching to the semantics of the higher-level applications that we can write and so we tend to say well we don't have these distinctions right what we have is you know one kernel that provides these services in a layered fashion right and the basic services are process management threading scheduler file management not necessarily the file systems itself but everything that the file systems use in order to interact with the rest of the system and managing files virtual memory inter process communication and security so why don't we start digging through some of these things oh wait first that's right I forgot where'd all these things come from right well the kernel is actually a collection of technologies from essentially three groups of places the Mach 3o provides the foundation for a lot of what goes on in the kernel especially virtual memory scheduling and IPC the the bsd portion the main bsd portion of our code was picked up from the for for lights project right and that gives us a process model our scheduling our file access and then we picked up most of the networking code from various flavors of freebsd right so let's dig in and start talking about process management in darwin right at the very fundamental level every process is a mock task right and every application is a process so at the very lowest level you have a mocktail a mock task is the unit of resource ownership as far as mock is concerned right every task owns threads it controls them it has virtual memory space and is managed through that mock task and it has a port namespace to collect all the IPC rights that are usable by that task right and so traditionally you can create tasks you can spend them and resume them and create new threads in them and get all kinds of information about them you can also one of the things people tend to do is create exception handlers for them right so that you can catch exceptions that happen in a task and process those and you can also get death a notification and be told when certain tasks that you have the handle to go away well that's a nice set of services right but typically you won't be able to use those directly I mean you actually can create a mock task all by itself in the system but you can't manage it right it's just this free-floating entity that no one else can see you snip you late so it's highly discouraged to ever create a mock task all by itself right instead you would tend to create a BST process and you do that through the standard BST api's you know v4 exact right create them and destroy them you'd go ahead and exit but the the BST process gives you these additional resources to go along with your task besides giving you the ability to manage them and name them right they give you the signal handlers they give you file descriptors they give you a whole collection of resources and what happens is when you when you have a bsd process right and you go look at the mock tasks KPIs that are available right a whole bunch of them go away you if you try to terminate a mock task that actually is part of a bsd process that'll just return you an error because the bsd part of the system doesn't have a chance to clean up and do the management that it would do right and so we don't allow that to happen of similarly creating new ones right we don't allow you to do that or we prefer you not do that right everything else is risky you can go ahead and create exception handlers you can go ahead and get info on the process itself or the task itself or get a list of threads or control threads create threads right but you shouldn't do anything else with the task right but again a lot of you will not be programming BSD processes you're actually going to be programming applications out at the higher level right either carbon cocoa Java whatever right and they add additional set of resources an additional set of API is for managing them actually many sets of API is for managing it one of the things that happens when you create those higher-level applications is they all talk to a common process management service that's a part of the core service core services in the system and it does all of the management for you and so you tend that's how you get things that pop up in actually right when you're looking at the tools that are available at that level right you have the doc and you have forced quit and all those things CPS the core process service is the thing that lets you manage processes and the larger applications all register with that our process viewer will actually let you view and inter SPECT just be of any bsd process in the system the same with top and PS and if you really want to see what's going on down at the the lower levels right you can use z print which is a tool that talks to the kernels zone management system and will basically print out statistics on how many of every kind of resource that the kernel has and in those list is all of the mock services and the mock resources that are available so you'll see how many mocked asks how many mock threads are being managed as well and so you can actually see and inspect some of the mock level resources with that tool so this is how you manage processes and handle exceptions and all of that is all at this level one of the things you have to be very careful about is although BSD processes have limits on the number of threat or the number open files and a lot of the other resources that are available to you one of the things that's not implemented in the kernel that shipped was ten point oh right is any ability to limit the resource allocations at the MOC level so any thread can go ahead and allocate these resources right and we don't have any limits on the amount of those resources you can go ahead and allocate and so if you have a runaway process right that's just leaking a port or leaking some kernel resource over and over and over and over again right over time the application may die that's certainly one outcome that might might come from this but another outcome from that particular problem is that it may actually just lock up the system and eventually panic the system because you've ran out of kernel resources in order to provide that so what you have to do is even though you're writing a carbon application or a cocoa application you need to take some of these tools top and PS in this case top if you were looking for leaks right and just watch your application running and if you happen to see something leaking away you need to address that okay so within a process you actually you obviously have threads all right and at the lowest level you have a mock thread mock does all the scheduling in the system some mock threads are the primary threading resource in the system one really interesting thing about mock threads it confuses a lot of people is that they actually have no resources other than scheduling attributes attributes and a register state that's it that is what a mock thread is right everything else you think about a thread stacks and per thread data and things like that mock doesn't know anything about those right it's all expected to be wrapped by some higher-level service and again at the mock level and an interesting thing is you can actually you know register for exception handling and death notification at the thread level and those kind of api's still are usable even when you look got it in the context of a BST threat or a pthread POSIX threads are the thing that provides the resources at the user level for a threat they provide the stack for a thread they provide the thread specific data implementation all right and those are the api's you can use to create them and manage them alright but again you may or may not just be stopping at a bsd process right you may be writing a carbon or a cocoa application and in those cases right you tend to not write to P threads you're gonna write to create a ns thread inside of cocoa or you're gonna create an MP task in a carbon application well those are BSD they are P threads right each and every one of those is a P thread each one of each and every one of those is a mock thread right and so you can have the breadth of services available to from each of those layers again at the thread level if you tried to destroy a mock thread right out from underneath of a P thread you can do it your applications free to do that it can do that to its own threads you're going to leave the P thread code implementation and alert right and so you better not do that but you could write and one nice thing about P threads the way the higher-level application services threading services wrap around the P thread level is that almost everything you can do to a P thread you can do from those on those higher level services and they tend to work well with each other right and so well how do I view threads in my system how do I tune for it how do I take care of the threading in my system and here's some tools you can do a thread viewer if anyone was at the performance tools meeting session yesterday you saw them going and actually showing thread viewer as an application that they were debugging during that process well they at the end of that meeting they the end of that session they decided that they were going to release that thread viewer to people as soon as possible so that's going to be a really nice application for viewing threads in the system in a graphical way and higher level because up until that point well you could sample threads with the sample app but that's kind of not something you would do ongoing and just watch your application go it's typically you've noticed a problem right and you would fire up sampler and go up and do what you needed to do right and top and PS I know I've had top running on the side of my system forever right but it's it's a lot it's like drinking from a firehose that's a lot of information it doesn't give you a graphical bang there's something going on there that I really need to worry about some of the tips well in Mac OS 10 we promote people to lazy in it as much as possible in their system right if you have a framework or anything else in your system you really want to delay initializing it one of the problems with the big bounces the bounce marks when you're launching an application intent is that a lot of the code brought over from nine basically had this model initialize everything once upfront right as much as you can and then will use it later right almost for free well in 10 what you're doing is initializing it all up what upfront once each time each application launches right and so one of the services you can use to get around that problem is this pthread ones facility which basically at the front of each major access point into your service right you can put a P thread once call the initialization routine at the front of that right and the P threads code will guarantee that the very first time you call one of your functions that has this in it it'll go call the initialization routine but it won't ever allow it to be called again from that code so that way you can delay your initialization until the very first time you're called now also a lot of people like to create their own debuggers or their own debugging environment and so they tend to want to get the exceptions from an application as it's running filter them through their own set of interfaces right and decide whether or not to let the system see rest of them later and so you can catch exceptions at any one of three places in mock right you can catch exceptions at the thread level at the tasks level and you can actually catch them at the the widest level the host level all right BSD tends to hook itself at the host level and so you know when a processor thread runs along and executes invalid instruction it's gone is send an exception down this chain it's gonna first send the exception message out to the thread level handler the thread lilifer thread level handler says he handled it then fine we'll just let the thread continue and we'll we'll go on from there if he didn't then you were gonna send it on to the next level right to the process level the task level and there's another handler sitting there if there is one then we'll send it to him and then same thing down below well BSD tends to be at the task level you're gonna see debuggers like gdb and things like that are gonna be sitting at the task level so bsts at the host gdb is at the task right and if you want to be able to intercept and get in there and do something on your own then you would tend to do it at the thread level okay so now that we have threads we obviously have to schedule them right and how do we schedule them well this has been somewhat of a mystery inside of Mac os10 there's obviously something going on with this banding you can see different threads being assigned different priorities but we have we've been messing with this tuning it and so we've been kind of adverse to putting out exactly what the banding is that we have in the system but now that you're trying to write real applications right you're gonna need to know alright some of you are writing multimedia applications and you really need to know how to get to be a fixed priority process how to how to set your priority well these are actually the bands that we have at the very highest so we have a range from 0 to 127 the very highest level are what we call time constraint threads right and so any thread that's registered as a time constraint thread and you don't have to be privileged to say you you want a time constraint thread right they will run up in that highest band somewhere and we that we won't tell you right but it's based on the time constraints that you provide and then we marry that with a bunch of other information and decide what priority you actually get within that band right but they tend to run at a fixed priority in that band so they'll just run run run run run run run if they have things to do and instance there are much higher band than most other applications obviously we're going to schedule those first we're also going to preemptively schedule those and so even if something else lowers running along in the kernel doing your kernel service if one of these comes along we're going to schedule it right well that leads into a concern obviously is that if any application can do this and can set one of these threads up really high then obviously any application can kill the system and there's no way you'd get it back it just runs up there forever and ever well we actually have limits to what can happen in a time constraint thread and so if you're running for too long in a time constraint thread then you get bumped back into the normal application band for a while and then if you settle down then we'll put you back into the time constraint band if you don't ever settle down then you just stay down there in the in the normal application ban okay and actually when you're in the application in the time constraint bin you're actually scheduled above the kernel threads above i/o threads so your your stuff will happen before will handle disk activity right it will be the first thing that kernel will go and run and then below the kernel in IO is is the core services threads things like the the GUI managers right so if you're running a time constraint thread and it's just chewing away guess what you know you you might even have trouble moving that Mouse around you might have trouble selecting that application to kill it right if it runs away that's why if it's run away it will get bumped down so that the core service threads have a chance to run and go ahead and get you for the rest of the threads you tend they tend to be grouped into two categories its GUI based threads and regular kind of background activity regular BSD process kind of threads right and the GUI ones tend to be a little bit higher in the bands then the the default ones but all of these threads are priority adjusted so as they run and take time they tend to start at their base and work their way down as they consume CPU under contention so if they're consuming CPU and nobody else is contending for the CPU they're fine they'll just stay stay stay stay stay as soon as they start contending for the CPU with other threads and other things once around they get nicked a little bit each time this happens right until those other threads get a chance to run right and then as a few Quantum's expire and they've been nicked then they drift back up and drift down so every thread tends to balance itself in this group and that's the standard policy in the system is to time share and adjust one of the things you can do in that category is assign precedence to your threads so if I have two priority two normal application threads right but I always want this one to have precedence over this one within my application then you can use the precedence policy setting this is given ordering to those and like I said we have we can take those threads and schedule them fully preemptively both kernel end user so we have a fully pre-emptive kernel if you're a time constraint thread you will interrupt things that right out of the kernel and we'll switch to you immediately right and we can obviously balance those across multiple CPUs all right when you're at the bsd process level well you have a few more things that come out for you you have the ability to set nice and if you've noticed in Mac OS 10 that actually doesn't do anything but the later versions that soon you will see a version that has that fixed right at the P thread level you can set your own scheduling attributes all right those will feed into the precedents into the timeshare in Lincoln and standard policy constraints and outlet the higher-level right you have management going on even beyond what this the mock level manages so if you're writing cooperative threads where you have deferred threads inside of your carbon application carbon is actually getting involved there and trying to make sure that those things run even though they're each a mock thread he's trying to make sure they run in the right order again you know some of the standard tools to look at things but the big tip here is don't use the old api's for setting things as round-robin or time share that are still available in the mach kernel you have use the new get policy set policy ap is that take the precedence and the time constraint all right so now that we've got scheduling and able to run let's see what we can do with anything outside of ourselves right and for that we need to access files typically right inside of the file management system of the whole kernel mock tasks actually has no concept of file right so you would think that mock is really not involved in this discussion but that's not true every file in the system really is managed and controlled the cache for the data that that application is managed and controlled by mock through what's called vm objects so mock manages the cache in the system the vm page cache and all of our filesystem activity right goes through the vm page cache to do what it needs to do so as you're reading from files reading files off a desk those files are stored in the regular vm cache right we don't have a file system cache and a vm cache for things that are you know applications that are mapped into your program we have one cache read read read read read it all goes into one pile right and it pushes things off the end of the pile right and again at the higher level those are wrapped yet again by different handles out at the application level one interesting that happens the interesting thing that happens there is that bsd is this basically a synchronous file access system right and a lot of the carbon applications are using a synchronous file i/o well how that works is that the actual carbon library in the system will go ahead and create worker threads that will issue the synchronous bsd calls for you right and manage sending you the asynchronous response later on so if you open files asynchronously in carbon right and you start at you start doing asynchronous reads in carbon or asynchronous writes don't be surprised when you go look you know with the tools and see there's another thread in my application that I have no can I didn't create right and it's created for you by that higher level right some really good tools to tune your use of files right is FS usage it's a tool that will basically as you're accessing a file it will spew out what's going on every access every read/write open/close either by a particular application or by any application overall and so you can get a basically a real-time view of everything that's going on file activity wise also there's another tool LSO F another command-line tool both of these are command line and it'll basically list every open file in the system right and who has it open what file descriptor number it is within that process it's a very useful tool alright big tip because we have this one cache right that handles all mapped files all your libraries all your frameworks all your executables and it's also the cache where you handle you know all the reading of files reading and writing a files if you happen to be reading something once and only once right spewing in a big image file or something like that that you're gonna process once right you don't need that file in the cache anymore you've got it in your application right having a copy of it in your application and having the original one in the cache just means we are taking up double the space in BM at least temporarily for that data so whenever you can use the no cash options right at the carbon level you have no cash reads and writes at the bsd level we actually have enough control that you can specify to say these are no cash operations ya really need to use the no cash operations alright otherwise as you run through memory write with big files you can push really important pieces of the system like the system framework and everything that you use and your own code right out of memory one thing that also gets people every once in a while is that while you typically were able to open in a carbon application as many files as you wanted until you hit the system limit in bsd there's a soft limit for the number of open per process and that's 256 right and so as you open ffs wraps inside of Carbon applications right you may end up running into this limit typically it's a bug right typically it's because you forget them to close them right and you just open open open open or open and eventually you'll hit the 256 limit we basically you have that limit now you can change it with a assist control or sorry yeah there's an API at the bsd level to basically up the limit for you right the same thing can happen at a system-wide level we have a system-wide level of number of V nodes which are the open file descriptors up there the open file handles right and those are you know there's a system-wide limit determined that boot time based on the amount of memory in the system and essentially you know some other tunable parameters well you can tune those up as well with us as control okay now we have files when we talked a little bit about VM right but we need to talk about the rest of what happens with VM right the mach vm pretty much controls the virtual memory in all of Mac OS 10 BSD provides some wrapper services to that but it's mostly managed by mock right mock provides the protected address spaces that Mac os10 you know is promoted here we have protected address spaces right one nice thing about the way mock does it is you have basically extreme flexibility and how you want to assemble an address space right you can put stuff here there everywhere it's really wonderful when you're trying to emulate an old system well guess what that's exactly what we're trying to do it's one of the key benefits of using mock VM is if you don't put if stuff had to be up there you can put it up there okay it also provides control sharing of resources so you can map things in exclusively into one application you can map them in copy-on-write into one but read right into the other so you can write into your piece of memory and the other guy can see it I can't modify it right or you can map things in readwrite into both all right so it's a really flexible way of putting systems together right and what does it look like well we showed in the picture before we showed a VM object and we showed cache pages sitting off of it and we showed this thing called a V node well the V node from the mock view of things is just an abstract memory manager it doesn't understand what that is all right it just has a protocol to talk to it and anybody can be one of those right and provide services and as long as you do will do the right thing well here you have to address faces each one of which has some portion of an object mapped in in this case they tend to have they have the same object mapped in the same part of the same object but they haven't mapped at two different addresses ones up at zero and the other ones somewhere down inside right and so you're running along and all of a sudden one of the guys takes a fault because the page isn't existing all right so we send a message basically not send a message but the the address space queries the virtual memory object and says do I have this page cache well guess what no I don't have this page cache so let me put a placeholder in case somebody else comes along and tries to do the same thing I won't do this again right which is sending a request to the memory object and the memory object sends back a data page and then we make that data page available in the application it's an L of a sudden you can go on and run but look what happened over in the other address space the guy with the same area mapped in but in a different part of his address space well we have the page cache now he doesn't have the page available to him right and if you had 250 objects that these guys share in common each one would have to have 250 entries pointing at you know each of the individual objects well if you're absolutely sure that you're going to have a whole bunch of them objects that are in common between two applications you can set up what's called a shared region which basically is a recursive address space right you can have an address space entry that points at another address space for any portion of it all right and we tend to use this in our system and I'll show you what for in a second right but we have two of them that we put into place one that tends to be sitting it's seven bazillion and the other one that's sitting at a bazillion right one is directly mapped shared by each of the applications and another is mapped copy-on-write by each of the applications so let's get rid of that copy-on-write one because it's a little confusing right for the moment right and what's backing that that shared address space well the same stuff that was backing the other address space right a reference to a memory object which has some cache pages associated with it and a reference off to some manager that knows how to fill in the data that it doesn't already have cached so now you come along and take a fault on that address right it queries the the shared address space and the shared address space then doesn't have the page either so it basic query is the object itself and we gotten up we don't have it so let's put a placeholder in place and we put the placeholder in the shared region well guess what because it's truly shared by the other guys the placeholder actually shows up in everybody at the same time right we sent the request on to the pager when he sends the data back wham the data shows up in every address space at the same time what do we use that for well if you take a dump of a typical mop Co application this is the layout you're gonna see right down it zero we tend to have a guard page all right that'll catch zero faults you know zero references and raise an exception for you if you don't like that idea you can go ahead and put another page there it's fine just replace that but that's the typical behavior right starting on the first page on up to the first gigabyte is typically your application where the application itself is mapped where the heaps and stuff tend to come right but heaps can be there and they can be you can fill up basically any of the space any of the holes in here with memory that you like so if you have a heat manager and like ours the basis says get me hunks right and then I'll subdivide them right once you run out of space between the application and one gig if you have more than that in heaps it'll go and find spots basically the first fit for another chunk going on up the line but if you notice it's seven and eight bazillion respectively right there's a read-only section and a copy-on-write section well this is where all the frameworks tend to fall right that your applications use so we have 70 some-odd frameworks that are a standard part of Mac OS 10 right if we had to map those into each application separately right and manage them separately and relocate them separately right we'd be going through a lot of extra overhead right as each application launched so what we do instead is have a shared region that points off at all the shared text of an application we relocate it once if it has to be relocated but typically it doesn't because a lot of our system is pre bound our libraries and they sit and point off in that one area right and then we map the data part of that you know add another one or yeah 256 Meg off of that right copy-on-write into each application so as each one takes a rights particular parts of the data they get their own copy by doing this at 256 Meg offsets we actually get to take advantage of something that happens in the powerpc right which is that you can actually truly share TLB entries and everything like that on a 256 Meg boundary with people so at the 7 bazillion where all the frameworks are alright we're actually sharing TLB entries and everything between every application right unless that application goes in and replaces the library or overloads the library or says you know use a different library for me right then we have to relocate the other parts of that collection of libraries at which point you get your own private copy and it behaves like a traditional old-fashioned application right so how do you go ahead and debug a you know the VM services you have well one of the best benefi will to you if you are watching at the tool session yesterday is malloc debug it's a wonderful thing to see you know individual parts of your heap being leaked leaked away and whether or not you're actually using them anymore and whether they could be reclaimed right but that doesn't catch memory allocations that happen outside of the heap manager right and there's lots of reasons why memory would be allocated outside the heap manager and directly fill up your address space right and there's this tool called VM map which will actually just give you a dump of all the it's a command-line tool sorry that will give you a dump of all the mappings in your system in your application and you can find the ones that you don't seem to realize you don't remember having right and start investigating those and what you'll tend to find is that something sent you a piece of memory and you just forgot about it all right something in the system sent it to you out of line in a message or some other way or you allocated a hunk directly with VM allocate right instead of using the the malloc tools and you just let it dangle all right and that will show you those you can also see those in top right so you the police you go first is top and to watch your application running if you see the number of memory entries going up and up and up and up and up right you're probably forgetting to do it's something that you really needed to deallocate all right one of the things that happens is when you do one of those VM allocates right they tend to start at zero and find the first fit right so when you're looking through your address map and you see a bunch of entries up by zero right these are probably pieces of memory that were allocated with the Amalekite and you might want to look at those another really important tip goes along with the no cash option is if you map things into your address space or you malloc a big hunk of memory right or you allocate it and you use it and now you're done with it but you know you really don't want to keep allocating it and deallocating it because maybe it's expensive well you want to kill it all right kill it out of the cache and there's a couple of ways you can do that there's an EM sync option at the POSIX level that let you kill pages there's another one at the Mach level called vmm sync they're really useable interchangeably depends on what API set you want to stick to but you need to kill them okay so we talked about all these things we've got you know tasks and threads and address spaces and they're all protected but when you have a protected address space in a protected environment you need to communicate somehow and so that brings us to the IPC services right and again Mach plays a big part in the IPC services of Mac OS 10 not so much in what happens at the BSD level so in a BSD process it might not be that important but in Mac OS 10 in general it actually becomes very important so an address sorry the basic idea of IPC service in Mac OS 10 is mock IPC mock IPC manages writes in port namespaces associated with each task you have rights to ports it's kind of like an open file descriptor inside of BSD but instead it's - a communications channel a small one called a mock port so here I have a mach port in the second task that gives me the right to send the message to the first task what's really nice about Mac o ten or about Mach IPC is that if you have memory and you have other port rights right you can collect those together and send them in messages over to the other task and so you can do really flexible communication so I've got a piece of memory in my address space in task 2 and I've got another port right in task 2 one that I own the receive write for and what I do is I build a little message that basically contains you know some general description of what I'm sending but it also contains a reference to each of these things right and I send it over to the test to that port that I have right and when it's received over in task one guess what now he has new virtual memory and he has new port rights right and so he can use the port right I just get gave him to send the message back to me saying I'm done what I'm doing all right and so all the RPC in the interaction that goes on inside of Mac OS 10 or a large portion of it happens via this mechanism when you want to open a window write that in a GUI application well the frameworks inside of your application talked to the core graphic server the window server by sending a message a mock message over there saying we need to do something and what they do is they arrange to have a piece of shared memory in common to do most of the communication but then they are constantly sending messages back and forth to each other about what the state of that is so again you have this inside of each task you have a collection of these ports right and they can represent you know just a basic message queue there's also variants there like semaphores lock sets right there handles to things that the kernel implements and they can be collected in sets and that collection in sets is really important because if you look inside of an application that GUI application in Mac OS 10 you gotta see at least one of these CF run loop things right which is the basic primitive of the event mechanism inside of Mac OS 10 and a CF run loop is actually just a wrapper around a mock port set right or a collection of mach port set so you may have many port sets and the CF run loops own some of them and put some rights and portraits into them and each of those port rights represents thing that can drive events a source of events that your application may need to deal with so he's already got a bunch in this support set but you know as time goes on he has more and more and more and what what you realize is while you're talking to a lot of things inside of Mac os10 V ports every once in a while you're talking to her traditional BSD application or you're talking to a traditional you know who knows right there's lots of other ways you can communicate with things but you need to somehow you know most applications feed that back into the run loop so that your application can see the events driven by these other sources well you can't be sitting at a single weight right when you do a CF run loop wait all right it sits on a port set waiting for a message right if that isn't coming in via port set that thread isn't going to see it or through a port it's not gonna see it so that thread connect that run loop can actually create worker threads for the kinds of IPC that he doesn't that is in port based receives the in this case off of a socket receives the message off a socket or the data office socket and tickles another port inside the port set to wake the run loop up some of those other sources that you can get things on right at the bsd level you have sockets and POSIX semaphores right and you have P thread synchronizers right now the P thread synchronizers our intro task only but as time goes on they'll become you know inter task as POSIX says they're allowed to be and then they're gonna have to feed into this mechanism as well if you want to be able to receive them in a single place right and then what happens at the outer level again is you have a port set that's wrapped by a run loop that becomes the foundation of your event queue inside of your application and so well as you're watching your applications your main thread is going to be calling you know wait next event let's hopefully not maybe it's you hopefully it's using carbon events but if it is calling wait next event that's going to be calling CF run loop we'll see if run loop actually built up one of these port sets of all the things that can drive events into it right and then that's calling Mach message trap typically Mach message overwrite trap doing a receive waiting for stuff to come in right so you're gonna see that over and over and over and over again in each of your applications again when you're looking in sampler you're gonna see that kind of thing you're also gonna see it in SE usage and you're gonna if you run se usage at the bottom it tends to list all the threads and what they're doing what they're currently waiting on all right and you're gonna see Mach message over I trap Mach message over I trap mic message overwrite trap message over a trap right they're all coming in on run loops of some sort or another or directly receiving on a Mach message right ports represent almost everything in my core or in Mac os10 a large portion of things so like again if you have a window open the handle for the window is a port so when you look at the cg debug stuff phrase has a list down the side of the things the ports that it has open to represent each one of those windows right and if you're tempted to use the the IPC directly the mock IPC we prefer you not there's a tool called mig it's mock interface generator and it's basically an ideal compiler that wraps around mock messaging and you can specify routines that go both directions or one-way messages and it generates wrapper routines that generate those messages for you and receive those messages for you so you don't have to understand and manipulate the low-level messaging it's just a nice convenience okay so now we have the ability to communicate but we're supposed to have a secure system here all right how do we do that well again a lot comes back to those ports you have ports are restricted you can't just invent a port name inside of mock and say I want to send a message to that port right you have to somebody has to give you that or ascend right to that port in the first place now some of them are registered globally we can just look them up and get them so you can send some common service a message saying I want to do something and it'll respond to that all right but in a lot of ways a lot of cases they aren't registered globally so maybe you'll talk to a service through a global port and it will send you back a port that only you can talk to it to directly manipulate your windows that's why inside of the Windows Server communication right you get a new port per window because it only wants you and only you to be able to manipulate that window and the port right mechanism allows that to happen without him doing anything on his side I received a message on that port it must be him or somebody he delegated to send this message I'll do it right so they're pre-authorized and in fact Mac OS I mean MOC part of Mac OS 10 has no authorization facility at all right it basically says if you've got that port and you send a message on it we'll do what that message says to do right and those messages those ports represent things inside of the kernel as well so if you have a task or a thread or any of those other kernel resources they're represented by unique ports you get a hold of one of those ports a thread port you send a message to it saying terminate guess what it'll terminate right so you got to be careful about sending your ports out but it's also a really nice mechanism to say you know we're not going to just say that ap eyes are available and usable by the application themselves like threading ap eyes if that application wants to send its thread port over to a friend that friend can issue all the threading api's itself directly on that port and we'll treat it at the kernel level just like the application had done it itself the same thing with managing the port space the port space is represented by the task port and so getting things in and out of your own port space is done with that same thing the only nod to authorization that the the Mach level services provide is that each message that sent is sent with a tag some kind of security tag on it that basically says I don't know what this is but somebody said five was associated with the guy who sent this message so I'm gonna send five along right well what happens is the BSD layer is the guy who says what five means right he provides the identification and authorization in the system identification is you IDs inside the BSD world right user IDs you have user IDs and effective user IDs and your group IDs an effective group IDs and you have you know correct collection of groups that you're allowed to be in right and whatever you BSD says this task has a security token is what gets sent along well BSD is also the guy who maintains permissions at the file level makes sense because he's the guy who implements the file systems at his level and so all the authorization to gain access to files is done by the BSD layer right and he does somewhat similar to what MOC does right once he gains has given access to something through the file system he has a file descriptor which is basically the access point the restricted access point and permissions are associated with that file descriptor so it's it's pre-authorized pre cached authorizations right but BSD semantics and pot and mock semantics alone aren't enough for Mac os10 in general right you have applications that want to run as a general user a regular old user that need to do privileged things right sometimes we have a privilege server that's just sitting over there waiting to do that thing for you right and other times we have a server that is privileged to do specific things and will authorize you time each time to to do that one particular thing through the new authorization API that happens as a core service API right also at that level you have keychains and key chain management and all that stuff is done up above the basic primitives of the BSD file and UID stuff and the MA sport stuff all right again FS usage is nice because it shows you what kind of accesses you're doing to a file LS Oh F will tell you what kind of access is you have to a file VM map will tell you what kind of permissions you have on certain memory so if you've read write or rewrite copy-on-write so that when you actually touch the thing you get a unique copy instead of being able to write to the actual main store so you can get a feel for what's going on in the system that way one thing to do is take a nod from the Mach part and the BSD part which is to cash authorizations right if you have to do some of your own work well yes you could set up a server that receives messages and just constantly looks at the the security token on the bottom of a message and says well am I allowed to take this from this guy because he says he's five right do I allow five to do this or do I say no right that's kind of awkward to keep doing that over and over and over again right so you would prefer to establish a unique connection with each of your clients in that situation and receive only and pass out the send right on the other side only to that one guy and then every time a message comes in on that right you allow him to go ahead and access it all right so those were the basic services inside the kernel right where can you get more information about how this stuff all really works because this was far too much and far too quick to get to much of anything totally useful out of it well there's a good resource right on the developer CD and if you've installed that now it's right on the disk of your system and most people don't even realize it's there right under the developer section there's a documentation section under that there's a kernel section right and there's descriptions there's a basic description of the kernel services again some more details about how they're managed what the api's are and especially on this particular part there's a reference to something called the OSF documentation well our mock kernel is the OSF mach kernel so if you clink click through that link you're going to go ahead and find the documentation for the mocks api's that we have in our system they're not 100% accurate they're quite a few years old and we've made some changes internally but they're pretty good and it gives you a really good idea of how the mock part of the system works there's obviously the Darwin open source pages you can go to those all right and the Mac os10 home page and our tech writers have renamed the book on me it's the design implementation of the four for BSD operating system by mcusic it's great for the BSD side of things right where can you learn more here today sorry but for those of people who are watching via the DVD later on you can go look up these sessions the performance tool session was really good it shows you how to see the effects of all of these interactions inside of an application that you're writing the same thing with the debugging stuff so when you get your CD later go look at the debugging and the performance stuff they're really important you just saw the leveraging the BSD more than likely if you were here and in a few minutes you'll get to do feedback [Applause] you
