Moves resource requests to procdata (XCC)
[akaros.git] / kern / include / kthread.h
1 /* Copyright (c) 2010 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Kernel threading.  These are for blocking within the kernel for whatever
6  * reason, usually during blocking IO operations.  Check out
7  * Documentation/kthreads.txt for more info than you care about. */
8
9 #ifndef ROS_KERN_KTHREAD_H
10 #define ROS_KERN_KTHREAD_H
11
12 #include <ros/common.h>
13 #include <trap.h>
14 #include <sys/queue.h>
15 #include <atomic.h>
16
17 struct proc;
18 struct kthread;
19 TAILQ_HEAD(kthread_tailq, kthread);
20
21 /* This captures the essence of a kernel context that we want to suspend.  When
22  * a kthread is running, we make sure its stacktop is the default kernel stack,
23  * meaning it will receive the interrupts from userspace. */
24 struct kthread {
25         struct trapframe                        context;
26         uintptr_t                                       stacktop;
27         struct proc                                     *proc;
28         struct syscall                          *sysc;
29         TAILQ_ENTRY(kthread)            link;
30         /* ID, other shit, etc */
31 };
32
33 /* Semaphore for kthreads to sleep on.  0 or less means you need to sleep */
34 struct semaphore {
35         struct kthread_tailq            waiters;
36         int                                             nr_signals;
37         spinlock_t                                      lock;
38 };
39
40 /* This doesn't have to be inline, but it doesn't matter for now */
41 static inline void init_sem(struct semaphore *sem, int signals)
42 {
43         TAILQ_INIT(&sem->waiters);
44         sem->nr_signals = signals;
45         spinlock_init(&sem->lock);
46 }
47
48 /* Down and up for the semaphore are a little more low-level than usual, since
49  * they are meant to be called by functions that manage the sleeping of a
50  * kthread.  For instance, __down_sem() always returns right away.  For now,
51  * these are just examples, since the actual usage will probably need lower
52  * access. */
53
54 /* Down : decrement, if it was 0 or less, we need to sleep.  Returns false if
55  * the kthread did not need to sleep (the signal was already there). */
56 static inline bool __down_sem(struct semaphore *sem, struct kthread *kthread)
57 {
58         bool retval = FALSE;
59         spin_lock(&sem->lock);
60         if (sem->nr_signals-- <= 0) {
61                 /* Need to sleep */
62                 retval = TRUE;
63                 TAILQ_INSERT_TAIL(&sem->waiters, kthread, link);
64         }
65         spin_unlock(&sem->lock);
66         return retval;
67 }
68
69 /* Ups the semaphore.  If it was < 0, we need to wake up someone, which is the
70  * return value.  If you think there should be at most one, set exactly_one. */
71 static inline struct kthread *__up_sem(struct semaphore *sem, bool exactly_one)
72 {
73         struct kthread *kthread = 0;
74         spin_lock(&sem->lock);
75         if (sem->nr_signals++ < 0) {
76                 /* could do something with 'priority' here */
77                 kthread = TAILQ_FIRST(&sem->waiters);
78                 TAILQ_REMOVE(&sem->waiters, kthread, link);
79                 if (exactly_one)
80                         assert(TAILQ_EMPTY(&sem->waiters));
81         } else {
82                 assert(TAILQ_EMPTY(&sem->waiters));
83         }
84         spin_unlock(&sem->lock);
85         return kthread;
86 }
87
88 void kthread_init(void);
89 void sleep_on(struct semaphore *sem);
90 void restart_kthread(struct kthread *kthread);
91 void kthread_runnable(struct kthread *kthread);
92 /* Kmsg handler to launch/run a kthread.  This must be a routine message, since
93  * it does not return. */
94 void __launch_kthread(struct trapframe *tf, uint32_t srcid, long a0, long a1,
95                           long a2);
96
97 #endif /* ROS_KERN_KTHREAD_H */