~statik/ubuntu/maverick/erlang/erlang-merge-testing

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_process_lock.h

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-05-01 10:14:38 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090501101438-6qlr6rsdxgyzrg2z
Tags: 1:13.b-dfsg-2
* Cleaned up patches: removed unneeded patch which helped to support
  different SCTP library versions, made sure that changes for m68k
  architecture applied only when building on this architecture.
* Removed duplicated information from binary packages descriptions.
* Don't require libsctp-dev build-dependency on solaris-i386 architecture
  which allows to build Erlang on Nexenta (thanks to Tim Spriggs for
  the suggestion).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* ``The contents of this file are subject to the Erlang Public License,
 
1
/*
 
2
 * %CopyrightBegin%
 
3
 * 
 
4
 * Copyright Ericsson AB 2007-2009. All Rights Reserved.
 
5
 * 
 
6
 * The contents of this file are subject to the Erlang Public License,
2
7
 * Version 1.1, (the "License"); you may not use this file except in
3
8
 * compliance with the License. You should have received a copy of the
4
9
 * Erlang Public License along with this software. If not, it can be
5
 
 * retrieved via the world wide web at http://www.erlang.org/.
 
10
 * retrieved online at http://www.erlang.org/.
6
11
 * 
7
12
 * Software distributed under the License is distributed on an "AS IS"
8
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
14
 * the License for the specific language governing rights and limitations
10
15
 * under the License.
11
16
 * 
12
 
 * The Initial Developer of the Original Code is Ericsson AB.
13
 
 * Portions created by Ericsson are Copyright 2007, Ericsson AB.
14
 
 * All Rights Reserved.''
15
 
 * 
16
 
 *     $Id$
 
17
 * %CopyrightEnd%
17
18
 */
18
19
 
19
20
 
30
31
#define ERTS_PROC_LOCK_DEBUG
31
32
#endif
32
33
 
 
34
#ifdef ERTS_ENABLE_LOCK_COUNT
 
35
#include "erl_lock_count.h"
 
36
#endif
 
37
 
33
38
#include "erl_smp.h"
34
39
 
35
40
#define ERTS_PROC_LOCK_ATOMIC_IMPL 0
64
69
#ifdef ERTS_PROC_LOCK_DEBUG
65
70
    erts_smp_atomic_t locked[ERTS_PROC_LOCK_MAX_BIT+1];
66
71
#endif
 
72
#ifdef ERTS_ENABLE_LOCK_COUNT
 
73
    erts_lcnt_lock_t lcnt_main;
 
74
    erts_lcnt_lock_t lcnt_link;
 
75
    erts_lcnt_lock_t lcnt_msgq;
 
76
    erts_lcnt_lock_t lcnt_status;
 
77
#endif
67
78
} erts_proc_lock_t;
68
79
 
69
80
/* Process lock flags */
168
179
                                         | ERTS_PROC_LOCK_STATUS)
169
180
#define ERTS_PROC_LOCKS_MSG_SEND        (ERTS_PROC_LOCK_MSGQ            \
170
181
                                         | ERTS_PROC_LOCK_STATUS)
171
 
#define ERTS_PROC_LOCKS_XSIG_SEND       (ERTS_PROC_LOCK_MSGQ            \
172
 
                                         | ERTS_PROC_LOCK_STATUS)
 
182
#define ERTS_PROC_LOCKS_XSIG_SEND       ERTS_PROC_LOCK_STATUS
173
183
 
174
184
#define ERTS_PROC_LOCKS_ALL \
175
185
  ((((ErtsProcLocks) 1) << (ERTS_PROC_LOCK_MAX_BIT + 1)) - 1)
185
195
#endif /* #ifndef ERTS_PROC_LOCK_TYPE__ */
186
196
 
187
197
#ifndef ERTS_PROCESS_LOCK_ONLY_PROC_LOCK_TYPE__
188
 
#ifndef ERTS_PROCESS_LOCK_H__
189
 
#define ERTS_PROCESS_LOCK_H__
 
198
#ifndef ERTS_PROC_LOCK_LOCK_CHECK__
 
199
#define  ERTS_PROC_LOCK_LOCK_CHECK__
 
200
 
 
201
/* Lock counter implemetation */
 
202
 
 
203
#ifdef ERTS_ENABLE_LOCK_COUNT
 
204
#define erts_smp_proc_lock__(P,I,L) erts_smp_proc_lock_x__(P,I,L,__FILE__,__LINE__)
 
