text: .
  To help avoid pitfalls during the implementation phase, I believe it is essential that the design team
  thoroughly document the aspects of their implementation blueprints. The apsects which should be thoroughly
  documented include any and all of::
  If you are putting together a good-sized project and you lack experience, I would suggest seeking outside help. The OpenSolaris community (general discussion list) is a good place to start.
  Lately I've been bugged to blog SOMETHING other than my usual rambling technobabble. In case anybody cares here's what's rolling in my iPod this month. No, I don't always mix them. :)
  This blog entry is a continuation of my previous blog entry, Observing the Solaris Kernel.
  For my second demo I'll take a look at the anatomy of a simple
  process. As before, let's start out with a really simple program:
  % cat simple2.c
  int
  main(void)
  {
  sleep(99999);
  return (0);
  }
  % gcc -o simple2 simple2.c
  % ./simple2
  ^Z[1] + Stopped (SIGTSTP) ./simple2
  %
  In another window, as root, I fire up mdb in kernel target mode, and look
  up the proc structure of the process:
  root@rutamaya > mdb -k
  Loading modules: [ unix krtld genunix specfs dtrace pcplusmp ufs ip sctp usba fctl nca lofs random nfs logindmux ptm cpc fcip sppp ]
  mdb> ::ps !head -1
  S PID PPID PGID SID UID FLAGS ADDR NAME
  mdb> ::ps !grep simple2
  R 127247 127218 127247 127193 125946 0x42004000 fffffead763de3c0 simple2
  mdb> fffffead763de3c0::print proc_t
  {
  p_exec = 0xfffffe819091a840
  p_as = 0xffffffff899c1010
  p_lockp = 0xffffffff84a6db40
  p_crlock = {
  _opaque = [ 0 ]
  }
  p_cred = 0xffffffff923e14e8
  ...
  Let's take a look at the context of the process in the kernel, to see
  what it looks like after I sent it a SIGSTOP using ctrl+z from the
  terminal:
  mdb> fffffead763de3c0::walk thread
  fffffe814473abc0
  mdb> fffffe814473abc0:()
  ::walk thread takes a process structure pointer and
  "walks" all of the threads in the process (in Solaris there is
  a 1:1 mapping of user thread to kernel thread these days). Since our simple
  program is single-threaded this yields a single thread pointer, which we
  could have also gotten at by hand by looking at the p_tlist member
  of the proc structure:
  mdb> fffffead763de3c0::print proc_t p_tlist
  p_tlist = 0xfffffe814473abc0
  ::findstack takes a thread pointer and walks the thread stack in the
  kernel. We can see that cv_waituntil_sig() was called from nanosleep(),
  and it was interrupted by the SIGSTOP signal causing the process to
  call stop().
  Using the pipe facility in mdb and a new dcmd I haven't yet used,
  ::pid2proc, I can also shorten everything I've done so far into an equivalent
  two-liner:
  mdb> ::ps !grep simple2
  R 127247 127218 127247 127193 125946 0x42004000 fffffead763de3c0 simple2
  mdb> 0t127247::pid2proc | ::walk thread | :()
  Note the 0t prefix is needed because the PID is displayed by ::ps in decimal,
  just as if I had run the ps command in a terminal. In fact I could have done
  this from inside mdb using the shell pipe facility I've already used in this
  demo:
  mdb> !ps -ef | grep simple2
  elowe 127247 127218 0 10:04:24 pts/1 0:00 ./simple2
  In my first demo, I examined the user and group ID within a file; as we saw
  from running ::print to look at the proc structure, p_cred
  also contains a pointer to a cred structure, which holds the identity
  of a unique user on the system. Since I started the process from another
  terminal window under my normal UNIX account, the cred structure should
  contain the credentials associated with my UNIX login.
  mdb> fffffead7ceb43c0::print proc_t p_cred|::print cred_t
  {
  cr_ref = 0x32
  cr_uid = 0x1ebfa
  cr_gid = 0xa
  ...
  mdb> fffffead7ceb43c0::print proc_t p_cred|::print cred_t cr_uid|::map =D
  125946
  That's me. Since ::print likes hex more than I do, I used the ::map dcmd
  to pipe the dot from ::print cred_t cr_uid into =D, which is the mdb syntax
  to display a number in integer decimal format.
  There are plenty of interesting things to explore on your own just by
  starting from the process structure, so this is a great start for folks who
  are just starting out learning about UNIX internals.
  Technorati Tags:
  [OpenSolaris
  Solaris]
  This
  I: none requested
  config:
  NAME STATE READ WRITE CKSUM]
  The translation storage buffer (TSB) is a SPARC-specific data structure used to speed up TLB miss handling in the UltraSPARC family of CPUs. Since these CPUs implement TLB miss handling via a trap mechanism, performance of the low-level trap handling code in the operating system is crucial to overall system performance.
  The TSB is implemented in software as a direct-mapped, virtually-indexed, virtually-tagged (VIVT) cache. While its size is a minimum of the processor's page size (8K), its upper bound is practically unlimited. The UltraSPARC CPUs have a translation assist mechanism which, given the base address of the TSB in a register, provides a pre-computed TSB entry pointer corresponding to the virtual address of the translation miss. This mechanism only supports TSBs up to 1M in size, which is where the current software support is capped1.
  On a TLB miss trap (%tt = {0x64, 0x68, 0x6C}) the trap handler corresponding to the particular trap code is invoked from the trap table by the CPU. For a ITLB or DTLB miss, the TSB is searched for a valid entry whose tag matches the virtual address of the translation miss. If the entry is found, it is loaded from the TSB into the TLB, and the trapped instruction is retry'd. If the entry is not found, the translation hash tables are searched using the current process address space pointer as well as the virtual address as the hash key.
  Prior to Solaris 10, the user process TSBs used to come from a global pool of fixed size which was allocated at boot. In Solaris 10, the Dynamic TSB project made significant changes to all of the SPARC HAT layer, but in particular, changed the implementation so that TSBs are allocated dynamically.
  1This is only true for user processes. The kernel itself is a special case, and usually has a larger TSB -- up to 16MB in size. The trap handlers ignore the precomputed pointer on kernel misses, and compute the TSB entry index manually.
  When.!
  The other day, there was a good internal thread going on one of the bigger internal Sun mailing lists, and it reminded me of an important point that I think is worth sharing with the outside world -- particularly now that OpenSolaris has landed. Having access to the source can be dangerous to developers if you're trying to develop stable, forward-compatible software for your users. The particular thread was centered around the use of private members of the vnode in a third party filesystem -- but it really could apply to development of any software on any system where folks have unrestricted access to the source code.
  There is a myth that so-called "private" interfaces in Solaris are private simply because Solaris is a proprietary operating system, and Sun does not want some external software developer having access to our mytical secret sauce. It goes on -- furthermore, Sun intentionally makes these interfaces cryptically presented in the header files, and does not document them, simply because they provide a better way of doing something than the documented ones. Sun does this so that our software will somehow be better than anyone else can write, giving us a competitive edge, so we can keep selling our proprietary system running on our proprietary hardware.
  BZZT! WRONG!!!
  Spin again!
  Solaris provides an interface stability taxonomy which defines certain levels of stability for the programming interfaces which are presented to developers (this taxonomy is documented in the attributes(5) man page). The interface stability taxonomy provides classifications which make it clear what the commitment level of Sun is to maintain backward compatability with any programs that use that interface in the future.
  When devloping software, if you want your software to run on future releases of Solaris, you must be careful to use only interfaces which have a suitable commitment level. Interfaces you run across while looking through the source code or headers, if not documented, aren't guaranteed to work in the future -- and are very likely NOT to work in the future. This means your program will stop working if Sun or the OpenSolaris community decides to change that interface for any reason, at any time, even in a patch. Which, needless to say, will cause headaches for the users of your software!
  Getting back to the thread, Jim Carlson summed things up quite well, when he stated thus:
  ...we[1] reserve the right to change these interfaces in whatever way we
  choose, at any time at all (including in patches), without notice of
  any kind, and without any attempt to preserve any sort of
  compatibility.
  Thus, if you depend on private interfaces by writing your own software
  that uses them, then you'll end up hurting yourself.
  This is roughly the equivalent of a "no user serviceable parts inside"
  warning on an appliance. It doesn't mean that you can't open it up
  and poke around inside if you really know what you're doing. But if
  you do, and you end up electrocuting yourself or starting a fire, you
  have nobody else to blame.
  [1] "We" in the above sentence means "everyone working on the code."
  If that turns out to be a community-based effort, then it's the
  members of that community who own and direct it.
  Don't believe the myth, and don't electrocute your customers -- it's not worth it. Now that Solaris is opened up, if there isn't a way to do what you want to do, you can create one (or ask the community to help)!
  Today's Page Hits: 71