dri-devel Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2] drm/syncobj: Add documentation for timeline syncobj
@ 2020-01-14 12:19 Lionel Landwerlin
  2020-01-14 14:25 ` Christian König
  0 siblings, 1 reply; 4+ messages in thread
From: Lionel Landwerlin @ 2020-01-14 12:19 UTC (permalink / raw)
  To: dri-devel; +Cc: Jason Ekstrand, Christian Koenig

We've added a set of new APIs to manipulate syncobjs holding timelines
of dma_fence. This adds a bit of documentation about how this works.

v2: Small language nits (Lionel)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Christian Koenig <Christian.Koenig@amd.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
Cc: David(ChunMing) Zhou <David1.Zhou@amd.com>
---
 drivers/gpu/drm/drm_syncobj.c | 87 +++++++++++++++++++++++++++++------
 1 file changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 669c93fe2500..42d46414f767 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -43,27 +43,66 @@
  *  - Signal a syncobj (set a trivially signaled fence)
  *  - Wait for a syncobj's fence to appear and be signaled
  *
+ * The syncobj userspace API also provides operations to manipulate a syncobj
+ * in terms of a timeline of struct &dma_fence_chain rather than a single
+ * struct &dma_fence, through the following operations:
+ *
+ *   - Signal a given point on the timeline
+ *   - Wait for a given point to appear and/or be signaled
+ *   - Import and export from/to a given point of a timeline
+ *
  * At it's core, a syncobj is simply a wrapper around a pointer to a struct
  * &dma_fence which may be NULL.
  * When a syncobj is first created, its pointer is either NULL or a pointer
  * to an already signaled fence depending on whether the
  * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
  * &DRM_IOCTL_SYNCOBJ_CREATE.
- * When GPU work which signals a syncobj is enqueued in a DRM driver,
- * the syncobj fence is replaced with a fence which will be signaled by the
- * completion of that work.
- * When GPU work which waits on a syncobj is enqueued in a DRM driver, the
- * driver retrieves syncobj's current fence at the time the work is enqueued
- * waits on that fence before submitting the work to hardware.
- * If the syncobj's fence is NULL, the enqueue operation is expected to fail.
- * All manipulation of the syncobjs's fence happens in terms of the current
- * fence at the time the ioctl is called by userspace regardless of whether
- * that operation is an immediate host-side operation (signal or reset) or
- * or an operation which is enqueued in some driver queue.
- * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to
- * manipulate a syncobj from the host by resetting its pointer to NULL or
+ *
+ * If the syncobj is considered as a binary (its state is either signaled or
+ * unsignaled) primitive, when GPU work is enqueued in a DRM driver to signal
+ * the syncobj, the syncobj's fence is replaced with a fence which will be
+ * signaled by the completion of that work.
+ * If the syncobj is considered as a timeline primitive, when GPU work is
+ * enqueued in a DRM driver to signal the a given point of the syncobj, a new
+ * struct &dma_fence_chain pointing to the DRM driver's fence and also
+ * pointing to the previous fence that was in the syncobj. The new struct
+ * &dma_fence_chain fence replace the syncobj's fence and will be signaled by
+ * completion of the DRM driver's work and also any work associated with the
+ * fence previously in the syncobj.
+ *
+ * When GPU work which waits on a syncobj is enqueued in a DRM driver, at the
+ * time the work is enqueued, it waits on the syncobj's fence before
+ * submitting the work to hardware. That fence is either :
+ *
+ *    - The syncobj's current fence if the syncobj is considered as a binary
+ *      primitive.
+ *    - The struct &dma_fence associated with a given point if the syncobj is
+ *      considered as a timeline primitive.
+ *
+ * If the syncobj's fence is NULL or not present in the syncobj's timeline,
+ * the enqueue operation is expected to fail.
+ *
+ * With binary syncobj, all manipulation of the syncobjs's fence happens in
+ * terms of the current fence at the time the ioctl is called by userspace
+ * regardless of whether that operation is an immediate host-side operation
+ * (signal or reset) or or an operation which is enqueued in some driver
+ * queue. &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used
+ * to manipulate a syncobj from the host by resetting its pointer to NULL or
  * setting its pointer to a fence which is already signaled.
  *
+ * With a timeline syncobj, all manipulation of the synobj's fence happens in
+ * terms of a u64 value referring to point in the timeline. See
+ * dma_fence_chain_find_seqno() to see how a given point is found in the
+ * timeline.
+ *
+ * Note that applications should be careful to always use timeline set of
+ * ioctl() when dealing with syncobj considered as timeline. Using a binary
+ * set of ioctl() with a syncobj considered as timeline could result incorrect
+ * synchronization. The use of binary syncobj is supported through the
+ * timeline set of ioctl() by using a point value of 0, this will reproduce
+ * the behavior of the binary set of ioctl() (for example replace the
+ * syncobj's fence when signaling).
+ *
  *
  * Host-side wait on syncobjs
  * --------------------------
@@ -87,6 +126,16 @@
  * synchronize between the two.
  * This requirement is inherited from the Vulkan fence API.
  *
+ * Similarly, &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT takes an array of syncobj
+ * handles as well as an array of u64 points and does a host-side wait on all
+ * of syncobj fences at the given points simultaneously.
+ *
+ * &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT also adds the ability to wait for a given
+ * fence to materialize on the timeline without waiting for the fence to be
+ * signaled by using the &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE flag. This
+ * requirement is inherited from the wait-before-signal behavior required by
+ * the Vulkan timeline semaphore API.
+ *
  *
  * Import/export of syncobjs
  * -------------------------
@@ -120,6 +169,18 @@
  * Because sync files are immutable, resetting or signaling the syncobj
  * will not affect any sync files whose fences have been imported into the
  * syncobj.
+ *
+ *
+ * Import/export of timeline points in timeline syncobjs
+ * -----------------------------------------------------
+ *
+ * &DRM_IOCTL_SYNCOBJ_TRANSFER provides a mechanism to transfer a struct
+ * &dma_fence_chain of a syncobj at a given u64 point to another u64 point
+ * into another syncobj.
+ *
+ * Note that if you want to transfer a struct &dma_fence_chain from a given
+ * point on a timeline syncobj from/into a binary syncobj, you can use the
+ * point 0 to mean take/replace the fence in the syncobj.
  */
 
 #include <linux/anon_inodes.h>
-- 
2.25.0.rc2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] drm/syncobj: Add documentation for timeline syncobj
  2020-01-14 12:19 [PATCH v2] drm/syncobj: Add documentation for timeline syncobj Lionel Landwerlin
@ 2020-01-14 14:25 ` Christian König
  2020-01-20 11:02   ` Lionel Landwerlin
  0 siblings, 1 reply; 4+ messages in thread
From: Christian König @ 2020-01-14 14:25 UTC (permalink / raw)
  To: Lionel Landwerlin, dri-devel; +Cc: Jason Ekstrand

Am 14.01.20 um 13:19 schrieb Lionel Landwerlin:
> We've added a set of new APIs to manipulate syncobjs holding timelines
> of dma_fence. This adds a bit of documentation about how this works.
>
> v2: Small language nits (Lionel)
>
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> Cc: Christian Koenig <Christian.Koenig@amd.com>
> Cc: Jason Ekstrand <jason@jlekstrand.net>
> Cc: David(ChunMing) Zhou <David1.Zhou@amd.com>

Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/gpu/drm/drm_syncobj.c | 87 +++++++++++++++++++++++++++++------
>   1 file changed, 74 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> index 669c93fe2500..42d46414f767 100644
> --- a/drivers/gpu/drm/drm_syncobj.c
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -43,27 +43,66 @@
>    *  - Signal a syncobj (set a trivially signaled fence)
>    *  - Wait for a syncobj's fence to appear and be signaled
>    *
> + * The syncobj userspace API also provides operations to manipulate a syncobj
> + * in terms of a timeline of struct &dma_fence_chain rather than a single
> + * struct &dma_fence, through the following operations:
> + *
> + *   - Signal a given point on the timeline
> + *   - Wait for a given point to appear and/or be signaled
> + *   - Import and export from/to a given point of a timeline
> + *
>    * At it's core, a syncobj is simply a wrapper around a pointer to a struct
>    * &dma_fence which may be NULL.
>    * When a syncobj is first created, its pointer is either NULL or a pointer
>    * to an already signaled fence depending on whether the
>    * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
>    * &DRM_IOCTL_SYNCOBJ_CREATE.
> - * When GPU work which signals a syncobj is enqueued in a DRM driver,
> - * the syncobj fence is replaced with a fence which will be signaled by the
> - * completion of that work.
> - * When GPU work which waits on a syncobj is enqueued in a DRM driver, the
> - * driver retrieves syncobj's current fence at the time the work is enqueued
> - * waits on that fence before submitting the work to hardware.
> - * If the syncobj's fence is NULL, the enqueue operation is expected to fail.
> - * All manipulation of the syncobjs's fence happens in terms of the current
> - * fence at the time the ioctl is called by userspace regardless of whether
> - * that operation is an immediate host-side operation (signal or reset) or
> - * or an operation which is enqueued in some driver queue.
> - * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to
> - * manipulate a syncobj from the host by resetting its pointer to NULL or
> + *
> + * If the syncobj is considered as a binary (its state is either signaled or
> + * unsignaled) primitive, when GPU work is enqueued in a DRM driver to signal
> + * the syncobj, the syncobj's fence is replaced with a fence which will be
> + * signaled by the completion of that work.
> + * If the syncobj is considered as a timeline primitive, when GPU work is
> + * enqueued in a DRM driver to signal the a given point of the syncobj, a new
> + * struct &dma_fence_chain pointing to the DRM driver's fence and also
> + * pointing to the previous fence that was in the syncobj. The new struct
> + * &dma_fence_chain fence replace the syncobj's fence and will be signaled by
> + * completion of the DRM driver's work and also any work associated with the
> + * fence previously in the syncobj.
> + *
> + * When GPU work which waits on a syncobj is enqueued in a DRM driver, at the
> + * time the work is enqueued, it waits on the syncobj's fence before
> + * submitting the work to hardware. That fence is either :
> + *
> + *    - The syncobj's current fence if the syncobj is considered as a binary
> + *      primitive.
> + *    - The struct &dma_fence associated with a given point if the syncobj is
> + *      considered as a timeline primitive.
> + *
> + * If the syncobj's fence is NULL or not present in the syncobj's timeline,
> + * the enqueue operation is expected to fail.
> + *
> + * With binary syncobj, all manipulation of the syncobjs's fence happens in
> + * terms of the current fence at the time the ioctl is called by userspace
> + * regardless of whether that operation is an immediate host-side operation
> + * (signal or reset) or or an operation which is enqueued in some driver
> + * queue. &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used
> + * to manipulate a syncobj from the host by resetting its pointer to NULL or
>    * setting its pointer to a fence which is already signaled.
>    *
> + * With a timeline syncobj, all manipulation of the synobj's fence happens in
> + * terms of a u64 value referring to point in the timeline. See
> + * dma_fence_chain_find_seqno() to see how a given point is found in the
> + * timeline.
> + *
> + * Note that applications should be careful to always use timeline set of
> + * ioctl() when dealing with syncobj considered as timeline. Using a binary
> + * set of ioctl() with a syncobj considered as timeline could result incorrect
> + * synchronization. The use of binary syncobj is supported through the
> + * timeline set of ioctl() by using a point value of 0, this will reproduce
> + * the behavior of the binary set of ioctl() (for example replace the
> + * syncobj's fence when signaling).
> + *
>    *
>    * Host-side wait on syncobjs
>    * --------------------------
> @@ -87,6 +126,16 @@
>    * synchronize between the two.
>    * This requirement is inherited from the Vulkan fence API.
>    *
> + * Similarly, &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT takes an array of syncobj
> + * handles as well as an array of u64 points and does a host-side wait on all
> + * of syncobj fences at the given points simultaneously.
> + *
> + * &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT also adds the ability to wait for a given
> + * fence to materialize on the timeline without waiting for the fence to be
> + * signaled by using the &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE flag. This
> + * requirement is inherited from the wait-before-signal behavior required by
> + * the Vulkan timeline semaphore API.
> + *
>    *
>    * Import/export of syncobjs
>    * -------------------------
> @@ -120,6 +169,18 @@
>    * Because sync files are immutable, resetting or signaling the syncobj
>    * will not affect any sync files whose fences have been imported into the
>    * syncobj.
> + *
> + *
> + * Import/export of timeline points in timeline syncobjs
> + * -----------------------------------------------------
> + *
> + * &DRM_IOCTL_SYNCOBJ_TRANSFER provides a mechanism to transfer a struct
> + * &dma_fence_chain of a syncobj at a given u64 point to another u64 point
> + * into another syncobj.
> + *
> + * Note that if you want to transfer a struct &dma_fence_chain from a given
> + * point on a timeline syncobj from/into a binary syncobj, you can use the
> + * point 0 to mean take/replace the fence in the syncobj.
>    */
>   
>   #include <linux/anon_inodes.h>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] drm/syncobj: Add documentation for timeline syncobj
  2020-01-14 14:25 ` Christian König