205
#define erts_smp_proc_lock(P,L) erts_smp_proc_lock_x(P,L,__FILE__,__LINE__)
 
206
#endif
 
207
 
 
208
#if defined(ERTS_SMP) && defined (ERTS_ENABLE_LOCK_COUNT)
 
209
 
 
210
void erts_lcnt_proc_lock_init(Process *p);
 
211
void erts_lcnt_proc_lock_destroy(Process *p);
 
212
void erts_lcnt_proc_lock(erts_proc_lock_t *lock, ErtsProcLocks locks);
 
213
void erts_lcnt_proc_lock_post_x(erts_proc_lock_t *lock, ErtsProcLocks locks, char *file, unsigned int line);
 
214
void erts_lcnt_proc_lock_unaquire(erts_proc_lock_t *lock, ErtsProcLocks locks);
 
215
void erts_lcnt_proc_unlock(erts_proc_lock_t *lock, ErtsProcLocks locks);
 
216
void erts_lcnt_proc_trylock(erts_proc_lock_t *lock, ErtsProcLocks locks, int res);
 
217
 
 
218
#endif /* ERTS_ENABLE_LOCK_COUNT*/
 
219
 
 
220
 
190
221
 
191
222
/* --- Process lock checking ----------------------------------------------- */
192
223
 
212
243
#define ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(P)
213
244
#endif
214
245
 
 
246
#endif /* #ifndef ERTS_PROC_LOCK_LOCK_CHECK__ */
 
247
#endif /* #ifndef ERTS_PROCESS_LOCK_ONLY_PROC_LOCK_TYPE__ */
 
248
 
 
249
#if !defined(ERTS_PROCESS_LOCK_ONLY_PROC_LOCK_TYPE__) \
 
250
    && !defined(ERTS_PROCESS_LOCK_ONLY_LOCK_CHECK_PROTO__)
 
251
#ifndef ERTS_PROCESS_LOCK_H__
 
252
#define ERTS_PROCESS_LOCK_H__
 
253
 
215
254
#ifdef ERTS_SMP
216
255
 
217
256
typedef struct {
238
277
  ((ErtsProcLocks) erts_smp_atomic_band(&(L)->flags, (long) (MSK)))
239
278
#define ERTS_PROC_LOCK_FLGS_BOR_(L, MSK) \
240
279
  ((ErtsProcLocks) erts_smp_atomic_bor(&(L)->flags, (long) (MSK)))
 
280
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_(L, NEW, EXPECTED) \
 
281
  ((ErtsProcLocks) erts_smp_atomic_cmpxchg(&(L)->flags, \
 
282
                                           (long) (NEW), (long) (EXPECTED)))
241
283
#define ERTS_PROC_LOCK_FLGS_READ_(L) \
242
284
  ((ErtsProcLocks) erts_smp_atomic_read(&(L)->flags))
243
285
 
266
308
    return res;
267
309
}
268
310
 
 
311
ERTS_GLB_INLINE ErtsProcLocks
 
312
erts_proc_lock_flags_cmpxchg(erts_proc_lock_t *lck, ErtsProcLocks new,
 
313
                             ErtsProcLocks expected)
 
314
{
 
315
    ErtsProcLocks res = lck->flags;
 
316
    if (res == expected)
 
317
        lck->flags = new;
 
318
    return res;
 
319
}
 
320
 
269
321
#endif
270
322
 
271
323
#define ERTS_PROC_LOCK_FLGS_BAND_(L, MSK) erts_proc_lock_flags_band((L), (MSK))
272
324
#define ERTS_PROC_LOCK_FLGS_BOR_(L, MSK) erts_proc_lock_flags_bor((L), (MSK))
 
325
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_(L, NEW, EXPECTED) \
 
326
  erts_proc_lock_flags_cmpxchg((L), (NEW), (EXPECTED))
273
327
#define ERTS_PROC_LOCK_FLGS_READ_(L) ((L)->flags)
274
328
 
275
329
#endif /* end no opt atomic ops */
285
339
void erts_proc_unlock_failed(Process *,
286
340
                             erts_pix_lock_t *,
287
341
                             ErtsProcLocks);
288
 
void erts_proc_trylock_failed(Process *,
289
 
                              erts_pix_lock_t *pix_lck,
290
 
                              ErtsProcLocks,
291
 
                              ErtsProcLocks);
