7b1c62f3ac8fedf654329cc9d21ef9246a0001b6
[akaros.git] / user / c3po / threads / threadlib_internal.h
1
2 #ifndef THREADLIB_INTERNAL_H
3 #define THREADLIB_INTERNAL_H
4
5 #include "threadlib.h"
6 #include "util.h"
7 #include "blocking_graph.h"
8 #include "signal.h"
9 #include "ucontext.h"
10 #ifdef USE_NIO
11 #include <libaio.h>
12 #endif
13
14 // provide a way to adjust the behavior when unimplemented function is called
15 #define notimplemented(x) output("WARNING: " #x " not implemented!\n")
16
17 // thread attributes
18 // This is a separate struct because pthread has API for users to initizalize
19 // pthread_attr_t structs before thread creation
20 struct _thread_attr {
21   thread_t *thread;    // != NULL when is bound to a thread
22
23   // Attributes below are valid only when thread == NULL
24   int joinable:1;
25   int daemon:1;
26
27   char *name;
28 };
29
30 #define THREAD_SIG_MAX 32
31
32 struct thread_st {
33   unsigned tid;   // thread id, mainly for readability of debug output
34   struct thread_st *self; // pointer to itself 
35   struct ucontext *context;
36   void *stack;
37   void *stack_bottom;
38   int stack_fingerprint;
39 //  int __errno;        // thread-local errno
40
41   // misc. short fields, grouped to save space
42   enum {
43         RUNNING=0,
44     RUNNABLE,
45     SUSPENDED,
46     ZOMBIE,          // not yet reaped, for joinable threads
47     GHOST            // already freed, no valid thread should be in this state
48   } state:3;
49
50   unsigned int joinable:1;
51   unsigned int key_data_count:8;  // big enough for THREAD_KEY_MAX
52   unsigned int timeout:1;         // whether it is waken up because of timeout
53   unsigned int sig_waiting:1;   // the thread is waiting for a signal (any not blocked in sig_mask). 
54                         // when it arrives, the thread should be waken up and 
55                         // the signal handler should *not* be called
56   short sig_num_received;       // number of signals in sigs_received
57
58 #ifdef USE_NIO
59   struct iocb iocb;        // aio control block
60   int ioret;               // i/o ret value, set by polling loop and used by wrapping functions
61   int iocount;             // number of I/O operations done without blocking, used to yield the processor when reached a fixed amount
62 #endif
63
64   // startup stuff
65   void* (*initial_func)(void *);
66   void *initial_arg;
67   char *name;
68   int stack_size_kb_log2;
69
70   const void **key_data_value;  // thread specific values
71
72   // stats for the blocking graph.
73   // FIXME: move curr_stats to global var, to save space here.  (only need one anyway)
74   thread_stats_t prev_stats;
75   thread_stats_t curr_stats;
76
77   // per-thread signals
78   // NOTE: external(global) signals are in corresponding global variable
79   sigset_t sig_received;        // per-thread received but unhandled signals
80   sigset_t sig_mask;            // masked signals for this thread
81
82   thread_t *join_thread;   // thread waiting for the completion of the thread
83   void *ret;               // return value, returned to user by thread_join()
84
85   long long sleep;         // relative time for this thread to sleep after the prev one in sleep queue
86                            // -1 means thread is not in the sleep queue
87 };
88
89
90 extern thread_t *current;
91 extern int in_scheduler;
92
93
94 // scheduler functions
95 #define DECLARE_SCHEDULER(s) \
96   extern void s##_init(void); \
97   extern void s##_add_thread(thread_t *t); \
98   extern thread_t* s##_next_thread(void); 
99
100 DECLARE_SCHEDULER(sched_global_rr);
101 DECLARE_SCHEDULER(sched_global_lifo);
102 DECLARE_SCHEDULER(sched_graph_rr);
103 DECLARE_SCHEDULER(sched_graph_rr_down);
104 DECLARE_SCHEDULER(sched_graph_batch);
105 DECLARE_SCHEDULER(sched_graph_highnum);
106 DECLARE_SCHEDULER(sched_graph_priority);
107
108 extern void sched_graph_generic_init(void);
109 extern void sched_graph_generic_add_thread(thread_t *t);
110
111 #define strong_alias(name, aliasname) extern __typeof (name) aliasname __attribute__ ((alias (#name)));
112 #define valid_thread(t) (t != NULL  &&  t != (thread_t*)-1)
113 #define thread_alive(t) ((t)->state == RUNNABLE || (t)->state == SUSPENDED)
114
115 // Internal constants
116
117 #define _BIT(n) (1<<(n))
118 #define THREAD_RWLOCK_INITIALIZED _BIT(0)
119
120 #define THREAD_COND_INITIALIZED _BIT(0)
121
122 #ifndef FALSE
123 #define FALSE (0)
124 #endif
125 #ifndef TRUE
126 #define TRUE (~FALSE)
127 #endif
128
129 #define return_errno(return_val,errno_val) \
130         do { errno = (errno_val); \
131              debug("return 0x%lx with errno %d(\"%s\")\n", \
132                         (unsigned long)(return_val), (errno), strerror((errno))); \
133              return (return_val); } while (0)
134
135 #define return_errno_unlatch(ret,err,latch) \
136 do { \
137   thread_unlatch(latch); \
138   errno = (err); \
139   debug("return 0x%lx with errno %d(\"%s\")\n", (unsigned long)(ret), (err), strerror((err))); \
140   return (ret); \
141 } while (0)
142
143
144 extern void dump_debug_info();
145 extern void dump_thread_state();
146
147 extern long long total_stack_in_use;
148
149 // process all pending signals.  returns 1 is any actually handled, 0 otherwise
150 extern int sig_process_pending();
151
152 #endif /* THREADLIB_INTERNAL_H */