少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
 * \file
 * Monitor locking functions
 *
 * Author:
 *    Dick Porter (dick@ximian.com)
 *
 * (C) 2003 Ximian, Inc
 */
 
#ifndef _MONO_METADATA_MONITOR_H_
#define _MONO_METADATA_MONITOR_H_
 
#include <glib.h>
#include <mono/metadata/object.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-coop-semaphore.h>
 
G_BEGIN_DECLS
 
#define OWNER_MASK        0x0000ffff
#define ENTRY_COUNT_MASK    0xffff0000
#define ENTRY_COUNT_WAITERS    0x80000000
#define ENTRY_COUNT_ZERO    0x7fff0000
#define ENTRY_COUNT_SHIFT    16
 
struct _MonoThreadsSync
{
    /*
     * The entry count field can be negative, which would mean that the entry_sem is
     * signaled and nobody is waiting to acquire it. This can happen when the thread
     * that was waiting is either interrupted or timeouts, and the owner releases
     * the lock before the forementioned thread updates the entry count.
     *
     * The 0 entry_count value is encoded as ENTRY_COUNT_ZERO, positive numbers being
     * greater than it and negative numbers smaller than it.
     */
    guint32 status;            /* entry_count (16) | owner_id (16) */
    guint32 nest;
#ifdef HAVE_MOVING_COLLECTOR
    gint32 hash_code;
#endif
    GSList *wait_list;
    void *data;
    MonoCoopSem *entry_sem;
};
 
/*
 * Lock word format:
 *
 * The least significant bit stores whether a hash for the object is computed
 * which is stored either in the lock word or in the MonoThreadsSync structure
 * that the lock word points to.
 *
 * The second bit stores whether the lock word is inflated, containing an
 * address to the MonoThreadsSync structure.
 *
 * If both bits are 0, either the lock word is free (entire lock word is 0)
 * or it is a thin/flat lock.
 *
 * 32-bit
 *            LOCK_WORD_FLAT:    [owner:22 | nest:8 | status:2]
 *       LOCK_WORD_THIN_HASH:    [hash:30 | status:2]
 *        LOCK_WORD_INFLATED:    [sync:30 | status:2]
 *        LOCK_WORD_FAT_HASH:    [sync:30 | status:2]
 *
 * 64-bit
 *            LOCK_WORD_FLAT:    [unused:22 | owner:32 | nest:8 | status:2]
 *       LOCK_WORD_THIN_HASH:    [hash:62 | status:2]
 *        LOCK_WORD_INFLATED:    [sync:62 | status:2]
 *        LOCK_WORD_FAT_HASH:    [sync:62 | status:2]
 *
 * In order to save processing time and to have one additional value, the nest
 * count starts from 0 for the lock word (just valid thread ID in the lock word
 * means that the thread holds the lock once, although nest is 0).
 * FIXME Have the same convention on inflated locks
 */
 
typedef union {
#if SIZEOF_REGISTER == 8
    guint64 lock_word;
#elif SIZEOF_REGISTER == 4
    guint32 lock_word;
#endif
    MonoThreadsSync *sync;
} LockWord;
 
 
enum {
    LOCK_WORD_FLAT = 0,
    LOCK_WORD_HAS_HASH = 1,
    LOCK_WORD_INFLATED = 2,
 
    LOCK_WORD_STATUS_BITS = 2,
    LOCK_WORD_NEST_BITS = 8,
 
    LOCK_WORD_STATUS_MASK = (1 << LOCK_WORD_STATUS_BITS) - 1,
    LOCK_WORD_NEST_MASK = ((1 << LOCK_WORD_NEST_BITS) - 1) << LOCK_WORD_STATUS_BITS,
 
    LOCK_WORD_HASH_SHIFT = LOCK_WORD_STATUS_BITS,
    LOCK_WORD_NEST_SHIFT = LOCK_WORD_STATUS_BITS,
    LOCK_WORD_OWNER_SHIFT = LOCK_WORD_STATUS_BITS + LOCK_WORD_NEST_BITS
};
 
MONO_API void mono_locks_dump (gboolean include_untaken);
 
void mono_monitor_init (void);
void mono_monitor_cleanup (void);
 
MonoBoolean mono_monitor_enter_internal (MonoObject *obj);
void mono_monitor_enter_v4_internal (MonoObject *obj, MonoBoolean *lock_taken);
 
guint32 mono_monitor_enter_fast (MonoObject *obj);
guint32 mono_monitor_enter_v4_fast (MonoObject *obj, MonoBoolean *lock_taken);
 
guint32 mono_monitor_get_object_monitor_gchandle (MonoObject *object);
 
void mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset);
#define MONO_THREADS_SYNC_MEMBER_OFFSET(o)    ((o)>>8)
#define MONO_THREADS_SYNC_MEMBER_SIZE(o)    ((o)&0xff)
 
extern MonoBoolean ves_icall_System_Threading_Monitor_Monitor_test_owner(MonoObject *obj);
extern MonoBoolean ves_icall_System_Threading_Monitor_Monitor_test_synchronised(MonoObject *obj);
extern void ves_icall_System_Threading_Monitor_Monitor_pulse(MonoObject *obj);
extern void ves_icall_System_Threading_Monitor_Monitor_pulse_all(MonoObject *obj);
extern MonoBoolean ves_icall_System_Threading_Monitor_Monitor_wait(MonoObject *obj, guint32 ms);
extern void ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject *obj, guint32 ms, MonoBoolean *lockTaken);
extern void ves_icall_System_Threading_Monitor_Monitor_Enter (MonoObject *obj);
G_END_DECLS
 
#endif /* _MONO_METADATA_MONITOR_H_ */