1/*
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 7009231
27 * @summary C1: Incorrect CAS code for longs on SPARC 32bit
28 *
29 * @run main/othervm -Xbatch compiler.codegen.Test7009231
30 */
31
32package compiler.codegen;
33
34import java.util.concurrent.atomic.AtomicLong;
35
36public class Test7009231 {
37    public static void main(String[] args) throws InterruptedException {
38        doTest(8);
39    }
40
41    private static void doTest(int nThreads) throws InterruptedException {
42        Thread[]         aThreads = new Thread[nThreads];
43        final AtomicLong atl      = new AtomicLong();
44
45        for (int i = 0; i < nThreads; i++) {
46          aThreads[i] = new RunnerThread(atl, 1L << (8 * i));
47        }
48
49        for (int i = 0; i < nThreads; i++) {
50          aThreads[i].start();
51        }
52
53        for (int i = 0; i < nThreads; i++) {
54          aThreads[i].join();
55        }
56    }
57
58    public static class RunnerThread extends Thread {
59        public RunnerThread(AtomicLong atomic, long lMask) {
60            m_lMask  = lMask;
61            m_atomic = atomic;
62        }
63
64        public void run() {
65            AtomicLong atomic = m_atomic;
66            long       lMask  = m_lMask;
67            for (int i = 0; i < 100000; i++) {
68                setBit(atomic, lMask);
69                clearBit(atomic, lMask);
70            }
71        }
72
73        protected void setBit(AtomicLong atomic, long lMask) {
74            long lWord;
75            do {
76                lWord = atomic.get();
77            } while (!atomic.compareAndSet(lWord, lWord | lMask));
78
79            if ((atomic.get() & lMask) == 0L) {
80                throw new InternalError();
81            }
82        }
83
84        protected void clearBit(AtomicLong atomic, long lMask) {
85            long lWord;
86            do {
87                lWord = atomic.get();
88            } while (!atomic.compareAndSet(lWord, lWord & ~lMask));
89
90            if ((atomic.get() & lMask) != 0L) {
91                throw new InternalError();
92            }
93        }
94
95        private long m_lMask;
96        private AtomicLong m_atomic;
97    }
98}
99