summaryrefslogtreecommitdiff
path: root/kern/sync_asm.S
blob: b3fc8529ccbe48bdd2e8a2ce019daa82814dfaa2 (plain)
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
/** @file sync_asm.S
 *
 *  @brief locks.
 *
 *  @author Hanjie Wu (hanjiew)
 *  @bug No functional bugs
 */

.text

#define EFL_IF 0x00000200

.global save_clear_if
.type save_clear_if, %function
save_clear_if:
    pushf
    pop %eax
    cli
    ret

.global restore_if
.type restore_if, %function
restore_if:
    mov 0x4(%esp), %eax
    push %eax
    popf
    ret

.global spl_lock
.type spl_lock, %function
spl_lock:
    pushf
    pop %edx
    cli
    mov 0x4(%esp), %esi
    mov $1, %edi
.spl_lock_try:
    xor %eax, %eax
    lock cmpxchg %edi, (%esi)
    test %eax, %eax
    jnz .spl_lock_try
    mov %edx, %eax
    ret

.global spl_unlock
.type spl_unlock, %function
spl_unlock:
    mov 0x8(%esp), %eax
    mov 0x4(%esp), %esi
    xor %edx, %edx
    mov %edx, (%esi)
    push %eax
    popf
    ret

.global yield_to_spl_unlock
.type yield_to_spl_unlock, %function
yield_to_spl_unlock:
    mov 0xc(%esp), %edi
    mov 0x8(%esp), %esi
    mov 0x4(%esp), %eax
    push %edi /* old_if, will be restored when switching back */
    push %ebx
    push %ebp
    mov %esi, %ebx
    push %esp
    push %eax
    call save_and_setup_env
    mov %eax, %esp
    xor %eax, %eax
    mov %eax, (%ebx)
    pop %ebp
    pop %ebx
    popf
    ret