Coverage Report

Created: 2026-10-22 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tdengine/source/util/src/tlockfree.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * SPDX-License-Identifier: AGPL-3.0-or-later
5
 *
6
 * This program is free software: you can use, redistribute, and/or modify
7
 * it under the terms of the GNU Affero General Public License, version 3
8
 * or later ("AGPL"), as published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 * FITNESS FOR A PARTICULAR PURPOSE.
13
 *
14
 * You should have received a copy of the GNU Affero General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#define _DEFAULT_SOURCE
19
#include "tlockfree.h"
20
21
93
#define TD_RWLATCH_WRITE_FLAG 0x40000000
22
23
0
void taosInitRWLatch(SRWLatch *pLatch) { *pLatch = 0; }
24
25
0
void taosWLockLatch(SRWLatch *pLatch) {
26
0
  SRWLatch oLatch, nLatch;
27
0
  int32_t  nLoops = 0;
28
29
  // Set write flag
30
0
  while (1) {
31
0
    oLatch = atomic_load_32(pLatch);
32
0
    if (oLatch & TD_RWLATCH_WRITE_FLAG) {
33
0
      nLoops++;
34
0
      if (nLoops > 1000) {
35
0
        (void)sched_yield();
36
0
        nLoops = 0;
37
0
      }
38
0
      continue;
39
0
    }
40
41
0
    nLatch = oLatch | TD_RWLATCH_WRITE_FLAG;
42
0
    if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) break;
43
0
  }
44
45
  // wait for all reads end
46
0
  nLoops = 0;
47
0
  while (1) {
48
0
    oLatch = atomic_load_32(pLatch);
49
0
    if (oLatch == TD_RWLATCH_WRITE_FLAG) break;
50
0
    nLoops++;
51
0
    if (nLoops > 1000) {
52
0
      (void)sched_yield();
53
0
      nLoops = 0;
54
0
    }
55
0
  }
56
0
}
57
58
0
void taosWWaitLockLatch(SRWLatch *pLatch) {
59
0
  SRWLatch oLatch, nLatch;
60
0
  int32_t  nLoops = 0;
61
62
  // Set write flag
63
0
  while (1) {
64
0
    oLatch = atomic_load_32(pLatch);
65
0
    if (oLatch & TD_RWLATCH_WRITE_FLAG) {
66
0
      taosMsleep(1);
67
0
      continue;
68
0
    }
69
70
0
    nLatch = oLatch | TD_RWLATCH_WRITE_FLAG;
71
0
    if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) break;
72
0
  }
73
74
  // wait for all reads end
75
0
  nLoops = 0;
76
0
  while (1) {
77
0
    oLatch = atomic_load_32(pLatch);
78
0
    if (oLatch == TD_RWLATCH_WRITE_FLAG) break;
79
0
    taosMsleep(1);
80
0
  }
81
0
}
82
83
// no reentrant
84
0
int32_t taosWTryLockLatch(SRWLatch *pLatch) {
85
0
  SRWLatch oLatch, nLatch;
86
0
  oLatch = atomic_load_32(pLatch);
87
0
  if (oLatch) {
88
0
    return -1;
89
0
  }
90
91
0
  nLatch = oLatch | TD_RWLATCH_WRITE_FLAG;
92
0
  if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) {
93
0
    return 0;
94
0
  }
95
96
0
  return -1;
97
0
}
98
99
0
int32_t taosWTryForceLockLatch(SRWLatch *pLatch) {
100
0
  SRWLatch oLatch, nLatch;
101
102
0
  while (1) {
103
0
    oLatch = atomic_load_32(pLatch);
104
0
    if (oLatch) {
105
0
      nLatch = oLatch | TD_RWLATCH_WRITE_FLAG;
106
0
      if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) {
107
0
        return -1;
108
0
      }
109
      
110
0
      continue;
111
0
    } else {
112
0
      nLatch = oLatch | TD_RWLATCH_WRITE_FLAG;
113
0
      if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) {
114
0
        return 0;
115
0
      }
116
      
117
0
      continue;
118
0
    }
119
0
  }
120
121
0
  return -1;
122
0
}
123
124
0
bool taosIsOnlyWLocked(SRWLatch *pLatch) {
125
0
  return TD_RWLATCH_WRITE_FLAG == atomic_load_32(pLatch);
126
0
}
127
128
0
bool taosHasRWWFlag(SRWLatch *pLatch) {
129
0
  return TD_RWLATCH_WRITE_FLAG & atomic_load_32(pLatch);
130
0
}
131
132
0
void taosWUnLockLatch(SRWLatch *pLatch) { atomic_store_32(pLatch, 0); }
133
134
93
void taosRLockLatch(SRWLatch *pLatch) {
135
93
  SRWLatch oLatch, nLatch;
136
93
  int32_t  nLoops = 0;
137
138
93
  while (1) {
139
93
    oLatch = atomic_load_32(pLatch);
140
93
    if (oLatch & TD_RWLATCH_WRITE_FLAG) {
141
0
      nLoops++;
142
0
      if (nLoops > 1000) {
143
0
        (void)sched_yield();
144
0
        nLoops = 0;
145
0
      }
146
0
      continue;
147
0
    }
148
149
93
    nLatch = oLatch + 1;
150
93
    if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) break;
151
93
  }
152
93
}
153
154
// no reentrant
155
0
int32_t taosRTryLockLatch(SRWLatch *pLatch) {
156
0
  SRWLatch oLatch, nLatch;
157
0
  int32_t  nLoops = 0;
158
159
0
  while (1) {
160
0
    oLatch = atomic_load_32(pLatch);
161
0
    if (oLatch & TD_RWLATCH_WRITE_FLAG) {
162
0
      return -1;
163
0
    }
164
165
0
    nLatch = oLatch + 1;
166
0
    if (atomic_val_compare_exchange_32(pLatch, oLatch, nLatch) == oLatch) {
167
0
      break;
168
0
    }
169
0
  }
170
171
0
  return 0;
172
0
}
173
174
93
void taosRUnLockLatch(SRWLatch *pLatch) { (void)atomic_sub_fetch_32(pLatch, 1); }
175
176
0
int32_t taosRUnLockLatch_r(SRWLatch *pLatch) { return atomic_sub_fetch_32(pLatch, 1); }