I missed some of your comments.

On 2022-04-02 02:21, Honnappa Nagarahalli wrote:

<snip>

+ * Example usage:
+ * @code{.c}
+ * #define MAX_Y_LEN (16)
+ * // Application-defined example data structure, protected by a seqlock.
+ * struct config {
+ *         rte_seqlock_t lock;
+ *         int param_x;
+ *         char param_y[MAX_Y_LEN];
+ * };
+ *
+ * // Accessor function for reading config fields.
+ * void
+ * config_read(const struct config *config, int *param_x, char
+*param_y)
+ * {
+ *         // Temporary variables, just to improve readability.
I think the above comment is not necessary. It is beneficial to copy the 
protected data to keep the read side critical section small.


The data here would be copied into the buffers supplied by config_read() anyways, so it's a copy regardless.

+ *         int tentative_x;
+ *         char tentative_y[MAX_Y_LEN];
+ *         uint32_t sn;
+ *
+ *         sn = rte_seqlock_read_lock(&config->lock);
+ *         do {
+ *                 // Loads may be atomic or non-atomic, as in this example.
+ *                 tentative_x = config->param_x;
+ *                 strcpy(tentative_y, config->param_y);
+ *         } while (!rte_seqlock_read_tryunlock(&config->lock, &sn));
+ *         // An application could skip retrying, and try again later, if
+ *         // progress is possible without the data.
+ *
+ *         *param_x = tentative_x;
+ *         strcpy(param_y, tentative_y);
+ * }
+ *
+ * // Accessor function for writing config fields.
+ * void
+ * config_update(struct config *config, int param_x, const char
+*param_y)
+ * {
+ *         rte_seqlock_write_lock(&config->lock);
+ *         // Stores may be atomic or non-atomic, as in this example.
+ *         config->param_x = param_x;
+ *         strcpy(config->param_y, param_y);
+ *         rte_seqlock_write_unlock(&config->lock);
+ * }
+ * @endcode
+ *
+ * @see
+ * https://en.wikipedia.org/wiki/Seqlock.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_spinlock.h>
+
+/**
+ * The RTE seqlock type.
+ */
+typedef struct {
+       uint32_t sn; /**< A sequence number for the protected data. */
+       rte_spinlock_t lock; /**< Spinlock used to serialize writers.  */ }
Suggest using ticket lock for the writer side. It should have low overhead when 
there is a single writer, but provides better functionality when there are 
multiple writers.


Is a seqlock the synchronization primitive of choice for high-contention cases? I would say no, but I'm not sure what you would use instead.

<snip>

Reply via email to