Phong, this may be interesting for you. Olga
---------- Forwarded message ---------- From: Vitaliy Gusev <gusev.vita...@nexenta.com> Date: Mon, Aug 27, 2012 at 3:12 PM Subject: [developer] [PATCH] kernel: "seqlock" syncronization primitive To: garr...@damore.org Cc: gusev.vita...@nexenta.com, develo...@lists.illumos.org, gordon.r...@nexenta.com, mahr...@delphix.com, richl...@richlowe.net # HG changeset patch # User Vitaliy Gusev <gusev.vita...@nexenta.com> # Date 1346072919 -14400 # Node ID aae4235aadf76a9cbe117ae391fb3831f8c0ec1b # Parent aeac1998cacba75a501e86ccf28f9e32cb9ed1c7 kernel: "seqlock" syncronization primitive This is implementation of "seqlock". Idea was borrowed from the Linux kernel. "seqlock" brings huge performance improvement. The case of usage - when there are a lot of readers, but very raraly writers. Readers enter to a cirtical-section without any atomic or LOCK operations, so don't waste system bus. Therefore readers are very fast even on multi-CPUs system. Note, seqlock can be used only to protect non-pointers data: - numbers (char, short, int, long, long long, ...) - arrays - opaque data - flags Example: struct data { seqlock_t lock; int uid; int map_uid; } struct data *data; /* data allocation and initialization */ Reader: int seq; int uid, map_id; do { seq = seq_read_begin(&data->lock); uid = data->id; map_uid = data->uid; } while (seq_read_retry(&data->lock, seq)); /* Have valid uid -> map_uid */ Writer: seq_write_lock(&data->lock); data->uid = new_uid; data->map_uid = new_map_uid; seq_write_unlock(&data->lock); diff -r aeac1998cacb -r aae4235aadf7 usr/src/uts/common/Makefile.files --- a/usr/src/uts/common/Makefile.files Mon Aug 27 14:15:46 2012 +0400 +++ b/usr/src/uts/common/Makefile.files Mon Aug 27 17:08:39 2012 +0400 @@ -66,6 +66,7 @@ COMMON_CORE_OBJS += \ rctl_proc.o \ rwlock.o \ seg_kmem.o \ + seqlock.o \ softint.o \ string.o \ strtol.o \ diff -r aeac1998cacb -r aae4235aadf7 usr/src/uts/common/os/seqlock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/os/seqlock.c Mon Aug 27 17:08:39 2012 +0400 @@ -0,0 +1,66 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * + * seqlock.c - Implementation of sequence lock algorithm. + */ +#include <sys/types.h> +#include <sys/ddi.h> +#include <sys/mutex.h> +#include <sys/cpu.h> /* for SMT_PAUSE */ +#include <sys/cpuvar.h> /* for kpreempt */ +#include <sys/seqlock.h> + +void +seq_init(seqlock_t *seqlock) +{ + seqlock->sequence = 0; + mutex_init(&seqlock->lock, NULL, MUTEX_DEFAULT, NULL); +} + +void +seq_destroy(seqlock_t *seqlock) +{ + mutex_destroy(&seqlock->lock); +} + +int +seq_read_begin(volatile seqlock_t *seqlock) +{ + int seq; +again: + seq = seqlock->sequence; + if (seq & 0x1) { + SMT_PAUSE(); + goto again; + } + membar_consumer(); + return (seq); +} + +void +seq_write_lock(seqlock_t *seqlock) +{ + mutex_enter(&seqlock->lock); + kpreempt_disable(); + seqlock->sequence++; + membar_producer(); +} + +void +seq_write_unlock(seqlock_t *seqlock) +{ + seqlock->sequence++; + membar_producer(); + kpreempt_enable(); + mutex_exit(&seqlock->lock); +} diff -r aeac1998cacb -r aae4235aadf7 usr/src/uts/common/sys/seqlock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/seqlock.h Mon Aug 27 17:08:39 2012 +0400 @@ -0,0 +1,63 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * + * seqlock.h - Definitions of sequence lock algorithm. + * + * Example for reader: + * + * do { + * int seq = seq_read_begin(&seqlock); + * ... + * } while (seq_read_retry(&seqlock, seq)); + * + */ + +#ifndef _SYS_SEQLOCK_H +#define _SYS_SEQLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <sys/mutex.h> +#include <sys/atomic.h> /* for membar_consumer() */ + +typedef struct seqlock { + int sequence; + kmutex_t lock; +} seqlock_t; + +extern void seq_init(seqlock_t *); +extern void seq_destroy(seqlock_t *); +extern int seq_read_begin(volatile seqlock_t *); + +/* + * Code under seq_write_lock() should be fast and + * must not call sleeping function + */ +extern void seq_write_lock(seqlock_t *); +extern void seq_write_unlock(seqlock_t *); + +static boolean_t seq_read_retry(const seqlock_t *seqlock, int seq) +{ + membar_consumer(); + return (seqlock->sequence != seq); +} +#pragma inline(seq_read_retry) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SEQLOCK_H */ ------------------------------------------- illumos-developer Archives: https://www.listbox.com/member/archive/182179/=now RSS Feed: https://www.listbox.com/member/archive/rss/182179/21175218-fb99b1aa Modify Your Subscription: https://www.listbox.com/member/?member_id=21175218&id_secret=21175218-68edcfe3 Powered by Listbox: http://www.listbox.com -- , _ _ , { \/`o;====- Olga Kryzhanovska -====;o`\/ } .----'-/`-/ olga.kryzhanov...@gmail.com \-`\-'----. `'-..-| / http://twitter.com/fleyta \ |-..-'` /\/\ Solaris/BSD//C/C++ programmer /\/\ `--` `--` _______________________________________________ ast-developers mailing list ast-developers@research.att.com https://mailman.research.att.com/mailman/listinfo/ast-developers