summaryrefslogtreecommitdiff
path: root/kern/sync_asm.S
blob: 87fe7c6e8793b4ff792ca9ada404a580a7296418 (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
76
77
78
79
80
81
82
83
84
85
86
87
88
/** @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:
    push %ebx
    pushf
    pop %ebx
    cli
    mov 0x8(%esp), %ecx
    mov $1, %edx
.spl_lock_try:
    mov (%ecx), %eax
    test %eax, %eax
    jnz .spl_lock_try
    lock cmpxchg %edx, (%ecx)
    test %eax, %eax
    jnz .spl_lock_try
    mov %ebx, %eax
    pop %ebx
    ret

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

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