2 #include <ddekit/assert.h>
3 #include <ddekit/condvar.h>
4 #include <ddekit/memory.h>
5 #include <ddekit/panic.h>
6 #include <ddekit/timer.h>
8 #ifdef DDEBUG_LEVEL_THREAD
10 #define DDEBUG DDEBUG_LEVEL_THREAD
19 /* Incremented to generate unique thread IDs */
22 static ddekit_thread_t
*ready_queue
[DDEKIT_THREAD_PRIOS
];
24 static ddekit_thread_t
*sleep_queue
;
26 /* Handle to the running thread, set in _dde_kit_thread_schedule() */
27 static ddekit_thread_t
*current
= NULL
;
29 static void _ddekit_thread_start(ddekit_thread_t
*th
);
30 static void _ddekit_thread_sleep(unsigned long until
);
32 /*****************************************************************************
33 * _ddekit_thread_start *
34 ****************************************************************************/
35 static void _ddekit_thread_start(ddekit_thread_t
*th
)
37 /* entry point of newly created threads */
42 /*****************************************************************************
43 * _ddekit_thread_sleep *
44 ****************************************************************************/
45 static void _ddekit_thread_sleep(unsigned long until
)
47 current
->next
= sleep_queue
;
48 sleep_queue
= current
;
49 current
->sleep_until
= until
;
50 _ddekit_thread_schedule();
54 /*****************************************************************************
55 * DDEKIT public thread API (ddekit/thread.h) *
56 ****************************************************************************/
58 /*****************************************************************************
60 ****************************************************************************/
63 ddekit_thread_schedule();
66 /*****************************************************************************
67 * ddekit_thread_schedule *
68 ****************************************************************************/
69 void ddekit_thread_schedule()
71 _ddekit_thread_enqueue(current
);
72 _ddekit_thread_schedule();
75 /*****************************************************************************
76 * ddekit_thread_create *
77 ****************************************************************************/
79 ddekit_thread_create(void (*fun
)(void *), void *arg
, const char *name
)
82 (ddekit_thread_t
*) ddekit_simple_malloc(sizeof(ddekit_thread_t
));
84 strncpy(th
->name
, name
, DDEKIT_THREAD_NAMELEN
);
85 th
->name
[DDEKIT_THREAD_NAMELEN
-1] = 0;
87 th
->stack
= ddekit_large_malloc(DDEKIT_THREAD_STACKSIZE
);
93 th
->prio
= DDEKIT_THREAD_STDPRIO
;
95 th
->sleep_sem
= ddekit_sem_init(0);
100 void **ptr
= (void **)(th
->stack
+ DDEKIT_THREAD_STACKSIZE
);
105 /* TAKEN FROM P_THREAD (written by david?)*/
107 th
->jb
[0].__pc
= _ddekit_thread_start
;
108 th
->jb
[0].__sp
= ptr
;
110 #include <sys/jmp_buf.h>
111 #if defined(JB_PC) && defined(JB_SP)
114 *((void (**)(void))(&((char *)th
->jb
)[JB_PC
])) =
115 (void *)_ddekit_thread_start
;
117 *((void **)(&((char *)th
->jb
)[JB_SP
])) = ptr
;
119 #error "Unsupported Minix architecture"
121 #endif /* !__ACK__ */
123 DDEBUG_MSG_VERBOSE("created thread %s, stack at: %p\n", name
,
124 th
->stack
+ DDEKIT_THREAD_STACKSIZE
);
125 _ddekit_thread_enqueue(th
);
130 /*****************************************************************************
131 * ddekit_thread_get_data *
132 ****************************************************************************/
133 void *ddekit_thread_get_data(ddekit_thread_t
*thread
)
138 /*****************************************************************************
139 * ddekit_thread_get_my_data *
140 ****************************************************************************/
141 void *ddekit_thread_get_my_data(void)
143 return current
->data
;
146 /*****************************************************************************
147 * ddekit_thread_myself *
148 ****************************************************************************/
150 ddekit_thread_t
*ddekit_thread_myself(void)
155 /*****************************************************************************
156 * ddekit_thread_setup_myself *
157 ****************************************************************************/
159 ddekit_thread_t
*ddekit_thread_setup_myself(const char *name
) {
160 ddekit_thread_t
*th
=
161 (ddekit_thread_t
*) ddekit_simple_malloc(sizeof(ddekit_thread_t
));
163 strncpy(th
->name
, name
, DDEKIT_THREAD_NAMELEN
);
164 th
->name
[DDEKIT_THREAD_NAMELEN
-1] = 0;
168 th
->prio
= DDEKIT_THREAD_STDPRIO
;
169 th
->sleep_sem
= ddekit_sem_init(0);
171 _ddekit_print_backtrace(th
);
176 /*****************************************************************************
177 * ddekit_thread_set_data *
178 ****************************************************************************/
179 void ddekit_thread_set_data(ddekit_thread_t
*thread
, void *data
)
184 /*****************************************************************************
185 * ddekit_thread_set_my_data *
186 ****************************************************************************/
187 void ddekit_thread_set_my_data(void *data
)
189 current
->data
= data
;
192 /*****************************************************************************
193 * ddekit_thread_usleep *
194 ****************************************************************************/
195 void ddekit_thread_usleep(unsigned long usecs
)
198 * Cannot use usleep here, because it's implemented in vfs.
199 * Assuming the anyway no finder granularity than system's HZ value
200 * can be reached. So we use dde_kit_thread_msleep for now.
203 /* If no timeout is 0 return immediately */
207 unsigned long to
= usecs
/1000;
209 /* round up to to possible granularity */
214 ddekit_thread_msleep(to
);
217 /*****************************************************************************
218 * ddekit_thread_nsleep *
219 ****************************************************************************/
220 void ddekit_thread_nsleep(unsigned long nsecs
)
223 * Cannot use usleep here, because it's implemented in vfs.
224 * Assuming the anyway no finder granularity than system's HZ value
225 * can be reached. So we use dde_kit_thread_msleep.
228 /* If no timeout is 0 return immediately */
232 unsigned long to
= nsecs
/1000;
234 /* round up to to possible granularity */
239 ddekit_thread_usleep(to
);
242 /*****************************************************************************
243 * ddekit_thread_msleep *
244 ****************************************************************************/
245 void ddekit_thread_msleep(unsigned long msecs
)
249 to
= (msecs
*HZ
/1000);
255 ddekit_thread_t
*th
= ddekit_thread_myself();
258 ddekit_panic("th==NULL!");
261 if (th
->sleep_sem
== NULL
) {
262 ddekit_panic("th->sleepsem==NULL! %p %s ", th
, th
->name
);
265 /* generate a timer interrupt at to */
266 ddekit_add_timer(NULL
, NULL
, to
+jiffies
);
267 _ddekit_thread_sleep(to
+jiffies
);
270 /*****************************************************************************
271 * ddekit_thread_sleep *
272 ****************************************************************************/
273 void ddekit_thread_sleep(ddekit_lock_t
*lock
)
278 /*****************************************************************************
279 * ddekit_thread_exit *
280 ****************************************************************************/
281 void ddekit_thread_exit()
283 ddekit_sem_down(current
->sleep_sem
);
284 ddekit_panic("thread running after exit!\n");
289 /*****************************************************************************
290 * ddekit_thread_terminate *
291 ****************************************************************************/
292 void ddekit_thread_terminate(ddekit_thread_t
*thread
)
297 /*****************************************************************************
298 * ddekit_thread_get_name *
299 ****************************************************************************/
300 const char *ddekit_thread_get_name(ddekit_thread_t
*thread
)
305 /*****************************************************************************
306 * ddekit_thread_get_id *
307 ****************************************************************************/
308 int ddekit_thread_get_id(ddekit_thread_t
*thread
)
313 /*****************************************************************************
314 * ddekit_init_threads *
315 ****************************************************************************/
316 void ddekit_init_threads(void)
320 for (i
=0 ; i
< DDEKIT_THREAD_PRIOS
; i
++) {
321 ready_queue
[i
] = NULL
;
324 current
= ddekit_thread_setup_myself("main");
326 DDEBUG_MSG_INFO("ddekit thread subsystem initialized");
329 /*****************************************************************************
330 * DDEKIT internals (src/thread.h) *
331 *****************************************************************************/
333 /*****************************************************************************
334 * _ddekit_thread_schedule *
335 ****************************************************************************/
336 void _ddekit_thread_schedule()
339 DDEBUG_MSG_VERBOSE("called schedule id: %d name %s, prio: %d",
340 current
->id
, current
->name
, current
->prio
);
343 ddekit_thread_t
* th
= current
;
346 _ddekit_print_backtrace(th
);
349 /* save our context */
350 if (_setjmp(th
->jb
) == 0) {
354 /* find a runnable thread */
358 for (i
= DDEKIT_THREAD_PRIOS
-1; i
>= 0; i
--) {
359 if (ready_queue
[i
]!=NULL
) {
360 current
= ready_queue
[i
];
361 ready_queue
[i
] = current
->next
;
367 if (current
== NULL
) {
368 ddekit_panic("No runable threads?!");
371 DDEBUG_MSG_VERBOSE("switching to id: %d name %s, prio: %d",
372 current
->id
, current
->name
, current
->prio
);
374 _ddekit_print_backtrace(current
);
376 _longjmp(current
->jb
, 1);
381 /*****************************************************************************
382 * _ddekit_thread_enqueue *
383 ****************************************************************************/
384 void _ddekit_thread_enqueue(ddekit_thread_t
*th
)
387 DDEBUG_MSG_VERBOSE("enqueueing thread: id: %d name %s, prio: %d",
388 th
->id
, th
->name
, th
->prio
);
391 _ddekit_print_backtrace(th
);
394 ddekit_assert(th
->next
==NULL
);
396 if (ready_queue
[th
->prio
] != NULL
) {
397 ddekit_thread_t
*pos
= ready_queue
[th
->prio
];
398 while (pos
->next
!= NULL
) {
403 ready_queue
[th
->prio
] = th
;
407 /*****************************************************************************
408 * _ddekit_thread_set_myprio *
409 ****************************************************************************/
410 void _ddekit_thread_set_myprio(int prio
)
412 DDEBUG_MSG_VERBOSE("changing thread prio, id: %d name %s, old prio: %d, "
413 "new prio: %d", current
->id
, current
->name
, current
->prio
);
415 current
->prio
= prio
;
416 ddekit_thread_schedule();
419 /*****************************************************************************
420 * _ddekit_thread_wakeup_sleeping *
421 ****************************************************************************/
422 void _ddekit_thread_wakeup_sleeping()
424 ddekit_thread_t
*th
= sleep_queue
;
429 ddekit_thread_t
*th1
= th
->next
;
430 if (th
->sleep_until
> jiffies
) {
431 th
->next
= sleep_queue
;
435 _ddekit_thread_enqueue(th
);
440 ddekit_thread_schedule();
443 #define FUNC_STACKTRACE(statement) \
446 extern reg_t get_bp(void); \
451 pc= ((reg_t *)bp)[1]; \
452 hbp= ((reg_t *)bp)[0]; \
454 if (hbp != 0 && hbp <= bp) \
464 /*****************************************************************************
465 * _ddekit_print_backtrace *
466 ****************************************************************************/
467 void _ddekit_print_backtrace(ddekit_thread_t
*th
)
469 unsigned long bp
, pc
, hbp
;
471 ddekit_printf("%s: ", th
->name
);
476 #include <sys/jmp_buf.h>
479 bp
= (unsigned long) *((void **)(&((char *)th
->jb
)[JB_BP
]));
481 #error "Unsupported Minix architecture"
483 #endif /* !__ACK__ */
486 pc
= ((unsigned long *)bp
)[1];
487 hbp
= ((unsigned long *)bp
)[0];
489 ddekit_printf("0x%lx ", (unsigned long) pc
);
491 if (hbp
!= 0 && hbp
<= bp
) {
493 ddekit_printf("0x%lx ", (unsigned long) pc
);