Exemplo n.º 1
0
static void
limit_bandwidth (wgint bytes, struct ptimer *timer)
{
  double delta_t = ptimer_read (timer) - limit_data.chunk_start;
  double expected;

  limit_data.chunk_bytes += bytes;

  /* Calculate the amount of time we expect downloading the chunk
     should take.  If in reality it took less time, sleep to
     compensate for the difference.  */
  expected = (double) limit_data.chunk_bytes / opt.limit_rate;

  if (expected > delta_t)
    {
      double slp = expected - delta_t + limit_data.sleep_adjust;
      double t0, t1;
      if (slp < 0.2)
        {
          DEBUGP (("deferring a %.2f ms sleep (%s/%.2f).\n",
                   slp * 1000, number_to_static_string (limit_data.chunk_bytes),
                   delta_t));
          return;
        }

      if (slp > 1) // VisualWget: We do not expect to sleep more than 1 second.
        slp = 1;

      DEBUGP (("\nsleeping %.2f ms for %s bytes, adjust %.2f ms\n",
               slp * 1000, number_to_static_string (limit_data.chunk_bytes),
               limit_data.sleep_adjust));

      t0 = ptimer_read (timer);
      xsleep (slp);
      t1 = ptimer_measure (timer);

      /* Due to scheduling, we probably slept slightly longer (or
         shorter) than desired.  Calculate the difference between the
         desired and the actual sleep, and adjust the next sleep by
         that amount.  */
      limit_data.sleep_adjust = slp - (t1 - t0);
      /* If sleep_adjust is very large, it's likely due to suspension
         and not clock inaccuracy.  Don't enforce those.  */
      if (limit_data.sleep_adjust > 0.5)
        limit_data.sleep_adjust = 0.5;
      else if (limit_data.sleep_adjust < -0.5)
        limit_data.sleep_adjust = -0.5;
    }

  limit_data.chunk_bytes = 0;
  limit_data.chunk_start = ptimer_read (timer);
}
Exemplo n.º 2
0
float PTIDSensors::readTachometer(UInt32 index)
{
    if (ptimer_read() - tachometersLastUpdated >= NSEC_PER_SEC) {
        updateTachometers();
        tachometersLastUpdated = ptimer_read();
    }

    if (tachometers) {
        if (OSNumber *number = OSDynamicCast(OSNumber, tachometers->getObject(index))) {
            UInt64 value = number->unsigned32BitValue();
            return (value == 0x80000000) ? 0 : (float)value;
        }
    }
    
    return 0;
}
Exemplo n.º 3
0
float PTIDSensors::readTemperature(UInt32 index)
{
    if (ptimer_read() - temperaturesLastUpdated >= NSEC_PER_SEC) {
        updateTemperatures();
        temperaturesLastUpdated = ptimer_read();
    }
    
    if (temperatures) {
        if (OSNumber *number = OSDynamicCast(OSNumber, temperatures->getObject(index))) {
            UInt64 value = number->unsigned32BitValue();
            return (value == 0x80000000) ? 0 : (float)((value - 0xAAC) / 0xA);
        }
    }
    
    return 0;
}
int nouveau_therm_fan_rpm_get(struct nouveau_device *device)
{
	u32 cycles, cur, prev, stop = THERM_FAN_SENSE_CYCLES * 4 + 1;
	u64 start, interval;

	if (device->fan_tach.func != DCB_GPIO_UNUSED) {
        /* Time a complete rotation and extrapolate to RPM:
         * When the fan spins, it changes the value of GPIO FAN_SENSE.
         * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation.
         */
        start = ptimer_read();

        prev = device->gpio_get(device, 0, device->fan_tach.func, device->fan_tach.line);
        cycles = 0;
        do {
            IODelay(750); /* supports 0 < rpm < 7500 */
            
            cur = device->gpio_get(device, 0, device->fan_tach.func, device->fan_tach.line);
            if (prev != cur) {
                if (!start)
                    start = ptimer_read();
                cycles++;
                prev = cur;
            }
            
            interval = ptimer_read() - start;
            
        } while (cycles < stop && interval < 500000000);
        
        if (interval) {
            return (int)(((u64)60000000000ULL * (((u64)cycles - 1) / 4)) / interval);
        } else
            return -EIO;
    }
    
    nv_debug(device, "DCB_GPIO_FAN_SENSE func not found\n");
    
    return -EIO;
}
Exemplo n.º 5
0
const void *FakeSMCKey::getValue() 
{ 
	if (handler) {
        UInt64 now = ptimer_read();

        if (now - lastUpdated >= NSEC_PER_SEC) {
            IOReturn result = handler->callPlatformFunction(kFakeSMCGetValueCallback, true, (void *)key, (void *)value, (void *)size, 0);
            
            if (kIOReturnSuccess == result)
                lastUpdated = now;
            else 
                HWSensorsWarningLog("value update request callback returned error for key %s, return 0x%x", key, result);
        }
	}
    
	return value; 
};
Exemplo n.º 6
0
bool PTIDSensors::start(IOService * provider)
{
	if (!super::start(provider))
        return false;
    
	acpiDevice = (IOACPIPlatformDevice *)provider;
	
	if (!acpiDevice) {
        HWSensorsFatalLog("ACPI device not ready");
        return false;
    }
    
    // Update timers
    temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC;
    tachometersLastUpdated = temperaturesLastUpdated;
    
    acpiDevice->evaluateInteger("IVER", &version);
    
    if (version == 0) {
        OSString *name = OSDynamicCast(OSString, provider->getProperty("name"));
        
        if (name && name->isEqualTo("INT3F0D"))
            version = 0x30000;
        else
            return false;
    }
    
    setProperty("version", version, 64);
    
    // Parse sensors
    switch (version) {
        case 0x30000: {
            OSObject *object = NULL;
            
            // Temperatures
            if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) {
                
                OSArray *description = OSDynamicCast(OSArray, object);
                
                HWSensorsDebugLog("Parsing temperatures...");
                
                for (UInt32 index = 1; index < description->getCount(); index += 2) {
                    parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), (index - 1) / 2);
                }
            }
            else HWSensorsErrorLog("failed to evaluate TSDL table");
            
            // Tachometers
            if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) {
                
                OSArray *description = OSDynamicCast(OSArray, object);
                
                HWSensorsDebugLog("Parsing tachometers...");
                
                for (UInt32 index = 2; index < description->getCount(); index += 3) {
                    parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), (index - 2) / 3);
                }
            }
            else HWSensorsErrorLog("failed to evaluate OSDL table");
            
            break;
        }
            
        case 0x20001: {
            OSObject *object = NULL;
            
            // Temperatures
            if(kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) {
                
                OSArray *description = OSDynamicCast(OSArray, object);
                
                for (UInt32 index = 1; index < description->getCount(); index += 3) {
                    parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), index + 1);
                }
            }
            else HWSensorsErrorLog("failed to evaluate TMPV table");
            
            // Tachometers
            if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) {
                
                OSArray *description = OSDynamicCast(OSArray, object);
                
                for (UInt32 index = 2; index < description->getCount(); index += 4) {
                    parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), index + 1);
                }
            }
            else HWSensorsErrorLog("failed to evaluate OSDV table");
            
            break;
        }
            
        default:
            HWSensorsFatalLog("usupported interface version: 0x%x", (unsigned int)version);
            return false;
    }
    
    registerService();
    
    HWSensorsInfoLog("started");
    
	return true;
}
Exemplo n.º 7
0
int
fd_read_body (int fd, FILE *out, wgint toread, wgint startpos,
              wgint *qtyread, wgint *qtywritten, double *elapsed, int flags,
              FILE *out2)
{
  int ret = 0;
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))
  int dlbufsize = max (BUFSIZ, 8 * 1024);
  char *dlbuf = xmalloc (dlbufsize);

  struct ptimer *timer = NULL;
  double last_successful_read_tm = 0;

  /* The progress gauge, set according to the user preferences. */
  void *progress = NULL;

  /* Non-zero if the progress gauge is interactive, i.e. if it can
     continually update the display.  When true, smaller timeout
     values are used so that the gauge can update the display when
     data arrives slowly. */
  bool progress_interactive = false;

  bool exact = !!(flags & rb_read_exactly);

  /* Used only by HTTP/HTTPS chunked transfer encoding.  */
  bool chunked = flags & rb_chunked_transfer_encoding;
  wgint skip = 0;

  /* How much data we've read/written.  */
  wgint sum_read = 0;
  wgint sum_written = 0;
  wgint remaining_chunk_size = 0;

  if (flags & rb_skip_startpos)
    skip = startpos;

  if (opt.verbose)
    {
      /* If we're skipping STARTPOS bytes, pass 0 as the INITIAL
         argument to progress_create because the indicator doesn't
         (yet) know about "skipping" data.  */
      wgint start = skip ? 0 : startpos;
      progress = progress_create (start, start + toread);
      progress_interactive = progress_interactive_p (progress);
    }

  if (opt.limit_rate)
    limit_bandwidth_reset ();

  /* A timer is needed for tracking progress, for throttling, and for
     tracking elapsed time.  If either of these are requested, start
     the timer.  */
  if (progress || opt.limit_rate || elapsed)
    {
      timer = ptimer_new ();
      last_successful_read_tm = 0;
    }

  /* Use a smaller buffer for low requested bandwidths.  For example,
     with --limit-rate=2k, it doesn't make sense to slurp in 16K of
     data and then sleep for 8s.  With buffer size equal to the limit,
     we never have to sleep for more than one second.  */
  if (opt.limit_rate && opt.limit_rate < dlbufsize)
    dlbufsize = opt.limit_rate;

  /* Read from FD while there is data to read.  Normally toread==0
     means that it is unknown how much data is to arrive.  However, if
     EXACT is set, then toread==0 means what it says: that no data
     should be read.  */
  while (!exact || (sum_read < toread))
    {
      int rdsize;
      double tmout = opt.read_timeout;

      if (chunked)
        {
          if (remaining_chunk_size == 0)
            {
              char *line = fd_read_line (fd);
              char *endl;
              if (line == NULL)
                {
                  ret = -1;
                  break;
                }
              else if (out2 != NULL)
                fwrite (line, 1, strlen (line), out2);

              remaining_chunk_size = strtol (line, &endl, 16);
              xfree (line);

              if (remaining_chunk_size == 0)
                {
                  ret = 0;
                  line = fd_read_line (fd);
                  if (line == NULL)
                    ret = -1;
                  else
                    {
                      if (out2 != NULL)
                        fwrite (line, 1, strlen (line), out2);
                      xfree (line);
                    }
                  break;
                }
            }

          rdsize = MIN (remaining_chunk_size, dlbufsize);
        }
      else
        rdsize = exact ? MIN (toread - sum_read, dlbufsize) : dlbufsize;

      if (progress_interactive)
        {
          /* For interactive progress gauges, always specify a ~1s
             timeout, so that the gauge can be updated regularly even
             when the data arrives very slowly or stalls.  */
          tmout = 0.95;
          if (opt.read_timeout)
            {
              double waittm;
              waittm = ptimer_read (timer) - last_successful_read_tm;
              if (waittm + tmout > opt.read_timeout)
                {
                  /* Don't let total idle time exceed read timeout. */
                  tmout = opt.read_timeout - waittm;
                  if (tmout < 0)
                    {
                      /* We've already exceeded the timeout. */
                      ret = -1, errno = ETIMEDOUT;
                      break;
                    }
                }
            }
        }
      ret = fd_read (fd, dlbuf, rdsize, tmout);

      if (progress_interactive && ret < 0 && errno == ETIMEDOUT)
        ret = 0;                /* interactive timeout, handled above */
      else if (ret <= 0)
        break;                  /* EOF or read error */

      if (progress || opt.limit_rate || elapsed)
        {
          ptimer_measure (timer);
          if (ret > 0)
            last_successful_read_tm = ptimer_read (timer);
        }

      if (ret > 0)
        {
          sum_read += ret;
          int write_res = write_data (out, out2, dlbuf, ret, &skip, &sum_written);
          if (write_res < 0)
            {
              ret = (write_res == -3) ? -3 : -2;
              goto out;
            }
          if (chunked)
            {
              remaining_chunk_size -= ret;
              if (remaining_chunk_size == 0)
                {
                  char *line = fd_read_line (fd);
                  if (line == NULL)
                    {
                      ret = -1;
                      break;
                    }
                  else
                    {
                      if (out2 != NULL)
                        fwrite (line, 1, strlen (line), out2);
                      xfree (line);
                    }
                }
            }
        }

      if (opt.limit_rate)
        limit_bandwidth (ret, timer);

      if (progress)
        progress_update (progress, ret, ptimer_read (timer));
#ifdef WINDOWS
      if (toread > 0 && !opt.quiet)
        ws_percenttitle (100.0 *
                         (startpos + sum_read) / (startpos + toread));
#endif
    }
  if (ret < -1)
    ret = -1;

 out:
  if (progress)
    progress_finish (progress, ptimer_read (timer));

  if (elapsed)
    *elapsed = ptimer_read (timer);
  if (timer)
    ptimer_destroy (timer);

  if (qtyread)
    *qtyread += sum_read;
  if (qtywritten)
    *qtywritten += sum_written;

  free (dlbuf);

  return ret;
}
Exemplo n.º 8
0
int
fd_read_body (int fd, FILE *out, wgint toread, wgint startpos,
              wgint *qtyread, wgint *qtywritten, double *elapsed, int flags)
{
  double receive_message_time = 0; // VisualWget
  double send_message_time = 0; // VisualWget
  int ret = 0;

  static char dlbuf[16384];
  int dlbufsize = sizeof (dlbuf);

  struct ptimer *timer = NULL;
  double last_successful_read_tm = 0;

  /* The progress gauge, set according to the user preferences. */
  void *progress = NULL;

  /* Non-zero if the progress gauge is interactive, i.e. if it can
     continually update the display.  When true, smaller timeout
     values are used so that the gauge can update the display when
     data arrives slowly. */
  bool progress_interactive = false;

  bool exact = !!(flags & rb_read_exactly);
  wgint skip = 0;

  /* How much data we've read/written.  */
  wgint sum_read = 0;
  wgint sum_written = 0;

  if (flags & rb_skip_startpos)
    skip = startpos;

  if (opt.visualwget_listening_port != -1) // VisualWget: Send a start position and the number of bytes remain.
    {
      wgint sp = skip ? 0 : startpos;
      char *msg = (char *) xmalloc (2 + numdigit (sp) + 1 + numdigit (toread) + 2);

      sprintf (msg, "1 %I64d %I64d\n", sp, toread);
      SendMessageToVisualWget (msg);
      xfree (msg);
    }

  if (opt.verbose)
    {
      /* If we're skipping STARTPOS bytes, pass 0 as the INITIAL
         argument to progress_create because the indicator doesn't
         (yet) know about "skipping" data.  */
      progress = progress_create (skip ? 0 : startpos, startpos + toread);
      progress_interactive = progress_interactive_p (progress);
    }

  limit_bandwidth_reset (); // VisualWget: Always reset.

  /* A timer is needed for tracking progress, for throttling, and for
     tracking elapsed time.  If either of these are requested, start
     the timer.  */
  if (progress || opt.limit_rate || elapsed || opt.visualwget_listening_port != -1) // VisualWget
    {
      timer = ptimer_new ();
      last_successful_read_tm = 0;
    }

  /* Read from FD while there is data to read.  Normally toread==0
     means that it is unknown how much data is to arrive.  However, if
     EXACT is set, then toread==0 means what it says: that no data
     should be read.  */
  while (!exact || (sum_read < toread))
    {
      int rdsize;
      double tmout = opt.read_timeout;
      if (progress_interactive)
        {
          /* For interactive progress gauges, always specify a ~1s
             timeout, so that the gauge can be updated regularly even
             when the data arrives very slowly or stalls.  */
          tmout = 0.95;
          if (opt.read_timeout)
            {
              double waittm;
              waittm = ptimer_read (timer) - last_successful_read_tm;
              if (waittm + tmout > opt.read_timeout)
                {
                  /* Don't let total idle time exceed read timeout. */
                  tmout = opt.read_timeout - waittm;
                  if (tmout < 0)
                    {
                      /* We've already exceeded the timeout. */
                      ret = -1, errno = ETIMEDOUT;
                      break;
                    }
                }
            }
        }

      //
      // VisualWget: Receive message every 0.1 second
      // BUG FIXED: http://groups.google.com/group/visualwget-discuss/browse_thread/thread/5ef2e324c70722aa
      //
      if (receive_message_time == 0
          || ptimer_read (timer) - receive_message_time > 0.1)
        {
          receive_message_time = ptimer_read (timer);
          ReceiveMessagesFromVisualWget ();
        }

      /* Use a smaller buffer for low requested bandwidths.  For example,
         with --limit-rate=2k, it doesn't make sense to slurp in 16K of
         data and then sleep for 8s.  With buffer size equal to the limit,
         we never have to sleep for more than one second.  */
      if (opt.limit_rate && opt.limit_rate < sizeof (dlbuf)) // VisualWget: Set a correct download buffer size.
        dlbufsize = opt.limit_rate;
      else
        dlbufsize = sizeof (dlbuf);

      rdsize = exact ? MIN (toread - sum_read, dlbufsize) : dlbufsize;
      ret = fd_read (fd, dlbuf, rdsize, tmout);

      if (progress_interactive && ret < 0 && errno == ETIMEDOUT)
        ret = 0;                /* interactive timeout, handled above */
      else if (ret <= 0)
        break;                  /* EOF or read error */

      if (progress || opt.limit_rate || opt.visualwget_listening_port != -1) // VisualWget
        {
          ptimer_measure (timer);
          if (ret > 0)
            last_successful_read_tm = ptimer_read (timer);
        }

      if (opt.limit_rate) // VisualWget: Do this before writing data in order to prevent an incorrect information getting sent to VisualWget.
        limit_bandwidth (ret, timer);

      if (ret > 0)
        {
          sum_read += ret;
          if (!write_data (out, dlbuf, ret, &skip, &sum_written))
            {
              ret = -2;
              goto out;
            }

          // VisualWget: Send the total number of bytes read and elapsed time.
          if (send_message_time == 0
              || ptimer_read (timer) - send_message_time > 0.1
              || sum_read == toread)
            {
              send_message_time = ptimer_read (timer);

              if (opt.visualwget_listening_port != -1)
                {
                  wgint elapsed_time = (wgint) (ptimer_read (timer) * 1000);
                  char *msg = (char *) xmalloc (2 + numdigit (sum_read) + 1 + numdigit (elapsed_time) + 2);

                  sprintf (msg, "2 %I64d %I64d\n", sum_read, elapsed_time);
                  SendMessageToVisualWget (msg);
                  xfree (msg);
                }
            }
        }

      if (progress)
        progress_update (progress, ret, ptimer_read (timer));
#ifdef WINDOWS
      if (toread > 0 && !opt.quiet)
        ws_percenttitle (100.0 *
                         (startpos + sum_read) / (startpos + toread));
#endif
    }
  if (ret < -1)
    ret = -1;

 out:
  if (progress)
    progress_finish (progress, ptimer_read (timer));

  if (elapsed)
    *elapsed = ptimer_read (timer);
  if (timer)
    ptimer_destroy (timer);

  if (qtyread)
    *qtyread += sum_read;
  if (qtywritten)
    *qtywritten += sum_written;

  return ret;
}
Exemplo n.º 9
0
bool PTIDSensors::start(IOService * provider)
{
	if (!super::start(provider))
        return false;
    
	acpiDevice = (IOACPIPlatformDevice *)provider;
	
	if (!acpiDevice) {
        HWSensorsFatalLog("ACPI device not ready");
        return false;
    }
    
    // On some computers (eg. RehabMan's ProBook 4530s), the system will hang on startup
    // if kernel cache is used, because of the early call to updateTemperatures and/or
    // updateTachometers.  At least that is the case with an SSD and a valid pre-linked
    // kernel, along with kernel cache enabled.  This 1000ms sleep seems to fix the problem,
    // enabling a clean boot with PTIDSensors enabled.
    IOSleep(1000);
    
    // Update timers
    temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC;
    tachometersLastUpdated = temperaturesLastUpdated;
    
    acpiDevice->evaluateInteger("IVER", &version);
    
    if (version == 0) {
        OSString *name = OSDynamicCast(OSString, provider->getProperty("name"));
        
        if (name && name->isEqualTo("INT3F0D"))
            version = 0x30000;
        else
            return false;
    }
    
    setProperty("version", version, 64);
    
    // Parse sensors
    switch (version) {
        case 0x30000: {
            OSObject *object = NULL;
            
            // Temperatures
            if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) {
                if (OSArray *description = OSDynamicCast(OSArray, object)) {
                    HWSensorsDebugLog("Parsing temperatures...");
                    
                    int count = description->getCount();
                    for (int i = 1; i < count; i += 2) {
                        parseTemperatureName(OSDynamicCast(OSString, description->getObject(i)), i/2);
                    }
                }
            }
            else HWSensorsErrorLog("failed to evaluate TSDL table");
            
            // Tachometers
            if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) {
                if (OSArray *description = OSDynamicCast(OSArray, object)) {
                    HWSensorsDebugLog("Parsing tachometers...");
                    
                    int count = description->getCount();
                    for (int i = 2; i < count; i += 3) {
                        parseTachometerName(OSDynamicCast(OSString, description->getObject(i)), OSDynamicCast(OSString, description->getObject(i-1)), i/3);
                    }
                }
            }
            else HWSensorsErrorLog("failed to evaluate OSDL table");
            break;
        }
            
        case 0x20001: {
            OSObject *object = NULL;
            
            // Temperatures
            if (kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) {
                if (OSArray *description = OSDynamicCast(OSArray, object)) {
                    HWSensorsDebugLog("Parsing temperatures...");
                    
                    int count = description->getCount();
                    for (int i = 1; i < count; i += 3) {
                        parseTemperatureName(OSDynamicCast(OSString, description->getObject(i)), i+1);
                    }
                }
            }
            else HWSensorsErrorLog("failed to evaluate TMPV table");
            
            // Tachometers
            if (kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) {
                if (OSArray *description = OSDynamicCast(OSArray, object)) {
                    HWSensorsDebugLog("Parsing tachometers...");
                    
                    int count = description->getCount();
                    for (int i = 2; i < count; i += 4) {
                        parseTachometerName(OSDynamicCast(OSString, description->getObject(i)), OSDynamicCast(OSString, description->getObject(i-1)), i+1);
                    }
                }
            }
            else HWSensorsErrorLog("failed to evaluate OSDV table");
            break;
        }
            
        default:
            HWSensorsFatalLog("usupported interface version: 0x%x", (UInt32)version);
            return false;
    }
    
    registerService();
    
    HWSensorsInfoLog("started");
    
	return true;
}