zx_clock_update

总结

调整时钟对象。

声明

#include <zircon/syscalls.h>

zx_status_t zx_clock_update(zx_handle_t handle,
                            uint64_t options,
                            const void* args);

权限

handle 必须为 ZX_OBJ_TYPE_CLOCK 类型,且具有 ZX_RIGHT_WRITE

说明

时钟维护器可以动态控制三个不同的参数。它们分别是

  • 时钟的当前值。
  • 时钟的速率调整,以 PPM 与标称的偏差表示。
  • 时钟的当前估算误差范围。

当时钟维护者想要更改其中一个或多个参数时,可以使用 zx_clock_update 系统调用进行更改。从系统中所有其他用户的角度来看,更新时钟参数是一项原子操作。

时钟维护者执行的第一个更新操作必须包含有效值。此更新会启动时钟并定义其初始值。在此更新操作成功之前,系统会取消 ZX_CLOCK_STARTED 信号,之后会断言该信号,并在时钟的生命周期内保持该信号。

为了更新时钟,用户需要填写要调整的 zx_clock_update_args_v2_t 结构的字段,然后将该结构传递给更新调用,设置 options 中的位,这些位指示结构的显式版本(版本 2)以及哪些字段有效且应设置。定义的 options 位是

  • ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID
  • ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID
  • ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID
  • ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID

结构的版本是使用 ZX_CLOCK_ARGS_VERSION(...) 宏传递的,尤其是 ZX_CLOCK_ARGS_VERSION(2) 适用于版本 2 结构。

例如:

#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>

void MaintainMyClock(zx_handle_t the_clock) {
  zx_clock_update_args_v2_t args;
  zx_status_t status;

  // Set the clock's value to 1500. Note that this also starts the clock.
  args.synthetic_value = 1500;
  status = zx_clock_update(the_clock,
                           ZX_CLOCK_ARGS_VERSION(2) | ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID,
                           &args);
  if (status != ZX_OK) {
    // Panic!
    return;
  }

  // Make the clock run 23 PPM slower than nominal relative to clock monotonic.
  args.rate_adjust = -23;
  status = zx_clock_update(the_clock,
                           ZX_CLOCK_ARGS_VERSION(2) | ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID,
                           &args);
  if (status != ZX_OK) {
    // Halt and catch fire
    return;
  }

  // Set the clock to 100,000, make it run 50 PPM faster than nominal, and specify an error bound of
  // +/- 400mSec, all at the same time.
  const uint64_t options = ZX_CLOCK_ARGS_VERSION(2) |
                           ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID |
                           ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID |
                           ZX_CLOCK_UPDATE_OPTION_ERROR_BOUND_VALID;
  args.synthetic_value = 100000;
  args.rate_adjust = 50;
  args.error_bound = ZX_MSEC(400);
  status = zx_clock_update(the_clock, options, &args);
  if (status != ZX_OK) {
    // Burn down, fall over, and then sink into the swamp.
    return;
  }
}

明确提供的参考时间。

添加 V2 更新结构后,现在可以明确控制用于时钟更新操作的参考时间(存在一些限制)。请注意,成功后,由用户的更新参数指定的实际新引用 <-> 合成转换将在调用 zx_clock_update 期间替换旧转换。提供显式引用时间并不会影响实际转换的更新时间,但始终会在调用 zx_clock_update 期间生效。

RFC-0077 中提供的图表可能有助于了解下述操作的影响。

使用明确提供的参考时间更新合成值。

用户使用显式提供的参考时间 (R) 更新时钟的合成值 (S) 时,他们会指定一个点 ([R, S]),新转换将经过该点。换言之,新转换明确指定“当参考时间轴上的时间 R 时,合成时间轴上的时间 S ”。

#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>

// Set the syntheic value of the clock to be "synth" at the explicitly provided
// reference time "ref". In other words, upon success, this update operation will
// cause the clock's transformation from reference to synthetic time to
// specifically pass through the point (ref, synth)
zx_status_t SetSynthAtRef(zx_handle_t the_clock, zx_time_t ref, zx_time_t synth) {
  zx_clock_update_args_v2_t args;

  uint64_t options = ZX_CLOCK_ARGS_VERSION(2) |
                     ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID |
                     ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID;

  // Note that these options are equivalent, they just use a shorthand to
  // specify that both values are valid.
  options = ZX_CLOCK_ARGS_VERSION(2) | ZX_CLOCK_UPDATE_OPTION_BOTH_VALUES_VALID;

  args.reference_value = ref;
  args.synthetic_value = synth;
  return zx_clock_update(the_clock, options, args);
}

使用明确提供的参考时间更新费率调整。

T(R) 成为一个函数,该函数将参考时间 R 转换为更新操作之前的时钟的合成时间。当用户使用明确提供的参考时间 (R) 调整时钟的速率时,他们会为时钟指定新转换 T'(R) 的斜率,以便 T'(R) = T(R)。换言之,在参考时间 R 时,新转换经过的合成时间与旧转换相同,但斜率不同。

#include <zircon/syscalls.h>
#include <zircon/syscalls/clock.h>

zx_status_t SetRateAtRef(zx_handle_t the_clock, zx_time_t ref, int32_t ppm_adj) {
  zx_clock_update_args_v2_t args;

  const uint64_t options = ZX_CLOCK_ARGS_VERSION(2) |
                           ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID |
                           ZX_CLOCK_UPDATE_OPTION_RATE_ADJUST_VALID;
  args.reference_value = ref;
  args.rate_adjust = ppm_adj;

  return zx_clock_update(the_clock, options, args);
}

备注、规则和限制。

  • 不需要显式引用值。在更新操作期间,仍可以省略引用值。处理更新操作时,只会使用当前参考时间。
  • 为时钟更新操作提供显式引用值时,还必须提供合成值和/或速率调整。尝试仅更新显式引用值处的错误边界是不合法的。
  • 不允许明确为连续时钟的更新操作提供引用值,因为这几乎总是意味着不连续。
  • 允许为单调时钟的更新操作明确提供引用值,但前提是时钟行为在更新后保持单调。
  • 如果在更新操作期间明确提供的引用值会导致在参考时间“现在”执行的读取违反配置的时钟停止时间,则会导致操作被拒绝。
  • 更新单调时钟时,无法同时实现合成值更新和速率调整。

RFC-0077 中提供的详细信息可能有助于您理解其中一些规则和限制背后的原因。

返回值

如果成功,则返回 ZX_OK

错误

  • ZX_ERR_BAD_HANDLEhandle 是无效句柄,或者是非 ZX_OBJ_TYPE_CLOCK 对象类型的句柄。
  • ZX_ERR_ACCESS_DENIEDhandle 缺少 ZX_RIGHT_WRITE 右侧。
  • ZX_ERR_INVALID_ARGS:发出的更新请求与时钟的属性不兼容。如需详细了解允许的时钟更新操作,请参阅 DESCRIPTION 部分。否则,参数结构的版本/指针不正确。

另请参阅