github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/checklocks/test/basics.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package test
    16  
    17  import (
    18  	"sync"
    19  )
    20  
    21  func testLockedAccessValid(tc *oneGuardStruct) {
    22  	tc.mu.Lock()
    23  	tc.guardedField = 1
    24  	tc.mu.Unlock()
    25  }
    26  
    27  func testLockedAccessIgnore(tc *oneGuardStruct) {
    28  	tc.mu.Lock()
    29  	tc.unguardedField = 1
    30  	tc.mu.Unlock()
    31  }
    32  
    33  func testUnlockedAccessInvalidWrite(tc *oneGuardStruct) {
    34  	tc.guardedField = 2 // +checklocksfail
    35  }
    36  
    37  func testUnlockedAccessInvalidRead(tc *oneGuardStruct) {
    38  	x := tc.guardedField // +checklocksfail
    39  	_ = x
    40  }
    41  
    42  func testUnlockedAccessValid(tc *oneGuardStruct) {
    43  	tc.unguardedField = 2
    44  }
    45  
    46  func testCallValidAccess(tc *oneGuardStruct) {
    47  	callValidAccess(tc)
    48  }
    49  
    50  func callValidAccess(tc *oneGuardStruct) {
    51  	tc.mu.Lock()
    52  	tc.guardedField = 1
    53  	tc.mu.Unlock()
    54  }
    55  
    56  func testCallValueMixup(tc *oneGuardStruct) {
    57  	callValueMixup(tc, tc)
    58  }
    59  
    60  func callValueMixup(tc1, tc2 *oneGuardStruct) {
    61  	tc1.mu.Lock()
    62  	tc2.guardedField = 2 // +checklocksfail
    63  	tc1.mu.Unlock()
    64  }
    65  
    66  func testCallPreconditionsInvalid(tc *oneGuardStruct) {
    67  	callPreconditions(tc) // +checklocksfail
    68  }
    69  
    70  func testCallPreconditionsValid(tc *oneGuardStruct) {
    71  	tc.mu.Lock()
    72  	callPreconditions(tc)
    73  	tc.mu.Unlock()
    74  }
    75  
    76  // +checklocks:tc.mu
    77  func callPreconditions(tc *oneGuardStruct) {
    78  	tc.guardedField = 1
    79  }
    80  
    81  type nestedFieldsStruct struct {
    82  	mu sync.Mutex
    83  
    84  	// +checklocks:mu
    85  	nestedStruct struct {
    86  		nested1 int
    87  		nested2 int
    88  	}
    89  }
    90  
    91  func testNestedGuardValid(tc *nestedFieldsStruct) {
    92  	tc.mu.Lock()
    93  	tc.nestedStruct.nested1 = 1
    94  	tc.nestedStruct.nested2 = 2
    95  	tc.mu.Unlock()
    96  }
    97  
    98  func testNestedGuardInvalid(tc *nestedFieldsStruct) {
    99  	tc.nestedStruct.nested1 = 1 // +checklocksfail
   100  }
   101  
   102  type rwGuardStruct struct {
   103  	rwMu sync.RWMutex
   104  
   105  	// +checklocks:rwMu
   106  	guardedField int
   107  }
   108  
   109  func testRWValidRead(tc *rwGuardStruct) {
   110  	tc.rwMu.Lock()
   111  	tc.guardedField = 1
   112  	tc.rwMu.Unlock()
   113  }
   114  
   115  func testRWValidWrite(tc *rwGuardStruct) {
   116  	tc.rwMu.RLock()
   117  	tc.guardedField = 2
   118  	tc.rwMu.RUnlock()
   119  }
   120  
   121  func testRWInvalidWrite(tc *rwGuardStruct) {
   122  	tc.guardedField = 3 // +checklocksfail
   123  }
   124  
   125  func testRWInvalidRead(tc *rwGuardStruct) {
   126  	x := tc.guardedField + 3 // +checklocksfail
   127  	_ = x
   128  }
   129  
   130  func testTwoLocksDoubleGuardStructValid(tc *twoLocksDoubleGuardStruct) {
   131  	tc.mu.Lock()
   132  	tc.secondMu.Lock()
   133  	tc.doubleGuardedField = 1
   134  	tc.secondMu.Unlock()
   135  }
   136  
   137  func testTwoLocksDoubleGuardStructOnlyOne(tc *twoLocksDoubleGuardStruct) {
   138  	tc.mu.Lock()
   139  	tc.doubleGuardedField = 2 // +checklocksfail
   140  	tc.mu.Unlock()
   141  }
   142  
   143  func testTwoLocksDoubleGuardStructInvalid(tc *twoLocksDoubleGuardStruct) {
   144  	tc.doubleGuardedField = 3 // +checklocksfail:2
   145  }