]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/sched.c
Update bcachefs sources to 3610542890 bcachefs: Convert to skcipher interface for...
[bcachefs-tools-debian] / linux / sched.c
1
2 #include <string.h>
3
4 #include <linux/math64.h>
5 #include <linux/printk.h>
6 #include <linux/rcupdate.h>
7 #include <linux/sched.h>
8 #include <linux/timer.h>
9
10 __thread struct task_struct *current;
11
12 void __put_task_struct(struct task_struct *t)
13 {
14         pthread_join(t->thread, NULL);
15         free(t);
16 }
17
18 /* returns true if process was woken up, false if it was already running */
19 int wake_up_process(struct task_struct *p)
20 {
21         int ret;
22
23         pthread_mutex_lock(&p->lock);
24         ret = p->state != TASK_RUNNING;
25         p->state = TASK_RUNNING;
26
27         pthread_cond_signal(&p->wait);
28         pthread_mutex_unlock(&p->lock);
29
30         return ret;
31 }
32
33 void schedule(void)
34 {
35         rcu_quiescent_state();
36
37         pthread_mutex_lock(&current->lock);
38
39         while (current->state != TASK_RUNNING)
40                 pthread_cond_wait(&current->wait, &current->lock);
41
42         pthread_mutex_unlock(&current->lock);
43 }
44
45 static void process_timeout(unsigned long __data)
46 {
47         wake_up_process((struct task_struct *)__data);
48 }
49
50 long schedule_timeout(long timeout)
51 {
52         struct timer_list timer;
53         unsigned long expire;
54
55         switch (timeout)
56         {
57         case MAX_SCHEDULE_TIMEOUT:
58                 /*
59                  * These two special cases are useful to be comfortable
60                  * in the caller. Nothing more. We could take
61                  * MAX_SCHEDULE_TIMEOUT from one of the negative value
62                  * but I' d like to return a valid offset (>=0) to allow
63                  * the caller to do everything it want with the retval.
64                  */
65                 schedule();
66                 goto out;
67         default:
68                 /*
69                  * Another bit of PARANOID. Note that the retval will be
70                  * 0 since no piece of kernel is supposed to do a check
71                  * for a negative retval of schedule_timeout() (since it
72                  * should never happens anyway). You just have the printk()
73                  * that will tell you if something is gone wrong and where.
74                  */
75                 if (timeout < 0) {
76                         printk(KERN_ERR "schedule_timeout: wrong timeout "
77                                 "value %lx\n", timeout);
78                         current->state = TASK_RUNNING;
79                         goto out;
80                 }
81         }
82
83         expire = timeout + jiffies;
84
85         setup_timer(&timer, process_timeout, (unsigned long)current);
86         mod_timer(&timer, expire);
87         schedule();
88         del_timer_sync(&timer);
89
90         timeout = expire - jiffies;
91 out:
92         return timeout < 0 ? 0 : timeout;
93 }
94
95 unsigned long __msecs_to_jiffies(const unsigned int m)
96 {
97         /*
98          * Negative value, means infinite timeout:
99          */
100         if ((int)m < 0)
101                 return MAX_JIFFY_OFFSET;
102         return _msecs_to_jiffies(m);
103 }
104
105 u64 nsecs_to_jiffies64(u64 n)
106 {
107 #if (NSEC_PER_SEC % HZ) == 0
108         /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
109         return div_u64(n, NSEC_PER_SEC / HZ);
110 #elif (HZ % 512) == 0
111         /* overflow after 292 years if HZ = 1024 */
112         return div_u64(n * HZ / 512, NSEC_PER_SEC / 512);
113 #else
114         /*
115          * Generic case - optimized for cases where HZ is a multiple of 3.
116          * overflow after 64.99 years, exact for HZ = 60, 72, 90, 120 etc.
117          */
118         return div_u64(n * 9, (9ull * NSEC_PER_SEC + HZ / 2) / HZ);
119 #endif
120 }
121
122 unsigned long nsecs_to_jiffies(u64 n)
123 {
124         return (unsigned long)nsecs_to_jiffies64(n);
125 }
126
127 unsigned int jiffies_to_msecs(const unsigned long j)
128 {
129 #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
130         return (MSEC_PER_SEC / HZ) * j;
131 #elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
132         return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
133 #else
134 # if BITS_PER_LONG == 32
135         return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32;
136 # else
137         return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN;
138 # endif
139 #endif
140 }
141
142 unsigned int jiffies_to_usecs(const unsigned long j)
143 {
144         /*
145          * Hz usually doesn't go much further MSEC_PER_SEC.
146          * jiffies_to_usecs() and usecs_to_jiffies() depend on that.
147          */
148         BUILD_BUG_ON(HZ > USEC_PER_SEC);
149
150 #if !(USEC_PER_SEC % HZ)
151         return (USEC_PER_SEC / HZ) * j;
152 #else
153 # if BITS_PER_LONG == 32
154         return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32;
155 # else
156         return (j * HZ_TO_USEC_NUM) / HZ_TO_USEC_DEN;
157 # endif
158 #endif
159 }
160
161 __attribute__((constructor(101)))
162 static void sched_init(void)
163 {
164         struct task_struct *p = malloc(sizeof(*p));
165
166         memset(p, 0, sizeof(*p));
167
168         p->state        = TASK_RUNNING;
169         pthread_mutex_init(&p->lock, NULL);
170         pthread_cond_init(&p->wait, NULL);
171         atomic_set(&p->usage, 1);
172         init_completion(&p->exited);
173
174         current = p;
175
176         rcu_init();
177         rcu_register_thread();
178 }