1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 /* 12 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 13 * 14 * seqlock.c - Implementation of sequence lock algorithm. 15 */ 16 #include <sys/types.h> 17 #include <sys/ddi.h> 18 #include <sys/mutex.h> 19 #include <sys/cpu.h> /* for SMT_PAUSE */ 20 #include <sys/cpuvar.h> /* for kpreempt */ 21 #include <sys/seqlock.h> 22 23 void 24 seq_init(seqlock_t *seqlock) 25 { 26 seqlock->sequence = 0; 27 mutex_init(&seqlock->lock, NULL, MUTEX_DEFAULT, NULL); 28 } 29 30 void 31 seq_destroy(seqlock_t *seqlock) 32 { 33 mutex_destroy(&seqlock->lock); 34 } 35 36 int 37 seq_read_begin(volatile seqlock_t *seqlock) 38 { 39 int seq; 40 again: 41 seq = seqlock->sequence; 42 if (seq & 0x1) { 43 SMT_PAUSE(); 44 goto again; 45 } 46 membar_consumer(); 47 return (seq); 48 } 49 50 void 51 seq_write_lock(seqlock_t *seqlock) 52 { 53 mutex_enter(&seqlock->lock); 54 kpreempt_disable(); 55 seqlock->sequence++; 56 membar_producer(); 57 } 58 59 void 60 seq_write_unlock(seqlock_t *seqlock) 61 { 62 seqlock->sequence++; 63 membar_producer(); 64 kpreempt_enable(); 65 mutex_exit(&seqlock->lock); 66 }