Home | History | Annotate | Download | only in mDNSCore
      1 February 2002:
      2 
      3 The mDNSResponder code has a slight architectural change to improve
      4 efficiency.
      5 
      6 The mDNSResponder code previously called ScheduleNextTask() after every
      7 operation, to calculate the time at which it needed to be called back to
      8 perform its next timed operation. When the workload is light, and
      9 protocol operations are rare and far apart, this makes sense.
     10 
     11 However, on networks where there is a lot of mDNS traffic (or the CPU is
     12 slow), this leads to the following anomolous behaviour: mDNSResponder
     13 spends a lot of CPU time working out what to do next, when what it needs
     14 to do next should be obvious: Finish processing the big backlog of
     15 packets that have been received.
     16 
     17 To remedy this, mDNSResponder now only executes ScheduleNextTask() when
     18 there is no other obvious work waiting to be done. However, the
     19 mDNSResponder code does not have direct access to this knowledge. Only
     20 the platform layer below knows whether there are packets waiting to be
     21 processed. Only the client layer above knows whether it is in the
     22 process of performing a long sequence of back-to-back mDNS API calls.
     23 
     24 This means that the new architecture places an additional responsibility
     25 on the client layer and/or platform support layer. As long as they have
     26 immediate work to do, they should call the appropriate mDNSCore routines
     27 to accomplish that work. With each call, mDNSCore will do only what it
     28 immediately has to do to satisfy the call. Any optional work will be
     29 deferred. As soon as there is no more immediate work to do, the calling
     30 layer MUST call mDNS_Execute(). Failure to call mDNS_Execute() will lead
     31 to unreliable or incorrect operation.
     32 
     33 The value returned from mDNS_Execute() is the next time (in absolute
     34 platform time units) at which mDNS_Execute() MUST be called again to
     35 perform its next necessary operation (e.g. transmitting its next
     36 scheduled query packet, etc.) Note that the time returned is an absolute
     37 time, not the time *interval* between now and the next required call.
     38 For OS APIs that work in terms of intervals instead of absolute times,
     39 mDNSPlatformTimeNow() must be subtracted from the absolute time to get
     40 the interval between now and the next event.
     41 
     42 In a single-threaded application using a blocking select() call as its
     43 main synchronization point, this means that you should call
     44 mDNS_Execute() before calling select(), and the timeout value you pass
     45 to select() MUST NOT be larger than that indicated by the result
     46 returned from mDNS_Execute(). After the blocking select() call returns,
     47 you should do whatever work you have to do, and then, if mDNS packets
     48 were received, or mDNS API calls were made, be sure to call
     49 mDNS_Execute() again, and if necessary adjust your timeout value
     50 accordingly, before going back into the select() call.
     51 
     52 In an asynchronous or interrupt-driven application, there are three
     53 places that should call mDNS_Execute():
     54 
     55 1. After delivering received packets, the platform support layer should
     56 call mDNS_Execute(), and use the value returned to set the platform
     57 callback timer to fire at the indicated time.
     58 
     59 2. After making any mDNS API call or series of calls, the client layer
     60 should call mDNS_Execute(), and use the value returned to set the
     61 platform callback timer to fire at the indicated time.
     62 
     63 3. When the platform callback timer fires, it should call mDNS_Execute()
     64 (to allow mDNSCore to perform its necessary work) and then the timer
     65 routine use the result returned to reset itself to fire at the right
     66 time for the next scheduled event.
     67