1
/* ``The contents of this file are subject to the Erlang Public License,
2
* Version 1.1, (the "License"); you may not use this file except in
3
* compliance with the License. You should have received a copy of the
4
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
7
* Software distributed under the License is distributed on an "AS IS"
8
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
* the License for the specific language governing rights and limitations
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
20
* Description: A lock checker that checks that each thread acquires
21
* locks according to a predefined global lock order. The
22
* global lock order is used to prevent deadlocks. If the
23
* lock order is violated, an error message is printed
24
* and the emulator aborts. The lock checker is only
25
* intended to be enabled when debugging.
27
* Author: Rickard Green
34
/* Needed for VxWorks va_arg */
37
#ifdef ERTS_ENABLE_LOCK_CHECK
39
#include "erl_lock_check.h"
41
#include "erl_threads.h"
46
} erts_lc_lock_order_t;
49
* Global lock order for locks in the emulator.
51
* Locks early (low indexes) in the 'erts_lock_order' array should be
52
* locked before locks late (high indexes) in the array. Each lock has
53
* a name which is set on initialization. If multiple locks with the
54
* same name are used, either an immediate Erlang term (e.g. internal
55
* pid) or the address of the lock is used for internal lock order.
56
* The immediate Erlang term used for internal lock order is also set
57
* on initialization. Locks with small immediate Erlang terms should
58
* be locked before locks with large immediate Erlang terms, and
59
* locks with small addresses should be locked before locks with
60
* large addresses. The immediate terms and adresses (boxed pointers)
61
* are compared as unsigned integers not as Erlang terms.
63
* Once a spinlock or rw(spin)lock has been locked, the thread is not
64
* allowed to lock mutexes, rwmutexes or process locks until all
65
* spinlocks and rwlocks have been unlocked. This restriction is not
66
* reflected by the lock order below, but the lock checker will still
67
* check for violations of this restriction.
69
static erts_lc_lock_order_t erts_lock_order[] = {
71
* "Lock name" "Internal lock order
73
* if only one lock use
78
{ "bif_timers", NULL },
80
{ "proc_main", "pid" },
81
{ "proc_link", "pid" },
82
{ "proc_msgq", "pid" },
83
{ "proc_status", "pid" },
86
{ "db_tab", "address" },
87
{ "meta_pid_to_tab", NULL },
88
{ "meta_pid_to_fixed_tab", NULL },
89
{ "db_tables", NULL },
90
{ "dist_entry", "address" },
91
{ "node_table", NULL },
92
{ "dist_table", NULL },
93
{ "sys_tracers", NULL },
94
{ "trace_pattern", NULL },
95
{ "module_tab", NULL },
96
{ "export_tab", NULL },
99
{ "asyncq", "address" },
101
{ "async_ready", NULL },
103
{ "efile_drv", "address" },
104
#ifdef ENABLE_CHILD_WAITER_THREAD
105
{ "child_status", NULL },
107
{ "drv_ev_state", NULL },
108
{ "pollset", "address" },
109
{ "binary_alloc", NULL },
110
{ "alcu_init_atoms", NULL },
111
{ "mseg_init_atoms", NULL },
113
{ "sys_msg_q", NULL },
114
{ "atom_tab", NULL },
115
{ "make_ref", NULL },
116
{ "message_alloc_lock", NULL },
117
{ "ptimer_pre_alloc_lock", NULL, },
118
{ "btm_pre_alloc_lock", NULL, },
120
{ "mtrace_op", NULL },
123
{ "fix_alloc", "index" },
124
{ "alcu_allocator", "index" },
129
{ "timer_wheel", NULL },
130
{ "timeofday", NULL },
131
{ "system_block", NULL },
132
{ "breakpoints", NULL },
133
{ "pollsets_lock", NULL },
135
{ "mtrace_buf", NULL }
138
#define ERTS_LOCK_ORDER_SIZE \
139
(sizeof(erts_lock_order)/sizeof(erts_lc_lock_order_t))
141
#define LOCK_IS_TYPE_ORDER_VIOLATION(LCK_FLG, LCKD_FLG) \
142
(((LCKD_FLG) & (ERTS_LC_FLG_LT_SPINLOCK|ERTS_LC_FLG_LT_RWSPINLOCK)) \
144
& ERTS_LC_FLG_LT_ALL \
145
& ~(ERTS_LC_FLG_LT_SPINLOCK|ERTS_LC_FLG_LT_RWSPINLOCK)))
148
lock_type(Uint16 flags)
150
switch (flags & ERTS_LC_FLG_LT_ALL) {
151
case ERTS_LC_FLG_LT_SPINLOCK: return "[spinlock]";
152
case ERTS_LC_FLG_LT_RWSPINLOCK: return "[rw(spin)lock]";
153
case ERTS_LC_FLG_LT_MUTEX: return "[mutex]";
154
case ERTS_LC_FLG_LT_RWMUTEX: return "[rwmutex]";
155
case ERTS_LC_FLG_LT_PROCLOCK: return "[proclock]";
161
rw_op_str(Uint16 flags)
163
switch (flags & ERTS_LC_FLG_LO_READ_WRITE) {
164
case ERTS_LC_FLG_LO_READ_WRITE:
166
case ERTS_LC_FLG_LO_READ:
168
case ERTS_LC_FLG_LO_WRITE:
169
erts_fprintf(stderr, "\nInternal error\n");
177
typedef struct erts_lc_locked_lock_t_ erts_lc_locked_lock_t;
178
struct erts_lc_locked_lock_t_ {
179
erts_lc_locked_lock_t *next;
180
erts_lc_locked_lock_t *prev;
186
typedef struct erts_lc_locked_locks_t_ erts_lc_locked_locks_t;
187
struct erts_lc_locked_locks_t_ {
190
erts_lc_locked_locks_t *next;
191
erts_lc_locked_locks_t *prev;
192
erts_lc_locked_lock_t *first;
193
erts_lc_locked_lock_t *last;
196
typedef union erts_lc_free_block_t_ erts_lc_free_block_t;
197
union erts_lc_free_block_t_ {
198
erts_lc_free_block_t *next;
199
erts_lc_locked_lock_t lock;
202
static ethr_tsd_key locks_key;
204
static erts_lc_locked_locks_t *erts_locked_locks;
206
static erts_lc_free_block_t *free_blocks;
208
#ifdef ERTS_LC_STATIC_ALLOC
209
#define ERTS_LC_FB_CHUNK_SIZE 10000
211
#define ERTS_LC_FB_CHUNK_SIZE 10
214
#ifdef ETHR_HAVE_NATIVE_LOCKS
215
static ethr_spinlock_t free_blocks_lock;
216
#define ERTS_LC_LOCK ethr_spin_lock
217
#define ERTS_LC_UNLOCK ethr_spin_unlock
219
static ethr_mutex free_blocks_lock;
220
#define ERTS_LC_LOCK ethr_mutex_lock
221
#define ERTS_LC_UNLOCK ethr_mutex_unlock
224
static ERTS_INLINE void
227
if (ERTS_LC_LOCK(&free_blocks_lock) != 0)
231
static ERTS_INLINE void
234
if (ERTS_LC_UNLOCK(&free_blocks_lock) != 0)
238
static ERTS_INLINE void lc_free(void *p)
240
erts_lc_free_block_t *fb = (erts_lc_free_block_t *) p;
242
memset((void *) p, 0xdf, sizeof(erts_lc_free_block_t));
245
fb->next = free_blocks;
250
#ifdef ERTS_LC_STATIC_ALLOC
252
static void *lc_core_alloc(void)
255
erts_fprintf(stderr, "Lock checker out of memory!\n");
261
static void *lc_core_alloc(void)
264
erts_lc_free_block_t *fbs;
266
fbs = (erts_lc_free_block_t *) malloc(sizeof(erts_lc_free_block_t)
267
* ERTS_LC_FB_CHUNK_SIZE);
269
erts_fprintf(stderr, "Lock checker failed to allocate memory!\n");
272
for (i = 1; i < ERTS_LC_FB_CHUNK_SIZE - 1; i++) {
274
memset((void *) &fbs[i], 0xdf, sizeof(erts_lc_free_block_t));
276
fbs[i].next = &fbs[i+1];
279
memset((void *) &fbs[ERTS_LC_FB_CHUNK_SIZE-1],
280
0xdf, sizeof(erts_lc_free_block_t));
283
fbs[ERTS_LC_FB_CHUNK_SIZE-1].next = free_blocks;
284
free_blocks = &fbs[1];
285
return (void *) &fbs[0];
290
static ERTS_INLINE void *lc_alloc(void)
295
res = lc_core_alloc();
297
res = (void *) free_blocks;
298
free_blocks = free_blocks->next;
305
static erts_lc_locked_locks_t *
306
create_locked_locks(char *thread_name)
308
erts_lc_locked_locks_t *l_lcks = malloc(sizeof(erts_lc_locked_locks_t));
312
l_lcks->thread_name = strdup(thread_name ? thread_name : "unknown");
313
if (!l_lcks->thread_name)
316
l_lcks->tid = erts_thr_self();
317
l_lcks->first = NULL;
321
l_lcks->next = erts_locked_locks;
322
if (erts_locked_locks)
323
erts_locked_locks->prev = l_lcks;
324
erts_locked_locks = l_lcks;
326
erts_tsd_set(locks_key, (void *) l_lcks);
331
destroy_locked_locks(erts_lc_locked_locks_t *l_lcks)
333
ASSERT(l_lcks->thread_name);
334
free((void *) l_lcks->thread_name);
335
ASSERT(l_lcks->first == NULL);
336
ASSERT(l_lcks->last == NULL);
340
l_lcks->prev->next = l_lcks->next;
342
ASSERT(erts_locked_locks == l_lcks);
343
erts_locked_locks = l_lcks->next;
347
l_lcks->next->prev = l_lcks->prev;
350
free((void *) l_lcks);
354
static ERTS_INLINE erts_lc_locked_locks_t *
355
get_my_locked_locks(void)
357
return erts_tsd_get(locks_key);
360
static ERTS_INLINE erts_lc_locked_locks_t *
361
make_my_locked_locks(void)
363
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
367
return create_locked_locks(NULL);
370
static ERTS_INLINE erts_lc_locked_lock_t *
371
new_locked_lock(erts_lc_lock_t *lck, Uint16 op_flags)
373
erts_lc_locked_lock_t *l_lck = (erts_lc_locked_lock_t *) lc_alloc();
377
l_lck->extra = lck->extra;
378
l_lck->flags = lck->flags | op_flags;
383
print_lock2(char *prefix, Sint16 id, Eterm extra, Uint16 flags, char *suffix)
385
char *lname = (0 <= id && id < ERTS_LOCK_ORDER_SIZE
386
? erts_lock_order[id].name
409
print_lock(char *prefix, erts_lc_lock_t *lck, char *suffix)
411
print_lock2(prefix, lck->id, lck->extra, lck->flags, suffix);
415
print_curr_locks(erts_lc_locked_locks_t *l_lcks)
417
erts_lc_locked_lock_t *l_lck;
418
if (!l_lcks || !l_lcks->first)
420
"Currently no locks are locked by the %s thread.\n",
421
l_lcks->thread_name);
424
"Currently these locks are locked by the %s thread:\n",
425
l_lcks->thread_name);
426
for (l_lck = l_lcks->first; l_lck; l_lck = l_lck->next)
427
print_lock2(" ", l_lck->id, l_lck->extra, l_lck->flags, "\n");
432
print_lock_order(void)
435
erts_fprintf(stderr, "Lock order:\n");
436
for (i = 1; i < ERTS_LOCK_ORDER_SIZE; i++) {
437
if (erts_lock_order[i].internal_order)
440
erts_lock_order[i].name,
441
erts_lock_order[i].internal_order);
443
erts_fprintf(stderr, " %s\n", erts_lock_order[i].name);
448
uninitialized_lock(void)
450
erts_fprintf(stderr, "Performing operations on uninitialized lock!\n");
451
print_curr_locks(get_my_locked_locks());
456
lock_twice(char *prefix, erts_lc_locked_locks_t *l_lcks, erts_lc_lock_t *lck,
459
erts_fprintf(stderr, "%s%s", prefix, rw_op_str(op_flags));
460
print_lock(" ", lck, " lock which is already locked by thread!\n");
461
print_curr_locks(l_lcks);
466
unlock_op_mismatch(erts_lc_locked_locks_t *l_lcks, erts_lc_lock_t *lck,
469
erts_fprintf(stderr, "Unlocking%s ", rw_op_str(op_flags));
470
print_lock("", lck, " lock which mismatch previous lock operation!\n");
471
print_curr_locks(l_lcks);
476
unlock_of_not_locked(erts_lc_locked_locks_t *l_lcks, erts_lc_lock_t *lck)
478
print_lock("Unlocking ", lck, " lock which is not locked by thread!\n");
479
print_curr_locks(l_lcks);
484
lock_order_violation(erts_lc_locked_locks_t *l_lcks, erts_lc_lock_t *lck)
486
print_lock("Lock order violation occured when locking ", lck, "!\n");
487
print_curr_locks(l_lcks);
493
type_order_violation(char *op, erts_lc_locked_locks_t *l_lcks,
496
erts_fprintf(stderr, "Lock type order violation occured when ");
497
print_lock(op, lck, "!\n");
499
print_curr_locks(l_lcks);
504
lock_mismatch(erts_lc_locked_locks_t *l_lcks, int exact,
505
int failed_have, erts_lc_lock_t *have, int have_len,
506
int failed_have_not, erts_lc_lock_t *have_not, int have_not_len)
509
erts_fprintf(stderr, "Lock mismatch found!\n");
510
if (failed_have >= 0) {
511
ASSERT(have && have_len > failed_have);
512
print_lock2("At least the ",
513
have[failed_have].id, have[failed_have].extra, 0,
514
" lock is not locked when it should have been\n");
516
else if (failed_have_not >= 0) {
517
ASSERT(have_not && have_not_len > failed_have_not);
518
print_lock2("At least the ",
519
have_not[failed_have_not].id,
520
have_not[failed_have_not].extra,
522
" lock is locked when it should not have been\n");
525
if (!have || have_len <= 0)
527
"Thread should not have any locks locked at all\n");
530
"Thread should have these and only these locks "
532
for (i = 0; i < have_len; i++)
533
print_lock2(" ", have[i].id, have[i].extra, 0, "\n");
537
if (have && have_len > 0) {
539
"Thread should at least have these locks locked:\n");
540
for (i = 0; i < have_len; i++)
541
print_lock2(" ", have[i].id, have[i].extra, 0, "\n");
543
if (have_not && have_not_len > 0) {
545
"Thread should at least not have these locks "
547
for (i = 0; i < have_not_len; i++)
548
print_lock2(" ", have_not[i].id, have_not[i].extra, 0, "\n");
551
print_curr_locks(l_lcks);
556
thread_exit_handler(void)
558
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
562
"Thread exiting while having locked locks!\n");
563
print_curr_locks(l_lcks);
566
destroy_locked_locks(l_lcks);
567
/* erts_tsd_set(locks_key, NULL); */
572
erts_lc_set_thread_name(char *thread_name)
574
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
576
(void) create_locked_locks(thread_name);
578
ASSERT(l_lcks->thread_name);
579
free((void *) l_lcks->thread_name);
580
l_lcks->thread_name = strdup(thread_name ? thread_name : "unknown");
581
if (!l_lcks->thread_name)
587
erts_lc_assert_failed(char *file, int line, char *assertion)
589
erts_fprintf(stderr, "%s:%d: Lock check assertion \"%s\" failed!\n",
590
file, line, assertion);
591
print_curr_locks(get_my_locked_locks());
596
void erts_lc_fail(char *fmt, ...)
599
erts_fprintf(stderr, "Lock check failed: ");
601
erts_vfprintf(stderr, fmt, args);
603
erts_fprintf(stderr, "\n");
604
print_curr_locks(get_my_locked_locks());
610
erts_lc_get_lock_order_id(char *name)
614
if (!name || name[0] == '\0')
615
erts_fprintf(stderr, "Missing lock name\n");
617
for (i = 0; i < ERTS_LOCK_ORDER_SIZE; i++)
618
if (strcmp(erts_lock_order[i].name, name) == 0)
621
"Lock name '%s' missing in lock order "
622
"(update erl_lock_check.c)\n",
631
find_lock(erts_lc_locked_lock_t **l_lcks, erts_lc_lock_t *lck)
633
erts_lc_locked_lock_t *l_lck = *l_lcks;
636
if (l_lck->id == lck->id && l_lck->extra == lck->extra) {
637
if ((l_lck->flags & lck->flags) == lck->flags)
641
else if (l_lck->id < lck->id
642
|| (l_lck->id == lck->id
643
&& l_lck->extra < lck->extra)) {
644
for (l_lck = l_lck->next; l_lck; l_lck = l_lck->next) {
645
if (l_lck->id > lck->id
646
|| (l_lck->id == lck->id
647
&& l_lck->extra >= lck->extra)) {
649
if (l_lck->id == lck->id
650
&& l_lck->extra == lck->extra
651
&& ((l_lck->flags & lck->flags) == lck->flags))
658
for (l_lck = l_lck->prev; l_lck; l_lck = l_lck->prev) {
659
if (l_lck->id < lck->id
660
|| (l_lck->id == lck->id
661
&& l_lck->extra <= lck->extra)) {
663
if (l_lck->id == lck->id
664
&& l_lck->extra == lck->extra
665
&& ((l_lck->flags & lck->flags) == lck->flags))
676
find_id(erts_lc_locked_lock_t **l_lcks, Sint16 id)
678
erts_lc_locked_lock_t *l_lck = *l_lcks;
683
else if (l_lck->id < id) {
684
for (l_lck = l_lck->next; l_lck; l_lck = l_lck->next) {
685
if (l_lck->id >= id) {
694
for (l_lck = l_lck->prev; l_lck; l_lck = l_lck->prev) {
695
if (l_lck->id <= id) {
708
erts_lc_have_locks(int *resv, erts_lc_lock_t *locks, int len)
710
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
714
for (i = 0; i < len; i++)
718
erts_lc_locked_lock_t *l_lck = l_lcks->first;
719
for (i = 0; i < len; i++)
720
resv[i] = find_lock(&l_lck, &locks[i]);
725
erts_lc_have_lock_ids(int *resv, int *ids, int len)
727
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
731
for (i = 0; i < len; i++)
735
erts_lc_locked_lock_t *l_lck = l_lcks->first;
736
for (i = 0; i < len; i++)
737
resv[i] = find_id(&l_lck, ids[i]);
742
erts_lc_check(erts_lc_lock_t *have, int have_len,
743
erts_lc_lock_t *have_not, int have_not_len)
746
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
747
erts_lc_locked_lock_t *l_lck;
749
if (have && have_len > 0) {
751
lock_mismatch(NULL, 0,
753
-1, have_not, have_not_len);
754
l_lck = l_lcks->first;
755
for (i = 0; i < have_len; i++) {
756
if (!find_lock(&l_lck, &have[i]))
757
lock_mismatch(l_lcks, 0,
759
-1, have_not, have_not_len);
762
if (have_not && have_not_len > 0 && l_lcks) {
763
l_lck = l_lcks->first;
764
for (i = 0; i < have_not_len; i++) {
765
if (find_lock(&l_lck, &have_not[i]))
766
lock_mismatch(l_lcks, 0,
768
i, have_not, have_not_len);
774
erts_lc_check_exact(erts_lc_lock_t *have, int have_len)
776
erts_lc_locked_locks_t *l_lcks = get_my_locked_locks();
777
if (!l_lcks && have && have_len > 0)
778
lock_mismatch(NULL, 1,
783
erts_lc_locked_lock_t *l_lck = l_lcks->first;
784
for (i = 0; i < have_len; i++) {
785
if (!find_lock(&l_lck, &have[i]))
786
lock_mismatch(l_lcks, 1,
790
for (i = 0, l_lck = l_lcks->first; l_lck; l_lck = l_lck->next)
793
lock_mismatch(l_lcks, 1,
800
erts_lc_trylock_force_busy_flg(erts_lc_lock_t *lck, Uint16 op_flags)
802
#ifdef ERTS_LC_DO_NOT_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION
806
* Force busy trylock if locking doesn't follow lock order.
807
* This in order to make sure that caller can handle
808
* the situation without causing a lock order violation.
810
erts_lc_locked_locks_t *l_lcks;
812
if (lck->inited != ERTS_LC_INITITALIZED)
813
uninitialized_lock();
818
l_lcks = get_my_locked_locks();
820
if (!l_lcks || !l_lcks->first) {
821
ASSERT(!l_lcks || !l_lcks->last);
825
erts_lc_locked_lock_t *tl_lck;
827
ASSERT(l_lcks->last);
829
#if 0 /* Ok when trylocking I guess... */
830
if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->last->flags))
831
type_order_violation("trylocking ", l_lcks, lck);
834
if (l_lcks->last->id < lck->id
835
|| (l_lcks->last->id == lck->id
836
&& l_lcks->last->extra < lck->extra))
840
* Lock order violation
844
/* Check that we are not trying to lock this lock twice */
845
for (tl_lck = l_lcks->last; tl_lck; tl_lck = tl_lck->prev) {
846
if (tl_lck->id < lck->id
847
|| (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) {
848
if (tl_lck->id == lck->id && tl_lck->extra == lck->extra)
849
lock_twice("Trylocking", l_lcks, lck, op_flags);
854
#ifndef ERTS_LC_ALLWAYS_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION
855
/* We only force busy if a lock order violation would occur
856
and when on an even millisecond. */
858
erts_thr_timeval_t time;
859
erts_thr_time_now(&time);
861
if ((time.tv_nsec / 1000000) & 1)
871
void erts_lc_trylock_flg(int locked, erts_lc_lock_t *lck, Uint16 op_flags)
873
erts_lc_locked_locks_t *l_lcks;
874
erts_lc_locked_lock_t *l_lck;
876
if (lck->inited != ERTS_LC_INITITALIZED)
877
uninitialized_lock();
882
l_lcks = make_my_locked_locks();
883
l_lck = locked ? new_locked_lock(lck, op_flags) : NULL;
886
ASSERT(!l_lcks->first);
888
l_lcks->first = l_lcks->last = l_lck;
891
erts_lc_locked_lock_t *tl_lck;
892
#if 0 /* Ok when trylocking I guess... */
893
if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->last->flags))
894
type_order_violation("trylocking ", l_lcks, lck);
897
for (tl_lck = l_lcks->last; tl_lck; tl_lck = tl_lck->prev) {
898
if (tl_lck->id < lck->id
899
|| (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) {
900
if (tl_lck->id == lck->id && tl_lck->extra == lck->extra)
901
lock_twice("Trylocking", l_lcks, lck, op_flags);
903
l_lck->next = tl_lck->next;
904
l_lck->prev = tl_lck;
906
tl_lck->next->prev = l_lck;
908
l_lcks->last = l_lck;
909
tl_lck->next = l_lck;
916
l_lck->next = l_lcks->first;
917
l_lcks->first->prev = l_lck;
918
l_lcks->first = l_lck;
924
void erts_lc_lock_flg(erts_lc_lock_t *lck, Uint16 op_flags)
926
erts_lc_locked_locks_t *l_lcks;
927
erts_lc_locked_lock_t *l_lck;
929
if (lck->inited != ERTS_LC_INITITALIZED)
930
uninitialized_lock();
935
l_lcks = make_my_locked_locks();
936
l_lck = new_locked_lock(lck, op_flags);
939
ASSERT(!l_lcks->first);
940
l_lcks->last = l_lcks->first = l_lck;
942
else if (l_lcks->last->id < lck->id
943
|| (l_lcks->last->id == lck->id
944
&& l_lcks->last->extra < lck->extra)) {
945
if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->last->flags))
946
type_order_violation("locking ", l_lcks, lck);
947
l_lck->prev = l_lcks->last;
948
l_lcks->last->next = l_lck;
949
l_lcks->last = l_lck;
951
else if (l_lcks->last->id == lck->id && l_lcks->last->extra == lck->extra)
952
lock_twice("Locking", l_lcks, lck, op_flags);
954
lock_order_violation(l_lcks, lck);
957
void erts_lc_unlock_flg(erts_lc_lock_t *lck, Uint16 op_flags)
959
erts_lc_locked_locks_t *l_lcks;
960
erts_lc_locked_lock_t *l_lck;
962
if (lck->inited != ERTS_LC_INITITALIZED)
963
uninitialized_lock();
968
l_lcks = get_my_locked_locks();
970
for (l_lck = l_lcks ? l_lcks->last : NULL; l_lck; l_lck = l_lck->prev) {
971
if (l_lck->id == lck->id && l_lck->extra == lck->extra) {
972
if ((l_lck->flags & ERTS_LC_FLG_LO_ALL) != op_flags)
973
unlock_op_mismatch(l_lcks, lck, op_flags);
975
l_lck->prev->next = l_lck->next;
977
l_lcks->first = l_lck->next;
979
l_lck->next->prev = l_lck->prev;
981
l_lcks->last = l_lck->prev;
982
lc_free((void *) l_lck);
987
unlock_of_not_locked(l_lcks, lck);
991
erts_lc_trylock_force_busy(erts_lc_lock_t *lck)
993
return erts_lc_trylock_force_busy_flg(lck, 0);
997
erts_lc_trylock(int locked, erts_lc_lock_t *lck)
999
erts_lc_trylock_flg(locked, lck, 0);
1003
erts_lc_lock(erts_lc_lock_t *lck)
1005
erts_lc_lock_flg(lck, 0);
1009
erts_lc_unlock(erts_lc_lock_t *lck)
1011
erts_lc_unlock_flg(lck, 0);
1015
erts_lc_init_lock(erts_lc_lock_t *lck, char *name, Uint16 flags)
1017
lck->id = erts_lc_get_lock_order_id(name);
1018
lck->extra = make_boxed(&lck->extra);
1020
lck->inited = ERTS_LC_INITITALIZED;
1024
erts_lc_init_lock_x(erts_lc_lock_t *lck, char *name, Uint16 flags, Eterm extra)
1026
lck->id = erts_lc_get_lock_order_id(name);
1029
lck->inited = ERTS_LC_INITITALIZED;
1033
erts_lc_destroy_lock(erts_lc_lock_t *lck)
1035
if (lck->inited != ERTS_LC_INITITALIZED)
1036
uninitialized_lock();
1040
lck->extra = THE_NON_VALUE;
1047
#ifdef ERTS_LC_STATIC_ALLOC
1049
static erts_lc_free_block_t fbs[ERTS_LC_FB_CHUNK_SIZE];
1050
for (i = 0; i < ERTS_LC_FB_CHUNK_SIZE - 1; i++) {
1052
memset((void *) &fbs[i], 0xdf, sizeof(erts_lc_free_block_t));
1054
fbs[i].next = &fbs[i+1];
1057
memset((void *) &fbs[ERTS_LC_FB_CHUNK_SIZE-1],
1058
0xdf, sizeof(erts_lc_free_block_t));
1060
fbs[ERTS_LC_FB_CHUNK_SIZE-1].next = NULL;
1061
free_blocks = &fbs[0];
1062
#else /* #ifdef ERTS_LC_STATIC_ALLOC */
1064
#endif /* #ifdef ERTS_LC_STATIC_ALLOC */
1066
#ifdef ETHR_HAVE_NATIVE_LOCKS
1067
if (ethr_spinlock_init(&free_blocks_lock) != 0)
1070
if (ethr_mutex_init(&free_blocks_lock) != 0)
1074
erts_tsd_key_create(&locks_key);
1078
erts_lc_late_init(void)
1080
erts_thr_install_exit_handler(thread_exit_handler);
1085
* erts_lc_pll(): print locked locks...
1090
print_curr_locks(get_my_locked_locks());
1094
#endif /* #ifdef ERTS_ENABLE_LOCK_CHECK */