Addition of c3po library, including revamp of Make system for user libraries.
[akaros.git] / user / c3po / threads / threadlib.h
1
2 #ifndef THREADLIB_H
3 #define THREADLIB_H
4
5 #include "pthread.h"
6 #include "resource_stats.h"
7 #include <time.h>
8 #include <signal.h>
9
10 #define likely(x)   __builtin_expect(!!(x),1)
11 #define unlikely(x) __builtin_expect(!!(x),0)
12
13 struct thread_st;
14 typedef struct thread_st thread_t;
15
16 typedef enum {
17   UNLOCKED = 0,
18   LOCKED   = 1,
19 } lock_state_t;
20
21 typedef struct latch_st {
22   thread_t *state;
23 } latch_t;
24
25 // Queue used for mutex implementation
26 typedef struct queue_st {
27   void **data;   /* allocated data */
28   int size;  /* allocated size */
29   int head, tail;   /* valid data in [head, tail) */
30 } queue_t;
31
32 typedef struct {
33   latch_t latch;
34   lock_state_t state;
35   int count;   // for recursive locking
36   char *name;
37   queue_t wait_queue;
38   thread_t *owner;   // for sanity checking in thread_mutex_unlock()
39 } mutex_t;
40
41 // the read-write lock structure
42 typedef struct rwlock_st { /* not hidden to avoid destructor */
43   int            rw_state;
44   unsigned int   rw_mode;
45   unsigned long  rw_readers;
46   mutex_t    rw_mutex_rd;
47   mutex_t    rw_mutex_rw;
48 } rwlock_t;
49
50 // the condition variable structure
51 typedef struct cond_st { /* not hidden to avoid destructor */
52   unsigned long cn_state;
53   unsigned int  cn_waiters;
54   queue_t wait_queue;
55 } cond_t;
56
57
58 // All thread attributes
59 enum {
60   THREAD_ATTR_JOINABLE = 1,
61   THREAD_ATTR_NAME,  // Not implemented
62   THREAD_ATTR_PRIO   // Not implemented
63 };
64
65 // Thread joinable attribute
66 enum {
67   THREAD_CREATE_DETACHED = 0,
68   THREAD_CREATE_JOINABLE = 1
69 };
70
71 enum {
72         OK = 0,
73         TIMEDOUT = 1,
74         INTERRUPTED = 2,
75 };
76
77 typedef struct _thread_attr *thread_attr_t;
78
79 void thread_exit(void *ret);
80 void thread_exit_program(int exitcode);
81 void thread_yield();
82 thread_t *thread_spawn(char *name, void* (*func)(void *), void *arg);
83 thread_t *thread_spawn_with_attr(char *name, void* (*func)(void *), 
84                             void *arg, thread_attr_t attr);  // added for pthread layer
85 // suspend the thread, optionally for a limited period of time (timeout)
86 // timeout == 0 -> suspend infinitely unless resumed by another thread
87 // return value: OK if resumed by someone else, TIMEDOUT is timedout
88 //               INTERRUPTED is interrupted by a signal
89 int thread_suspend_self(unsigned long long timeout);
90
91 // resume is made idempotent - resuming an already runnable thread does nothing
92 void thread_resume(thread_t* t);
93 inline char* thread_name(thread_t *t);
94 int thread_join(thread_t *t, void **val);
95 void thread_set_daemon(thread_t *t);
96
97 extern thread_t *current_thread;
98 static inline thread_t* thread_self() { return current_thread; }
99
100 // Key-based thread specific storage
101 typedef int thread_key_t;
102 #define THREAD_DESTRUCTOR_ITERATIONS 4
103 #define THREAD_KEY_MAX 256  // NOTE: change the size of thread_t.data_count if you change this!
104 int thread_key_create(thread_key_t *key, void (*destructor)(void *));
105 int thread_key_delete(thread_key_t key);
106 int thread_key_setdata(thread_key_t key, const void *value);
107 void *thread_key_getdata(thread_key_t key);
108
109 void thread_usleep(unsigned long long timeout);
110
111 // Mutex - return TRUE on success
112 inline int thread_mutex_init(mutex_t *m, char *name);
113 inline int thread_mutex_lock(mutex_t *m);
114 inline int thread_mutex_trylock(mutex_t *m);    // do not block, return FALSE when mutex held but others
115 inline int thread_mutex_unlock(mutex_t *m);
116
117 // Rwlocks
118 enum rwlock_op {
119   RWLOCK_RD = 1,
120   RWLOCK_RW
121 };
122
123 int thread_rwlock_init(rwlock_t *l);
124 int thread_rwlock_lock(rwlock_t *l, int op);
125 int thread_rwlock_trylock(rwlock_t *l, int op);
126 int thread_rwlock_unlock(rwlock_t *l);
127
128 // Condition variables
129 int thread_cond_init(cond_t *c);
130 int thread_cond_wait(cond_t *c, mutex_t *m);
131 int thread_cond_timedwait(cond_t *c, mutex_t *m, const struct timespec *timeout);
132 int thread_cond_signal(cond_t *c);
133 int thread_cond_broadcast(cond_t *c);
134
135 // attribute
136 thread_attr_t thread_attr_of(thread_t *t);
137 thread_attr_t thread_attr_new();
138 int thread_attr_init(thread_attr_t attr);
139 int thread_attr_set(thread_attr_t attr, int field, ...);
140 int thread_attr_get(thread_attr_t attr, int field, ...);
141 int thread_attr_destroy(thread_attr_t attr);
142
143 unsigned thread_tid(thread_t *t);
144
145 int thread_kill(thread_t* t, int sig);
146 int thread_kill_all(int sig);
147 int thread_sigwait(const sigset_t *set, int *sig);
148
149 extern inline void thread_stats_add_heap(long size);
150 extern inline void thread_stats_add_fds(int num);
151
152
153 typedef struct {
154   long active;
155   long long requests;
156   long long completions;
157   long long bytes_read;
158   long long bytes_written;
159   long long errors;
160 } iostats_t;
161
162 extern iostats_t sockio_stats;
163 extern iostats_t diskio_stats;
164
165 #define IOSTAT_START(type) {\
166   type##_stats.active++; \
167   type##_stats.requests++; \
168 }
169 #define IOSTAT_DONE(type, success) {\
170   type##_stats.active--; \
171   if( (success) ) type##_stats.completions++; \
172   else            type##_stats.errors++; \
173 }
174
175 extern int cap_override_rw;
176
177
178 extern const char *cap_current_syscall;  // used to inform the BG routines how they got there...
179 #define CAP_SET_SYSCALL()   if(!cap_current_syscall) cap_current_syscall = __FUNCTION__
180 #define CAP_CLEAR_SYSCALL() (cap_current_syscall = NULL)
181
182 extern void set_io_polling_func( void (*func)(long long) );
183
184 // latches
185
186 // FIXME: if there is a single kernel thread, it is an error if the latch is already locked 
187 // FIXME: need a spinlock, test&set, futex, etc. for multiple kernel threads 
188 #define LATCH_UNLOCKED NULL
189 #define LATCH_UNKNOWN ((thread_t*)-1)
190 #if OPTIMIZE < 2
191 #define thread_latch(latch) \
192 do {\
193   assert(latch.state == LATCH_UNLOCKED); \
194   latch.state = thread_self() ? thread_self() : LATCH_UNKNOWN; \
195 } while(0)
196 #else
197 #define thread_latch(latch) do { } while(0)
198 #endif
199  
200 #if OPTIMIZE < 2
201 #define thread_unlatch(latch) \
202 do { \
203   assert(latch.state != LATCH_UNLOCKED); \
204   latch.state = UNLOCKED; \
205 } while(0)
206 #else
207 #define thread_unlatch(latch) do { (void)(latch);} while(0)
208 #endif
209
210 #if OPTIMIZE < 2
211 #define thread_latch_init(latch) \
212 do { \
213   latch.state = LATCH_UNLOCKED; \
214 } while(0)
215 #else
216 #define thread_latch_init(latch) do {(void)(latch);} while(0)
217 #endif
218
219 #define LATCH_INITIALIZER_UNLOCKED ((latch_t) { LATCH_UNLOCKED })
220 #define LATCH_INITIALIZER_LOCKED   ((latch_t) { LATCH_UNKNOWN })
221
222 #endif /* THREADLIB_H */
223
224
225