292
342
 
293
343
ERTS_GLB_INLINE void erts_pix_lock(erts_pix_lock_t *);
294
344
ERTS_GLB_INLINE void erts_pix_unlock(erts_pix_lock_t *);
295
345
ERTS_GLB_INLINE int erts_lc_pix_lock_is_locked(erts_pix_lock_t *);
296
346
 
297
 
ERTS_GLB_INLINE void erts_inc_proc_lock_refc(Process *);
298
 
ERTS_GLB_INLINE void erts_dec_proc_lock_refc(Process *);
299
 
 
 
347
ERTS_GLB_INLINE ErtsProcLocks erts_smp_proc_raw_trylock__(Process *p,
 
348
                                                          ErtsProcLocks locks);
 
349
#ifdef ERTS_ENABLE_LOCK_COUNT
 
350
ERTS_GLB_INLINE void erts_smp_proc_lock_x__(Process *,
 
351
                                          erts_pix_lock_t *,
 
352
                                          ErtsProcLocks,
 
353
                                          char *file, unsigned int line);
 
354
#else
300
355
ERTS_GLB_INLINE void erts_smp_proc_lock__(Process *,
301
356
                                          erts_pix_lock_t *,
302
357
                                          ErtsProcLocks);
 
358
#endif
303
359
ERTS_GLB_INLINE void erts_smp_proc_unlock__(Process *,
304
360
                                            erts_pix_lock_t *,
305
361
                                            ErtsProcLocks);
342
398
#endif
343
399
}
344
400
 
345
 
ERTS_GLB_INLINE void erts_inc_proc_lock_refc(Process *p)
346
 
{
347
 
    erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
348
 
    erts_pix_lock(pixlck);
349
 
    ERTS_LC_ASSERT(p->lock.refc > 0);
350
 
    p->lock.refc++;
351
 
    erts_pix_unlock(pixlck);
352
 
}
353
 
 
354
 
ERTS_GLB_INLINE void erts_dec_proc_lock_refc(Process *p)
355
 
{
356
 
    Process *fp;
357
 
    erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
358
 
    erts_pix_lock(pixlck);
359
 
    ERTS_LC_ASSERT(p->lock.refc > 0);
360
 
    fp = --p->lock.refc == 0 ? p : NULL; 
361
 
    erts_pix_unlock(pixlck);
362
 
    if (fp)
363
 
        erts_free_proc(fp);
364
 
}
 
401
/*
 
402
 * Helper function for erts_smp_proc_lock__ and erts_smp_proc_trylock__.
 
403
 *
 
404
 * Attempts to grab all of 'locks' simultaneously.
 
405
 *
 
406
 * On success, returns zero.
 
407
 *
 
408
 * On failure, returns the p->locks at the moment it tried to grab them,
 
409
 * at least some of which will intersect with 'locks', so it is nonzero.
 
410
 *
 
411
 * This assumes p's pix lock is held on entry if !ERTS_PROC_LOCK_ATOMIC_IMPL.
 
412
 * Does not release the pix lock.
 
413
 */
 
414
ERTS_GLB_INLINE ErtsProcLocks
 
415
erts_smp_proc_raw_trylock__(Process *p, ErtsProcLocks locks)
 
416
{
 
417
    ErtsProcLocks expct_lflgs = 0;
 
418
 
 
419
    while (1) {
 
420
        ErtsProcLocks lflgs = ERTS_PROC_LOCK_FLGS_CMPXCHG_(&p->lock,
 
421
                                                           expct_lflgs | locks,
 
422
                                                           expct_lflgs);
 
423
        if (ERTS_LIKELY(lflgs == expct_lflgs)) {
 
424
            /* We successfully grabbed all locks. */
 
425
            return 0;
 
426
        }
 
427
 
 
428
        if (lflgs & locks) {
 
429
            /* Some locks we need are locked, give up. */
 
430
            return lflgs;
 
431
        }
 
432
 
 
433
        /* cmpxchg failed, try again (should be rare). */
 
434
        expct_lflgs = lflgs;
 
435
    }
 
436
}
 
437
 
365
438
 
366
439
ERTS_GLB_INLINE void
 
440
#ifdef ERTS_ENABLE_LOCK_COUNT
 
441
erts_smp_proc_lock_x__(Process *p,
 
442
                     erts_pix_lock_t *pix_lck,
 
443
                     ErtsProcLocks locks,
 
444
                     char *file, unsigned int line)
 
