summaryrefslogtreecommitdiff
path: root/kern/inc/sync.h
blob: 9bc53c81693568860047cc7b6a72a88557046789 (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/** @file sync.h
 *
 *  @brief locks.
 *
 *  @author Hanjie Wu (hanjiew)
 *  @bug No functional bugs
 */

#ifndef _SYNC_H_
#define _SYNC_H_

#include <common.h>

/** declaration of thread control block */
struct thread_s;
/** declaration of thread control block */
typedef struct thread_s thread_t;

/**
 * @brief save eflags and disable interrupt
 * @return eflags
 */
int save_clear_if();
/**
 * @brief restore eflags
 * @param old_if eflags
 */
void restore_if(int old_if);

/** spinlock structure, only needed for SMP */
typedef struct spl_s {
    int locked;
} spl_t;

/** initial value for spinlock */
#define SPL_INIT (spl_t){.locked = 0};

/**
 * @brief lock the spinlock and disable interrupts
 * @return original eflags
 */
int spl_lock(spl_t* spl);
/**
 * @brief unlock the spinlock and restore eflags
 * @param old_if eflags
 */
void spl_unlock(spl_t* spl, int old_if);

/**
 * @brief atomically yield to another thread and unlock the spinlock, eflags
 * will be restored when current thread become running again
 * @param t thread to yield to
 * @param spl spinlock
 * @param old_if eflags
 */
void yield_to_spl_unlock(thread_t* t, spl_t* spl, int old_if);

/** mutex structure */
typedef struct mutex_s {
    spl_t guard;
    int locked;
    queue_t* waiters;
} mutex_t;

/** initial value for mutex */
#define MUTEX_INIT \
    (mutex_t){.guard = {.locked = 0}, .locked = 0, .waiters = NULL};

/**
 * @brief lock the mutex, will be blocked if lock is held by other thread
 * @param m mutex
 */
void mutex_lock(mutex_t* m);
/**
 * @brief unlock the mutex, will wake up one blocked thread if there is one
 * @param m mutex
 */
void mutex_unlock(mutex_t* m);

/** cv structure */
typedef struct cv_s {
    spl_t guard;
    queue_t* waiters;
} cv_t;

/** initial value for cv */
#define CV_INIT \
    (cv_t) { .guard = {.locked = 0}, .waiters = NULL }

/**
 * @brief unlock the mutex m and wait for other threads to call cv_signal on cv
 * @param cv cv
 * @param m mutex
 */
void cv_wait(cv_t* cv, mutex_t* m);
/**
 * @brief signal a cv, will wake up one blocked thread if there is one
 * @param cv cv
 */
void cv_signal(cv_t* cv);

#endif