1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #ifndef _MUTEX_H_
6 #define _MUTEX_H_
7
8 #include <pthread.h>
9
10 #include <drivers/bug.h>
11 #include <drivers/spinlock.h>
12 #include <drivers/ddkc_log.h>
13 #include <drivers/spinlock.h>
14
15 #define MUTEX_INIT_DONE_FLAG 0xACBDFDBC
16
17 /**
18 * DEFINE_MUTEX(x) will define a mutex,
19 * but the mutex cannot be initialized when the mutex is global variable
20 * we use flag to record whether mutex is initialized or not
21 * */
22 struct mutex {
23 unsigned int flag;
24 spinlock_t s;
25 pthread_mutex_t m;
26 };
27
28 #define DEFINE_MUTEX(mutexname) struct mutex mutexname = {.flag = 0}
29
30 #define __mutex_init(lock, name, key) mutex_init(lock)
31
32 #define mutex_lock_nested(lock, depth) mutex_lock(lock)
33
34 // TODO: need to re-implement mutex_lock_interruptible
35 #define mutex_lock_interruptible(lock) ({\
36 pr_warn("mutex_lock_interruptible is defined as mutex_lock\r\n");\
37 mutex_lock((lock)); \
38 0;})
39
mutex_init(struct mutex * lock)40 static inline void mutex_init(struct mutex *lock) {
41 int r = 0;
42
43 if (lock->flag == MUTEX_INIT_DONE_FLAG) {
44 ddkc_warn( "MUTEX:possible mutex reinit detected\r\n");
45 BUG_ON_MSG(1, "mutex reinit detected");
46 return;
47 }
48
49 spin_lock_init(&lock->s);
50 r = pthread_mutex_init(&lock->m, NULL);
51 if (!r) {
52 lock->flag = MUTEX_INIT_DONE_FLAG;
53 ddkc_loud("MUTEX:pthread_mutex_init %p success\r\n", lock);
54 return;
55 }
56
57 ddkc_err("MUTEX:pthread_mutex_init %p fails, r:%d\r\n", lock, r);
58
59 return;
60 }
mutex_lock(struct mutex * lock)61 static inline void mutex_lock(struct mutex *lock) {
62 int r = 0;
63
64 // TODO: how to guarantee mutex_init procedure is atomic operation?
65 if (lock->flag != MUTEX_INIT_DONE_FLAG) {
66 ddkc_loud("MUTEX:uninitialized mutex:%p detected, init it\r\n", lock);
67 mutex_init(lock);
68 }
69
70 r = pthread_mutex_lock(&lock->m);
71
72 if (!r) {
73 ddkc_loud("MUTEX:pthread_mutex_lock %p success\r\n", lock);
74 return;
75 }
76 ddkc_err("MUTEX:pthread_mutex_lock %p fails, r:%d\r\n", lock, r);
77
78 return;
79 }
80
mutex_trylock(struct mutex * lock)81 static inline int mutex_trylock(struct mutex *lock) {
82 int r = 0;
83
84 if (lock->flag != MUTEX_INIT_DONE_FLAG) {
85 ddkc_loud("MUTEX:uninitialized mutex:%p detected, init it\r\n", lock);
86 mutex_init(lock);
87 }
88
89 r = pthread_mutex_trylock(&lock->m);
90
91 if (!r) {
92 ddkc_loud("MUTEX:pthread_mutex_trylock %p success\r\n", lock);
93 return 1;
94 }
95 ddkc_err("MUTEX:pthread_mutex_trylock fails, r:%d\r\n", r);
96
97 return 0;
98 }
99
mutex_unlock(struct mutex * lock)100 static inline void mutex_unlock(struct mutex *lock) {
101 int r = pthread_mutex_unlock(&lock->m);
102
103 if (!r) {
104 ddkc_loud("MUTEX:pthread_mutex_unlock %p success\r\n", lock);
105 return;
106 }
107 ddkc_err("MUTEX:pthread_mutex_unlock fails, r:%d\r\n", r);
108
109 return;
110 }
111
mutex_destroy(struct mutex * lock)112 static inline void mutex_destroy(struct mutex *lock) {
113 pthread_mutex_destroy(&lock->m);
114 lock->flag = ~MUTEX_INIT_DONE_FLAG;
115
116 }
117
118 #if 0
119 #define __MUTEX_INITIALIZER(lockname) \
120 { \
121 .blk_obj.blk_list.prev = &blk_obj.blk_list, \
122 .blk_obj.blk_list.next = &blk_obj.blk_list, \
123 .blk_obj.blk_policy = BLK_POLICY_PRI, \
124 .blk_obj.name = name, \
125 #if (RHINO_CONFIG_TASK_DEL > 0) \
126 .blk_obj.cancel = 0u, \
127 #endif \
128 .mutex_task = NULL, \
129 .mutex_list = NULL, \
130 .mm_alloc_flag = K_OBJ_STATIC_ALLOC, \
131 .blk_obj.obj_type = RHINO_MUTEX_OBJ_TYPE, \
132 }
133
134 #define DEFINE_MUTEX(mutexname) \
135 struct mutex_s mutexname = __MUTEX_INITIALIZER(mutexname)
136 #endif
137
138 #endif //_MUTEX_H_
139