445
#else
367
446
erts_smp_proc_lock__(Process *p,
368
447
                     erts_pix_lock_t *pix_lck,
369
448
                     ErtsProcLocks locks)
 
449
#endif
370
450
{
371
 
    ErtsProcLocks waiters, old_lflgs;
 
451
    ErtsProcLocks old_lflgs;
372
452
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
373
453
    erts_pix_lock(pix_lck);
374
454
#endif
 
455
#ifdef ERTS_ENABLE_LOCK_COUNT
 
456
    erts_lcnt_proc_lock(&(p->lock), locks);
 
457
#endif
375
458
 
376
459
    ERTS_LC_ASSERT((locks & ~ERTS_PROC_LOCKS_ALL) == 0);
377
 
    waiters = locks << ERTS_PROC_LOCK_WAITER_SHIFT;
378
 
    old_lflgs = ERTS_PROC_LOCK_FLGS_BOR_(&p->lock, locks);
379
 
 
380
 
    if (old_lflgs & (waiters | locks)) {
381
 
        /* erts_proc_lock_failed() always returns with pix_lck unlocked. */
 
460
 
 
461
    old_lflgs = erts_smp_proc_raw_trylock__(p, locks);
 
462
 
 
463
    if (old_lflgs != 0) {
 
464
        /*
 
465
         * There is lock contention, so let erts_proc_lock_failed() deal
 
466
         * with it. Note that erts_proc_lock_failed() returns with
 
467
         * pix_lck unlocked.
 
468
         */
382
469
        erts_proc_lock_failed(p, pix_lck, locks, old_lflgs);
383
470
    }
 
471
 
384
472
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
385
473
    else {
386
474
        ERTS_LC_ASSERT(locks == (ERTS_PROC_LOCK_FLGS_READ_(&p->lock) & locks));
387
475
        erts_pix_unlock(pix_lck);
388
476
    }
389
477
#endif
390
 
 
 
478
#ifdef ERTS_ENABLE_LOCK_COUNT
 
479
    erts_lcnt_proc_lock_post_x(&(p->lock), locks, file, line);
 
480
#endif
391
481
#ifdef ERTS_ENABLE_LOCK_CHECK
392
482
    erts_proc_lc_lock(p, locks);
393
483
#endif
405
495
                       erts_pix_lock_t *pix_lck,
406
496
                       ErtsProcLocks locks)
407
497
{
408
 
    ErtsProcLocks old_lflgs, waiters;
 
498
    ErtsProcLocks old_lflgs;
409
499
 
410
500
#if ERTS_PROC_LOCK_ATOMIC_IMPL
411
501
    ETHR_COMPILER_BARRIER;
412
502
#endif
413
503
 
 
504
#ifdef ERTS_ENABLE_LOCK_COUNT
 
505
    erts_lcnt_proc_unlock(&(p->lock), locks);
 
506
#endif
 
507
 
414
508
#ifdef ERTS_ENABLE_LOCK_CHECK
415
509
    erts_proc_lc_unlock(p, locks);
416
510
#endif
422
516
    erts_pix_lock(pix_lck);
423
517
#endif
424
518
 
 
519
    old_lflgs = ERTS_PROC_LOCK_FLGS_READ_(&p->lock);
 
520
 
425
521
    ERTS_LC_ASSERT((locks & ~ERTS_PROC_LOCKS_ALL) == 0);
426
 
    ERTS_LC_ASSERT(locks == (ERTS_PROC_LOCK_FLGS_READ_(&p->lock) & locks));
427
 
 
428
 
    old_lflgs = ERTS_PROC_LOCK_FLGS_BAND_(&p->lock, ~locks);
429
 
    waiters = (old_lflgs >> ERTS_PROC_LOCK_WAITER_SHIFT) & locks;
430
 
    if (waiters) {
431
 
        /* erts_proc_unlock_failed() always returns with pix_lck unlocked. */
432
 
        erts_proc_unlock_failed(p, pix_lck, waiters);
433
 
    }
 
522
    ERTS_LC_ASSERT(locks == (old_lflgs & locks));
 
523
 
 
524
    while (1) {
 
525
        /*
 
526
         * We'll atomically unlock every lock that has no waiter.
 
527
         * If any locks with waiters remain we'll let
 
528
         * erts_proc_unlock_failed() deal with them.
 
529
         */
 
530
        ErtsProcLocks wait_locks =
 
531
            (old_lflgs >> ERTS_PROC_LOCK_WAITER_SHIFT) & locks;
 
532
 
 
533
        /* What p->lock will look like with all non-waited locks released. */
 
534
        ErtsProcLocks want_lflgs = old_lflgs & (wait_locks | ~locks);
 
535
 
 
536
        if (want_lflgs != old_lflgs) {
 
537
            ErtsProcLocks new_lflgs =
 
538
                ERTS_PROC_LOCK_FLGS_CMPXCHG_(&p->lock, want_lflgs, old_lflgs);
 
539
 
 
540
            if (new_lflgs != old_lflgs) {
 
541
                /* cmpxchg failed, try again. */
 
542
                old_lflgs = new_lflgs;
 
543
                continue;
 
544
            }
 
545
        }
 
546
 
 
547
        /* We have successfully unlocked every lock with no waiter. */
 
548
 
 
549
        if (want_lflgs & locks) {
 
550
            /* Locks with waiters remain. */
 
551
            /* erts_proc_unlock_failed() returns with pix_lck unlocked. */
 
552
            erts_proc_unlock_failed(p, pix_lck, want_lflgs & locks);
 
553
        }
 
554
        else {
434
555
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
435
 
    else {
436
 
        erts_pix_unlock(pix_lck);
437
 
    }
 
556
            erts_pix_unlock(pix_lck);
438
557
#endif
 
558
        }
 
559
 
 
560
        break;
 
561
    }
439
562
}
440
563
 
441
564
ERTS_GLB_INLINE int
454
577
    else
455
578
#endif
456
579
    {
457
 
        ErtsProcLocks old_lflgs;
458
 
 
459
580
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
460
581
        erts_pix_lock(pix_lck);
461
582
#endif
462
583
 
463
 
        old_lflgs = ERTS_PROC_LOCK_FLGS_BOR_(&p->lock, locks);
464
 
        if (old_lflgs & (locks | (locks << ERTS_PROC_LOCK_WAITER_SHIFT))) {
 
584
        if (erts_smp_proc_raw_trylock__(p, locks) != 0) {
465
585
            /* Didn't get all locks... */
466
 
            /*
467
 
             * erts_proc_trylock_failed() always returns with pix_lck
468
 
             * unlocked.
469
 
             */
470
 
            erts_proc_trylock_failed(p, pix_lck, locks, old_lflgs);
471
586
            res = EBUSY;
 
587
 
 
588
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
 
589
            erts_pix_unlock(pix_lck);
 
590
#endif
472
591
        }
473
592
        else {
474
593
            res = 0;
485
604
#endif
486
605
        }
487
606
    }
 
607
#ifdef ERTS_ENABLE_LOCK_COUNT
 
608
    erts_lcnt_proc_trylock(&(p->lock), locks, res);
 
609
#endif
488
610
 
489
611
#ifdef ERTS_ENABLE_LOCK_CHECK
490
612
    erts_proc_lc_trylock(p, locks, res == 0);
523
645
 
524
646
#endif /* ERTS_SMP */
525
647
 
 
648
#ifdef ERTS_ENABLE_LOCK_COUNT
 
649
ERTS_GLB_INLINE void erts_smp_proc_lock_x(Process *, ErtsProcLocks, char *file, unsigned int line);
 
650
#else
526
651
ERTS_GLB_INLINE void erts_smp_proc_lock(Process *, ErtsProcLocks);
 
652
#endif
527
653
ERTS_GLB_INLINE void erts_smp_proc_unlock(Process *, ErtsProcLocks);
528
654
ERTS_GLB_INLINE int erts_smp_proc_trylock(Process *, ErtsProcLocks);
529
655
 
 
656
ERTS_GLB_INLINE void erts_smp_proc_inc_refc(Process *);
 
657
ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *);
 
658
 
530
659
 
531
660
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
532
661
 
533
662
ERTS_GLB_INLINE void
 
663
#ifdef ERTS_ENABLE_LOCK_COUNT
 
664
erts_smp_proc_lock_x(Process *p, ErtsProcLocks locks, char *file, unsigned int line)
 
665
#else
534
666
erts_smp_proc_lock(Process *p, ErtsProcLocks locks)
 
667
#endif 
535
668
{
536
 
#ifdef ERTS_SMP
 
669
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_COUNT)
 
670
    erts_smp_proc_lock_x__(p,
 
671
#if ERTS_PROC_LOCK_ATOMIC_IMPL
 
672
                         NULL,
 
673
#else
 
674
                         ERTS_PID2PIXLOCK(p->id),
 
675
#endif /*ERTS_PROC_LOCK_ATOMIC_IMPL*/
 
676
                         locks, file, line);
 
677
#elif defined(ERTS_SMP)
537
678
    erts_smp_proc_lock__(p,
538
679
#if ERTS_PROC_LOCK_ATOMIC_IMPL
539
680
                         NULL,
540
681
#else
541
682
                         ERTS_PID2PIXLOCK(p->id),
542
 
#endif
 
683
#endif /*ERTS_PROC_LOCK_ATOMIC_IMPL*/
543
684
                         locks);
544
 
#endif
 
685
#endif /*ERTS_SMP*/
545
686
}
546
687
 
