tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / us_manager / callbacks.c
1 #include <linux/mutex.h>
2 #include <linux/list.h>
3 #include <linux/slab.h>
4 #include <linux/module.h>
5 #include "callbacks.h"
6
7 static LIST_HEAD(cbs_list);
8 static DEFINE_MUTEX(cbs_mutex);
9 static int cur_handle = 0;
10
11 struct cb_item {
12         struct list_head list;
13         enum callback_t type;
14         int handle;
15         void (*func)(void);
16 };
17
18 static inline void __lock_cbs_list(void)
19 {
20         mutex_lock(&cbs_mutex);
21 }
22
23 static inline void __unlock_cbs_list(void)
24 {
25         mutex_unlock(&cbs_mutex);
26 }
27
28 static inline int __get_new_handle(void)
29 {
30         return cur_handle++;
31 }
32
33 static inline void __free_cb(struct cb_item *cb)
34 {
35         list_del(&cb->list);
36         kfree(cb);
37 }
38
39 static struct cb_item *__get_cb_by_handle(int handle)
40 {
41         struct cb_item *cb;
42
43         list_for_each_entry(cb, &cbs_list, list)
44                 if (cb->handle == handle)
45                         return cb;
46
47         return NULL;
48 }
49
50
51 /**
52  * @brief Executes callbacks on start/stop
53  *
54  * @param cbt Callback type
55  * @return Void
56  */
57 void exec_cbs(enum callback_t cbt)
58 {
59         struct cb_item *cb;
60
61         __lock_cbs_list();
62
63         list_for_each_entry(cb, &cbs_list, list)
64                 if (cb->type == cbt)
65                         cb->func();
66
67         __unlock_cbs_list();
68 }
69
70 /**
71  * @brief Removes all callbacks from list
72  *
73  * @return Void
74  */
75 void remove_all_cbs(void)
76 {
77         struct cb_item *cb, *n;
78
79         __lock_cbs_list();
80
81         list_for_each_entry_safe(cb, n, &cbs_list, list)
82                 __free_cb(cb);
83
84         __unlock_cbs_list();
85 }
86
87 /**
88  * @brief Registers callback on event
89  *
90  * @param cbt Callback type
91  * @param func Callback function
92  * @return Handle on succes, error code on error
93  */
94 int us_manager_reg_cb(enum callback_t cbt, void (*func)(void))
95 {
96         struct cb_item *cb;
97         int handle;
98
99         cb = kmalloc(sizeof(*cb), GFP_KERNEL);
100         if (cb == NULL)
101                 return -ENOMEM;
102
103         handle = __get_new_handle();
104
105         INIT_LIST_HEAD(&cb->list);
106         cb->type = cbt;
107         cb->handle = handle;
108         cb->func = func;
109
110         __lock_cbs_list();
111         list_add_tail(&cb->list, &cbs_list);
112         __unlock_cbs_list();
113
114         return handle;
115 }
116 EXPORT_SYMBOL_GPL(us_manager_reg_cb);
117
118 /**
119  * @brief Unegisters callback by handle
120  *
121  * @param handle Callback handle
122  * @return Void
123  */
124 void us_manager_unreg_cb(int handle)
125 {
126         struct cb_item *cb;
127
128         __lock_cbs_list();
129
130         cb = __get_cb_by_handle(handle);
131         if (cb == NULL)
132                 goto handle_not_found;
133
134         __free_cb(cb);
135
136 handle_not_found:
137         __unlock_cbs_list();
138 }
139 EXPORT_SYMBOL_GPL(us_manager_unreg_cb);