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