547
688
ERTS_GLB_INLINE void
575
716
}
576
717
 
577
718
 
 
719
ERTS_GLB_INLINE void erts_smp_proc_inc_refc(Process *p)
 
720
{
 
721
#ifdef ERTS_SMP
 
722
    erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
 
723
    erts_pix_lock(pixlck);
 
724
    ERTS_LC_ASSERT(p->lock.refc > 0);
 
725
    p->lock.refc++;
 
726
    erts_pix_unlock(pixlck);
 
727
#endif
 
728
}
 
729
 
 
730
ERTS_GLB_INLINE void erts_smp_proc_dec_refc(Process *p)
 
731
{
 
732
#ifdef ERTS_SMP
 
733
    Process *fp;
 
734
    erts_pix_lock_t *pixlck = ERTS_PID2PIXLOCK(p->id);
 
735
    erts_pix_lock(pixlck);
 
736
    ERTS_LC_ASSERT(p->lock.refc > 0);
 
737
    fp = --p->lock.refc == 0 ? p : NULL; 
 
738
    erts_pix_unlock(pixlck);
 
739
    if (fp)
 
740
        erts_free_proc(fp);
 
741
#endif
 
742
}
 
743
 
578
744
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
579
745
 
580
746
#ifdef ERTS_SMP
603
769
 