@ 2020-01-20 11:02   ` Lionel Landwerlin
  2020-01-20 13:34     ` Christian König
  0 siblings, 1 reply; 4+ messages in thread
From: Lionel Landwerlin @ 2020-01-20 11:02 UTC (permalink / raw)
  To: Christian König, dri-devel; +Cc: Jason Ekstrand

[-- Attachment #1.1: Type: text/plain, Size: 691 bytes --]

On 14/01/2020 16:25, Christian König wrote:
> Am 14.01.20 um 13:19 schrieb Lionel Landwerlin:
>> We've added a set of new APIs to manipulate syncobjs holding timelines
>> of dma_fence. This adds a bit of documentation about how this works.
>>
>> v2: Small language nits (Lionel)
>>
>> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
>> Cc: Christian Koenig <Christian.Koenig@amd.com>
>> Cc: Jason Ekstrand <jason@jlekstrand.net>
>> Cc: David(ChunMing) Zhou <David1.Zhou@amd.com>
>
> Reviewed-by: Christian König <christian.koenig@amd.com>

Thanks for the review Christian.

Feel free to merge this commit whenever, I don't think I have commit rights.


Cheers,


-Lionel


[-- Attachment #1.2: Type: text/html, Size: 1912 bytes --]

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">On 14/01/2020 16:25, Christian König
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:6b017f69-c798-40dc-aea6-ac6bcb3a49bf@amd.com">Am
      14.01.20 um 13:19 schrieb Lionel Landwerlin:
      <br>
      <blockquote type="cite" style="color: #000000;">We've added a set
        of new APIs to manipulate syncobjs holding timelines
        <br>
        of dma_fence. This adds a bit of documentation about how this
        works.
        <br>
        <br>
        v2: Small language nits (Lionel)
        <br>
        <br>
        Signed-off-by: Lionel Landwerlin <a
          class="moz-txt-link-rfc2396E"
          href="mailto:lionel.g.landwerlin@intel.com"
          moz-do-not-send="true">&lt;lionel.g.landwerlin@intel.com&gt;</a>
        <br>
        Cc: Christian Koenig <a class="moz-txt-link-rfc2396E"
          href="mailto:Christian.Koenig@amd.com" moz-do-not-send="true">&lt;Christian.Koenig@amd.com&gt;</a>
        <br>
        Cc: Jason Ekstrand <a class="moz-txt-link-rfc2396E"
          href="mailto:jason@jlekstrand.net" moz-do-not-send="true">&lt;jason@jlekstrand.net&gt;</a>
        <br>
        Cc: David(ChunMing) Zhou <a class="moz-txt-link-rfc2396E"
          href="mailto:David1.Zhou@amd.com" moz-do-not-send="true">&lt;David1.Zhou@amd.com&gt;</a>
        <br>
      </blockquote>
      <br>
      Reviewed-by: Christian König <a class="moz-txt-link-rfc2396E"
        href="mailto:christian.koenig@amd.com" moz-do-not-send="true">&lt;christian.koenig@amd.com&gt;</a></blockquote>
    <p>Thanks for the review Christian.</p>
    <p>Feel free to merge this commit whenever, I don't think I have
      commit rights.</p>
    <p><br>
    </p>
    <p>Cheers,</p>
    <p><br>
    </p>
    <p>-Lionel<br>
    </p>
  </body>
</html>

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] drm/syncobj: Add documentation for timeline syncobj
  2020-01-20 11:02   ` Lionel Landwerlin
@ 2020-01-20 13:34     ` Christian König
  0 siblings, 0 replies; 4+ messages in thread
From: Christian König @ 2020-01-20 13:34 UTC (permalink / raw)
  To: Lionel Landwerlin, dri-devel; +Cc: Jason Ekstrand

[-- Attachment #1.1: Type: text/plain, Size: 792 bytes --]

Am 20.01.20 um 12:02 schrieb Lionel Landwerlin:
> On 14/01/2020 16:25, Christian König wrote:
>> Am 14.01.20 um 13:19 schrieb Lionel Landwerlin:
>>> We've added a set of new APIs to manipulate syncobjs holding timelines
>>> of dma_fence. This adds a bit of documentation about how this works.
>>>
>>> v2: Small language nits (Lionel)
>>>
>>> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
>>> Cc: Christian Koenig <Christian.Koenig@amd.com>
>>> Cc: Jason Ekstrand <jason@jlekstrand.net>
>>> Cc: David(ChunMing) Zhou <David1.Zhou@amd.com>
>>
>> Reviewed-by: Christian König <christian.koenig@amd.com>
>
> Thanks for the review Christian.
>
> Feel free to merge this commit whenever, I don't think I have commit 
> rights.
>

Done.

Christian.

>
> Cheers,
>
>
> -Lionel
>


[-- Attachment #1.2: Type: text/html, Size: 2288 bytes --]

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Am 20.01.20 um 12:02 schrieb Lionel
      Landwerlin:<br>
    </div>
    <blockquote type="cite" cite="mid:1c286a24-5474-fdea-9993-a2b32dfdacbb@intel.com">
      
      <div class="moz-cite-prefix">On 14/01/2020 16:25, Christian König
        wrote:<br>
      </div>
      <blockquote type="cite" cite="mid:6b017f69-c798-40dc-aea6-ac6bcb3a49bf@amd.com">Am
        14.01.20 um 13:19 schrieb Lionel Landwerlin: <br>
        <blockquote type="cite" style="color: #000000;">We've added a
          set of new APIs to manipulate syncobjs holding timelines <br>
          of dma_fence. This adds a bit of documentation about how this
          works. <br>
          <br>
          v2: Small language nits (Lionel) <br>
          <br>
          Signed-off-by: Lionel Landwerlin <a class="moz-txt-link-rfc2396E" href="mailto:lionel.g.landwerlin@intel.com" moz-do-not-send="true">&lt;lionel.g.landwerlin@intel.com&gt;</a>
          <br>
          Cc: Christian Koenig <a class="moz-txt-link-rfc2396E" href="mailto:Christian.Koenig@amd.com" moz-do-not-send="true">&lt;Christian.Koenig@amd.com&gt;</a>
          <br>
          Cc: Jason Ekstrand <a class="moz-txt-link-rfc2396E" href="mailto:jason@jlekstrand.net" moz-do-not-send="true">&lt;jason@jlekstrand.net&gt;</a>
          <br>
          Cc: David(ChunMing) Zhou <a class="moz-txt-link-rfc2396E" href="mailto:David1.Zhou@amd.com" moz-do-not-send="true">&lt;David1.Zhou@amd.com&gt;</a>
          <br>
        </blockquote>
        <br>
        Reviewed-by: Christian König <a class="moz-txt-link-rfc2396E" href="mailto:christian.koenig@amd.com" moz-do-not-send="true">&lt;christian.koenig@amd.com&gt;</a></blockquote>
      <p>Thanks for the review Christian.</p>
      <p>Feel free to merge this commit whenever, I don't think I have
        commit rights.</p>
    </blockquote>
    <br>
    Done.<br>
    <br>
    Christian.<br>
    <br>
    <blockquote type="cite" cite="mid:1c286a24-5474-fdea-9993-a2b32dfdacbb@intel.com">
      <p><br>
      </p>
      <p>Cheers,</p>
      <p><br>
      </p>
      <p>-Lionel<br>
      </p>
    </blockquote>
    <br>
  </body>
</html>

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, back to index

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-14 12:19 [PATCH v2] drm/syncobj: Add documentation for timeline syncobj Lionel Landwerlin
2020-01-14 14:25 ` Christian König
2020-01-20 11:02   ` Lionel Landwerlin
2020-01-20 13:34     ` Christian König

dri-devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/dri-devel/0 dri-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dri-devel dri-devel/ https://lore.kernel.org/dri-devel \
		dri-devel@lists.freedesktop.org
	public-inbox-index dri-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.freedesktop.lists.dri-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git