STRUCT DRM_XE_SYNC(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct drm_xe_sync - sync object

okay so first things first, bestie: this is a page from the Kernel API Manual, and it's all about struct drm_xe_sync β€” literally just the sync object, the little glow-up gremlin that tells your GPU work "hey, wait for this / signal that" ✨


🌸 SYNOPSIS

struct drm_xe_sync {
    __u64 extensions;
  #define DRM_XE_SYNC_TYPE_SYNCOBJ                0x0;
  #define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ       0x1;
  #define DRM_XE_SYNC_TYPE_USER_FENCE             0x2;
    __u32 type;
  #define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0);
    __u32 flags;
    union {
      __u32 handle;
      __u64 addr;
    };
    __u64 timeline_value;
    __u64 reserved[2];
 };

πŸŽ€ Members

  • extensions β€” pointer to the first extension struct, if there even is one (no pressure, it can be nothing πŸ’…)
  • type β€” what kind of sync object this is, the whole vibe check of the thing
  • flags β€” the sync flags, your little toggles
  • {unnamed_union} β€” anonymous, no name, mysterious, main character energy ✨
  • handle β€” the handle for the object
  • addr β€” address of the user fence. and this one's got lore, so listen up πŸ‘‘: when the sync gets passed in via the exec IOCTL, this is a GPU address in the VM. when the sync gets passed in via the VM bind IOCTL, this is a user pointer. either way, it's on you β€” it's the user's responsibility that this address is present and mapped when the user fence is signalled. and it must be qword aligned, no cap 🫢
  • timeline_value β€” input for the timeline sync object. needs to be different than 0 when it's used with DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ (so like... not zero, bestie, fr fr)
  • reserved β€” reserved πŸ’€ (hands off)

πŸ”₯ Description

the type can be:

  • DRM_XE_SYNC_TYPE_SYNCOBJ
  • DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ
  • DRM_XE_SYNC_TYPE_USER_FENCE

and the flags can be:

  • DRM_XE_SYNC_FLAG_SIGNAL

a minimal use of struct drm_xe_sync looks like this, and yes it ate:

struct drm_xe_sync sync = {
    .flags = DRM_XE_SYNC_FLAG_SIGNAL,
    .type = DRM_XE_SYNC_TYPE_SYNCOBJ,
};
struct drm_syncobj_create syncobj_create = { 0 };
ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, syncobj_create);
sync.handle = syncobj_create.handle;
    ...
    use of sync in drm_xe_exec or drm_xe_vm_bind
    ...
struct drm_syncobj_wait wait = {
    .handles = sync.handle,
    .timeout_nsec = INT64_MAX,
    .count_handles = 1,
    .flags = 0,
    .first_signaled = 0,
    .pad = 0,
};
ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, wait);

like, create the syncobj, stash the handle, do your drm_xe_exec or drm_xe_vm_bind thing, then wait on it. iconic behavior honestly 🌈


πŸ¦‹ SEE ALSO

the kernel file is ./include/uapi/drm/xe_drm.h β€” go read it, iykyk πŸ“–

and here's the whole friend group, everybody's invited to the group chat πŸ’–:

Xe Device Block Diagram(9), Xe uAPI Overview(9), Xe IOCTL Extensions(9), struct drm_xe_user_extension(9), struct drm_xe_ext_set_property(9), struct drm_xe_engine_class_instance(9), struct drm_xe_engine(9), struct drm_xe_query_engines(9), enum drm_xe_memory_class(9), struct drm_xe_mem_region(9), struct drm_xe_query_mem_regions(9), struct drm_xe_query_config(9), struct drm_xe_gt(9), struct drm_xe_query_gt_list(9), struct drm_xe_query_topology_mask(9), struct drm_xe_query_engine_cycles(9), struct drm_xe_query_uc_fw_version(9), struct drm_xe_query_pxp_status(9), struct drm_xe_device_query(9), struct drm_xe_gem_create(9), struct drm_xe_gem_mmap_offset(9), struct drm_xe_vm_create(9), struct drm_xe_vm_destroy(9), struct drm_xe_vm_bind_op(9), struct drm_xe_vm_bind(9), struct drm_xe_vm_get_property(9), struct drm_xe_exec_queue_create(9), struct drm_xe_exec_queue_destroy(9), struct drm_xe_exec_queue_get_property(9), struct drm_xe_exec(9), struct drm_xe_wait_user_fence(9), enum drm_xe_observation_type(9), enum drm_xe_observation_op(9), struct drm_xe_observation_param(9), enum drm_xe_observation_ioctls(9), enum drm_xe_oa_unit_type(9), struct drm_xe_oa_unit(9), struct drm_xe_query_oa_units(9), enum drm_xe_oa_format_type(9), enum drm_xe_oa_property_id(9), struct drm_xe_oa_config(9), struct drm_xe_oa_stream_status(9), struct drm_xe_oa_stream_info(9), enum drm_xe_pxp_session_type(9), enum drm_xe_eu_stall_property_id(9), struct drm_xe_query_eu_stall(9), struct drm_xe_madvise(9), struct drm_xe_mem_range_attr(9), struct drm_xe_vm_query_mem_range_attr(9), struct drm_xe_exec_queue_set_property(9), Xe DRM RAS(9), enum drm_xe_ras_error_severity(9), enum drm_xe_ras_error_component(9)


πŸ’€ quick reminder before you go: that addr alignment thing and the "present and mapped" thing are real, not a vibe β€” get them wrong and it's not slay, it's a crash.

okay that's the whole page, mwah 🫢 this came out of ./include/uapi/drm and it's dated October 2026, filed under struct drm_xe_sync(9) β€” go forth and sync responsibly, bestie πŸ’œπŸŽ€

πŸ“¦ where this page comes from