604
770
#define ERTS_P2P_FLG_ALLOW_OTHER_X      (1 <<  0)
605
771
#define ERTS_P2P_FLG_TRY_LOCK           (1 <<  1)
 
772
#define ERTS_P2P_FLG_SMP_INC_REFC       (1 <<  2)
606
773
 
607
774
#define ERTS_PROC_LOCK_BUSY ((Process *) &erts_proc_lock_busy)
608
775
extern const Process erts_proc_lock_busy;
615
782
 
616
783
#ifdef ERTS_SMP
617
784
void
618
 
erts_pid2proc_trylock_failed(Process *p,
619
 
                             erts_pix_lock_t *pixlck,
620
 
                             ErtsProcLocks locks,
621
 
                             ErtsProcLocks wlocks,
622
 
                             ErtsProcLocks old_lflgs);
623
 
void
624
785
erts_pid2proc_safelock(Process *c_p,
625
786
                       ErtsProcLocks c_p_have_locks,
626
787
                       Process **proc,
627
 
                       ErtsProcLocks have_locks,
628
788
                       ErtsProcLocks need_locks,
629
 
                       ErtsProcLocks wait_locks,
630
789
                       erts_pix_lock_t *pix_lock,
631
790
                       int flags);
632
791
ERTS_GLB_INLINE Process *erts_pid2proc_unlocked_opt(Eterm pid, int flags);
681
840
    ErtsProcLocks need_locks;
682
841
    Uint pix;
683
842
    Process *proc;
 
843
#ifdef ERTS_ENABLE_LOCK_COUNT
 
844
    ErtsProcLocks lcnt_locks;
 
845
#endif
684
846
 
685
847
#ifdef ERTS_ENABLE_LOCK_CHECK
686
848
    if (c_p) {
689
851
            erts_proc_lc_might_unlock(c_p, might_unlock);
690
852
    }
