1 #include <common/mutex.h>
2 #include <mm/slab.h>
3 #include <sched/sched.h>
4 
5 /**
6  * @brief 初始化互斥量
7  *
8  * @param lock mutex结构体
9  */
mutex_init(mutex_t * lock)10 void mutex_init(mutex_t *lock)
11 {
12     atomic_set(&lock->count, 1);
13     spin_init(&lock->wait_lock);
14     list_init(&lock->wait_list);
15 }
16 
__mutex_sleep()17 static void __mutex_sleep()
18 {
19     current_pcb->state = PROC_UNINTERRUPTIBLE;
20     current_pcb->flags |= PF_NEED_SCHED;
21     sched();
22 }
23 
__mutex_acquire(mutex_t * lock)24 static void __mutex_acquire(mutex_t *lock)
25 {
26 }
27 /**
28  * @brief 对互斥量加锁
29  *
30  * @param lock mutex结构体
31  */
mutex_lock(mutex_t * lock)32 void mutex_lock(mutex_t *lock)
33 {
34     bool lock_ok = 0;
35 
36     while (lock_ok == false)
37     {
38         spin_lock(&lock->wait_lock);
39         if (likely(mutex_is_locked(lock)))
40         {
41             struct mutex_waiter_t *waiter = (struct mutex_waiter_t *)kzalloc(sizeof(struct mutex_waiter_t), 0);
42             if (waiter == NULL)
43             {
44                 kerror("In mutex_lock: no memory to alloc waiter. Program's behaviour might be indetermined!");
45                 spin_unlock(&lock->wait_lock);
46                 return;
47             }
48             // memset(waiter, 0, sizeof(struct mutex_waiter_t));
49             waiter->pcb = current_pcb;
50             list_init(&waiter->list);
51             list_append(&lock->wait_list, &waiter->list);
52 
53             spin_unlock(&lock->wait_lock);
54 
55             __mutex_sleep();
56         }
57         else
58         {
59             atomic_dec(&lock->count);
60             spin_unlock(&lock->wait_lock);
61             lock_ok = true;
62         }
63     }
64 }
65 
66 /**
67  * @brief 对互斥量解锁
68  *
69  * @param lock mutex结构体
70  */
mutex_unlock(mutex_t * lock)71 void mutex_unlock(mutex_t *lock)
72 {
73     if (unlikely(!mutex_is_locked(lock)))
74         return;
75 
76     spin_lock(&lock->wait_lock);
77     struct mutex_waiter_t *wt = NULL;
78     if (mutex_is_locked(lock))
79     {
80         if (!list_empty(&lock->wait_list))
81             wt = container_of(list_next(&lock->wait_list), struct mutex_waiter_t, list);
82 
83         atomic_inc(&lock->count);
84         if (wt != NULL)
85             list_del(&wt->list);
86     }
87 
88     spin_unlock(&lock->wait_lock);
89 
90     if (wt != NULL)
91     {
92         process_wakeup(wt->pcb);
93         kfree(wt);
94     }
95 }
96 
97 /**
98  * @brief 尝试对互斥量加锁
99  *
100  * @param lock mutex结构体
101  *
102  * @return 成功加锁->1, 加锁失败->0
103  */
mutex_trylock(mutex_t * lock)104 int mutex_trylock(mutex_t *lock)
105 {
106     if (mutex_is_locked(lock))
107         return 0;
108 
109     spin_lock(&lock->wait_lock);
110     if (mutex_is_locked(lock))
111     {
112         spin_unlock(&lock->wait_lock);
113         return 0;
114     }
115     else
116     {
117         atomic_dec(&lock->count);
118         spin_unlock(&lock->wait_lock);
119         return 1;
120     }
121 }