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 }