691
853
#endif
692
 
 
693
854
    if (is_not_internal_pid(pid)) {
694
855
        proc = NULL;
695
856
        goto done;
703
864
    ERTS_LC_ASSERT((pid_need_locks & ERTS_PROC_LOCKS_ALL) == pid_need_locks);
704
865
    need_locks = pid_need_locks;
705
866
 
 
867
    pix_lock = ERTS_PIX2PIXLOCK(pix);
 
868
 
706
869
    if (c_p && c_p->id == pid) {
707
870
        ASSERT(c_p->id != ERTS_INVALID_PID);
708
871
        ASSERT(c_p == process_tab[pix]);
713
876
        need_locks &= ~c_p_have_locks;
714
877
        if (!need_locks) {
715
878
            proc = c_p;
 
879
            erts_pix_lock(pix_lock);
 
880
            if (flags & ERTS_P2P_FLG_SMP_INC_REFC)
 
881
                proc->lock.refc++;
 
882
            erts_pix_unlock(pix_lock);
716
883
            goto done;
717
884
        }
718
885
    }
719
886
 
720
 
    pix_lock = ERTS_PIX2PIXLOCK(pix);
721
887
    erts_pix_lock(pix_lock);
722
888
 
723
889
    proc = process_tab[pix];
726
892
                                && ERTS_PROC_IS_EXITING(proc))) {
727
893
            proc = NULL;
728
894
        }
 
895
        else if (!need_locks) {
 
896
            if (flags & ERTS_P2P_FLG_SMP_INC_REFC)
 
897
                proc->lock.refc++;
 
898
        }
729
899
        else {
730
 
            ErtsProcLocks have_locks, wait_locks;
 
900
            int busy;
 
901
 
 
902
#ifdef ERTS_ENABLE_LOCK_COUNT
 
903
            lcnt_locks = need_locks;
 
904
            if (!(flags & ERTS_P2P_FLG_TRY_LOCK)) {
 
905
                erts_lcnt_proc_lock(&proc->lock, need_locks);
 
906
            }
 
907
#endif
731
908
 
732
909
#ifdef ERTS_ENABLE_LOCK_CHECK
733
 
            if (erts_proc_lc_trylock_force_busy(proc, need_locks)) {
734
 
                /* Make sure erts_proc_safelock() is enough to handle
735
 
                   a potential lock order violation situation... */
736
 
                have_locks = 0;
737
 
                wait_locks = 0;
738
 
                if (flags & ERTS_P2P_FLG_TRY_LOCK) {
739
 
                    erts_pix_unlock(pix_lock);
740
 
                    proc = ERTS_PROC_LOCK_BUSY;
741
 
                    goto done;
742
 
                }
743
 
            }
744
 
            else
 
910
            /* Make sure erts_pid2proc_safelock() is enough to handle
 
911
               a potential lock order violation situation... */
 
912
            busy = erts_proc_lc_trylock_force_busy(proc, need_locks);
 
913
            if (!busy)
745
914
#endif
746
915
            {
747
 
                /* Try to aquire as many locks as possible... */
748
 
                ErtsProcLocks old_lflgs;
 
916
                /* Try a quick trylock to grab all the locks we need. */
 
917
                busy = (int) erts_smp_proc_raw_trylock__(proc, need_locks);
 
918
#ifdef ERTS_ENABLE_LOCK_CHECK
 
919
                erts_proc_lc_trylock(proc, need_locks, !busy);
 
920
#endif
 
921
#ifdef ERTS_PROC_LOCK_DEBUG
 
922
                if (!busy)
 
923
                    erts_proc_lock_op_debug(proc, need_locks, 1);
 
924
#endif
 
925
            }
749
926
 
750
 
                have_locks = need_locks;
751
 
                old_lflgs = ERTS_PROC_LOCK_FLGS_BOR_(&proc->lock, need_locks);
752
 
                have_locks &= ~old_lflgs;
753
 
                wait_locks = old_lflgs >> ERTS_PROC_LOCK_WAITER_SHIFT;
754
 
                wait_locks &= have_locks;
755
 
                have_locks &= ~wait_locks;
756
 
#ifdef ERTS_ENABLE_LOCK_CHECK
757
 
                if (flags & ERTS_P2P_FLG_TRY_LOCK) {
758
 
                    erts_proc_lc_trylock(proc,
759
 
                                         need_locks,
760
 
                                         need_locks == have_locks);
 
927
#ifdef ERTS_ENABLE_LOCK_COUNT
 
928
            if (flags & ERTS_P2P_FLG_TRY_LOCK) {
 
929
                if (busy) {
 
930
                    erts_lcnt_proc_trylock(&proc->lock, need_locks, EBUSY);
 
931
                } else {
 
932
                    erts_lcnt_proc_trylock(&proc->lock, need_locks, 0);
761
933
                }
 
934
            }
 
935
#endif
 
936
            if (!busy) {
 
937
                if (flags & ERTS_P2P_FLG_SMP_INC_REFC)
 
938
                    proc->lock.refc++;
 
939
#ifdef ERTS_ENABLE_LOCK_COUNT
 
940
                /* all is great */
 
941
                if (!(flags & ERTS_P2P_FLG_TRY_LOCK)) {
 
942
                    erts_lcnt_proc_lock_post_x(&proc->lock, lcnt_locks, __FILE__, __LINE__);
 
943
                }
 
944
#endif
 
945
            }
 
946
            else {
 
947
                if (flags & ERTS_P2P_FLG_TRY_LOCK)
 
948
                    proc = ERTS_PROC_LOCK_BUSY;
762
949
                else {
763
 
                    if (need_locks != have_locks)
764
 
                        erts_proc_lc_trylock(proc, need_locks & ~have_locks, 0);
765
 
                    if (have_locks)
766
 
                        erts_proc_lc_trylock(proc, have_locks, 1);
767
 
                }
768
 
#endif
769
 
#ifdef ERTS_PROC_LOCK_DEBUG
770
 
                if (!(flags & ERTS_P2P_FLG_TRY_LOCK)
771
 
                    || need_locks == have_locks)
772
 
                    erts_proc_lock_op_debug(proc, have_locks, 1);
773
 
#endif
774
 
                ERTS_SMP_LC_ASSERT(!wait_locks || (need_locks & ~have_locks));
775
 
 
776
 
                if ((flags & ERTS_P2P_FLG_TRY_LOCK)
777
 
                    && (need_locks & ~have_locks)) {
778
 
                    erts_pid2proc_trylock_failed(proc,
779
 
                                                 pix_lock,
780
 
                                                 need_locks,
781
 
                                                 wait_locks,
782
 
                                                 old_lflgs); /* Unlocks
783
 
                                                                pixlck */
784
 
                    proc = ERTS_PROC_LOCK_BUSY;
785
 
                    goto done;
786
 
                }
787
 
 
788
 
                need_locks &= ~have_locks;
 
950
                    if (flags & ERTS_P2P_FLG_SMP_INC_REFC)
 
951
                        proc->lock.refc++;
 
952
#ifdef ERTS_ENABLE_LOCK_COUNT
 
953
                    erts_lcnt_proc_lock_unaquire(&proc->lock, lcnt_locks);
 
954
#endif
 
955
                    erts_pid2proc_safelock(c_p,
 
956
                                           c_p_have_locks,
 
957
                                           &proc,
 
958
                                           pid_need_locks,
 
959
                                           pix_lock,
 
960
                                           flags);
 
961
                }
789
962
            }
790
 
 
791
 
            if (need_locks)
792
 
                erts_pid2proc_safelock(c_p,
793
 
                                       c_p_have_locks,
794
 
                                       &proc,
795
 
                                       have_locks,
796
 
                                       pid_need_locks,
797
 
                                       wait_locks,
798
 
                                       pix_lock,
799
 
                                       flags);
800
 
        }
 
963
        }
801
964
    }
802
965
 
803
966
    erts_pix_unlock(pix_lock);
804
967
#ifdef ERTS_PROC_LOCK_DEBUG
805
968
    ERTS_LC_ASSERT(!proc
 
969
                   || proc == ERTS_PROC_LOCK_BUSY
806
970
                   || (pid_need_locks ==
807
971
                       (ERTS_PROC_LOCK_FLGS_READ_(&proc->lock)
808
972
                        & pid_need_locks)));
809
973
#endif
810
974
 
811
 
 done:
 
975
 
 
976
 done:          
812
977
 
813
978
#if ERTS_PROC_LOCK_ATOMIC_IMPL
814
979
    ETHR_COMPILER_BARRIER;
821
986
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
822
987
 
823
988
#endif /* #ifndef ERTS_PROCESS_LOCK_H__ */
824
 
#endif /* #ifndef ERTS_PROCESS_LOCK_ONLY_PROC_LOCK_TYPE__ */
 
989
#endif /* #if !defined(ERTS_PROCESS_LOCK_ONLY_PROC_LOCK_TYPE__) 
 
990
          && !defined(ERTS_PROCESS_LOCK_ONLY_LOCK_CHECK_PROTO__) */